@camstack/addon-provider-hikvision 1.1.24 → 1.1.25
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 +194 -14
- package/dist/addon.mjs +194 -14
- package/package.json +4 -7
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-
|
|
9
|
+
//#region ../types/dist/event-category-H4AVePnn.mjs
|
|
10
10
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
11
11
|
EventCategory["SystemBoot"] = "system.boot";
|
|
12
12
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -156,6 +156,9 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
156
156
|
EventCategory["RecordingSegmentWritten"] = "recording.segment.written";
|
|
157
157
|
EventCategory["RecordingPolicyFallback"] = "recording.policy.fallback";
|
|
158
158
|
EventCategory["RecordingRetentionCompleted"] = "recording.retention.completed";
|
|
159
|
+
/** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
|
|
160
|
+
* thumb is a scrub gap the recorder's keyframe backfill covers. */
|
|
161
|
+
EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
|
|
159
162
|
EventCategory["DetectionEvent"] = "detection.event";
|
|
160
163
|
EventCategory["SessionTrackNew"] = "session.track.new";
|
|
161
164
|
EventCategory["SessionTrackExpired"] = "session.track.expired";
|
|
@@ -11057,10 +11060,23 @@ var deviceDiscoveryCapability = {
|
|
|
11057
11060
|
}
|
|
11058
11061
|
};
|
|
11059
11062
|
/**
|
|
11060
|
-
* Doorbell button cap.
|
|
11061
|
-
*
|
|
11062
|
-
*
|
|
11063
|
-
*
|
|
11063
|
+
* Doorbell button cap. Two kinds of providers coexist behind this cap
|
|
11064
|
+
* name (same pattern as `snapshot`):
|
|
11065
|
+
*
|
|
11066
|
+
* - **Native** providers: registered per-device by device-driver
|
|
11067
|
+
* addons via `ctx.registerNativeCap` — either on a
|
|
11068
|
+
* `DeviceType.Button` accessory with `role: DeviceRole.Doorbell`,
|
|
11069
|
+
* or directly on the camera (Reolink registers at camera level).
|
|
11070
|
+
* Emits an `onPressed` event every time the firmware pushes a
|
|
11071
|
+
* ring; status tracks the last press and a pressCount since start
|
|
11072
|
+
* (diagnostic).
|
|
11073
|
+
*
|
|
11074
|
+
* - **Wrapper** provider: the `virtual-doorbell` system builtin
|
|
11075
|
+
* (`@camstack/system/builtins/doorbell`). Turns ANY binary-ish
|
|
11076
|
+
* device (contact / switch / event-emitter …) into a doorbell for
|
|
11077
|
+
* a camera. `defaultActive: false` — the operator explicitly binds
|
|
11078
|
+
* it per camera in the device-bindings UI, then picks the source
|
|
11079
|
+
* device + trigger in the per-device settings.
|
|
11064
11080
|
*
|
|
11065
11081
|
* The DeviceEventPropagator re-emits `onPressed` on the camera parent
|
|
11066
11082
|
* — subscribers listening at the camera level receive ring events
|
|
@@ -11081,7 +11097,10 @@ var doorbellCapability = {
|
|
|
11081
11097
|
scope: "device",
|
|
11082
11098
|
deviceNative: true,
|
|
11083
11099
|
mode: "singleton",
|
|
11084
|
-
|
|
11100
|
+
kind: "wrapper",
|
|
11101
|
+
defaultActive: false,
|
|
11102
|
+
deviceTypes: [DeviceType.Button, DeviceType.Camera],
|
|
11103
|
+
exposesDeviceSettings: true,
|
|
11085
11104
|
methods: {},
|
|
11086
11105
|
events: {
|
|
11087
11106
|
/**
|
|
@@ -17445,6 +17464,14 @@ var ConfigEntrySchema = object({
|
|
|
17445
17464
|
value: unknown(),
|
|
17446
17465
|
description: string().optional()
|
|
17447
17466
|
});
|
|
17467
|
+
var DeviceLinkModeSchema = _enum(["auto", "manual"]);
|
|
17468
|
+
/** One resolved linked device — the compact projection consumers need. */
|
|
17469
|
+
var LinkedDeviceSchema = object({
|
|
17470
|
+
deviceId: number(),
|
|
17471
|
+
name: string(),
|
|
17472
|
+
location: string().nullable(),
|
|
17473
|
+
features: array(string())
|
|
17474
|
+
});
|
|
17448
17475
|
var SavedDeviceRowSchema = object({
|
|
17449
17476
|
/** Numeric id reserved at allocateDeviceId time. */
|
|
17450
17477
|
id: number(),
|
|
@@ -17666,7 +17693,10 @@ method(object({
|
|
|
17666
17693
|
}), _void(), {
|
|
17667
17694
|
kind: "mutation",
|
|
17668
17695
|
auth: "admin"
|
|
17669
|
-
}), method(object({ addonId: string() }), array(SavedDeviceRowSchema)), method(object({ addonId: string().optional() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }),
|
|
17696
|
+
}), method(object({ addonId: string() }), array(SavedDeviceRowSchema)), method(object({ addonId: string().optional() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), object({
|
|
17697
|
+
mode: DeviceLinkModeSchema,
|
|
17698
|
+
devices: array(LinkedDeviceSchema)
|
|
17699
|
+
})), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
|
|
17670
17700
|
deviceId: number(),
|
|
17671
17701
|
values: record(string(), unknown())
|
|
17672
17702
|
}), object({ success: literal(true) }), {
|
|
@@ -18935,6 +18965,61 @@ var EventKindSchema = _enum([
|
|
|
18935
18965
|
"object",
|
|
18936
18966
|
"audio"
|
|
18937
18967
|
]);
|
|
18968
|
+
/**
|
|
18969
|
+
* Spatial filter for `listTracks` — the rect + polygon variants of the shared
|
|
18970
|
+
* MaskShape vocabulary (see `mask-shape.ts`). Coordinates are NORMALIZED 0..1
|
|
18971
|
+
* of the camera frame (top-left origin), matching the drawing-plane editor.
|
|
18972
|
+
*/
|
|
18973
|
+
var TrackZoneFilterSchema = discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
|
|
18974
|
+
/** Closed icon vocabulary so clients render a known glyph per kind. */
|
|
18975
|
+
var EventKindIconSchema = _enum([
|
|
18976
|
+
"motion",
|
|
18977
|
+
"audio",
|
|
18978
|
+
"person",
|
|
18979
|
+
"vehicle",
|
|
18980
|
+
"animal",
|
|
18981
|
+
"door",
|
|
18982
|
+
"pir",
|
|
18983
|
+
"smoke",
|
|
18984
|
+
"water",
|
|
18985
|
+
"button",
|
|
18986
|
+
"generic"
|
|
18987
|
+
]);
|
|
18988
|
+
var EventKindCategorySchema = _enum([
|
|
18989
|
+
"motion",
|
|
18990
|
+
"audio",
|
|
18991
|
+
"detection",
|
|
18992
|
+
"sensor",
|
|
18993
|
+
"custom"
|
|
18994
|
+
]);
|
|
18995
|
+
var EventKindDescriptorSchema = object({
|
|
18996
|
+
/** Stable kind id (e.g. 'motion', 'person', 'contact'). */
|
|
18997
|
+
kind: string(),
|
|
18998
|
+
label: string(),
|
|
18999
|
+
/** Hex color for timeline/legend rendering. */
|
|
19000
|
+
color: string(),
|
|
19001
|
+
icon: EventKindIconSchema,
|
|
19002
|
+
category: EventKindCategorySchema,
|
|
19003
|
+
/** Which cap + device contributes this kind. For built-ins the camera
|
|
19004
|
+
* itself; for sensor kinds the LINKED source device. */
|
|
19005
|
+
source: object({
|
|
19006
|
+
capName: string(),
|
|
19007
|
+
deviceId: number()
|
|
19008
|
+
})
|
|
19009
|
+
});
|
|
19010
|
+
var SensorEventSchema = object({
|
|
19011
|
+
id: string(),
|
|
19012
|
+
/** The CAMERA the event is attributed to (a sensor linked to N cameras
|
|
19013
|
+
* yields N rows, one per camera). */
|
|
19014
|
+
deviceId: number(),
|
|
19015
|
+
/** The linked sensor device whose state changed. */
|
|
19016
|
+
sourceDeviceId: number(),
|
|
19017
|
+
/** Event kind id — matches an `EventKindDescriptor.kind`. */
|
|
19018
|
+
kind: string(),
|
|
19019
|
+
/** Snapshot of the sensor cap's runtime-state slice at the change. */
|
|
19020
|
+
value: record(string(), unknown()).nullable(),
|
|
19021
|
+
timestamp: number()
|
|
19022
|
+
});
|
|
18938
19023
|
var TrackPositionSchema = object({
|
|
18939
19024
|
x: number(),
|
|
18940
19025
|
y: number(),
|
|
@@ -18948,6 +19033,30 @@ var TrackSnapshotSchema = object({
|
|
|
18948
19033
|
mediaKey: string()
|
|
18949
19034
|
});
|
|
18950
19035
|
/**
|
|
19036
|
+
* Normalized 0..1 trajectory envelope (min/max over every position bbox,
|
|
19037
|
+
* divided by the track's detection-frame dims), computed at persist time.
|
|
19038
|
+
* Absent when the frame dims were unknown when the track was persisted
|
|
19039
|
+
* (legacy rows / dims-less sources) and on active (in-RAM) tracks.
|
|
19040
|
+
*/
|
|
19041
|
+
var TrackEnvelopeSchema = object({
|
|
19042
|
+
minX: number(),
|
|
19043
|
+
minY: number(),
|
|
19044
|
+
maxX: number(),
|
|
19045
|
+
maxY: number()
|
|
19046
|
+
});
|
|
19047
|
+
/**
|
|
19048
|
+
* Row projection for track list queries. `full` (default) returns the
|
|
19049
|
+
* complete Track including the frame-rate `positions[]` history and the
|
|
19050
|
+
* `snapshots[]` references — megabytes across a page of tracks. `slim`
|
|
19051
|
+
* keeps every scalar the list surfaces actually render (ids, class(es),
|
|
19052
|
+
* label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
|
|
19053
|
+
* zonesVisited, bestEventId, envelope) and returns `positions` /
|
|
19054
|
+
* `snapshots` as EMPTY arrays — detail views re-fetch the full row via
|
|
19055
|
+
* `getTrack`. Mirrors the event-store `projection` convention
|
|
19056
|
+
* (`getObjectEvents` et al.).
|
|
19057
|
+
*/
|
|
19058
|
+
var TrackProjectionSchema = _enum(["full", "slim"]);
|
|
19059
|
+
/**
|
|
18951
19060
|
* One audio-classification label heard on the track's camera while the
|
|
18952
19061
|
* track was alive, aggregated per label. An "episode" is one persisted
|
|
18953
19062
|
* audio event (the confident-classification path: score ≥ the device's
|
|
@@ -18998,7 +19107,11 @@ var TrackSchema = object({
|
|
|
18998
19107
|
/** Audio-classification labels heard on the camera during the track's
|
|
18999
19108
|
* life (score ≥ device `classificationMinScore`), aggregated per label.
|
|
19000
19109
|
* Absent on legacy rows / tracks with no confident audio. */
|
|
19001
|
-
audioLabels: array(TrackAudioLabelSchema).readonly().optional()
|
|
19110
|
+
audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
|
|
19111
|
+
/** Normalized 0..1 trajectory envelope (see {@link TrackEnvelopeSchema}).
|
|
19112
|
+
* Populated from the persisted envelope columns on historical reads;
|
|
19113
|
+
* absent on legacy rows, dims-less tracks and active (in-RAM) tracks. */
|
|
19114
|
+
envelope: TrackEnvelopeSchema.optional()
|
|
19002
19115
|
});
|
|
19003
19116
|
var BaseEventFields = {
|
|
19004
19117
|
id: string(),
|
|
@@ -19108,11 +19221,13 @@ var MediaFileSchema = object({
|
|
|
19108
19221
|
sizeBytes: number(),
|
|
19109
19222
|
timestamp: number()
|
|
19110
19223
|
});
|
|
19224
|
+
var DEFAULT_EVENT_QUERY_LIMIT = 1e3;
|
|
19225
|
+
var MAX_EVENT_QUERY_LIMIT = 5e3;
|
|
19111
19226
|
var DeviceEventQueryInput = object({
|
|
19112
19227
|
deviceId: number(),
|
|
19113
19228
|
since: number().optional(),
|
|
19114
19229
|
until: number().optional(),
|
|
19115
|
-
limit: number().int().min(1).max(
|
|
19230
|
+
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT),
|
|
19116
19231
|
/** `slim` drops heavy JSON fields (regions/bbox/zones) and carries an
|
|
19117
19232
|
* optional `mediaUrl` (populated by B5). `full` (default) keeps today's
|
|
19118
19233
|
* exact behaviour. Callers may omit this field — the store defaults to
|
|
@@ -19120,6 +19235,27 @@ var DeviceEventQueryInput = object({
|
|
|
19120
19235
|
projection: _enum(["full", "slim"]).optional()
|
|
19121
19236
|
});
|
|
19122
19237
|
var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
|
|
19238
|
+
var RecentTracksQueryInput = object({
|
|
19239
|
+
/** Devices to merge. An empty array yields `{ tracks: [], nextCursor: null }`. */
|
|
19240
|
+
deviceIds: array(number()),
|
|
19241
|
+
/** Window lower bound on `lastSeen` (inclusive). */
|
|
19242
|
+
since: number().optional(),
|
|
19243
|
+
/** Window upper bound on `lastSeen` (inclusive). */
|
|
19244
|
+
until: number().optional(),
|
|
19245
|
+
/** Page size. Default 200, max 1000. */
|
|
19246
|
+
limit: number().int().min(1).max(1e3).default(200),
|
|
19247
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`.
|
|
19248
|
+
* Encodes the (lastSeen, trackId) sort position — treat as opaque. */
|
|
19249
|
+
cursor: string().optional(),
|
|
19250
|
+
/** See {@link TrackProjectionSchema}. Default `full`. */
|
|
19251
|
+
projection: TrackProjectionSchema.optional()
|
|
19252
|
+
});
|
|
19253
|
+
var RecentTracksPageSchema = object({
|
|
19254
|
+
/** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
|
|
19255
|
+
tracks: array(TrackSchema).readonly(),
|
|
19256
|
+
/** Cursor for the next page, or null when this page is the last. */
|
|
19257
|
+
nextCursor: string().nullable()
|
|
19258
|
+
});
|
|
19123
19259
|
var KeyEventQueryInput = object({
|
|
19124
19260
|
deviceId: number(),
|
|
19125
19261
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
@@ -19202,11 +19338,25 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19202
19338
|
deviceId: number(),
|
|
19203
19339
|
since: number().optional(),
|
|
19204
19340
|
until: number().optional(),
|
|
19205
|
-
limit: number().optional()
|
|
19206
|
-
|
|
19341
|
+
limit: number().optional(),
|
|
19342
|
+
/** Spatial filter — only tracks whose trajectory intersects the zone
|
|
19343
|
+
* (normalized 0..1 rect or polygon). SQL-prefiltered on the persisted
|
|
19344
|
+
* envelope columns, then precisely tested per position. Tracks with
|
|
19345
|
+
* an unknown envelope (no frame dims at persist time) always match. */
|
|
19346
|
+
zone: TrackZoneFilterSchema.optional(),
|
|
19347
|
+
/** See {@link TrackProjectionSchema}. Default `full` (backward
|
|
19348
|
+
* compatible — omitting the field keeps today's exact behaviour). */
|
|
19349
|
+
projection: TrackProjectionSchema.optional()
|
|
19350
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
|
|
19207
19351
|
kind: "mutation",
|
|
19208
19352
|
auth: "admin"
|
|
19209
|
-
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(
|
|
19353
|
+
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({
|
|
19354
|
+
deviceId: number(),
|
|
19355
|
+
since: number().optional(),
|
|
19356
|
+
until: number().optional(),
|
|
19357
|
+
kinds: array(string()).optional(),
|
|
19358
|
+
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
|
|
19359
|
+
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
|
|
19210
19360
|
deviceId: number(),
|
|
19211
19361
|
since: number(),
|
|
19212
19362
|
until: number(),
|
|
@@ -22622,7 +22772,12 @@ var RecordingStorageUsageSchema = object({
|
|
|
22622
22772
|
/**
|
|
22623
22773
|
* Result of locating footage at a wall-clock instant for one device/profile.
|
|
22624
22774
|
* `segment` carries the covering segment's window; `gap` reports the forward
|
|
22625
|
-
* nearest covered edge (`null` past the end of footage / when none exists)
|
|
22775
|
+
* nearest covered edge (`null` past the end of footage / when none exists)
|
|
22776
|
+
* and the backward covered edge `prevEndMs` (exclusive end of the nearest
|
|
22777
|
+
* footage behind the epoch; `null` when none — optional so older providers
|
|
22778
|
+
* that omit it stay valid). `prevEndMs` lets a backward frame-step hop the
|
|
22779
|
+
* small inter-segment cracks (durMs under-covers the span to the next
|
|
22780
|
+
* startMs by ~11-17 ms) instead of no-opping at a segment head.
|
|
22626
22781
|
*/
|
|
22627
22782
|
var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
|
|
22628
22783
|
kind: literal("segment"),
|
|
@@ -22631,7 +22786,8 @@ var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
|
|
|
22631
22786
|
bytes: number()
|
|
22632
22787
|
}), object({
|
|
22633
22788
|
kind: literal("gap"),
|
|
22634
|
-
nearestEdgeMs: number().nullable()
|
|
22789
|
+
nearestEdgeMs: number().nullable(),
|
|
22790
|
+
prevEndMs: number().nullable().optional()
|
|
22635
22791
|
})]);
|
|
22636
22792
|
/** Raw bytes of one finalized footage segment (read off disk on the recording node). */
|
|
22637
22793
|
var ReadSegmentBytesResultSchema = object({ data: _instanceof(Uint8Array) });
|
|
@@ -24411,6 +24567,12 @@ Object.freeze({
|
|
|
24411
24567
|
addonId: null,
|
|
24412
24568
|
access: "view"
|
|
24413
24569
|
},
|
|
24570
|
+
"deviceManager.getLinkedDevices": {
|
|
24571
|
+
capName: "device-manager",
|
|
24572
|
+
capScope: "system",
|
|
24573
|
+
addonId: null,
|
|
24574
|
+
access: "view"
|
|
24575
|
+
},
|
|
24414
24576
|
"deviceManager.getRoleDisplayDefaults": {
|
|
24415
24577
|
capName: "device-manager",
|
|
24416
24578
|
capScope: "system",
|
|
@@ -25965,6 +26127,12 @@ Object.freeze({
|
|
|
25965
26127
|
addonId: null,
|
|
25966
26128
|
access: "view"
|
|
25967
26129
|
},
|
|
26130
|
+
"pipelineAnalytics.getSensorEvents": {
|
|
26131
|
+
capName: "pipeline-analytics",
|
|
26132
|
+
capScope: "device",
|
|
26133
|
+
addonId: null,
|
|
26134
|
+
access: "view"
|
|
26135
|
+
},
|
|
25968
26136
|
"pipelineAnalytics.getTrack": {
|
|
25969
26137
|
capName: "pipeline-analytics",
|
|
25970
26138
|
capScope: "device",
|
|
@@ -25977,6 +26145,18 @@ Object.freeze({
|
|
|
25977
26145
|
addonId: null,
|
|
25978
26146
|
access: "view"
|
|
25979
26147
|
},
|
|
26148
|
+
"pipelineAnalytics.listEventKinds": {
|
|
26149
|
+
capName: "pipeline-analytics",
|
|
26150
|
+
capScope: "device",
|
|
26151
|
+
addonId: null,
|
|
26152
|
+
access: "view"
|
|
26153
|
+
},
|
|
26154
|
+
"pipelineAnalytics.listRecentTracks": {
|
|
26155
|
+
capName: "pipeline-analytics",
|
|
26156
|
+
capScope: "device",
|
|
26157
|
+
addonId: null,
|
|
26158
|
+
access: "view"
|
|
26159
|
+
},
|
|
25980
26160
|
"pipelineAnalytics.listTracks": {
|
|
25981
26161
|
capName: "pipeline-analytics",
|
|
25982
26162
|
capScope: "device",
|
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-
|
|
10
|
+
//#region ../types/dist/event-category-H4AVePnn.mjs
|
|
11
11
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
12
12
|
EventCategory["SystemBoot"] = "system.boot";
|
|
13
13
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -157,6 +157,9 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
157
157
|
EventCategory["RecordingSegmentWritten"] = "recording.segment.written";
|
|
158
158
|
EventCategory["RecordingPolicyFallback"] = "recording.policy.fallback";
|
|
159
159
|
EventCategory["RecordingRetentionCompleted"] = "recording.retention.completed";
|
|
160
|
+
/** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
|
|
161
|
+
* thumb is a scrub gap the recorder's keyframe backfill covers. */
|
|
162
|
+
EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
|
|
160
163
|
EventCategory["DetectionEvent"] = "detection.event";
|
|
161
164
|
EventCategory["SessionTrackNew"] = "session.track.new";
|
|
162
165
|
EventCategory["SessionTrackExpired"] = "session.track.expired";
|
|
@@ -11058,10 +11061,23 @@ var deviceDiscoveryCapability = {
|
|
|
11058
11061
|
}
|
|
11059
11062
|
};
|
|
11060
11063
|
/**
|
|
11061
|
-
* Doorbell button cap.
|
|
11062
|
-
*
|
|
11063
|
-
*
|
|
11064
|
-
*
|
|
11064
|
+
* Doorbell button cap. Two kinds of providers coexist behind this cap
|
|
11065
|
+
* name (same pattern as `snapshot`):
|
|
11066
|
+
*
|
|
11067
|
+
* - **Native** providers: registered per-device by device-driver
|
|
11068
|
+
* addons via `ctx.registerNativeCap` — either on a
|
|
11069
|
+
* `DeviceType.Button` accessory with `role: DeviceRole.Doorbell`,
|
|
11070
|
+
* or directly on the camera (Reolink registers at camera level).
|
|
11071
|
+
* Emits an `onPressed` event every time the firmware pushes a
|
|
11072
|
+
* ring; status tracks the last press and a pressCount since start
|
|
11073
|
+
* (diagnostic).
|
|
11074
|
+
*
|
|
11075
|
+
* - **Wrapper** provider: the `virtual-doorbell` system builtin
|
|
11076
|
+
* (`@camstack/system/builtins/doorbell`). Turns ANY binary-ish
|
|
11077
|
+
* device (contact / switch / event-emitter …) into a doorbell for
|
|
11078
|
+
* a camera. `defaultActive: false` — the operator explicitly binds
|
|
11079
|
+
* it per camera in the device-bindings UI, then picks the source
|
|
11080
|
+
* device + trigger in the per-device settings.
|
|
11065
11081
|
*
|
|
11066
11082
|
* The DeviceEventPropagator re-emits `onPressed` on the camera parent
|
|
11067
11083
|
* — subscribers listening at the camera level receive ring events
|
|
@@ -11082,7 +11098,10 @@ var doorbellCapability = {
|
|
|
11082
11098
|
scope: "device",
|
|
11083
11099
|
deviceNative: true,
|
|
11084
11100
|
mode: "singleton",
|
|
11085
|
-
|
|
11101
|
+
kind: "wrapper",
|
|
11102
|
+
defaultActive: false,
|
|
11103
|
+
deviceTypes: [DeviceType.Button, DeviceType.Camera],
|
|
11104
|
+
exposesDeviceSettings: true,
|
|
11086
11105
|
methods: {},
|
|
11087
11106
|
events: {
|
|
11088
11107
|
/**
|
|
@@ -17446,6 +17465,14 @@ var ConfigEntrySchema = object({
|
|
|
17446
17465
|
value: unknown(),
|
|
17447
17466
|
description: string().optional()
|
|
17448
17467
|
});
|
|
17468
|
+
var DeviceLinkModeSchema = _enum(["auto", "manual"]);
|
|
17469
|
+
/** One resolved linked device — the compact projection consumers need. */
|
|
17470
|
+
var LinkedDeviceSchema = object({
|
|
17471
|
+
deviceId: number(),
|
|
17472
|
+
name: string(),
|
|
17473
|
+
location: string().nullable(),
|
|
17474
|
+
features: array(string())
|
|
17475
|
+
});
|
|
17449
17476
|
var SavedDeviceRowSchema = object({
|
|
17450
17477
|
/** Numeric id reserved at allocateDeviceId time. */
|
|
17451
17478
|
id: number(),
|
|
@@ -17667,7 +17694,10 @@ method(object({
|
|
|
17667
17694
|
}), _void(), {
|
|
17668
17695
|
kind: "mutation",
|
|
17669
17696
|
auth: "admin"
|
|
17670
|
-
}), method(object({ addonId: string() }), array(SavedDeviceRowSchema)), method(object({ addonId: string().optional() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }),
|
|
17697
|
+
}), method(object({ addonId: string() }), array(SavedDeviceRowSchema)), method(object({ addonId: string().optional() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), object({
|
|
17698
|
+
mode: DeviceLinkModeSchema,
|
|
17699
|
+
devices: array(LinkedDeviceSchema)
|
|
17700
|
+
})), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
|
|
17671
17701
|
deviceId: number(),
|
|
17672
17702
|
values: record(string(), unknown())
|
|
17673
17703
|
}), object({ success: literal(true) }), {
|
|
@@ -18936,6 +18966,61 @@ var EventKindSchema = _enum([
|
|
|
18936
18966
|
"object",
|
|
18937
18967
|
"audio"
|
|
18938
18968
|
]);
|
|
18969
|
+
/**
|
|
18970
|
+
* Spatial filter for `listTracks` — the rect + polygon variants of the shared
|
|
18971
|
+
* MaskShape vocabulary (see `mask-shape.ts`). Coordinates are NORMALIZED 0..1
|
|
18972
|
+
* of the camera frame (top-left origin), matching the drawing-plane editor.
|
|
18973
|
+
*/
|
|
18974
|
+
var TrackZoneFilterSchema = discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
|
|
18975
|
+
/** Closed icon vocabulary so clients render a known glyph per kind. */
|
|
18976
|
+
var EventKindIconSchema = _enum([
|
|
18977
|
+
"motion",
|
|
18978
|
+
"audio",
|
|
18979
|
+
"person",
|
|
18980
|
+
"vehicle",
|
|
18981
|
+
"animal",
|
|
18982
|
+
"door",
|
|
18983
|
+
"pir",
|
|
18984
|
+
"smoke",
|
|
18985
|
+
"water",
|
|
18986
|
+
"button",
|
|
18987
|
+
"generic"
|
|
18988
|
+
]);
|
|
18989
|
+
var EventKindCategorySchema = _enum([
|
|
18990
|
+
"motion",
|
|
18991
|
+
"audio",
|
|
18992
|
+
"detection",
|
|
18993
|
+
"sensor",
|
|
18994
|
+
"custom"
|
|
18995
|
+
]);
|
|
18996
|
+
var EventKindDescriptorSchema = object({
|
|
18997
|
+
/** Stable kind id (e.g. 'motion', 'person', 'contact'). */
|
|
18998
|
+
kind: string(),
|
|
18999
|
+
label: string(),
|
|
19000
|
+
/** Hex color for timeline/legend rendering. */
|
|
19001
|
+
color: string(),
|
|
19002
|
+
icon: EventKindIconSchema,
|
|
19003
|
+
category: EventKindCategorySchema,
|
|
19004
|
+
/** Which cap + device contributes this kind. For built-ins the camera
|
|
19005
|
+
* itself; for sensor kinds the LINKED source device. */
|
|
19006
|
+
source: object({
|
|
19007
|
+
capName: string(),
|
|
19008
|
+
deviceId: number()
|
|
19009
|
+
})
|
|
19010
|
+
});
|
|
19011
|
+
var SensorEventSchema = object({
|
|
19012
|
+
id: string(),
|
|
19013
|
+
/** The CAMERA the event is attributed to (a sensor linked to N cameras
|
|
19014
|
+
* yields N rows, one per camera). */
|
|
19015
|
+
deviceId: number(),
|
|
19016
|
+
/** The linked sensor device whose state changed. */
|
|
19017
|
+
sourceDeviceId: number(),
|
|
19018
|
+
/** Event kind id — matches an `EventKindDescriptor.kind`. */
|
|
19019
|
+
kind: string(),
|
|
19020
|
+
/** Snapshot of the sensor cap's runtime-state slice at the change. */
|
|
19021
|
+
value: record(string(), unknown()).nullable(),
|
|
19022
|
+
timestamp: number()
|
|
19023
|
+
});
|
|
18939
19024
|
var TrackPositionSchema = object({
|
|
18940
19025
|
x: number(),
|
|
18941
19026
|
y: number(),
|
|
@@ -18949,6 +19034,30 @@ var TrackSnapshotSchema = object({
|
|
|
18949
19034
|
mediaKey: string()
|
|
18950
19035
|
});
|
|
18951
19036
|
/**
|
|
19037
|
+
* Normalized 0..1 trajectory envelope (min/max over every position bbox,
|
|
19038
|
+
* divided by the track's detection-frame dims), computed at persist time.
|
|
19039
|
+
* Absent when the frame dims were unknown when the track was persisted
|
|
19040
|
+
* (legacy rows / dims-less sources) and on active (in-RAM) tracks.
|
|
19041
|
+
*/
|
|
19042
|
+
var TrackEnvelopeSchema = object({
|
|
19043
|
+
minX: number(),
|
|
19044
|
+
minY: number(),
|
|
19045
|
+
maxX: number(),
|
|
19046
|
+
maxY: number()
|
|
19047
|
+
});
|
|
19048
|
+
/**
|
|
19049
|
+
* Row projection for track list queries. `full` (default) returns the
|
|
19050
|
+
* complete Track including the frame-rate `positions[]` history and the
|
|
19051
|
+
* `snapshots[]` references — megabytes across a page of tracks. `slim`
|
|
19052
|
+
* keeps every scalar the list surfaces actually render (ids, class(es),
|
|
19053
|
+
* label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
|
|
19054
|
+
* zonesVisited, bestEventId, envelope) and returns `positions` /
|
|
19055
|
+
* `snapshots` as EMPTY arrays — detail views re-fetch the full row via
|
|
19056
|
+
* `getTrack`. Mirrors the event-store `projection` convention
|
|
19057
|
+
* (`getObjectEvents` et al.).
|
|
19058
|
+
*/
|
|
19059
|
+
var TrackProjectionSchema = _enum(["full", "slim"]);
|
|
19060
|
+
/**
|
|
18952
19061
|
* One audio-classification label heard on the track's camera while the
|
|
18953
19062
|
* track was alive, aggregated per label. An "episode" is one persisted
|
|
18954
19063
|
* audio event (the confident-classification path: score ≥ the device's
|
|
@@ -18999,7 +19108,11 @@ var TrackSchema = object({
|
|
|
18999
19108
|
/** Audio-classification labels heard on the camera during the track's
|
|
19000
19109
|
* life (score ≥ device `classificationMinScore`), aggregated per label.
|
|
19001
19110
|
* Absent on legacy rows / tracks with no confident audio. */
|
|
19002
|
-
audioLabels: array(TrackAudioLabelSchema).readonly().optional()
|
|
19111
|
+
audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
|
|
19112
|
+
/** Normalized 0..1 trajectory envelope (see {@link TrackEnvelopeSchema}).
|
|
19113
|
+
* Populated from the persisted envelope columns on historical reads;
|
|
19114
|
+
* absent on legacy rows, dims-less tracks and active (in-RAM) tracks. */
|
|
19115
|
+
envelope: TrackEnvelopeSchema.optional()
|
|
19003
19116
|
});
|
|
19004
19117
|
var BaseEventFields = {
|
|
19005
19118
|
id: string(),
|
|
@@ -19109,11 +19222,13 @@ var MediaFileSchema = object({
|
|
|
19109
19222
|
sizeBytes: number(),
|
|
19110
19223
|
timestamp: number()
|
|
19111
19224
|
});
|
|
19225
|
+
var DEFAULT_EVENT_QUERY_LIMIT = 1e3;
|
|
19226
|
+
var MAX_EVENT_QUERY_LIMIT = 5e3;
|
|
19112
19227
|
var DeviceEventQueryInput = object({
|
|
19113
19228
|
deviceId: number(),
|
|
19114
19229
|
since: number().optional(),
|
|
19115
19230
|
until: number().optional(),
|
|
19116
|
-
limit: number().int().min(1).max(
|
|
19231
|
+
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT),
|
|
19117
19232
|
/** `slim` drops heavy JSON fields (regions/bbox/zones) and carries an
|
|
19118
19233
|
* optional `mediaUrl` (populated by B5). `full` (default) keeps today's
|
|
19119
19234
|
* exact behaviour. Callers may omit this field — the store defaults to
|
|
@@ -19121,6 +19236,27 @@ var DeviceEventQueryInput = object({
|
|
|
19121
19236
|
projection: _enum(["full", "slim"]).optional()
|
|
19122
19237
|
});
|
|
19123
19238
|
var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
|
|
19239
|
+
var RecentTracksQueryInput = object({
|
|
19240
|
+
/** Devices to merge. An empty array yields `{ tracks: [], nextCursor: null }`. */
|
|
19241
|
+
deviceIds: array(number()),
|
|
19242
|
+
/** Window lower bound on `lastSeen` (inclusive). */
|
|
19243
|
+
since: number().optional(),
|
|
19244
|
+
/** Window upper bound on `lastSeen` (inclusive). */
|
|
19245
|
+
until: number().optional(),
|
|
19246
|
+
/** Page size. Default 200, max 1000. */
|
|
19247
|
+
limit: number().int().min(1).max(1e3).default(200),
|
|
19248
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`.
|
|
19249
|
+
* Encodes the (lastSeen, trackId) sort position — treat as opaque. */
|
|
19250
|
+
cursor: string().optional(),
|
|
19251
|
+
/** See {@link TrackProjectionSchema}. Default `full`. */
|
|
19252
|
+
projection: TrackProjectionSchema.optional()
|
|
19253
|
+
});
|
|
19254
|
+
var RecentTracksPageSchema = object({
|
|
19255
|
+
/** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
|
|
19256
|
+
tracks: array(TrackSchema).readonly(),
|
|
19257
|
+
/** Cursor for the next page, or null when this page is the last. */
|
|
19258
|
+
nextCursor: string().nullable()
|
|
19259
|
+
});
|
|
19124
19260
|
var KeyEventQueryInput = object({
|
|
19125
19261
|
deviceId: number(),
|
|
19126
19262
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
@@ -19203,11 +19339,25 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19203
19339
|
deviceId: number(),
|
|
19204
19340
|
since: number().optional(),
|
|
19205
19341
|
until: number().optional(),
|
|
19206
|
-
limit: number().optional()
|
|
19207
|
-
|
|
19342
|
+
limit: number().optional(),
|
|
19343
|
+
/** Spatial filter — only tracks whose trajectory intersects the zone
|
|
19344
|
+
* (normalized 0..1 rect or polygon). SQL-prefiltered on the persisted
|
|
19345
|
+
* envelope columns, then precisely tested per position. Tracks with
|
|
19346
|
+
* an unknown envelope (no frame dims at persist time) always match. */
|
|
19347
|
+
zone: TrackZoneFilterSchema.optional(),
|
|
19348
|
+
/** See {@link TrackProjectionSchema}. Default `full` (backward
|
|
19349
|
+
* compatible — omitting the field keeps today's exact behaviour). */
|
|
19350
|
+
projection: TrackProjectionSchema.optional()
|
|
19351
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
|
|
19208
19352
|
kind: "mutation",
|
|
19209
19353
|
auth: "admin"
|
|
19210
|
-
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(
|
|
19354
|
+
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({
|
|
19355
|
+
deviceId: number(),
|
|
19356
|
+
since: number().optional(),
|
|
19357
|
+
until: number().optional(),
|
|
19358
|
+
kinds: array(string()).optional(),
|
|
19359
|
+
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
|
|
19360
|
+
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
|
|
19211
19361
|
deviceId: number(),
|
|
19212
19362
|
since: number(),
|
|
19213
19363
|
until: number(),
|
|
@@ -22623,7 +22773,12 @@ var RecordingStorageUsageSchema = object({
|
|
|
22623
22773
|
/**
|
|
22624
22774
|
* Result of locating footage at a wall-clock instant for one device/profile.
|
|
22625
22775
|
* `segment` carries the covering segment's window; `gap` reports the forward
|
|
22626
|
-
* nearest covered edge (`null` past the end of footage / when none exists)
|
|
22776
|
+
* nearest covered edge (`null` past the end of footage / when none exists)
|
|
22777
|
+
* and the backward covered edge `prevEndMs` (exclusive end of the nearest
|
|
22778
|
+
* footage behind the epoch; `null` when none — optional so older providers
|
|
22779
|
+
* that omit it stay valid). `prevEndMs` lets a backward frame-step hop the
|
|
22780
|
+
* small inter-segment cracks (durMs under-covers the span to the next
|
|
22781
|
+
* startMs by ~11-17 ms) instead of no-opping at a segment head.
|
|
22627
22782
|
*/
|
|
22628
22783
|
var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
|
|
22629
22784
|
kind: literal("segment"),
|
|
@@ -22632,7 +22787,8 @@ var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
|
|
|
22632
22787
|
bytes: number()
|
|
22633
22788
|
}), object({
|
|
22634
22789
|
kind: literal("gap"),
|
|
22635
|
-
nearestEdgeMs: number().nullable()
|
|
22790
|
+
nearestEdgeMs: number().nullable(),
|
|
22791
|
+
prevEndMs: number().nullable().optional()
|
|
22636
22792
|
})]);
|
|
22637
22793
|
/** Raw bytes of one finalized footage segment (read off disk on the recording node). */
|
|
22638
22794
|
var ReadSegmentBytesResultSchema = object({ data: _instanceof(Uint8Array) });
|
|
@@ -24412,6 +24568,12 @@ Object.freeze({
|
|
|
24412
24568
|
addonId: null,
|
|
24413
24569
|
access: "view"
|
|
24414
24570
|
},
|
|
24571
|
+
"deviceManager.getLinkedDevices": {
|
|
24572
|
+
capName: "device-manager",
|
|
24573
|
+
capScope: "system",
|
|
24574
|
+
addonId: null,
|
|
24575
|
+
access: "view"
|
|
24576
|
+
},
|
|
24415
24577
|
"deviceManager.getRoleDisplayDefaults": {
|
|
24416
24578
|
capName: "device-manager",
|
|
24417
24579
|
capScope: "system",
|
|
@@ -25966,6 +26128,12 @@ Object.freeze({
|
|
|
25966
26128
|
addonId: null,
|
|
25967
26129
|
access: "view"
|
|
25968
26130
|
},
|
|
26131
|
+
"pipelineAnalytics.getSensorEvents": {
|
|
26132
|
+
capName: "pipeline-analytics",
|
|
26133
|
+
capScope: "device",
|
|
26134
|
+
addonId: null,
|
|
26135
|
+
access: "view"
|
|
26136
|
+
},
|
|
25969
26137
|
"pipelineAnalytics.getTrack": {
|
|
25970
26138
|
capName: "pipeline-analytics",
|
|
25971
26139
|
capScope: "device",
|
|
@@ -25978,6 +26146,18 @@ Object.freeze({
|
|
|
25978
26146
|
addonId: null,
|
|
25979
26147
|
access: "view"
|
|
25980
26148
|
},
|
|
26149
|
+
"pipelineAnalytics.listEventKinds": {
|
|
26150
|
+
capName: "pipeline-analytics",
|
|
26151
|
+
capScope: "device",
|
|
26152
|
+
addonId: null,
|
|
26153
|
+
access: "view"
|
|
26154
|
+
},
|
|
26155
|
+
"pipelineAnalytics.listRecentTracks": {
|
|
26156
|
+
capName: "pipeline-analytics",
|
|
26157
|
+
capScope: "device",
|
|
26158
|
+
addonId: null,
|
|
26159
|
+
access: "view"
|
|
26160
|
+
},
|
|
25981
26161
|
"pipelineAnalytics.listTracks": {
|
|
25982
26162
|
capName: "pipeline-analytics",
|
|
25983
26163
|
capScope: "device",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-provider-hikvision",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.25",
|
|
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",
|
|
@@ -81,16 +81,13 @@
|
|
|
81
81
|
"typecheck": "tsc --noEmit",
|
|
82
82
|
"publish": "npm publish --access public"
|
|
83
83
|
},
|
|
84
|
+
"dependencies": {
|
|
85
|
+
"werift": "^0.22.9"
|
|
86
|
+
},
|
|
84
87
|
"peerDependencies": {
|
|
85
88
|
"@camstack/types": "*",
|
|
86
|
-
"werift": "^0.22.9",
|
|
87
89
|
"zod": "^4.3.6"
|
|
88
90
|
},
|
|
89
|
-
"peerDependenciesMeta": {
|
|
90
|
-
"werift": {
|
|
91
|
-
"optional": true
|
|
92
|
-
}
|
|
93
|
-
},
|
|
94
91
|
"devDependencies": {
|
|
95
92
|
"@camstack/types": "*",
|
|
96
93
|
"typescript": "~6.0.3",
|