@camstack/addon-provider-reolink 1.2.14 → 1.2.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/addon.js CHANGED
@@ -26,7 +26,7 @@ let fs_promises = require("fs/promises");
26
26
  fs_promises = require_chunk.__toESM(fs_promises, 1);
27
27
  let node_os = require("node:os");
28
28
  node_os = require_chunk.__toESM(node_os);
29
- //#region ../types/dist/event-category-BLcNejAE.mjs
29
+ //#region ../types/dist/event-category-Bz24uP1U.mjs
30
30
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
31
31
  EventCategory["SystemBoot"] = "system.boot";
32
32
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -297,6 +297,19 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
297
297
  */
298
298
  EventCategory["DeviceStateChanged"] = "device.state-changed";
299
299
  /**
300
+ * Frame occupancy for a camera CHANGED — a tracked object was gained or
301
+ * lost. Carries `{ deviceId, totalObjects, byClass, zones }`.
302
+ *
303
+ * Emitted only on a change, so a steady scene is silent. It exists so a
304
+ * client can stop polling `zoneAnalytics.getCurrentSnapshot`: that was the
305
+ * one live badge with no push signal at all, and it cost a request every
306
+ * four seconds per visible camera.
307
+ *
308
+ * Like every event it is telemetry and may be dropped ([D8]) — a consumer
309
+ * keeps a slow reconcile rather than trusting it alone.
310
+ */
311
+ EventCategory["ZoneAnalyticsOccupancyChanged"] = "zone-analytics.occupancy-changed";
312
+ /**
300
313
  * Cap event fired by every device that registers the `battery`
301
314
  * capability. Mirrors the cap definition's `onStatusChanged`. Carries
302
315
  * `{ deviceId, status: BatteryStatus }`. Subscribers (alert center,
@@ -9567,6 +9580,29 @@ var NcOccupancyConditionSchema = object({
9567
9580
  count: number().int().min(0).default(1),
9568
9581
  sustainSeconds: number().int().min(0).max(3600).default(15)
9569
9582
  });
9583
+ /**
9584
+ * Which zone-crossing DIRECTION a rule accepts (`ObjectEvent.zoneCrossing`).
9585
+ *
9586
+ * The values are not symmetric, and deliberately so — the absent value has to
9587
+ * mean exactly what every rule authored before this condition existed already
9588
+ * does:
9589
+ * - `enter` — entries and every NON-crossing record (movement state,
9590
+ * package, sensor). Exits are rejected. **This is the absent behaviour**:
9591
+ * an operator who never asked for exits must not start receiving them.
9592
+ * - `exit` — ONLY an exit crossing. A record that is not a crossing at all
9593
+ * fails closed, because "the car left the drive" is a question about a
9594
+ * boundary, not about a detection.
9595
+ * - `any` — no direction filter; entries, exits and non-crossings alike.
9596
+ *
9597
+ * A rule asking for a direction should normally also scope `zones`, which the
9598
+ * engine evaluates against the crossed zone as well as the current membership
9599
+ * (an exit's membership no longer contains the zone it just left).
9600
+ */
9601
+ var NcCrossingSchema = _enum([
9602
+ "enter",
9603
+ "exit",
9604
+ "any"
9605
+ ]);
9570
9606
  /** Admin-zone membership condition (zone IDs as stamped by the ZoneEngine). */
