@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.
- package/dist/addon.js +160 -46
- package/dist/addon.mjs +160 -46
- 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.
|
|
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",
|