@camstack/addon-provider-hikvision 1.2.142 → 1.2.143

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.
Files changed (3) hide show
  1. package/dist/addon.js +160 -46
  2. package/dist/addon.mjs +160 -46
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -10802,6 +10802,57 @@ var ClipSearchStrictnessSchema = _enum([
10802
10802
  "balanced",
10803
10803
  "strict"
10804
10804
  ]);
10805
+ new Set([
10806
+ {
10807
+ id: "person",
10808
+ name: "Person"
10809
+ },
10810
+ {
10811
+ id: "vehicle",
10812
+ name: "Vehicle"
10813
+ },
10814
+ {
10815
+ id: "animal",
10816
+ name: "Animal"
10817
+ },
10818
+ {
10819
+ id: "package",
10820
+ name: "Package"
10821
+ }
10822
+ ].map((l) => l.id));
10823
+ var COCO_TO_MACRO = {
10824
+ mapping: {
10825
+ person: "person",
10826
+ bicycle: "vehicle",
10827
+ car: "vehicle",
10828
+ motorcycle: "vehicle",
10829
+ airplane: "vehicle",
10830
+ bus: "vehicle",
10831
+ train: "vehicle",
10832
+ truck: "vehicle",
10833
+ boat: "vehicle",
10834
+ bird: "animal",
10835
+ cat: "animal",
10836
+ dog: "animal",
10837
+ horse: "animal",
10838
+ sheep: "animal",
10839
+ cow: "animal",
10840
+ elephant: "animal",
10841
+ bear: "animal",
10842
+ zebra: "animal",
10843
+ giraffe: "animal",
10844
+ suitcase: "package",
10845
+ backpack: "package",
10846
+ handbag: "package"
10847
+ },
10848
+ preserveOriginal: false
10849
+ };
10850
+ /** Steps a root detector may declare it fills. */
10851
+ var FILLABLE_STEP_IDS = [
10852
+ "animal-classifier",
10853
+ "vehicle-classifier",
10854
+ "package-detection"
10855
+ ];
10805
10856
  var MODEL_FORMATS = [
10806
10857
  "onnx",
10807
10858
  "coreml",
@@ -10934,6 +10985,12 @@ var ModelLicenseSchema = preprocess((value) => typeof value === "string" ? { wei
10934
10985
  /** True when the weights or their data forbid commercial use. */
10935
10986
  nonCommercial: boolean().optional()
10936
10987
  }));
