@camstack/addon-provider-hikvision 1.2.8 → 1.2.9

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
@@ -6,7 +6,7 @@ let node_http = require("node:http");
6
6
  let node_https = require("node:https");
7
7
  let node_crypto = require("node:crypto");
8
8
  let node_os = require("node:os");
9
- //#region ../types/dist/event-category-BLcNejAE.mjs
9
+ //#region ../types/dist/event-category-Bz24uP1U.mjs
10
10
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
11
11
  EventCategory["SystemBoot"] = "system.boot";
12
12
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -277,6 +277,19 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
277
277
  */
278
278
  EventCategory["DeviceStateChanged"] = "device.state-changed";
279
279
  /**
280
+ * Frame occupancy for a camera CHANGED — a tracked object was gained or
281
+ * lost. Carries `{ deviceId, totalObjects, byClass, zones }`.
282
+ *
283
+ * Emitted only on a change, so a steady scene is silent. It exists so a
284
+ * client can stop polling `zoneAnalytics.getCurrentSnapshot`: that was the
285
+ * one live badge with no push signal at all, and it cost a request every
286
+ * four seconds per visible camera.
287
+ *
288
+ * Like every event it is telemetry and may be dropped ([D8]) — a consumer
289
+ * keeps a slow reconcile rather than trusting it alone.
290
+ */
291
+ EventCategory["ZoneAnalyticsOccupancyChanged"] = "zone-analytics.occupancy-changed";
292
+ /**
280
293
  * Cap event fired by every device that registers the `battery`
281
294
  * capability. Mirrors the cap definition's `onStatusChanged`. Carries
282
295
  * `{ deviceId, status: BatteryStatus }`. Subscribers (alert center,
@@ -9589,6 +9602,29 @@ var NcOccupancyConditionSchema = object({
9589
9602
  count: number().int().min(0).default(1),
9590
9603
  sustainSeconds: number().int().min(0).max(3600).default(15)
9591
9604
  });
9605
+ /**
9606
+ * Which zone-crossing DIRECTION a rule accepts (`ObjectEvent.zoneCrossing`).
9607
+ *
9608
+ * The values are not symmetric, and deliberately so — the absent value has to
9609
+ * mean exactly what every rule authored before this condition existed already
9610
+ * does:
9611
+ * - `enter` — entries and every NON-crossing record (movement state,
9612
+ * package, sensor). Exits are rejected. **This is the absent behaviour**:
9613
+ * an operator who never asked for exits must not start receiving them.
9614
+ * - `exit` — ONLY an exit crossing. A record that is not a crossing at all
9615
+ * fails closed, because "the car left the drive" is a question about a
9616
+ * boundary, not about a detection.
9617
+ * - `any` — no direction filter; entries, exits and non-crossings alike.
9618
+ *
9619
+ * A rule asking for a direction should normally also scope `zones`, which the
9620
+ * engine evaluates against the crossed zone as well as the current membership
9621
+ * (an exit's membership no longer contains the zone it just left).
9622
+ */
9623
+ var NcCrossingSchema = _enum([
9624
+ "enter",
9625
+ "exit",
9626
+ "any"
9627
+ ]);
9592
9628
  /** Admin-zone membership condition (zone IDs as stamped by the ZoneEngine). */
