@camstack/addon-provider-reolink 1.1.25 → 1.1.26
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 +1 -1
package/dist/addon.js
CHANGED
|
@@ -26,7 +26,7 @@ let fs_promises = require("fs/promises");
|
|
|
26
26
|
fs_promises = require_chunk.__toESM(fs_promises, 1);
|
|
27
27
|
let node_os = require("node:os");
|
|
28
28
|
node_os = require_chunk.__toESM(node_os);
|
|
29
|
-
//#region ../types/dist/event-category-
|
|
29
|
+
//#region ../types/dist/event-category-H4AVePnn.mjs
|
|
30
30
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
31
31
|
EventCategory["SystemBoot"] = "system.boot";
|
|
32
32
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -176,6 +176,9 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
176
176
|
EventCategory["RecordingSegmentWritten"] = "recording.segment.written";
|
|
177
177
|
EventCategory["RecordingPolicyFallback"] = "recording.policy.fallback";
|
|
178
178
|
EventCategory["RecordingRetentionCompleted"] = "recording.retention.completed";
|
|
179
|
+
/** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
|
|
180
|
+
* thumb is a scrub gap the recorder's keyframe backfill covers. */
|
|
181
|
+
EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
|
|
179
182
|
EventCategory["DetectionEvent"] = "detection.event";
|
|
180
183
|
EventCategory["SessionTrackNew"] = "session.track.new";
|
|
181
184
|
EventCategory["SessionTrackExpired"] = "session.track.expired";
|
|
@@ -11035,10 +11038,23 @@ var deviceDiscoveryCapability = {
|
|
|
11035
11038
|
}
|
|
11036
11039
|
};
|
|
11037
11040
|
/**
|
|
11038
|
-
* Doorbell button cap.
|
|
11039
|
-
*
|
|
11040
|
-
*
|
|
11041
|
-
*
|
|
11041
|
+
* Doorbell button cap. Two kinds of providers coexist behind this cap
|
|
11042
|
+
* name (same pattern as `snapshot`):
|
|
11043
|
+
*
|
|
11044
|
+
* - **Native** providers: registered per-device by device-driver
|
|
11045
|
+
* addons via `ctx.registerNativeCap` — either on a
|
|
11046
|
+
* `DeviceType.Button` accessory with `role: DeviceRole.Doorbell`,
|
|
11047
|
+
* or directly on the camera (Reolink registers at camera level).
|
|
11048
|
+
* Emits an `onPressed` event every time the firmware pushes a
|
|
11049
|
+
* ring; status tracks the last press and a pressCount since start
|
|
11050
|
+
* (diagnostic).
|
|
11051
|
+
*
|
|
11052
|
+
* - **Wrapper** provider: the `virtual-doorbell` system builtin
|
|
11053
|
+
* (`@camstack/system/builtins/doorbell`). Turns ANY binary-ish
|
|
11054
|
+
* device (contact / switch / event-emitter …) into a doorbell for
|
|
11055
|
+
* a camera. `defaultActive: false` — the operator explicitly binds
|
|
11056
|
+
* it per camera in the device-bindings UI, then picks the source
|
|
11057
|
+
* device + trigger in the per-device settings.
|
|
11042
11058
|
*
|
|
11043
11059
|
* The DeviceEventPropagator re-emits `onPressed` on the camera parent
|
|
11044
11060
|
* — subscribers listening at the camera level receive ring events
|
|
@@ -11059,7 +11075,10 @@ var doorbellCapability = {
|
|
|
11059
11075
|
scope: "device",
|
|
11060
11076
|
deviceNative: true,
|
|
11061
11077
|
mode: "singleton",
|
|
11062
|
-
|
|
11078
|
+
kind: "wrapper",
|
|
11079
|
+
defaultActive: false,
|
|
11080
|
+
deviceTypes: [DeviceType.Button, DeviceType.Camera],
|
|
11081
|
+
exposesDeviceSettings: true,
|
|
11063
11082
|
methods: {},
|
|
11064
11083
|
events: {
|
|
11065
11084
|
/**
|
|
@@ -17423,6 +17442,14 @@ var ConfigEntrySchema = object({
|
|
|
17423
17442
|
value: unknown(),
|
|
17424
17443
|
description: string().optional()
|
|
17425
17444
|
});
|
|
17445
|
+
var DeviceLinkModeSchema = _enum(["auto", "manual"]);
|
|
17446
|
+
/** One resolved linked device — the compact projection consumers need. */
|
|
17447
|
+
var LinkedDeviceSchema = object({
|
|
17448
|
+
deviceId: number(),
|
|
17449
|
+
name: string(),
|
|
17450
|
+
location: string().nullable(),
|
|
17451
|
+
features: array(string())
|
|
17452
|
+
});
|
|
17426
17453
|
var SavedDeviceRowSchema = object({
|
|
17427
17454
|
/** Numeric id reserved at allocateDeviceId time. */
|
|
17428
17455
|
id: number(),
|
|
@@ -17644,7 +17671,10 @@ method(object({
|
|
|
17644
17671
|
}), _void(), {
|
|
17645
17672
|
kind: "mutation",
|
|
17646
17673
|
auth: "admin"
|
|
17647
|
-
}), 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() }),
|
|
17674
|
+
}), 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({
|
|
17675
|
+
mode: DeviceLinkModeSchema,
|
|
17676
|
+
devices: array(LinkedDeviceSchema)
|
|
17677
|
+
})), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
|
|
17648
17678
|
deviceId: number(),
|
|
17649
17679
|
values: record(string(), unknown())
|
|
17650
17680
|
}), object({ success: literal(true) }), {
|
|
@@ -18913,6 +18943,61 @@ var EventKindSchema = _enum([
|
|
|
18913
18943
|
"object",
|
|
18914
18944
|
"audio"
|
|
18915
18945
|
]);
|
|
18946
|
+
/**
|
|
18947
|
+
* Spatial filter for `listTracks` — the rect + polygon variants of the shared
|
|
18948
|
+
* MaskShape vocabulary (see `mask-shape.ts`). Coordinates are NORMALIZED 0..1
|
|
18949
|
+
* of the camera frame (top-left origin), matching the drawing-plane editor.
|
|
18950
|
+
*/
|
|
18951
|
+
var TrackZoneFilterSchema = discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
|
|
18952
|
+
/** Closed icon vocabulary so clients render a known glyph per kind. */
|
|
18953
|
+
var EventKindIconSchema = _enum([
|
|
18954
|
+
"motion",
|
|
18955
|
+
"audio",
|
|
18956
|
+
"person",
|
|
18957
|
+
"vehicle",
|
|
18958
|
+
"animal",
|
|
18959
|
+
"door",
|
|
18960
|
+
"pir",
|
|
18961
|
+
"smoke",
|
|
18962
|
+
"water",
|
|
18963
|
+
"button",
|
|
18964
|
+
"generic"
|
|
18965
|
+
]);
|
|
18966
|
+
var EventKindCategorySchema = _enum([
|
|
18967
|
+
"motion",
|
|
18968
|
+
"audio",
|
|
18969
|
+
"detection",
|
|
18970
|
+
"sensor",
|
|
18971
|
+
"custom"
|
|
18972
|
+
]);
|
|
18973
|
+
var EventKindDescriptorSchema = object({
|
|
18974
|
+
/** Stable kind id (e.g. 'motion', 'person', 'contact'). */
|
|
18975
|
+
kind: string(),
|
|
18976
|
+
label: string(),
|
|
18977
|
+
/** Hex color for timeline/legend rendering. */
|
|
18978
|
+
color: string(),
|
|
18979
|
+
icon: EventKindIconSchema,
|
|
18980
|
+
category: EventKindCategorySchema,
|
|
18981
|
+
/** Which cap + device contributes this kind. For built-ins the camera
|
|
18982
|
+
* itself; for sensor kinds the LINKED source device. */
|
|
18983
|
+
source: object({
|
|
18984
|
+
capName: string(),
|
|
18985
|
+
deviceId: number()
|
|
18986
|
+
})
|
|
18987
|
+
});
|
|
18988
|
+
var SensorEventSchema = object({
|
|
18989
|
+
id: string(),
|
|
18990
|
+
/** The CAMERA the event is attributed to (a sensor linked to N cameras
|
|
18991
|
+
* yields N rows, one per camera). */
|
|
18992
|
+
deviceId: number(),
|
|
18993
|
+
/** The linked sensor device whose state changed. */
|
|
18994
|
+
sourceDeviceId: number(),
|
|
18995
|
+
/** Event kind id — matches an `EventKindDescriptor.kind`. */
|
|
18996
|
+
kind: string(),
|
|
18997
|
+
/** Snapshot of the sensor cap's runtime-state slice at the change. */
|
|
18998
|
+
value: record(string(), unknown()).nullable(),
|
|
18999
|
+
timestamp: number()
|
|
19000
|
+
});
|
|
18916
19001
|
var TrackPositionSchema = object({
|
|
18917
19002
|
x: number(),
|
|
18918
19003
|
y: number(),
|
|
@@ -18926,6 +19011,30 @@ var TrackSnapshotSchema = object({
|
|
|
18926
19011
|
mediaKey: string()
|
|
18927
19012
|
});
|
|
18928
19013
|
/**
|
|
19014
|
+
* Normalized 0..1 trajectory envelope (min/max over every position bbox,
|
|
19015
|
+
* divided by the track's detection-frame dims), computed at persist time.
|
|
19016
|
+
* Absent when the frame dims were unknown when the track was persisted
|
|
19017
|
+
* (legacy rows / dims-less sources) and on active (in-RAM) tracks.
|
|
19018
|
+
*/
|
|
19019
|
+
var TrackEnvelopeSchema = object({
|
|
19020
|
+
minX: number(),
|
|
19021
|
+
minY: number(),
|
|
19022
|
+
maxX: number(),
|
|
19023
|
+
maxY: number()
|
|
19024
|
+
});
|
|
19025
|
+
/**
|
|
19026
|
+
* Row projection for track list queries. `full` (default) returns the
|
|
19027
|
+
* complete Track including the frame-rate `positions[]` history and the
|
|
19028
|
+
* `snapshots[]` references — megabytes across a page of tracks. `slim`
|
|
19029
|
+
* keeps every scalar the list surfaces actually render (ids, class(es),
|
|
19030
|
+
* label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
|
|
19031
|
+
* zonesVisited, bestEventId, envelope) and returns `positions` /
|
|
19032
|
+
* `snapshots` as EMPTY arrays — detail views re-fetch the full row via
|
|
19033
|
+
* `getTrack`. Mirrors the event-store `projection` convention
|
|
19034
|
+
* (`getObjectEvents` et al.).
|
|
19035
|
+
*/
|
|
19036
|
+
var TrackProjectionSchema = _enum(["full", "slim"]);
|
|
19037
|
+
/**
|
|
18929
19038
|
* One audio-classification label heard on the track's camera while the
|
|
18930
19039
|
* track was alive, aggregated per label. An "episode" is one persisted
|
|
18931
19040
|
* audio event (the confident-classification path: score ≥ the device's
|
|
@@ -18976,7 +19085,11 @@ var TrackSchema = object({
|
|
|
18976
19085
|
/** Audio-classification labels heard on the camera during the track's
|
|
18977
19086
|
* life (score ≥ device `classificationMinScore`), aggregated per label.
|
|
18978
19087
|
* Absent on legacy rows / tracks with no confident audio. */
|
|
18979
|
-
audioLabels: array(TrackAudioLabelSchema).readonly().optional()
|
|
19088
|
+
audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
|
|
19089
|
+
/** Normalized 0..1 trajectory envelope (see {@link TrackEnvelopeSchema}).
|
|
19090
|
+
* Populated from the persisted envelope columns on historical reads;
|
|
19091
|
+
* absent on legacy rows, dims-less tracks and active (in-RAM) tracks. */
|
|
19092
|
+
envelope: TrackEnvelopeSchema.optional()
|
|
18980
19093
|
});
|
|
18981
19094
|
var BaseEventFields = {
|
|
18982
19095
|
id: string(),
|
|
@@ -19086,11 +19199,13 @@ var MediaFileSchema = object({
|
|
|
19086
19199
|
sizeBytes: number(),
|
|
19087
19200
|
timestamp: number()
|
|
19088
19201
|
});
|
|
19202
|
+
var DEFAULT_EVENT_QUERY_LIMIT = 1e3;
|
|
19203
|
+
var MAX_EVENT_QUERY_LIMIT = 5e3;
|
|
19089
19204
|
var DeviceEventQueryInput = object({
|
|
19090
19205
|
deviceId: number(),
|
|
19091
19206
|
since: number().optional(),
|
|
19092
19207
|
until: number().optional(),
|
|
19093
|
-
limit: number().int().min(1).max(
|
|
19208
|
+
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT),
|
|
19094
19209
|
/** `slim` drops heavy JSON fields (regions/bbox/zones) and carries an
|
|
19095
19210
|
* optional `mediaUrl` (populated by B5). `full` (default) keeps today's
|
|
19096
19211
|
* exact behaviour. Callers may omit this field — the store defaults to
|
|
@@ -19098,6 +19213,27 @@ var DeviceEventQueryInput = object({
|
|
|
19098
19213
|
projection: _enum(["full", "slim"]).optional()
|
|
19099
19214
|
});
|
|
19100
19215
|
var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
|
|
19216
|
+
var RecentTracksQueryInput = object({
|
|
19217
|
+
/** Devices to merge. An empty array yields `{ tracks: [], nextCursor: null }`. */
|
|
19218
|
+
deviceIds: array(number()),
|
|
19219
|
+
/** Window lower bound on `lastSeen` (inclusive). */
|
|
19220
|
+
since: number().optional(),
|
|
19221
|
+
/** Window upper bound on `lastSeen` (inclusive). */
|
|
19222
|
+
until: number().optional(),
|
|
19223
|
+
/** Page size. Default 200, max 1000. */
|
|
19224
|
+
limit: number().int().min(1).max(1e3).default(200),
|
|
19225
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`.
|
|
19226
|
+
* Encodes the (lastSeen, trackId) sort position — treat as opaque. */
|
|
19227
|
+
cursor: string().optional(),
|
|
19228
|
+
/** See {@link TrackProjectionSchema}. Default `full`. */
|
|
19229
|
+
projection: TrackProjectionSchema.optional()
|
|
19230
|
+
});
|
|
19231
|
+
var RecentTracksPageSchema = object({
|
|
19232
|
+
/** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
|
|
19233
|
+
tracks: array(TrackSchema).readonly(),
|
|
19234
|
+
/** Cursor for the next page, or null when this page is the last. */
|
|
19235
|
+
nextCursor: string().nullable()
|
|
19236
|
+
});
|
|
19101
19237
|
var KeyEventQueryInput = object({
|
|
19102
19238
|
deviceId: number(),
|
|
19103
19239
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
@@ -19180,11 +19316,25 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19180
19316
|
deviceId: number(),
|
|
19181
19317
|
since: number().optional(),
|
|
19182
19318
|
until: number().optional(),
|
|
19183
|
-
limit: number().optional()
|
|
19184
|
-
|
|
19319
|
+
limit: number().optional(),
|
|
19320
|
+
/** Spatial filter — only tracks whose trajectory intersects the zone
|
|
19321
|
+
* (normalized 0..1 rect or polygon). SQL-prefiltered on the persisted
|
|
19322
|
+
* envelope columns, then precisely tested per position. Tracks with
|
|
19323
|
+
* an unknown envelope (no frame dims at persist time) always match. */
|
|
19324
|
+
zone: TrackZoneFilterSchema.optional(),
|
|
19325
|
+
/** See {@link TrackProjectionSchema}. Default `full` (backward
|
|
19326
|
+
* compatible — omitting the field keeps today's exact behaviour). */
|
|
19327
|
+
projection: TrackProjectionSchema.optional()
|
|
19328
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
|
|
19185
19329
|
kind: "mutation",
|
|
19186
19330
|
auth: "admin"
|
|
19187
|
-
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(
|
|
19331
|
+
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({
|
|
19332
|
+
deviceId: number(),
|
|
19333
|
+
since: number().optional(),
|
|
19334
|
+
until: number().optional(),
|
|
19335
|
+
kinds: array(string()).optional(),
|
|
19336
|
+
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
|
|
19337
|
+
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
|
|
19188
19338
|
deviceId: number(),
|
|
19189
19339
|
since: number(),
|
|
19190
19340
|
until: number(),
|
|
@@ -22554,7 +22704,12 @@ var RecordingStorageUsageSchema = object({
|
|
|
22554
22704
|
/**
|
|
22555
22705
|
* Result of locating footage at a wall-clock instant for one device/profile.
|
|
22556
22706
|
* `segment` carries the covering segment's window; `gap` reports the forward
|
|
22557
|
-
* nearest covered edge (`null` past the end of footage / when none exists)
|
|
22707
|
+
* nearest covered edge (`null` past the end of footage / when none exists)
|
|
22708
|
+
* and the backward covered edge `prevEndMs` (exclusive end of the nearest
|
|
22709
|
+
* footage behind the epoch; `null` when none — optional so older providers
|
|
22710
|
+
* that omit it stay valid). `prevEndMs` lets a backward frame-step hop the
|
|
22711
|
+
* small inter-segment cracks (durMs under-covers the span to the next
|
|
22712
|
+
* startMs by ~11-17 ms) instead of no-opping at a segment head.
|
|
22558
22713
|
*/
|
|
22559
22714
|
var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
|
|
22560
22715
|
kind: literal("segment"),
|
|
@@ -22563,7 +22718,8 @@ var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
|
|
|
22563
22718
|
bytes: number()
|
|
22564
22719
|
}), object({
|
|
22565
22720
|
kind: literal("gap"),
|
|
22566
|
-
nearestEdgeMs: number().nullable()
|
|
22721
|
+
nearestEdgeMs: number().nullable(),
|
|
22722
|
+
prevEndMs: number().nullable().optional()
|
|
22567
22723
|
})]);
|
|
22568
22724
|
/** Raw bytes of one finalized footage segment (read off disk on the recording node). */
|
|
22569
22725
|
var ReadSegmentBytesResultSchema = object({ data: _instanceof(Uint8Array) });
|
|
@@ -24343,6 +24499,12 @@ Object.freeze({
|
|
|
24343
24499
|
addonId: null,
|
|
24344
24500
|
access: "view"
|
|
24345
24501
|
},
|
|
24502
|
+
"deviceManager.getLinkedDevices": {
|
|
24503
|
+
capName: "device-manager",
|
|
24504
|
+
capScope: "system",
|
|
24505
|
+
addonId: null,
|
|
24506
|
+
access: "view"
|
|
24507
|
+
},
|
|
24346
24508
|
"deviceManager.getRoleDisplayDefaults": {
|
|
24347
24509
|
capName: "device-manager",
|
|
24348
24510
|
capScope: "system",
|
|
@@ -25897,6 +26059,12 @@ Object.freeze({
|
|
|
25897
26059
|
addonId: null,
|
|
25898
26060
|
access: "view"
|
|
25899
26061
|
},
|
|
26062
|
+
"pipelineAnalytics.getSensorEvents": {
|
|
26063
|
+
capName: "pipeline-analytics",
|
|
26064
|
+
capScope: "device",
|
|
26065
|
+
addonId: null,
|
|
26066
|
+
access: "view"
|
|
26067
|
+
},
|
|
25900
26068
|
"pipelineAnalytics.getTrack": {
|
|
25901
26069
|
capName: "pipeline-analytics",
|
|
25902
26070
|
capScope: "device",
|
|
@@ -25909,6 +26077,18 @@ Object.freeze({
|
|
|
25909
26077
|
addonId: null,
|
|
25910
26078
|
access: "view"
|
|
25911
26079
|
},
|
|
26080
|
+
"pipelineAnalytics.listEventKinds": {
|
|
26081
|
+
capName: "pipeline-analytics",
|
|
26082
|
+
capScope: "device",
|
|
26083
|
+
addonId: null,
|
|
26084
|
+
access: "view"
|
|
26085
|
+
},
|
|
26086
|
+
"pipelineAnalytics.listRecentTracks": {
|
|
26087
|
+
capName: "pipeline-analytics",
|
|
26088
|
+
capScope: "device",
|
|
26089
|
+
addonId: null,
|
|
26090
|
+
access: "view"
|
|
26091
|
+
},
|
|
25912
26092
|
"pipelineAnalytics.listTracks": {
|
|
25913
26093
|
capName: "pipeline-analytics",
|
|
25914
26094
|
capScope: "device",
|
package/dist/addon.mjs
CHANGED
|
@@ -21,7 +21,7 @@ import netImpl from "net";
|
|
|
21
21
|
import { fileURLToPath } from "url";
|
|
22
22
|
import { mkdir } from "fs/promises";
|
|
23
23
|
import os from "node:os";
|
|
24
|
-
//#region ../types/dist/event-category-
|
|
24
|
+
//#region ../types/dist/event-category-H4AVePnn.mjs
|
|
25
25
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
26
26
|
EventCategory["SystemBoot"] = "system.boot";
|
|
27
27
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -171,6 +171,9 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
171
171
|
EventCategory["RecordingSegmentWritten"] = "recording.segment.written";
|
|
172
172
|
EventCategory["RecordingPolicyFallback"] = "recording.policy.fallback";
|
|
173
173
|
EventCategory["RecordingRetentionCompleted"] = "recording.retention.completed";
|
|
174
|
+
/** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
|
|
175
|
+
* thumb is a scrub gap the recorder's keyframe backfill covers. */
|
|
176
|
+
EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
|
|
174
177
|
EventCategory["DetectionEvent"] = "detection.event";
|
|
175
178
|
EventCategory["SessionTrackNew"] = "session.track.new";
|
|
176
179
|
EventCategory["SessionTrackExpired"] = "session.track.expired";
|
|
@@ -11030,10 +11033,23 @@ var deviceDiscoveryCapability = {
|
|
|
11030
11033
|
}
|
|
11031
11034
|
};
|
|
11032
11035
|
/**
|
|
11033
|
-
* Doorbell button cap.
|
|
11034
|
-
*
|
|
11035
|
-
*
|
|
11036
|
-
*
|
|
11036
|
+
* Doorbell button cap. Two kinds of providers coexist behind this cap
|
|
11037
|
+
* name (same pattern as `snapshot`):
|
|
11038
|
+
*
|
|
11039
|
+
* - **Native** providers: registered per-device by device-driver
|
|
11040
|
+
* addons via `ctx.registerNativeCap` — either on a
|
|
11041
|
+
* `DeviceType.Button` accessory with `role: DeviceRole.Doorbell`,
|
|
11042
|
+
* or directly on the camera (Reolink registers at camera level).
|
|
11043
|
+
* Emits an `onPressed` event every time the firmware pushes a
|
|
11044
|
+
* ring; status tracks the last press and a pressCount since start
|
|
11045
|
+
* (diagnostic).
|
|
11046
|
+
*
|
|
11047
|
+
* - **Wrapper** provider: the `virtual-doorbell` system builtin
|
|
11048
|
+
* (`@camstack/system/builtins/doorbell`). Turns ANY binary-ish
|
|
11049
|
+
* device (contact / switch / event-emitter …) into a doorbell for
|
|
11050
|
+
* a camera. `defaultActive: false` — the operator explicitly binds
|
|
11051
|
+
* it per camera in the device-bindings UI, then picks the source
|
|
11052
|
+
* device + trigger in the per-device settings.
|
|
11037
11053
|
*
|
|
11038
11054
|
* The DeviceEventPropagator re-emits `onPressed` on the camera parent
|
|
11039
11055
|
* — subscribers listening at the camera level receive ring events
|
|
@@ -11054,7 +11070,10 @@ var doorbellCapability = {
|
|
|
11054
11070
|
scope: "device",
|
|
11055
11071
|
deviceNative: true,
|
|
11056
11072
|
mode: "singleton",
|
|
11057
|
-
|
|
11073
|
+
kind: "wrapper",
|
|
11074
|
+
defaultActive: false,
|
|
11075
|
+
deviceTypes: [DeviceType.Button, DeviceType.Camera],
|
|
11076
|
+
exposesDeviceSettings: true,
|
|
11058
11077
|
methods: {},
|
|
11059
11078
|
events: {
|
|
11060
11079
|
/**
|
|
@@ -17418,6 +17437,14 @@ var ConfigEntrySchema = object({
|
|
|
17418
17437
|
value: unknown(),
|
|
17419
17438
|
description: string().optional()
|
|
17420
17439
|
});
|
|
17440
|
+
var DeviceLinkModeSchema = _enum(["auto", "manual"]);
|
|
17441
|
+
/** One resolved linked device — the compact projection consumers need. */
|
|
17442
|
+
var LinkedDeviceSchema = object({
|
|
17443
|
+
deviceId: number(),
|
|
17444
|
+
name: string(),
|
|
17445
|
+
location: string().nullable(),
|
|
17446
|
+
features: array(string())
|
|
17447
|
+
});
|
|
17421
17448
|
var SavedDeviceRowSchema = object({
|
|
17422
17449
|
/** Numeric id reserved at allocateDeviceId time. */
|
|
17423
17450
|
id: number(),
|
|
@@ -17639,7 +17666,10 @@ method(object({
|
|
|
17639
17666
|
}), _void(), {
|
|
17640
17667
|
kind: "mutation",
|
|
17641
17668
|
auth: "admin"
|
|
17642
|
-
}), 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() }),
|
|
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() }), object({
|
|
17670
|
+
mode: DeviceLinkModeSchema,
|
|
17671
|
+
devices: array(LinkedDeviceSchema)
|
|
17672
|
+
})), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
|
|
17643
17673
|
deviceId: number(),
|
|
17644
17674
|
values: record(string(), unknown())
|
|
17645
17675
|
}), object({ success: literal(true) }), {
|
|
@@ -18908,6 +18938,61 @@ var EventKindSchema = _enum([
|
|
|
18908
18938
|
"object",
|
|
18909
18939
|
"audio"
|
|
18910
18940
|
]);
|
|
18941
|
+
/**
|
|
18942
|
+
* Spatial filter for `listTracks` — the rect + polygon variants of the shared
|
|
18943
|
+
* MaskShape vocabulary (see `mask-shape.ts`). Coordinates are NORMALIZED 0..1
|
|
18944
|
+
* of the camera frame (top-left origin), matching the drawing-plane editor.
|
|
18945
|
+
*/
|
|
18946
|
+
var TrackZoneFilterSchema = discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
|
|
18947
|
+
/** Closed icon vocabulary so clients render a known glyph per kind. */
|
|
18948
|
+
var EventKindIconSchema = _enum([
|
|
18949
|
+
"motion",
|
|
18950
|
+
"audio",
|
|
18951
|
+
"person",
|
|
18952
|
+
"vehicle",
|
|
18953
|
+
"animal",
|
|
18954
|
+
"door",
|
|
18955
|
+
"pir",
|
|
18956
|
+
"smoke",
|
|
18957
|
+
"water",
|
|
18958
|
+
"button",
|
|
18959
|
+
"generic"
|
|
18960
|
+
]);
|
|
18961
|
+
var EventKindCategorySchema = _enum([
|
|
18962
|
+
"motion",
|
|
18963
|
+
"audio",
|
|
18964
|
+
"detection",
|
|
18965
|
+
"sensor",
|
|
18966
|
+
"custom"
|
|
18967
|
+
]);
|
|
18968
|
+
var EventKindDescriptorSchema = object({
|
|
18969
|
+
/** Stable kind id (e.g. 'motion', 'person', 'contact'). */
|
|
18970
|
+
kind: string(),
|
|
18971
|
+
label: string(),
|
|
18972
|
+
/** Hex color for timeline/legend rendering. */
|
|
18973
|
+
color: string(),
|
|
18974
|
+
icon: EventKindIconSchema,
|
|
18975
|
+
category: EventKindCategorySchema,
|
|
18976
|
+
/** Which cap + device contributes this kind. For built-ins the camera
|
|
18977
|
+
* itself; for sensor kinds the LINKED source device. */
|
|
18978
|
+
source: object({
|
|
18979
|
+
capName: string(),
|
|
18980
|
+
deviceId: number()
|
|
18981
|
+
})
|
|
18982
|
+
});
|
|
18983
|
+
var SensorEventSchema = object({
|
|
18984
|
+
id: string(),
|
|
18985
|
+
/** The CAMERA the event is attributed to (a sensor linked to N cameras
|
|
18986
|
+
* yields N rows, one per camera). */
|
|
18987
|
+
deviceId: number(),
|
|
18988
|
+
/** The linked sensor device whose state changed. */
|
|
18989
|
+
sourceDeviceId: number(),
|
|
18990
|
+
/** Event kind id — matches an `EventKindDescriptor.kind`. */
|
|
18991
|
+
kind: string(),
|
|
18992
|
+
/** Snapshot of the sensor cap's runtime-state slice at the change. */
|
|
18993
|
+
value: record(string(), unknown()).nullable(),
|
|
18994
|
+
timestamp: number()
|
|
18995
|
+
});
|
|
18911
18996
|
var TrackPositionSchema = object({
|
|
18912
18997
|
x: number(),
|
|
18913
18998
|
y: number(),
|
|
@@ -18921,6 +19006,30 @@ var TrackSnapshotSchema = object({
|
|
|
18921
19006
|
mediaKey: string()
|
|
18922
19007
|
});
|
|
18923
19008
|
/**
|
|
19009
|
+
* Normalized 0..1 trajectory envelope (min/max over every position bbox,
|
|
19010
|
+
* divided by the track's detection-frame dims), computed at persist time.
|
|
19011
|
+
* Absent when the frame dims were unknown when the track was persisted
|
|
19012
|
+
* (legacy rows / dims-less sources) and on active (in-RAM) tracks.
|
|
19013
|
+
*/
|
|
19014
|
+
var TrackEnvelopeSchema = object({
|
|
19015
|
+
minX: number(),
|
|
19016
|
+
minY: number(),
|
|
19017
|
+
maxX: number(),
|
|
19018
|
+
maxY: number()
|
|
19019
|
+
});
|
|
19020
|
+
/**
|
|
19021
|
+
* Row projection for track list queries. `full` (default) returns the
|
|
19022
|
+
* complete Track including the frame-rate `positions[]` history and the
|
|
19023
|
+
* `snapshots[]` references — megabytes across a page of tracks. `slim`
|
|
19024
|
+
* keeps every scalar the list surfaces actually render (ids, class(es),
|
|
19025
|
+
* label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
|
|
19026
|
+
* zonesVisited, bestEventId, envelope) and returns `positions` /
|
|
19027
|
+
* `snapshots` as EMPTY arrays — detail views re-fetch the full row via
|
|
19028
|
+
* `getTrack`. Mirrors the event-store `projection` convention
|
|
19029
|
+
* (`getObjectEvents` et al.).
|
|
19030
|
+
*/
|
|
19031
|
+
var TrackProjectionSchema = _enum(["full", "slim"]);
|
|
19032
|
+
/**
|
|
18924
19033
|
* One audio-classification label heard on the track's camera while the
|
|
18925
19034
|
* track was alive, aggregated per label. An "episode" is one persisted
|
|
18926
19035
|
* audio event (the confident-classification path: score ≥ the device's
|
|
@@ -18971,7 +19080,11 @@ var TrackSchema = object({
|
|
|
18971
19080
|
/** Audio-classification labels heard on the camera during the track's
|
|
18972
19081
|
* life (score ≥ device `classificationMinScore`), aggregated per label.
|
|
18973
19082
|
* Absent on legacy rows / tracks with no confident audio. */
|
|
18974
|
-
audioLabels: array(TrackAudioLabelSchema).readonly().optional()
|
|
19083
|
+
audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
|
|
19084
|
+
/** Normalized 0..1 trajectory envelope (see {@link TrackEnvelopeSchema}).
|
|
19085
|
+
* Populated from the persisted envelope columns on historical reads;
|
|
19086
|
+
* absent on legacy rows, dims-less tracks and active (in-RAM) tracks. */
|
|
19087
|
+
envelope: TrackEnvelopeSchema.optional()
|
|
18975
19088
|
});
|
|
18976
19089
|
var BaseEventFields = {
|
|
18977
19090
|
id: string(),
|
|
@@ -19081,11 +19194,13 @@ var MediaFileSchema = object({
|
|
|
19081
19194
|
sizeBytes: number(),
|
|
19082
19195
|
timestamp: number()
|
|
19083
19196
|
});
|
|
19197
|
+
var DEFAULT_EVENT_QUERY_LIMIT = 1e3;
|
|
19198
|
+
var MAX_EVENT_QUERY_LIMIT = 5e3;
|
|
19084
19199
|
var DeviceEventQueryInput = object({
|
|
19085
19200
|
deviceId: number(),
|
|
19086
19201
|
since: number().optional(),
|
|
19087
19202
|
until: number().optional(),
|
|
19088
|
-
limit: number().int().min(1).max(
|
|
19203
|
+
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT),
|
|
19089
19204
|
/** `slim` drops heavy JSON fields (regions/bbox/zones) and carries an
|
|
19090
19205
|
* optional `mediaUrl` (populated by B5). `full` (default) keeps today's
|
|
19091
19206
|
* exact behaviour. Callers may omit this field — the store defaults to
|
|
@@ -19093,6 +19208,27 @@ var DeviceEventQueryInput = object({
|
|
|
19093
19208
|
projection: _enum(["full", "slim"]).optional()
|
|
19094
19209
|
});
|
|
19095
19210
|
var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
|
|
19211
|
+
var RecentTracksQueryInput = object({
|
|
19212
|
+
/** Devices to merge. An empty array yields `{ tracks: [], nextCursor: null }`. */
|
|
19213
|
+
deviceIds: array(number()),
|
|
19214
|
+
/** Window lower bound on `lastSeen` (inclusive). */
|
|
19215
|
+
since: number().optional(),
|
|
19216
|
+
/** Window upper bound on `lastSeen` (inclusive). */
|
|
19217
|
+
until: number().optional(),
|
|
19218
|
+
/** Page size. Default 200, max 1000. */
|
|
19219
|
+
limit: number().int().min(1).max(1e3).default(200),
|
|
19220
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`.
|
|
19221
|
+
* Encodes the (lastSeen, trackId) sort position — treat as opaque. */
|
|
19222
|
+
cursor: string().optional(),
|
|
19223
|
+
/** See {@link TrackProjectionSchema}. Default `full`. */
|
|
19224
|
+
projection: TrackProjectionSchema.optional()
|
|
19225
|
+
});
|
|
19226
|
+
var RecentTracksPageSchema = object({
|
|
19227
|
+
/** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
|
|
19228
|
+
tracks: array(TrackSchema).readonly(),
|
|
19229
|
+
/** Cursor for the next page, or null when this page is the last. */
|
|
19230
|
+
nextCursor: string().nullable()
|
|
19231
|
+
});
|
|
19096
19232
|
var KeyEventQueryInput = object({
|
|
19097
19233
|
deviceId: number(),
|
|
19098
19234
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
@@ -19175,11 +19311,25 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19175
19311
|
deviceId: number(),
|
|
19176
19312
|
since: number().optional(),
|
|
19177
19313
|
until: number().optional(),
|
|
19178
|
-
limit: number().optional()
|
|
19179
|
-
|
|
19314
|
+
limit: number().optional(),
|
|
19315
|
+
/** Spatial filter — only tracks whose trajectory intersects the zone
|
|
19316
|
+
* (normalized 0..1 rect or polygon). SQL-prefiltered on the persisted
|
|
19317
|
+
* envelope columns, then precisely tested per position. Tracks with
|
|
19318
|
+
* an unknown envelope (no frame dims at persist time) always match. */
|
|
19319
|
+
zone: TrackZoneFilterSchema.optional(),
|
|
19320
|
+
/** See {@link TrackProjectionSchema}. Default `full` (backward
|
|
19321
|
+
* compatible — omitting the field keeps today's exact behaviour). */
|
|
19322
|
+
projection: TrackProjectionSchema.optional()
|
|
19323
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
|
|
19180
19324
|
kind: "mutation",
|
|
19181
19325
|
auth: "admin"
|
|
19182
|
-
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(
|
|
19326
|
+
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({
|
|
19327
|
+
deviceId: number(),
|
|
19328
|
+
since: number().optional(),
|
|
19329
|
+
until: number().optional(),
|
|
19330
|
+
kinds: array(string()).optional(),
|
|
19331
|
+
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
|
|
19332
|
+
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
|
|
19183
19333
|
deviceId: number(),
|
|
19184
19334
|
since: number(),
|
|
19185
19335
|
until: number(),
|
|
@@ -22549,7 +22699,12 @@ var RecordingStorageUsageSchema = object({
|
|
|
22549
22699
|
/**
|
|
22550
22700
|
* Result of locating footage at a wall-clock instant for one device/profile.
|
|
22551
22701
|
* `segment` carries the covering segment's window; `gap` reports the forward
|
|
22552
|
-
* nearest covered edge (`null` past the end of footage / when none exists)
|
|
22702
|
+
* nearest covered edge (`null` past the end of footage / when none exists)
|
|
22703
|
+
* and the backward covered edge `prevEndMs` (exclusive end of the nearest
|
|
22704
|
+
* footage behind the epoch; `null` when none — optional so older providers
|
|
22705
|
+
* that omit it stay valid). `prevEndMs` lets a backward frame-step hop the
|
|
22706
|
+
* small inter-segment cracks (durMs under-covers the span to the next
|
|
22707
|
+
* startMs by ~11-17 ms) instead of no-opping at a segment head.
|
|
22553
22708
|
*/
|
|
22554
22709
|
var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
|
|
22555
22710
|
kind: literal("segment"),
|
|
@@ -22558,7 +22713,8 @@ var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
|
|
|
22558
22713
|
bytes: number()
|
|
22559
22714
|
}), object({
|
|
22560
22715
|
kind: literal("gap"),
|
|
22561
|
-
nearestEdgeMs: number().nullable()
|
|
22716
|
+
nearestEdgeMs: number().nullable(),
|
|
22717
|
+
prevEndMs: number().nullable().optional()
|
|
22562
22718
|
})]);
|
|
22563
22719
|
/** Raw bytes of one finalized footage segment (read off disk on the recording node). */
|
|
22564
22720
|
var ReadSegmentBytesResultSchema = object({ data: _instanceof(Uint8Array) });
|
|
@@ -24338,6 +24494,12 @@ Object.freeze({
|
|
|
24338
24494
|
addonId: null,
|
|
24339
24495
|
access: "view"
|
|
24340
24496
|
},
|
|
24497
|
+
"deviceManager.getLinkedDevices": {
|
|
24498
|
+
capName: "device-manager",
|
|
24499
|
+
capScope: "system",
|
|
24500
|
+
addonId: null,
|
|
24501
|
+
access: "view"
|
|
24502
|
+
},
|
|
24341
24503
|
"deviceManager.getRoleDisplayDefaults": {
|
|
24342
24504
|
capName: "device-manager",
|
|
24343
24505
|
capScope: "system",
|
|
@@ -25892,6 +26054,12 @@ Object.freeze({
|
|
|
25892
26054
|
addonId: null,
|
|
25893
26055
|
access: "view"
|
|
25894
26056
|
},
|
|
26057
|
+
"pipelineAnalytics.getSensorEvents": {
|
|
26058
|
+
capName: "pipeline-analytics",
|
|
26059
|
+
capScope: "device",
|
|
26060
|
+
addonId: null,
|
|
26061
|
+
access: "view"
|
|
26062
|
+
},
|
|
25895
26063
|
"pipelineAnalytics.getTrack": {
|
|
25896
26064
|
capName: "pipeline-analytics",
|
|
25897
26065
|
capScope: "device",
|
|
@@ -25904,6 +26072,18 @@ Object.freeze({
|
|
|
25904
26072
|
addonId: null,
|
|
25905
26073
|
access: "view"
|
|
25906
26074
|
},
|
|
26075
|
+
"pipelineAnalytics.listEventKinds": {
|
|
26076
|
+
capName: "pipeline-analytics",
|
|
26077
|
+
capScope: "device",
|
|
26078
|
+
addonId: null,
|
|
26079
|
+
access: "view"
|
|
26080
|
+
},
|
|
26081
|
+
"pipelineAnalytics.listRecentTracks": {
|
|
26082
|
+
capName: "pipeline-analytics",
|
|
26083
|
+
capScope: "device",
|
|
26084
|
+
addonId: null,
|
|
26085
|
+
access: "view"
|
|
26086
|
+
},
|
|
25907
26087
|
"pipelineAnalytics.listTracks": {
|
|
25908
26088
|
capName: "pipeline-analytics",
|
|
25909
26089
|
capScope: "device",
|