10988
+ /** One `fillsClassifierEffects` entry — see `ModelCatalogEntry.fillsClassifierEffects`. */
10989
+ var FillsClassifierEffectSchema = object({
10990
+ stepId: _enum(FILLABLE_STEP_IDS),
10991
+ labelToEffect: record(string(), string()),
10992
+ uncovered: array(string()).readonly()
10993
+ });
10937
10994
  var ModelCatalogEntrySchema = object({
10938
10995
  id: string(),
10939
10996
  name: string(),
@@ -11060,6 +11117,16 @@ var ModelCatalogEntrySchema = object({
11060
11117
  */
11061
11118
  classMap: DetectionCatalogClassMapSchema.optional(),
11062
11119
  /**
11120
+ * The pipeline steps this ROOT detector already does the work of (D715):
11121
+ * its labels name the effect the step exists to produce (`deer` for
11122
+ * `animal-classifier`, `package` for `package-detection`). Derived from the
11123
+ * labelmap by `deriveClassifierFills`, never hand-written; a COCO model
11124
+ * declares none. Whether a declaration is honoured is the step's own
11125
+ * `labelLink` policy (`resolveLabelLink`). `labelToEffect` values are in
11126
+ * `FILLABLE_STEP_VOCABULARIES` (guard `check-label-link-vocabulary`).
11127
+ */
11128
+ fillsClassifierEffects: array(FillsClassifierEffectSchema).readonly().optional(),
11129
+ /**
11063
11130
  * The model's CLIP feature-space contract (text encoder, dimension, vector
11064
11131
  * index, token window, search floor) — see `clip-model.ts`. Present ONLY on a
11065
11132
  * CLIP image encoder; its absence is what "not a CLIP model" means to the
@@ -18402,51 +18469,6 @@ method(object({}), array(TargetKindSchema)), method(object({}), array(TargetSche
18402
18469
  kind: "mutation",
18403
18470
  auth: "admin"
18404
18471
  });
18405
- new Set([
18406
- {
18407
- id: "person",
18408
- name: "Person"
18409
- },
18410
- {
18411
- id: "vehicle",
18412
- name: "Vehicle"
18413
- },
18414
- {
18415
- id: "animal",
18416
- name: "Animal"
18417
- },
18418
- {
18419
- id: "package",
18420
- name: "Package"
18421
- }
18422
- ].map((l) => l.id));
18423
- var COCO_TO_MACRO = {
18424
- mapping: {
18425
- person: "person",
18426
- bicycle: "vehicle",
18427
- car: "vehicle",
18428
- motorcycle: "vehicle",
18429
- airplane: "vehicle",
18430
- bus: "vehicle",
18431
- train: "vehicle",
18432
- truck: "vehicle",
18433
- boat: "vehicle",
18434
- bird: "animal",
18435
- cat: "animal",
18436
- dog: "animal",
18437
- horse: "animal",
18438
- sheep: "animal",
18439
- cow: "animal",
18440
- elephant: "animal",
18441
- bear: "animal",
18442
- zebra: "animal",
18443
- giraffe: "animal",
18444
- suitcase: "package",
18445
- backpack: "package",
18446
- handbag: "package"
18447
- },
18448
- preserveOriginal: false
18449
- };
18450
18472
  var AUDIO_MACRO_LABELS = [
18451
18473
  {
18452
18474
  id: "speech",
@@ -23888,7 +23910,8 @@ var PipelineModelOptionSchema = object({
23888
23910
  group: ModelVariantGroupSchema.optional(),
23889
23911
  legacy: boolean().optional(),
23890
23912
  provider: ModelProviderIdSchema.optional(),
23891
- defaultConfidence: number().optional()
23913
+ defaultConfidence: number().optional(),
23914
+ fillsClassifierEffects: array(FillsClassifierEffectSchema).readonly().optional()
23892
23915
  });
23893
23916
  var ConfigFieldBridge = custom();
23894
23917
  var PipelineAddonSchemaSchema = object({
@@ -59911,6 +59934,75 @@ function createAccessoryDevice(kind, ctx, parent) {
59911
59934
  default: throw new Error(`Hikvision provider does not implement accessory kind "${String(kind)}"`);
59912
59935
  }
59913
59936
  }
59937
+ var ALARM_INGRESS_MESSAGE = "hikvision: alarm event received";
59938
+ var countsRecord = (counts) => Object.fromEntries(counts);
59939
+ function createAlarmIngressLog(deps) {
59940
+ const intervalMs = deps.intervalMs ?? 6e4;
59941
+ const bursts = /* @__PURE__ */ new Map();
59942
+ const tags = { deviceId: deps.deviceId };
59943
+ const received = (ev) => {
59944
+ const existing = bursts.get(ev.camStreamId);
59945
+ const burst = existing ?? {
59946
+ startedAt: ev.at,
59947
+ lastLineAt: ev.at,
59948
+ counts: /* @__PURE__ */ new Map(),
59949
+ types: /* @__PURE__ */ new Set(),
59950
+ ticks: 0
59951
+ };
59952
+ if (!existing) bursts.set(ev.camStreamId, burst);
59953
+ burst.ticks += 1;
59954
+ if (!burst.types.has(ev.type)) {
59955
+ burst.types.add(ev.type);
59956
+ deps.logger.info(ALARM_INGRESS_MESSAGE, {
59957
+ tags,
59958
+ meta: {
59959
+ edge: "start",
59960
+ type: ev.type,
59961
+ state: ev.state,
59962
+ camStreamId: ev.camStreamId,
59963
+ ...ev.aiClass === null ? {} : { aiClass: ev.aiClass },
59964
+ ...existing ? { burstAgeMs: ev.at - burst.startedAt } : {}
59965
+ }
59966
+ });
59967
+ burst.lastLineAt = Math.max(burst.lastLineAt, ev.at);
59968
+ return;
59969
+ }
59970
+ burst.counts.set(ev.type, (burst.counts.get(ev.type) ?? 0) + 1);
59971
+ if (ev.at - burst.lastLineAt < intervalMs) return;
59972
+ deps.logger.info(ALARM_INGRESS_MESSAGE, {
59973
+ tags,
59974
+ meta: {
59975
+ edge: "ongoing",
59976
+ camStreamId: ev.camStreamId,
59977
+ counts: countsRecord(burst.counts),
59978
+ windowMs: ev.at - burst.lastLineAt,
59979
+ burstAgeMs: ev.at - burst.startedAt
59980
+ }
59981
+ });
59982
+ burst.counts.clear();
59983
+ burst.lastLineAt = ev.at;
59984
+ };
59985
+ const ended = (camStreamId, at) => {
59986
+ const burst = bursts.get(camStreamId);
59987
+ if (!burst) return;
59988
+ bursts.delete(camStreamId);
59989
+ deps.logger.info(ALARM_INGRESS_MESSAGE, {
59990
+ tags,
59991
+ meta: {
59992
+ edge: "end",
59993
+ camStreamId,
59994
+ counts: countsRecord(burst.counts),
59995
+ ticks: burst.ticks,
59996
+ types: [...burst.types],
59997
+ durationMs: at - burst.startedAt
59998
+ }
59999
+ });
60000
+ };
60001
+ return {
60002
+ received,
60003
+ ended
60004
+ };
60005
+ }
59914
60006
  function createAlarmTypeTally(deps) {
59915
60007
  const intervalMs = deps.intervalMs ?? 3e5;
59916
60008
  const lastLoggedAt = /* @__PURE__ */ new Map();
@@ -64297,6 +64389,20 @@ var HikvisionCamera = class HikvisionCamera extends BaseDevice {
64297
64389
  });
64298
64390
  return this.unhandledAlarmsTally;
64299
64391
  }
64392
+ /**
64393
+ * Sampled info-level ingress line for the motion-bearing alarms (VMD and
64394
+ * smart events): one at each burst's start, one per minute while it lasts,
64395
+ * one at its end — never one per ~1 Hz tick. Lazy for the same reason as
64396
+ * `unhandledAlarms`.
64397
+ */
64398
+ motionIngressLog = null;
64399
+ get motionIngress() {
64400
+ this.motionIngressLog ??= createAlarmIngressLog({
64401
+ logger: this.ctx.logger,
64402
+ deviceId: this.id
64403
+ });
64404
+ return this.motionIngressLog;
64405
+ }
64300
64406
  /** Hysteresis: drop motion-active back to inactive after this many ms with
64301
64407
  * no fresh `VMD` event. Hikvision fires VMD every ~1s while motion is
64302
64408
  * active; missing 2 ticks signals the burst is over. */
@@ -66872,6 +66978,13 @@ var HikvisionCamera = class HikvisionCamera extends BaseDevice {
66872
66978
  handleMotionEvent(ev, camStreamId) {
66873
66979
  const now = ev.observedAt;
66874
66980
  this.lastMotionAt.set(camStreamId, now);
66981
+ this.motionIngress.received({
66982
+ type: ev.type,
66983
+ state: ev.state,
66984
+ aiClass: ev.aiClass,
66985
+ camStreamId,
66986
+ at: now
66987
+ });
66875
66988
  this.ctx.eventBus.emit(providerMotionEvent(this.eventSource, {
66876
66989
  deviceId: this.id,
66877
66990
  detected: true,
@@ -66884,6 +66997,7 @@ var HikvisionCamera = class HikvisionCamera extends BaseDevice {
66884
66997
  const clearedAt = Date.now();
66885
66998
  this.lastMotionAt.set(camStreamId, 0);
66886
66999
  this.motionInactiveTimers.delete(camStreamId);
67000
+ this.motionIngress.ended(camStreamId, clearedAt);
66887
67001
  this.ctx.eventBus.emit(providerMotionEvent(this.eventSource, {
66888
67002
  deviceId: this.id,
66889
67003
  detected: false,
package/dist/addon.mjs CHANGED
@@ -10781,6 +10781,57 @@ var ClipSearchStrictnessSchema = _enum([
10781
10781
  "balanced",
10782
10782
  "strict"
10783
10783
  ]);
10784
+ new Set([
10785
+ {
10786
+ id: "person",
10787
+ name: "Person"
10788
+ },
10789
+ {
10790
+ id: "vehicle",
10791
+ name: "Vehicle"
10792
+ },
10793
+ {
10794
+ id: "animal",
10795
+ name: "Animal"
10796
+ },
10797
+ {
10798
+ id: "package",
10799
+ name: "Package"
10800
+ }
10801
+ ].map((l) => l.id));
10802
+ var COCO_TO_MACRO = {
10803
+ mapping: {
10804
+ person: "person",
10805
+ bicycle: "vehicle",
10806
+ car: "vehicle",
10807
+ motorcycle: "vehicle",
10808
+ airplane: "vehicle",
10809
+ bus: "vehicle",
10810
+ train: "vehicle",
10811
+ truck: "vehicle",
10812
+ boat: "vehicle",
10813
+ bird: "animal",
10814
+ cat: "animal",
10815
+ dog: "animal",
10816
+ horse: "animal",
10817
+ sheep: "animal",
10818
+ cow: "animal",
10819
+ elephant: "animal",
10820
+ bear: "animal",
10821
+ zebra: "animal",
10822
+ giraffe: "animal",
10823
+ suitcase: "package",
10824
+ backpack: "package",
10825
+ handbag: "package"
10826
+ },
10827
+ preserveOriginal: false
10828
+ };
10829
+ /** Steps a root detector may declare it fills. */
10830
+ var FILLABLE_STEP_IDS = [
10831
+ "animal-classifier",
10832
+ "vehicle-classifier",
10833
+ "package-detection"
10834
+ ];
10784
10835
  var MODEL_FORMATS = [
10785
10836
  "onnx",
10786
10837
  "coreml",
@@ -10913,6 +10964,12 @@ var ModelLicenseSchema = preprocess((value) => typeof value === "string" ? { wei
10913
10964
  /** True when the weights or their data forbid commercial use. */
10914
10965
  nonCommercial: boolean().optional()
10915
10966
  }));
10967
+ /** One `fillsClassifierEffects` entry — see `ModelCatalogEntry.fillsClassifierEffects`. */
10968
+ var FillsClassifierEffectSchema = object({
10969
+ stepId: _enum(FILLABLE_STEP_IDS),
10970
+ labelToEffect: record(string(), string()),
10971
+ uncovered: array(string()).readonly()
10972
+ });
10916
10973
  var ModelCatalogEntrySchema = object({
10917
10974
  id: string(),
10918
10975
  name: string(),
@@ -11039,6 +11096,16 @@ var ModelCatalogEntrySchema = object({
11039
11096
  */
11040
11097
  classMap: DetectionCatalogClassMapSchema.optional(),
11041
11098
  /**
11099
+ * The pipeline steps this ROOT detector already does the work of (D715):
11100
+ * its labels name the effect the step exists to produce (`deer` for
11101
+ * `animal-classifier`, `package` for `package-detection`). Derived from the
11102
+ * labelmap by `deriveClassifierFills`, never hand-written; a COCO model
11103
+ * declares none. Whether a declaration is honoured is the step's own
11104
+ * `labelLink` policy (`resolveLabelLink`). `labelToEffect` values are in
11105
+ * `FILLABLE_STEP_VOCABULARIES` (guard `check-label-link-vocabulary`).
11106
+ */
11107
+ fillsClassifierEffects: array(FillsClassifierEffectSchema).readonly().optional(),
11108
+ /**
11042
11109
  * The model's CLIP feature-space contract (text encoder, dimension, vector
11043
11110
  * index, token window, search floor) — see `clip-model.ts`. Present ONLY on a
11044
11111
  * CLIP image encoder; its absence is what "not a CLIP model" means to the
@@ -18381,51 +18448,6 @@ method(object({}), array(TargetKindSchema)), method(object({}), array(TargetSche
18381
18448
  kind: "mutation",
18382
18449
  auth: "admin"
18383
18450
  });
18384
- new Set([
18385
- {
18386
- id: "person",
18387
- name: "Person"
18388
- },
18389
- {
18390
- id: "vehicle",
18391
- name: "Vehicle"
18392
- },
18393
- {
18394
- id: "animal",
18395
- name: "Animal"
18396
- },
18397
- {
18398
- id: "package",
18399
- name: "Package"
18400
- }
18401
- ].map((l) => l.id));
18402
- var COCO_TO_MACRO = {
18403
- mapping: {
18404
- person: "person",
18405
- bicycle: "vehicle",
18406
- car: "vehicle",
18407
- motorcycle: "vehicle",
18408
- airplane: "vehicle",
18409
- bus: "vehicle",
18410
- train: "vehicle",
18411
- truck: "vehicle",
18412
- boat: "vehicle",
18413
- bird: "animal",
18414
- cat: "animal",
18415
- dog: "animal",
18416
- horse: "animal",
18417
- sheep: "animal",
18418
- cow: "animal",
18419
- elephant: "animal",
18420
- bear: "animal",
18421
- zebra: "animal",
18422
- giraffe: "animal",
18423
- suitcase: "package",
18424
- backpack: "package",
18425
- handbag: "package"
18426
- },
18427
- preserveOriginal: false
18428
- };
18429
18451
  var AUDIO_MACRO_LABELS = [
18430
18452
  {
18431
18453
  id: "speech",
@@ -23867,7 +23889,8 @@ var PipelineModelOptionSchema = object({
23867
23889
  group: ModelVariantGroupSchema.optional(),
23868
23890
  legacy: boolean().optional(),
23869
23891
  provider: ModelProviderIdSchema.optional(),
23870
- defaultConfidence: number().optional()
23892
+ defaultConfidence: number().optional(),
23893
+ fillsClassifierEffects: array(FillsClassifierEffectSchema).readonly().optional()
23871
23894
  });
23872
23895
  var ConfigFieldBridge = custom();
23873
23896
  var PipelineAddonSchemaSchema = object({
@@ -59890,6 +59913,75 @@ function createAccessoryDevice(kind, ctx, parent) {
59890
59913
  default: throw new Error(`Hikvision provider does not implement accessory kind "${String(kind)}"`);
59891
59914
  }
59892
59915
  }
59916
+ var ALARM_INGRESS_MESSAGE = "hikvision: alarm event received";
59917
+ var countsRecord = (counts) => Object.fromEntries(counts);
59918
+ function createAlarmIngressLog(deps) {
59919
+ const intervalMs = deps.intervalMs ?? 6e4;
59920
+ const bursts = /* @__PURE__ */ new Map();
59921
+ const tags = { deviceId: deps.deviceId };
59922
+ const received = (ev) => {
59923
+ const existing = bursts.get(ev.camStreamId);
59924
+ const burst = existing ?? {
59925
+ startedAt: ev.at,
59926
+ lastLineAt: ev.at,
59927
+ counts: /* @__PURE__ */ new Map(),
59928
+ types: /* @__PURE__ */ new Set(),
59929
+ ticks: 0
59930
+ };
59931
+ if (!existing) bursts.set(ev.camStreamId, burst);
59932
+ burst.ticks += 1;
59933
+ if (!burst.types.has(ev.type)) {
59934
+ burst.types.add(ev.type);
59935
+ deps.logger.info(ALARM_INGRESS_MESSAGE, {
59936
+ tags,
59937
+ meta: {
59938
+ edge: "start",
59939
+ type: ev.type,
59940
+ state: ev.state,
59941
+ camStreamId: ev.camStreamId,
59942
+ ...ev.aiClass === null ? {} : { aiClass: ev.aiClass },
59943
+ ...existing ? { burstAgeMs: ev.at - burst.startedAt } : {}
59944
+ }
59945
+ });
59946
+ burst.lastLineAt = Math.max(burst.lastLineAt, ev.at);
59947
+ return;
59948
+ }
59949
+ burst.counts.set(ev.type, (burst.counts.get(ev.type) ?? 0) + 1);
59950
+ if (ev.at - burst.lastLineAt < intervalMs) return;
59951
+ deps.logger.info(ALARM_INGRESS_MESSAGE, {
59952
+ tags,
59953
+ meta: {
59954
+ edge: "ongoing",
59955
+ camStreamId: ev.camStreamId,
59956
+ counts: countsRecord(burst.counts),
59957
+ windowMs: ev.at - burst.lastLineAt,
59958
+ burstAgeMs: ev.at - burst.startedAt
59959
+ }
59960
+ });
59961
+ burst.counts.clear();
59962
+ burst.lastLineAt = ev.at;
59963
+ };
59964
+ const ended = (camStreamId, at) => {
59965
+ const burst = bursts.get(camStreamId);
59966
+ if (!burst) return;
59967
+ bursts.delete(camStreamId);
59968
+ deps.logger.info(ALARM_INGRESS_MESSAGE, {
59969
+ tags,
59970
+ meta: {
59971
+ edge: "end",
59972
+ camStreamId,
59973
+ counts: countsRecord(burst.counts),
59974
+ ticks: burst.ticks,
59975
+ types: [...burst.types],
59976
+ durationMs: at - burst.startedAt
59977
+ }
59978
+ });
59979
+ };
59980
+ return {
59981
+ received,
59982
+ ended
59983
+ };
59984
+ }
59893
59985
  function createAlarmTypeTally(deps) {
59894
59986
  const intervalMs = deps.intervalMs ?? 3e5;
59895
59987
  const lastLoggedAt = /* @__PURE__ */ new Map();
@@ -64276,6 +64368,20 @@ var HikvisionCamera = class HikvisionCamera extends BaseDevice {
64276
64368
  });
64277
64369
  return this.unhandledAlarmsTally;
64278
64370
  }
64371
+ /**
64372
+ * Sampled info-level ingress line for the motion-bearing alarms (VMD and
64373
+ * smart events): one at each burst's start, one per minute while it lasts,
64374
+ * one at its end — never one per ~1 Hz tick. Lazy for the same reason as
64375
+ * `unhandledAlarms`.
64376
+ */
64377
+ motionIngressLog = null;
64378
+ get motionIngress() {
64379
+ this.motionIngressLog ??= createAlarmIngressLog({
64380
+ logger: this.ctx.logger,
64381
+ deviceId: this.id
64382
+ });
64383
+ return this.motionIngressLog;
64384
+ }
64279
64385
  /** Hysteresis: drop motion-active back to inactive after this many ms with
64280
64386
  * no fresh `VMD` event. Hikvision fires VMD every ~1s while motion is
64281
64387
  * active; missing 2 ticks signals the burst is over. */
@@ -66851,6 +66957,13 @@ var HikvisionCamera = class HikvisionCamera extends BaseDevice {
66851
66957
  handleMotionEvent(ev, camStreamId) {
66852
66958
  const now = ev.observedAt;
66853
66959
  this.lastMotionAt.set(camStreamId, now);
66960
+ this.motionIngress.received({
66961
+ type: ev.type,
66962
+ state: ev.state,
66963
+ aiClass: ev.aiClass,
66964
+ camStreamId,
66965
+ at: now
66966
+ });
66854
66967
  this.ctx.eventBus.emit(providerMotionEvent(this.eventSource, {
66855
66968
  deviceId: this.id,
66856
66969
  detected: true,
@@ -66863,6 +66976,7 @@ var HikvisionCamera = class HikvisionCamera extends BaseDevice {
66863
66976
  const clearedAt = Date.now();
66864
66977
  this.lastMotionAt.set(camStreamId, 0);
66865
66978
  this.motionInactiveTimers.delete(camStreamId);
66979
+ this.motionIngress.ended(camStreamId, clearedAt);
66866
66980
  this.ctx.eventBus.emit(providerMotionEvent(this.eventSource, {
66867
66981
  deviceId: this.id,
66868
66982
  detected: false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-hikvision",
3
- "version": "1.2.142",
3
+ "version": "1.2.143",
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",