9593
9629
  var NcZoneConditionSchema = object({
9594
9630
  ids: array(string().min(1)).min(1),
@@ -9613,6 +9649,13 @@ var NcConditionsSchema = object({
9613
9649
  /** Veto zones — any hit fails the rule. */
9614
9650
  zonesExclude: array(string().min(1)).optional(),
9615
9651
  /**
9652
+ * Zone-crossing direction. IMMEDIATE only — a crossing is a per-event fact
9653
+ * and a closed track carries none, so a `track-end` rule asking for one
9654
+ * fails closed (use `zones`, which tests `zonesVisited`). ABSENT = `enter`,
9655
+ * which is exactly today's behaviour. See {@link NcCrossingSchema}.
9656
+ */
9657
+ crossing: NcCrossingSchema.optional(),
9658
+ /**
9616
9659
  * Exact (case-insensitive) match on the record's collapsed `label`
9617
9660
  * (identity name / plate text / subclass).
9618
9661
  */
@@ -9801,11 +9844,31 @@ var NcMediaPolicySchema = object({
9801
9844
  */
9802
9845
  profile: CamProfileSchema.optional()
9803
9846
  });
9847
+ /**
9848
+ * Cooldown GRANULARITY over the subject's class — how much a fired
9849
+ * notification suppresses.
9850
+ * - `shared` (default, and the absent value) — one window for the whole
9851
+ * rule/scope: a cat silences the next dog for `cooldownSec`.
9852
+ * - `per-class` — an independent window per detected class, so cat→dog fires
9853
+ * at once and cat→cat still waits.
9854
+ *
9855
+ * AUDIO subjects are ALWAYS per-class regardless of this setting: a scream
9856
+ * must not be swallowed by a bark's window (the precedent this generalizes —
9857
+ * see `cooldownKey` in the rule engine).
9858
+ */
9859
+ var NcThrottleGranularitySchema = _enum(["shared", "per-class"]);
9804
9860
  /** Throttle — cooldown survives restarts (rebuilt from the outbox on boot). */
9805
9861
  var NcThrottleSchema = object({
9806
9862
  cooldownSec: number().int().min(0).max(86400).default(60),
9807
9863
  /** `rule` = one shared cooldown; `rule-device` = per-camera cooldown. */
9808
- scope: _enum(["rule", "rule-device"]).default("rule-device")
9864
+ scope: _enum(["rule", "rule-device"]).default("rule-device"),
9865
+ /**
9866
+ * Class granularity of the cooldown key. Optional rather than defaulted:
9867
+ * a Zod default does NOT run on the addon→addon cap path, so a persisted
9868
+ * rule authored before this field simply carries none — and the engine
9869
+ * reads absent as `shared`, the pre-existing behaviour.
9870
+ */
9871
+ granularity: NcThrottleGranularitySchema.optional()
9809
9872
  });
9810
9873
  /** Client-supplied rule fields (server stamps id/createdBy/createdAt/updatedAt). */
9811
9874
  var NcRuleInputSchema = object({
@@ -9913,6 +9976,7 @@ var NcConditionDescriptorSchema = object({
9913
9976
  "schedule",
9914
9977
  "plateMatcher",
9915
9978
  "packagePhase",
9979
+ "crossingSelect",
9916
9980
  "polygonDraw",
9917
9981
  "occupancy"
9918
9982
  ]),
@@ -19147,7 +19211,10 @@ method(object({
19147
19211
  }), method(object({
19148
19212
  deviceId: number(),
19149
19213
  caps: array(string()).readonly().optional()
19150
- }), record(string(), unknown().nullable()));
19214
+ }), record(string(), unknown().nullable())), method(object({
19215
+ deviceIds: array(number()).readonly(),
19216
+ caps: array(string()).readonly().optional()
19217
+ }), record(string(), record(string(), unknown().nullable())));
19151
19218
  method(object({ deviceId: number() }), record(string(), record(string(), unknown()))), method(object({
19152
19219
  deviceId: number(),
19153
19220
  capName: string()
@@ -20555,6 +20622,29 @@ var MotionEventSchema = object({
20555
20622
  * Absent on legacy rows ⇒ treat as `pipeline`.
20556
20623
  */
20557
20624
  var DetectionSourceSchema = _enum(["pipeline", "onboard"]);
20625
+ /**
20626
+ * The confirmed zone crossing that produced an object event. Present ONLY on
20627
+ * an event emitted BY a crossing (`zone.enter` / `zone.exit`); a movement-state
20628
+ * event (`object.entering` / `leaving` / `stationary` / `loitering`) and an
20629
+ * appearance event carry none, so a rule asking for a direction fails closed
20630
+ * on them.
20631
+ *
20632
+ * Exactly ONE crossing per event: the emitter turns each confirmed crossing
20633
+ * into its own event, so a frame in which a track enters A while leaving B
20634
+ * produces two events with two directions — never one ambiguous row.
20635
+ *
20636
+ * `zoneId` is load-bearing for an EXIT: the event's `zones` list is the
20637
+ * membership the box has NOW, and by definition it no longer contains the zone
20638
+ * that was just left. Without the id here, a zone-scoped rule could never match
20639
+ * the exit it asked for.
20640
+ */
20641
+ var ZoneCrossingSchema = object({
20642
+ direction: _enum(["enter", "exit"]),
20643
+ /** Admin zone id crossed. */
20644
+ zoneId: string(),
20645
+ /** Zone display name at crossing time (falls back to the id). */
20646
+ zoneName: string().optional()
20647
+ });
20558
20648
  var ObjectEventSchema = object({
20559
20649
  ...BaseEventFields,
20560
20650
  kind: literal("object"),
@@ -20581,6 +20671,12 @@ var ObjectEventSchema = object({
20581
20671
  zones: array(string()).readonly().optional(),
20582
20672
  /** Omitted in slim projection. */
20583
20673
  state: TrackStateSchema.optional(),
20674
+ /**
20675
+ * The zone crossing this event IS, when it is one. Absent on every other
20676
+ * event kind (movement state, appearance, package) — see
20677
+ * {@link ZoneCrossingSchema}. Omitted in slim projection.
20678
+ */
20679
+ zoneCrossing: ZoneCrossingSchema.optional(),
20584
20680
  /** Detection-frame dimensions in pixels — let consumers normalize the
20585
20681
  * pixel-space `bbox` onto a displayed image. Omitted in slim projection. */
20586
20682
  frameWidth: number().optional(),
@@ -26331,6 +26427,12 @@ Object.freeze({
26331
26427
  addonId: null,
26332
26428
  access: "view"
26333
26429
  },
26430
+ "deviceManager.getDeviceStatusAggregateBatch": {
26431
+ capName: "device-manager",
26432
+ capScope: "system",
26433
+ addonId: null,
26434
+ access: "view"
26435
+ },
26334
26436
  "deviceManager.getLinkedDevices": {
26335
26437
  capName: "device-manager",
26336
26438
  capScope: "system",
package/dist/addon.mjs CHANGED
@@ -7,7 +7,7 @@ import { networkInterfaces } from "node:os";
7
7
  var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
8
8
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
9
9
  //#endregion
10
- //#region ../types/dist/event-category-BLcNejAE.mjs
10
+ //#region ../types/dist/event-category-Bz24uP1U.mjs
11
11
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
12
12
  EventCategory["SystemBoot"] = "system.boot";
13
13
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -278,6 +278,19 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
278
278
  */
279
279
  EventCategory["DeviceStateChanged"] = "device.state-changed";
280
280
  /**
281
+ * Frame occupancy for a camera CHANGED — a tracked object was gained or
282
+ * lost. Carries `{ deviceId, totalObjects, byClass, zones }`.
283
+ *
284
+ * Emitted only on a change, so a steady scene is silent. It exists so a
285
+ * client can stop polling `zoneAnalytics.getCurrentSnapshot`: that was the
286
+ * one live badge with no push signal at all, and it cost a request every
287
+ * four seconds per visible camera.
288
+ *
289
+ * Like every event it is telemetry and may be dropped ([D8]) — a consumer
290
+ * keeps a slow reconcile rather than trusting it alone.
291
+ */
292
+ EventCategory["ZoneAnalyticsOccupancyChanged"] = "zone-analytics.occupancy-changed";
293
+ /**
281
294
  * Cap event fired by every device that registers the `battery`
282
295
  * capability. Mirrors the cap definition's `onStatusChanged`. Carries
283
296
  * `{ deviceId, status: BatteryStatus }`. Subscribers (alert center,
@@ -9590,6 +9603,29 @@ var NcOccupancyConditionSchema = object({
9590
9603
  count: number().int().min(0).default(1),
9591
9604
  sustainSeconds: number().int().min(0).max(3600).default(15)
9592
9605
  });
9606
+ /**
9607
+ * Which zone-crossing DIRECTION a rule accepts (`ObjectEvent.zoneCrossing`).
9608
+ *
9609
+ * The values are not symmetric, and deliberately so — the absent value has to
9610
+ * mean exactly what every rule authored before this condition existed already
9611
+ * does:
9612
+ * - `enter` — entries and every NON-crossing record (movement state,
9613
+ * package, sensor). Exits are rejected. **This is the absent behaviour**:
9614
+ * an operator who never asked for exits must not start receiving them.
9615
+ * - `exit` — ONLY an exit crossing. A record that is not a crossing at all
9616
+ * fails closed, because "the car left the drive" is a question about a
9617
+ * boundary, not about a detection.
9618
+ * - `any` — no direction filter; entries, exits and non-crossings alike.
9619
+ *
9620
+ * A rule asking for a direction should normally also scope `zones`, which the
9621
+ * engine evaluates against the crossed zone as well as the current membership
9622
+ * (an exit's membership no longer contains the zone it just left).
9623
+ */
9624
+ var NcCrossingSchema = _enum([
9625
+ "enter",
9626
+ "exit",
9627
+ "any"
9628
+ ]);
9593
9629
  /** Admin-zone membership condition (zone IDs as stamped by the ZoneEngine). */
9594
9630
  var NcZoneConditionSchema = object({
9595
9631
  ids: array(string().min(1)).min(1),
@@ -9614,6 +9650,13 @@ var NcConditionsSchema = object({
9614
9650
  /** Veto zones — any hit fails the rule. */
9615
9651
  zonesExclude: array(string().min(1)).optional(),
9616
9652
  /**
9653
+ * Zone-crossing direction. IMMEDIATE only — a crossing is a per-event fact
9654
+ * and a closed track carries none, so a `track-end` rule asking for one
9655
+ * fails closed (use `zones`, which tests `zonesVisited`). ABSENT = `enter`,
9656
+ * which is exactly today's behaviour. See {@link NcCrossingSchema}.
9657
+ */
9658
+ crossing: NcCrossingSchema.optional(),
9659
+ /**
9617
9660
  * Exact (case-insensitive) match on the record's collapsed `label`
9618
9661
  * (identity name / plate text / subclass).
9619
9662
  */
@@ -9802,11 +9845,31 @@ var NcMediaPolicySchema = object({
9802
9845
  */
9803
9846
  profile: CamProfileSchema.optional()
9804
9847
  });
9848
+ /**
9849
+ * Cooldown GRANULARITY over the subject's class — how much a fired
9850
+ * notification suppresses.
9851
+ * - `shared` (default, and the absent value) — one window for the whole
9852
+ * rule/scope: a cat silences the next dog for `cooldownSec`.
9853
+ * - `per-class` — an independent window per detected class, so cat→dog fires
9854
+ * at once and cat→cat still waits.
9855
+ *
9856
+ * AUDIO subjects are ALWAYS per-class regardless of this setting: a scream
9857
+ * must not be swallowed by a bark's window (the precedent this generalizes —
9858
+ * see `cooldownKey` in the rule engine).
9859
+ */
9860
+ var NcThrottleGranularitySchema = _enum(["shared", "per-class"]);
9805
9861
  /** Throttle — cooldown survives restarts (rebuilt from the outbox on boot). */
9806
9862
  var NcThrottleSchema = object({
9807
9863
  cooldownSec: number().int().min(0).max(86400).default(60),
9808
9864
  /** `rule` = one shared cooldown; `rule-device` = per-camera cooldown. */
9809
- scope: _enum(["rule", "rule-device"]).default("rule-device")
9865
+ scope: _enum(["rule", "rule-device"]).default("rule-device"),
9866
+ /**
9867
+ * Class granularity of the cooldown key. Optional rather than defaulted:
9868
+ * a Zod default does NOT run on the addon→addon cap path, so a persisted
9869
+ * rule authored before this field simply carries none — and the engine
9870
+ * reads absent as `shared`, the pre-existing behaviour.
9871
+ */
9872
+ granularity: NcThrottleGranularitySchema.optional()
9810
9873
  });
9811
9874
  /** Client-supplied rule fields (server stamps id/createdBy/createdAt/updatedAt). */
9812
9875
  var NcRuleInputSchema = object({
@@ -9914,6 +9977,7 @@ var NcConditionDescriptorSchema = object({
9914
9977
  "schedule",
9915
9978
  "plateMatcher",
9916
9979
  "packagePhase",
9980
+ "crossingSelect",
9917
9981
  "polygonDraw",
9918
9982
  "occupancy"
9919
9983
  ]),
@@ -19148,7 +19212,10 @@ method(object({
19148
19212
  }), method(object({
19149
19213
  deviceId: number(),
19150
19214
  caps: array(string()).readonly().optional()
19151
- }), record(string(), unknown().nullable()));
19215
+ }), record(string(), unknown().nullable())), method(object({
19216
+ deviceIds: array(number()).readonly(),
19217
+ caps: array(string()).readonly().optional()
19218
+ }), record(string(), record(string(), unknown().nullable())));
19152
19219
  method(object({ deviceId: number() }), record(string(), record(string(), unknown()))), method(object({
19153
19220
  deviceId: number(),
19154
19221
  capName: string()
@@ -20556,6 +20623,29 @@ var MotionEventSchema = object({
20556
20623
  * Absent on legacy rows ⇒ treat as `pipeline`.
20557
20624
  */
20558
20625
  var DetectionSourceSchema = _enum(["pipeline", "onboard"]);
20626
+ /**
20627
+ * The confirmed zone crossing that produced an object event. Present ONLY on
20628
+ * an event emitted BY a crossing (`zone.enter` / `zone.exit`); a movement-state
20629
+ * event (`object.entering` / `leaving` / `stationary` / `loitering`) and an
20630
+ * appearance event carry none, so a rule asking for a direction fails closed
20631
+ * on them.
20632
+ *
20633
+ * Exactly ONE crossing per event: the emitter turns each confirmed crossing
20634
+ * into its own event, so a frame in which a track enters A while leaving B
20635
+ * produces two events with two directions — never one ambiguous row.
20636
+ *
20637
+ * `zoneId` is load-bearing for an EXIT: the event's `zones` list is the
20638
+ * membership the box has NOW, and by definition it no longer contains the zone
20639
+ * that was just left. Without the id here, a zone-scoped rule could never match
20640
+ * the exit it asked for.
20641
+ */
20642
+ var ZoneCrossingSchema = object({
20643
+ direction: _enum(["enter", "exit"]),
20644
+ /** Admin zone id crossed. */
20645
+ zoneId: string(),
20646
+ /** Zone display name at crossing time (falls back to the id). */
20647
+ zoneName: string().optional()
20648
+ });
20559
20649
  var ObjectEventSchema = object({
20560
20650
  ...BaseEventFields,
20561
20651
  kind: literal("object"),
@@ -20582,6 +20672,12 @@ var ObjectEventSchema = object({
20582
20672
  zones: array(string()).readonly().optional(),
20583
20673
  /** Omitted in slim projection. */
20584
20674
  state: TrackStateSchema.optional(),
20675
+ /**
20676
+ * The zone crossing this event IS, when it is one. Absent on every other
20677
+ * event kind (movement state, appearance, package) — see
20678
+ * {@link ZoneCrossingSchema}. Omitted in slim projection.
20679
+ */
20680
+ zoneCrossing: ZoneCrossingSchema.optional(),
20585
20681
  /** Detection-frame dimensions in pixels — let consumers normalize the
20586
20682
  * pixel-space `bbox` onto a displayed image. Omitted in slim projection. */
20587
20683
  frameWidth: number().optional(),
@@ -26332,6 +26428,12 @@ Object.freeze({
26332
26428
  addonId: null,
26333
26429
  access: "view"
26334
26430
  },
26431
+ "deviceManager.getDeviceStatusAggregateBatch": {
26432
+ capName: "device-manager",
26433
+ capScope: "system",
26434
+ addonId: null,
26435
+ access: "view"
26436
+ },
26335
26437
  "deviceManager.getLinkedDevices": {
26336
26438
  capName: "device-manager",
26337
26439
  capScope: "system",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-hikvision",
3
- "version": "1.2.8",
3
+ "version": "1.2.9",
4
4
  "description": "Hikvision camera device provider addon for CamStack — ISAPI over HTTP(S) with digest auth (snapshot, alarm stream, RTSP discovery)",
5
5
  "keywords": [
6
6
  "camstack",