9571
9607
  var NcZoneConditionSchema = object({
9572
9608
  ids: array(string().min(1)).min(1),
@@ -9591,6 +9627,13 @@ var NcConditionsSchema = object({
9591
9627
  /** Veto zones — any hit fails the rule. */
9592
9628
  zonesExclude: array(string().min(1)).optional(),
9593
9629
  /**
9630
+ * Zone-crossing direction. IMMEDIATE only — a crossing is a per-event fact
9631
+ * and a closed track carries none, so a `track-end` rule asking for one
9632
+ * fails closed (use `zones`, which tests `zonesVisited`). ABSENT = `enter`,
9633
+ * which is exactly today's behaviour. See {@link NcCrossingSchema}.
9634
+ */
9635
+ crossing: NcCrossingSchema.optional(),
9636
+ /**
9594
9637
  * Exact (case-insensitive) match on the record's collapsed `label`
9595
9638
  * (identity name / plate text / subclass).
9596
9639
  */
@@ -9779,11 +9822,31 @@ var NcMediaPolicySchema = object({
9779
9822
  */
9780
9823
  profile: CamProfileSchema.optional()
9781
9824
  });
9825
+ /**
9826
+ * Cooldown GRANULARITY over the subject's class — how much a fired
9827
+ * notification suppresses.
9828
+ * - `shared` (default, and the absent value) — one window for the whole
9829
+ * rule/scope: a cat silences the next dog for `cooldownSec`.
9830
+ * - `per-class` — an independent window per detected class, so cat→dog fires
9831
+ * at once and cat→cat still waits.
9832
+ *
9833
+ * AUDIO subjects are ALWAYS per-class regardless of this setting: a scream
9834
+ * must not be swallowed by a bark's window (the precedent this generalizes —
9835
+ * see `cooldownKey` in the rule engine).
9836
+ */
9837
+ var NcThrottleGranularitySchema = _enum(["shared", "per-class"]);
9782
9838
  /** Throttle — cooldown survives restarts (rebuilt from the outbox on boot). */
9783
9839
  var NcThrottleSchema = object({
9784
9840
  cooldownSec: number().int().min(0).max(86400).default(60),
9785
9841
  /** `rule` = one shared cooldown; `rule-device` = per-camera cooldown. */
9786
- scope: _enum(["rule", "rule-device"]).default("rule-device")
9842
+ scope: _enum(["rule", "rule-device"]).default("rule-device"),
9843
+ /**
9844
+ * Class granularity of the cooldown key. Optional rather than defaulted:
9845
+ * a Zod default does NOT run on the addon→addon cap path, so a persisted
9846
+ * rule authored before this field simply carries none — and the engine
9847
+ * reads absent as `shared`, the pre-existing behaviour.
9848
+ */
9849
+ granularity: NcThrottleGranularitySchema.optional()
9787
9850
  });
9788
9851
  /** Client-supplied rule fields (server stamps id/createdBy/createdAt/updatedAt). */
9789
9852
  var NcRuleInputSchema = object({
@@ -9891,6 +9954,7 @@ var NcConditionDescriptorSchema = object({
9891
9954
  "schedule",
9892
9955
  "plateMatcher",
9893
9956
  "packagePhase",
9957
+ "crossingSelect",
9894
9958
  "polygonDraw",
9895
9959
  "occupancy"
9896
9960
  ]),
@@ -19125,7 +19189,10 @@ method(object({
19125
19189
  }), method(object({
19126
19190
  deviceId: number(),
19127
19191
  caps: array(string()).readonly().optional()
19128
- }), record(string(), unknown().nullable()));
19192
+ }), record(string(), unknown().nullable())), method(object({
19193
+ deviceIds: array(number()).readonly(),
19194
+ caps: array(string()).readonly().optional()
19195
+ }), record(string(), record(string(), unknown().nullable())));
19129
19196
  method(object({ deviceId: number() }), record(string(), record(string(), unknown()))), method(object({
19130
19197
  deviceId: number(),
19131
19198
  capName: string()
@@ -20533,6 +20600,29 @@ var MotionEventSchema = object({
20533
20600
  * Absent on legacy rows ⇒ treat as `pipeline`.
20534
20601
  */
20535
20602
  var DetectionSourceSchema = _enum(["pipeline", "onboard"]);
20603
+ /**
20604
+ * The confirmed zone crossing that produced an object event. Present ONLY on
20605
+ * an event emitted BY a crossing (`zone.enter` / `zone.exit`); a movement-state
20606
+ * event (`object.entering` / `leaving` / `stationary` / `loitering`) and an
20607
+ * appearance event carry none, so a rule asking for a direction fails closed
20608
+ * on them.
20609
+ *
20610
+ * Exactly ONE crossing per event: the emitter turns each confirmed crossing
20611
+ * into its own event, so a frame in which a track enters A while leaving B
20612
+ * produces two events with two directions — never one ambiguous row.
20613
+ *
20614
+ * `zoneId` is load-bearing for an EXIT: the event's `zones` list is the
20615
+ * membership the box has NOW, and by definition it no longer contains the zone
20616
+ * that was just left. Without the id here, a zone-scoped rule could never match
20617
+ * the exit it asked for.
20618
+ */
20619
+ var ZoneCrossingSchema = object({
20620
+ direction: _enum(["enter", "exit"]),
20621
+ /** Admin zone id crossed. */
20622
+ zoneId: string(),
20623
+ /** Zone display name at crossing time (falls back to the id). */
20624
+ zoneName: string().optional()
20625
+ });
20536
20626
  var ObjectEventSchema = object({
20537
20627
  ...BaseEventFields,
20538
20628
  kind: literal("object"),
@@ -20559,6 +20649,12 @@ var ObjectEventSchema = object({
20559
20649
  zones: array(string()).readonly().optional(),
20560
20650
  /** Omitted in slim projection. */
20561
20651
  state: TrackStateSchema.optional(),
20652
+ /**
20653
+ * The zone crossing this event IS, when it is one. Absent on every other
20654
+ * event kind (movement state, appearance, package) — see
20655
+ * {@link ZoneCrossingSchema}. Omitted in slim projection.
20656
+ */
20657
+ zoneCrossing: ZoneCrossingSchema.optional(),
20562
20658
  /** Detection-frame dimensions in pixels — let consumers normalize the
20563
20659
  * pixel-space `bbox` onto a displayed image. Omitted in slim projection. */
20564
20660
  frameWidth: number().optional(),
@@ -26263,6 +26359,12 @@ Object.freeze({
26263
26359
  addonId: null,
26264
26360
  access: "view"
26265
26361
  },
26362
+ "deviceManager.getDeviceStatusAggregateBatch": {
26363
+ capName: "device-manager",
26364
+ capScope: "system",
26365
+ addonId: null,
26366
+ access: "view"
26367
+ },
26266
26368
  "deviceManager.getLinkedDevices": {
26267
26369
  capName: "device-manager",
26268
26370
  capScope: "system",
package/dist/addon.mjs CHANGED
@@ -21,7 +21,7 @@ import netImpl from "net";
21
21
  import { fileURLToPath } from "url";
22
22
  import { mkdir } from "fs/promises";
23
23
  import os from "node:os";
24
- //#region ../types/dist/event-category-BLcNejAE.mjs
24
+ //#region ../types/dist/event-category-Bz24uP1U.mjs
25
25
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
26
26
  EventCategory["SystemBoot"] = "system.boot";
27
27
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -292,6 +292,19 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
292
292
  */
293
293
  EventCategory["DeviceStateChanged"] = "device.state-changed";
294
294
  /**
295
+ * Frame occupancy for a camera CHANGED — a tracked object was gained or
296
+ * lost. Carries `{ deviceId, totalObjects, byClass, zones }`.
297
+ *
298
+ * Emitted only on a change, so a steady scene is silent. It exists so a
299
+ * client can stop polling `zoneAnalytics.getCurrentSnapshot`: that was the
300
+ * one live badge with no push signal at all, and it cost a request every
301
+ * four seconds per visible camera.
302
+ *
303
+ * Like every event it is telemetry and may be dropped ([D8]) — a consumer
304
+ * keeps a slow reconcile rather than trusting it alone.
305
+ */
306
+ EventCategory["ZoneAnalyticsOccupancyChanged"] = "zone-analytics.occupancy-changed";
307
+ /**
295
308
  * Cap event fired by every device that registers the `battery`
296
309
  * capability. Mirrors the cap definition's `onStatusChanged`. Carries
297
310
  * `{ deviceId, status: BatteryStatus }`. Subscribers (alert center,
@@ -9562,6 +9575,29 @@ var NcOccupancyConditionSchema = object({
9562
9575
  count: number().int().min(0).default(1),
9563
9576
  sustainSeconds: number().int().min(0).max(3600).default(15)
9564
9577
  });
9578
+ /**
9579
+ * Which zone-crossing DIRECTION a rule accepts (`ObjectEvent.zoneCrossing`).
9580
+ *
9581
+ * The values are not symmetric, and deliberately so — the absent value has to
9582
+ * mean exactly what every rule authored before this condition existed already
9583
+ * does:
9584
+ * - `enter` — entries and every NON-crossing record (movement state,
9585
+ * package, sensor). Exits are rejected. **This is the absent behaviour**:
9586
+ * an operator who never asked for exits must not start receiving them.
9587
+ * - `exit` — ONLY an exit crossing. A record that is not a crossing at all
9588
+ * fails closed, because "the car left the drive" is a question about a
9589
+ * boundary, not about a detection.
9590
+ * - `any` — no direction filter; entries, exits and non-crossings alike.
9591
+ *
9592
+ * A rule asking for a direction should normally also scope `zones`, which the
9593
+ * engine evaluates against the crossed zone as well as the current membership
9594
+ * (an exit's membership no longer contains the zone it just left).
9595
+ */
9596
+ var NcCrossingSchema = _enum([
9597
+ "enter",
9598
+ "exit",
9599
+ "any"
9600
+ ]);
9565
9601
  /** Admin-zone membership condition (zone IDs as stamped by the ZoneEngine). */
9566
9602
  var NcZoneConditionSchema = object({
9567
9603
  ids: array(string().min(1)).min(1),
@@ -9586,6 +9622,13 @@ var NcConditionsSchema = object({
9586
9622
  /** Veto zones — any hit fails the rule. */
9587
9623
  zonesExclude: array(string().min(1)).optional(),
9588
9624
  /**
9625
+ * Zone-crossing direction. IMMEDIATE only — a crossing is a per-event fact
9626
+ * and a closed track carries none, so a `track-end` rule asking for one
9627
+ * fails closed (use `zones`, which tests `zonesVisited`). ABSENT = `enter`,
9628
+ * which is exactly today's behaviour. See {@link NcCrossingSchema}.
9629
+ */
9630
+ crossing: NcCrossingSchema.optional(),
9631
+ /**
9589
9632
  * Exact (case-insensitive) match on the record's collapsed `label`
9590
9633
  * (identity name / plate text / subclass).
9591
9634
  */
@@ -9774,11 +9817,31 @@ var NcMediaPolicySchema = object({
9774
9817
  */
9775
9818
  profile: CamProfileSchema.optional()
9776
9819
  });
9820
+ /**
9821
+ * Cooldown GRANULARITY over the subject's class — how much a fired
9822
+ * notification suppresses.
9823
+ * - `shared` (default, and the absent value) — one window for the whole
9824
+ * rule/scope: a cat silences the next dog for `cooldownSec`.
9825
+ * - `per-class` — an independent window per detected class, so cat→dog fires
9826
+ * at once and cat→cat still waits.
9827
+ *
9828
+ * AUDIO subjects are ALWAYS per-class regardless of this setting: a scream
9829
+ * must not be swallowed by a bark's window (the precedent this generalizes —
9830
+ * see `cooldownKey` in the rule engine).
9831
+ */
9832
+ var NcThrottleGranularitySchema = _enum(["shared", "per-class"]);
9777
9833
  /** Throttle — cooldown survives restarts (rebuilt from the outbox on boot). */
9778
9834
  var NcThrottleSchema = object({
9779
9835
  cooldownSec: number().int().min(0).max(86400).default(60),
9780
9836
  /** `rule` = one shared cooldown; `rule-device` = per-camera cooldown. */
9781
- scope: _enum(["rule", "rule-device"]).default("rule-device")
9837
+ scope: _enum(["rule", "rule-device"]).default("rule-device"),
9838
+ /**
9839
+ * Class granularity of the cooldown key. Optional rather than defaulted:
9840
+ * a Zod default does NOT run on the addon→addon cap path, so a persisted
9841
+ * rule authored before this field simply carries none — and the engine
9842
+ * reads absent as `shared`, the pre-existing behaviour.
9843
+ */
9844
+ granularity: NcThrottleGranularitySchema.optional()
9782
9845
  });
9783
9846
  /** Client-supplied rule fields (server stamps id/createdBy/createdAt/updatedAt). */
9784
9847
  var NcRuleInputSchema = object({
@@ -9886,6 +9949,7 @@ var NcConditionDescriptorSchema = object({
9886
9949
  "schedule",
9887
9950
  "plateMatcher",
9888
9951
  "packagePhase",
9952
+ "crossingSelect",
9889
9953
  "polygonDraw",
9890
9954
  "occupancy"
9891
9955
  ]),
@@ -19120,7 +19184,10 @@ method(object({
19120
19184
  }), method(object({
19121
19185
  deviceId: number(),
19122
19186
  caps: array(string()).readonly().optional()
19123
- }), record(string(), unknown().nullable()));
19187
+ }), record(string(), unknown().nullable())), method(object({
19188
+ deviceIds: array(number()).readonly(),
19189
+ caps: array(string()).readonly().optional()
19190
+ }), record(string(), record(string(), unknown().nullable())));
19124
19191
  method(object({ deviceId: number() }), record(string(), record(string(), unknown()))), method(object({
19125
19192
  deviceId: number(),
19126
19193
  capName: string()
@@ -20528,6 +20595,29 @@ var MotionEventSchema = object({
20528
20595
  * Absent on legacy rows ⇒ treat as `pipeline`.
20529
20596
  */
20530
20597
  var DetectionSourceSchema = _enum(["pipeline", "onboard"]);
20598
+ /**
20599
+ * The confirmed zone crossing that produced an object event. Present ONLY on
20600
+ * an event emitted BY a crossing (`zone.enter` / `zone.exit`); a movement-state
20601
+ * event (`object.entering` / `leaving` / `stationary` / `loitering`) and an
20602
+ * appearance event carry none, so a rule asking for a direction fails closed
20603
+ * on them.
20604
+ *
20605
+ * Exactly ONE crossing per event: the emitter turns each confirmed crossing
20606
+ * into its own event, so a frame in which a track enters A while leaving B
20607
+ * produces two events with two directions — never one ambiguous row.
20608
+ *
20609
+ * `zoneId` is load-bearing for an EXIT: the event's `zones` list is the
20610
+ * membership the box has NOW, and by definition it no longer contains the zone
20611
+ * that was just left. Without the id here, a zone-scoped rule could never match
20612
+ * the exit it asked for.
20613
+ */
20614
+ var ZoneCrossingSchema = object({
20615
+ direction: _enum(["enter", "exit"]),
20616
+ /** Admin zone id crossed. */
20617
+ zoneId: string(),
20618
+ /** Zone display name at crossing time (falls back to the id). */
20619
+ zoneName: string().optional()
20620
+ });
20531
20621
  var ObjectEventSchema = object({
20532
20622
  ...BaseEventFields,
20533
20623
  kind: literal("object"),
@@ -20554,6 +20644,12 @@ var ObjectEventSchema = object({
20554
20644
  zones: array(string()).readonly().optional(),
20555
20645
  /** Omitted in slim projection. */
20556
20646
  state: TrackStateSchema.optional(),
20647
+ /**
20648
+ * The zone crossing this event IS, when it is one. Absent on every other
20649
+ * event kind (movement state, appearance, package) — see
20650
+ * {@link ZoneCrossingSchema}. Omitted in slim projection.
20651
+ */
20652
+ zoneCrossing: ZoneCrossingSchema.optional(),
20557
20653
  /** Detection-frame dimensions in pixels — let consumers normalize the
20558
20654
  * pixel-space `bbox` onto a displayed image. Omitted in slim projection. */
20559
20655
  frameWidth: number().optional(),
@@ -26258,6 +26354,12 @@ Object.freeze({
26258
26354
  addonId: null,
26259
26355
  access: "view"
26260
26356
  },
26357
+ "deviceManager.getDeviceStatusAggregateBatch": {
26358
+ capName: "device-manager",
26359
+ capScope: "system",
26360
+ addonId: null,
26361
+ access: "view"
26362
+ },
26261
26363
  "deviceManager.getLinkedDevices": {
26262
26364
  capName: "device-manager",
26263
26365
  capScope: "system",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-reolink",
3
- "version": "1.2.14",
3
+ "version": "1.2.15",
4
4
  "description": "Reolink camera device provider addon for CamStack — native Baichuan protocol",
5
5
  "keywords": [
6
6
  "camstack",