@camstack/addon-provider-rtsp 1.1.23 → 1.1.24
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
|
@@ -23,7 +23,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
23
23
|
//#endregion
|
|
24
24
|
let node_net = require("node:net");
|
|
25
25
|
node_net = __toESM(node_net);
|
|
26
|
-
//#region ../types/dist/event-category-
|
|
26
|
+
//#region ../types/dist/event-category-H4AVePnn.mjs
|
|
27
27
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
28
28
|
EventCategory["SystemBoot"] = "system.boot";
|
|
29
29
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -173,6 +173,9 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
173
173
|
EventCategory["RecordingSegmentWritten"] = "recording.segment.written";
|
|
174
174
|
EventCategory["RecordingPolicyFallback"] = "recording.policy.fallback";
|
|
175
175
|
EventCategory["RecordingRetentionCompleted"] = "recording.retention.completed";
|
|
176
|
+
/** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
|
|
177
|
+
* thumb is a scrub gap the recorder's keyframe backfill covers. */
|
|
178
|
+
EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
|
|
176
179
|
EventCategory["DetectionEvent"] = "detection.event";
|
|
177
180
|
EventCategory["SessionTrackNew"] = "session.track.new";
|
|
178
181
|
EventCategory["SessionTrackExpired"] = "session.track.expired";
|
|
@@ -10906,10 +10909,23 @@ var deviceDiscoveryCapability = {
|
|
|
10906
10909
|
}
|
|
10907
10910
|
};
|
|
10908
10911
|
/**
|
|
10909
|
-
* Doorbell button cap.
|
|
10910
|
-
*
|
|
10911
|
-
*
|
|
10912
|
-
*
|
|
10912
|
+
* Doorbell button cap. Two kinds of providers coexist behind this cap
|
|
10913
|
+
* name (same pattern as `snapshot`):
|
|
10914
|
+
*
|
|
10915
|
+
* - **Native** providers: registered per-device by device-driver
|
|
10916
|
+
* addons via `ctx.registerNativeCap` — either on a
|
|
10917
|
+
* `DeviceType.Button` accessory with `role: DeviceRole.Doorbell`,
|
|
10918
|
+
* or directly on the camera (Reolink registers at camera level).
|
|
10919
|
+
* Emits an `onPressed` event every time the firmware pushes a
|
|
10920
|
+
* ring; status tracks the last press and a pressCount since start
|
|
10921
|
+
* (diagnostic).
|
|
10922
|
+
*
|
|
10923
|
+
* - **Wrapper** provider: the `virtual-doorbell` system builtin
|
|
10924
|
+
* (`@camstack/system/builtins/doorbell`). Turns ANY binary-ish
|
|
10925
|
+
* device (contact / switch / event-emitter …) into a doorbell for
|
|
10926
|
+
* a camera. `defaultActive: false` — the operator explicitly binds
|
|
10927
|
+
* it per camera in the device-bindings UI, then picks the source
|
|
10928
|
+
* device + trigger in the per-device settings.
|
|
10913
10929
|
*
|
|
10914
10930
|
* The DeviceEventPropagator re-emits `onPressed` on the camera parent
|
|
10915
10931
|
* — subscribers listening at the camera level receive ring events
|
|
@@ -10930,7 +10946,10 @@ var doorbellCapability = {
|
|
|
10930
10946
|
scope: "device",
|
|
10931
10947
|
deviceNative: true,
|
|
10932
10948
|
mode: "singleton",
|
|
10933
|
-
|
|
10949
|
+
kind: "wrapper",
|
|
10950
|
+
defaultActive: false,
|
|
10951
|
+
deviceTypes: [DeviceType.Button, DeviceType.Camera],
|
|
10952
|
+
exposesDeviceSettings: true,
|
|
10934
10953
|
methods: {},
|
|
10935
10954
|
events: {
|
|
10936
10955
|
/**
|
|
@@ -17282,6 +17301,14 @@ var ConfigEntrySchema = object({
|
|
|
17282
17301
|
value: unknown(),
|
|
17283
17302
|
description: string().optional()
|
|
17284
17303
|
});
|
|
17304
|
+
var DeviceLinkModeSchema = _enum(["auto", "manual"]);
|
|
17305
|
+
/** One resolved linked device — the compact projection consumers need. */
|
|
17306
|
+
var LinkedDeviceSchema = object({
|
|
17307
|
+
deviceId: number(),
|
|
17308
|
+
name: string(),
|
|
17309
|
+
location: string().nullable(),
|
|
17310
|
+
features: array(string())
|
|
17311
|
+
});
|
|
17285
17312
|
var SavedDeviceRowSchema = object({
|
|
17286
17313
|
/** Numeric id reserved at allocateDeviceId time. */
|
|
17287
17314
|
id: number(),
|
|
@@ -17503,7 +17530,10 @@ method(object({
|
|
|
17503
17530
|
}), _void(), {
|
|
17504
17531
|
kind: "mutation",
|
|
17505
17532
|
auth: "admin"
|
|
17506
|
-
}), 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() }),
|
|
17533
|
+
}), 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({
|
|
17534
|
+
mode: DeviceLinkModeSchema,
|
|
17535
|
+
devices: array(LinkedDeviceSchema)
|
|
17536
|
+
})), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
|
|
17507
17537
|
deviceId: number(),
|
|
17508
17538
|
values: record(string(), unknown())
|
|
17509
17539
|
}), object({ success: literal(true) }), {
|
|
@@ -18772,6 +18802,61 @@ var EventKindSchema = _enum([
|
|
|
18772
18802
|
"object",
|
|
18773
18803
|
"audio"
|
|
18774
18804
|
]);
|
|
18805
|
+
/**
|
|
18806
|
+
* Spatial filter for `listTracks` — the rect + polygon variants of the shared
|
|
18807
|
+
* MaskShape vocabulary (see `mask-shape.ts`). Coordinates are NORMALIZED 0..1
|
|
18808
|
+
* of the camera frame (top-left origin), matching the drawing-plane editor.
|
|
18809
|
+
*/
|
|
18810
|
+
var TrackZoneFilterSchema = discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
|
|
18811
|
+
/** Closed icon vocabulary so clients render a known glyph per kind. */
|
|
18812
|
+
var EventKindIconSchema = _enum([
|
|
18813
|
+
"motion",
|
|
18814
|
+
"audio",
|
|
18815
|
+
"person",
|
|
18816
|
+
"vehicle",
|
|
18817
|
+
"animal",
|
|
18818
|
+
"door",
|
|
18819
|
+
"pir",
|
|
18820
|
+
"smoke",
|
|
18821
|
+
"water",
|
|
18822
|
+
"button",
|
|
18823
|
+
"generic"
|
|
18824
|
+
]);
|
|
18825
|
+
var EventKindCategorySchema = _enum([
|
|
18826
|
+
"motion",
|
|
18827
|
+
"audio",
|
|
18828
|
+
"detection",
|
|
18829
|
+
"sensor",
|
|
18830
|
+
"custom"
|
|
18831
|
+
]);
|
|
18832
|
+
var EventKindDescriptorSchema = object({
|
|
18833
|
+
/** Stable kind id (e.g. 'motion', 'person', 'contact'). */
|
|
18834
|
+
kind: string(),
|
|
18835
|
+
label: string(),
|
|
18836
|
+
/** Hex color for timeline/legend rendering. */
|
|
18837
|
+
color: string(),
|
|
18838
|
+
icon: EventKindIconSchema,
|
|
18839
|
+
category: EventKindCategorySchema,
|
|
18840
|
+
/** Which cap + device contributes this kind. For built-ins the camera
|
|
18841
|
+
* itself; for sensor kinds the LINKED source device. */
|
|
18842
|
+
source: object({
|
|
18843
|
+
capName: string(),
|
|
18844
|
+
deviceId: number()
|
|
18845
|
+
})
|
|
18846
|
+
});
|
|
18847
|
+
var SensorEventSchema = object({
|
|
18848
|
+
id: string(),
|
|
18849
|
+
/** The CAMERA the event is attributed to (a sensor linked to N cameras
|
|
18850
|
+
* yields N rows, one per camera). */
|
|
18851
|
+
deviceId: number(),
|
|
18852
|
+
/** The linked sensor device whose state changed. */
|
|
18853
|
+
sourceDeviceId: number(),
|
|
18854
|
+
/** Event kind id — matches an `EventKindDescriptor.kind`. */
|
|
18855
|
+
kind: string(),
|
|
18856
|
+
/** Snapshot of the sensor cap's runtime-state slice at the change. */
|
|
18857
|
+
value: record(string(), unknown()).nullable(),
|
|
18858
|
+
timestamp: number()
|
|
18859
|
+
});
|
|
18775
18860
|
var TrackPositionSchema = object({
|
|
18776
18861
|
x: number(),
|
|
18777
18862
|
y: number(),
|
|
@@ -18785,6 +18870,30 @@ var TrackSnapshotSchema = object({
|
|
|
18785
18870
|
mediaKey: string()
|
|
18786
18871
|
});
|
|
18787
18872
|
/**
|
|
18873
|
+
* Normalized 0..1 trajectory envelope (min/max over every position bbox,
|
|
18874
|
+
* divided by the track's detection-frame dims), computed at persist time.
|
|
18875
|
+
* Absent when the frame dims were unknown when the track was persisted
|
|
18876
|
+
* (legacy rows / dims-less sources) and on active (in-RAM) tracks.
|
|
18877
|
+
*/
|
|
18878
|
+
var TrackEnvelopeSchema = object({
|
|
18879
|
+
minX: number(),
|
|
18880
|
+
minY: number(),
|
|
18881
|
+
maxX: number(),
|
|
18882
|
+
maxY: number()
|
|
18883
|
+
});
|
|
18884
|
+
/**
|
|
18885
|
+
* Row projection for track list queries. `full` (default) returns the
|
|
18886
|
+
* complete Track including the frame-rate `positions[]` history and the
|
|
18887
|
+
* `snapshots[]` references — megabytes across a page of tracks. `slim`
|
|
18888
|
+
* keeps every scalar the list surfaces actually render (ids, class(es),
|
|
18889
|
+
* label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
|
|
18890
|
+
* zonesVisited, bestEventId, envelope) and returns `positions` /
|
|
18891
|
+
* `snapshots` as EMPTY arrays — detail views re-fetch the full row via
|
|
18892
|
+
* `getTrack`. Mirrors the event-store `projection` convention
|
|
18893
|
+
* (`getObjectEvents` et al.).
|
|
18894
|
+
*/
|
|
18895
|
+
var TrackProjectionSchema = _enum(["full", "slim"]);
|
|
18896
|
+
/**
|
|
18788
18897
|
* One audio-classification label heard on the track's camera while the
|
|
18789
18898
|
* track was alive, aggregated per label. An "episode" is one persisted
|
|
18790
18899
|
* audio event (the confident-classification path: score ≥ the device's
|
|
@@ -18835,7 +18944,11 @@ var TrackSchema = object({
|
|
|
18835
18944
|
/** Audio-classification labels heard on the camera during the track's
|
|
18836
18945
|
* life (score ≥ device `classificationMinScore`), aggregated per label.
|
|
18837
18946
|
* Absent on legacy rows / tracks with no confident audio. */
|
|
18838
|
-
audioLabels: array(TrackAudioLabelSchema).readonly().optional()
|
|
18947
|
+
audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
|
|
18948
|
+
/** Normalized 0..1 trajectory envelope (see {@link TrackEnvelopeSchema}).
|
|
18949
|
+
* Populated from the persisted envelope columns on historical reads;
|
|
18950
|
+
* absent on legacy rows, dims-less tracks and active (in-RAM) tracks. */
|
|
18951
|
+
envelope: TrackEnvelopeSchema.optional()
|
|
18839
18952
|
});
|
|
18840
18953
|
var BaseEventFields = {
|
|
18841
18954
|
id: string(),
|
|
@@ -18945,11 +19058,13 @@ var MediaFileSchema = object({
|
|
|
18945
19058
|
sizeBytes: number(),
|
|
18946
19059
|
timestamp: number()
|
|
18947
19060
|
});
|
|
19061
|
+
var DEFAULT_EVENT_QUERY_LIMIT = 1e3;
|
|
19062
|
+
var MAX_EVENT_QUERY_LIMIT = 5e3;
|
|
18948
19063
|
var DeviceEventQueryInput = object({
|
|
18949
19064
|
deviceId: number(),
|
|
18950
19065
|
since: number().optional(),
|
|
18951
19066
|
until: number().optional(),
|
|
18952
|
-
limit: number().int().min(1).max(
|
|
19067
|
+
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT),
|
|
18953
19068
|
/** `slim` drops heavy JSON fields (regions/bbox/zones) and carries an
|
|
18954
19069
|
* optional `mediaUrl` (populated by B5). `full` (default) keeps today's
|
|
18955
19070
|
* exact behaviour. Callers may omit this field — the store defaults to
|
|
@@ -18957,6 +19072,27 @@ var DeviceEventQueryInput = object({
|
|
|
18957
19072
|
projection: _enum(["full", "slim"]).optional()
|
|
18958
19073
|
});
|
|
18959
19074
|
var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
|
|
19075
|
+
var RecentTracksQueryInput = object({
|
|
19076
|
+
/** Devices to merge. An empty array yields `{ tracks: [], nextCursor: null }`. */
|
|
19077
|
+
deviceIds: array(number()),
|
|
19078
|
+
/** Window lower bound on `lastSeen` (inclusive). */
|
|
19079
|
+
since: number().optional(),
|
|
19080
|
+
/** Window upper bound on `lastSeen` (inclusive). */
|
|
19081
|
+
until: number().optional(),
|
|
19082
|
+
/** Page size. Default 200, max 1000. */
|
|
19083
|
+
limit: number().int().min(1).max(1e3).default(200),
|
|
19084
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`.
|
|
19085
|
+
* Encodes the (lastSeen, trackId) sort position — treat as opaque. */
|
|
19086
|
+
cursor: string().optional(),
|
|
19087
|
+
/** See {@link TrackProjectionSchema}. Default `full`. */
|
|
19088
|
+
projection: TrackProjectionSchema.optional()
|
|
19089
|
+
});
|
|
19090
|
+
var RecentTracksPageSchema = object({
|
|
19091
|
+
/** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
|
|
19092
|
+
tracks: array(TrackSchema).readonly(),
|
|
19093
|
+
/** Cursor for the next page, or null when this page is the last. */
|
|
19094
|
+
nextCursor: string().nullable()
|
|
19095
|
+
});
|
|
18960
19096
|
var KeyEventQueryInput = object({
|
|
18961
19097
|
deviceId: number(),
|
|
18962
19098
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
@@ -19039,11 +19175,25 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19039
19175
|
deviceId: number(),
|
|
19040
19176
|
since: number().optional(),
|
|
19041
19177
|
until: number().optional(),
|
|
19042
|
-
limit: number().optional()
|
|
19043
|
-
|
|
19178
|
+
limit: number().optional(),
|
|
19179
|
+
/** Spatial filter — only tracks whose trajectory intersects the zone
|
|
19180
|
+
* (normalized 0..1 rect or polygon). SQL-prefiltered on the persisted
|
|
19181
|
+
* envelope columns, then precisely tested per position. Tracks with
|
|
19182
|
+
* an unknown envelope (no frame dims at persist time) always match. */
|
|
19183
|
+
zone: TrackZoneFilterSchema.optional(),
|
|
19184
|
+
/** See {@link TrackProjectionSchema}. Default `full` (backward
|
|
19185
|
+
* compatible — omitting the field keeps today's exact behaviour). */
|
|
19186
|
+
projection: TrackProjectionSchema.optional()
|
|
19187
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
|
|
19044
19188
|
kind: "mutation",
|
|
19045
19189
|
auth: "admin"
|
|
19046
|
-
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(
|
|
19190
|
+
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({
|
|
19191
|
+
deviceId: number(),
|
|
19192
|
+
since: number().optional(),
|
|
19193
|
+
until: number().optional(),
|
|
19194
|
+
kinds: array(string()).optional(),
|
|
19195
|
+
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
|
|
19196
|
+
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
|
|
19047
19197
|
deviceId: number(),
|
|
19048
19198
|
since: number(),
|
|
19049
19199
|
until: number(),
|
|
@@ -22295,7 +22445,12 @@ var RecordingStorageUsageSchema = object({
|
|
|
22295
22445
|
/**
|
|
22296
22446
|
* Result of locating footage at a wall-clock instant for one device/profile.
|
|
22297
22447
|
* `segment` carries the covering segment's window; `gap` reports the forward
|
|
22298
|
-
* nearest covered edge (`null` past the end of footage / when none exists)
|
|
22448
|
+
* nearest covered edge (`null` past the end of footage / when none exists)
|
|
22449
|
+
* and the backward covered edge `prevEndMs` (exclusive end of the nearest
|
|
22450
|
+
* footage behind the epoch; `null` when none — optional so older providers
|
|
22451
|
+
* that omit it stay valid). `prevEndMs` lets a backward frame-step hop the
|
|
22452
|
+
* small inter-segment cracks (durMs under-covers the span to the next
|
|
22453
|
+
* startMs by ~11-17 ms) instead of no-opping at a segment head.
|
|
22299
22454
|
*/
|
|
22300
22455
|
var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
|
|
22301
22456
|
kind: literal("segment"),
|
|
@@ -22304,7 +22459,8 @@ var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
|
|
|
22304
22459
|
bytes: number()
|
|
22305
22460
|
}), object({
|
|
22306
22461
|
kind: literal("gap"),
|
|
22307
|
-
nearestEdgeMs: number().nullable()
|
|
22462
|
+
nearestEdgeMs: number().nullable(),
|
|
22463
|
+
prevEndMs: number().nullable().optional()
|
|
22308
22464
|
})]);
|
|
22309
22465
|
/** Raw bytes of one finalized footage segment (read off disk on the recording node). */
|
|
22310
22466
|
var ReadSegmentBytesResultSchema = object({ data: _instanceof(Uint8Array) });
|
|
@@ -23886,6 +24042,12 @@ Object.freeze({
|
|
|
23886
24042
|
addonId: null,
|
|
23887
24043
|
access: "view"
|
|
23888
24044
|
},
|
|
24045
|
+
"deviceManager.getLinkedDevices": {
|
|
24046
|
+
capName: "device-manager",
|
|
24047
|
+
capScope: "system",
|
|
24048
|
+
addonId: null,
|
|
24049
|
+
access: "view"
|
|
24050
|
+
},
|
|
23889
24051
|
"deviceManager.getRoleDisplayDefaults": {
|
|
23890
24052
|
capName: "device-manager",
|
|
23891
24053
|
capScope: "system",
|
|
@@ -25440,6 +25602,12 @@ Object.freeze({
|
|
|
25440
25602
|
addonId: null,
|
|
25441
25603
|
access: "view"
|
|
25442
25604
|
},
|
|
25605
|
+
"pipelineAnalytics.getSensorEvents": {
|
|
25606
|
+
capName: "pipeline-analytics",
|
|
25607
|
+
capScope: "device",
|
|
25608
|
+
addonId: null,
|
|
25609
|
+
access: "view"
|
|
25610
|
+
},
|
|
25443
25611
|
"pipelineAnalytics.getTrack": {
|
|
25444
25612
|
capName: "pipeline-analytics",
|
|
25445
25613
|
capScope: "device",
|
|
@@ -25452,6 +25620,18 @@ Object.freeze({
|
|
|
25452
25620
|
addonId: null,
|
|
25453
25621
|
access: "view"
|
|
25454
25622
|
},
|
|
25623
|
+
"pipelineAnalytics.listEventKinds": {
|
|
25624
|
+
capName: "pipeline-analytics",
|
|
25625
|
+
capScope: "device",
|
|
25626
|
+
addonId: null,
|
|
25627
|
+
access: "view"
|
|
25628
|
+
},
|
|
25629
|
+
"pipelineAnalytics.listRecentTracks": {
|
|
25630
|
+
capName: "pipeline-analytics",
|
|
25631
|
+
capScope: "device",
|
|
25632
|
+
addonId: null,
|
|
25633
|
+
access: "view"
|
|
25634
|
+
},
|
|
25455
25635
|
"pipelineAnalytics.listTracks": {
|
|
25456
25636
|
capName: "pipeline-analytics",
|
|
25457
25637
|
capScope: "device",
|
package/dist/addon.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import net from "node:net";
|
|
2
|
-
//#region ../types/dist/event-category-
|
|
2
|
+
//#region ../types/dist/event-category-H4AVePnn.mjs
|
|
3
3
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
4
4
|
EventCategory["SystemBoot"] = "system.boot";
|
|
5
5
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -149,6 +149,9 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
149
149
|
EventCategory["RecordingSegmentWritten"] = "recording.segment.written";
|
|
150
150
|
EventCategory["RecordingPolicyFallback"] = "recording.policy.fallback";
|
|
151
151
|
EventCategory["RecordingRetentionCompleted"] = "recording.retention.completed";
|
|
152
|
+
/** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
|
|
153
|
+
* thumb is a scrub gap the recorder's keyframe backfill covers. */
|
|
154
|
+
EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
|
|
152
155
|
EventCategory["DetectionEvent"] = "detection.event";
|
|
153
156
|
EventCategory["SessionTrackNew"] = "session.track.new";
|
|
154
157
|
EventCategory["SessionTrackExpired"] = "session.track.expired";
|
|
@@ -10882,10 +10885,23 @@ var deviceDiscoveryCapability = {
|
|
|
10882
10885
|
}
|
|
10883
10886
|
};
|
|
10884
10887
|
/**
|
|
10885
|
-
* Doorbell button cap.
|
|
10886
|
-
*
|
|
10887
|
-
*
|
|
10888
|
-
*
|
|
10888
|
+
* Doorbell button cap. Two kinds of providers coexist behind this cap
|
|
10889
|
+
* name (same pattern as `snapshot`):
|
|
10890
|
+
*
|
|
10891
|
+
* - **Native** providers: registered per-device by device-driver
|
|
10892
|
+
* addons via `ctx.registerNativeCap` — either on a
|
|
10893
|
+
* `DeviceType.Button` accessory with `role: DeviceRole.Doorbell`,
|
|
10894
|
+
* or directly on the camera (Reolink registers at camera level).
|
|
10895
|
+
* Emits an `onPressed` event every time the firmware pushes a
|
|
10896
|
+
* ring; status tracks the last press and a pressCount since start
|
|
10897
|
+
* (diagnostic).
|
|
10898
|
+
*
|
|
10899
|
+
* - **Wrapper** provider: the `virtual-doorbell` system builtin
|
|
10900
|
+
* (`@camstack/system/builtins/doorbell`). Turns ANY binary-ish
|
|
10901
|
+
* device (contact / switch / event-emitter …) into a doorbell for
|
|
10902
|
+
* a camera. `defaultActive: false` — the operator explicitly binds
|
|
10903
|
+
* it per camera in the device-bindings UI, then picks the source
|
|
10904
|
+
* device + trigger in the per-device settings.
|
|
10889
10905
|
*
|
|
10890
10906
|
* The DeviceEventPropagator re-emits `onPressed` on the camera parent
|
|
10891
10907
|
* — subscribers listening at the camera level receive ring events
|
|
@@ -10906,7 +10922,10 @@ var doorbellCapability = {
|
|
|
10906
10922
|
scope: "device",
|
|
10907
10923
|
deviceNative: true,
|
|
10908
10924
|
mode: "singleton",
|
|
10909
|
-
|
|
10925
|
+
kind: "wrapper",
|
|
10926
|
+
defaultActive: false,
|
|
10927
|
+
deviceTypes: [DeviceType.Button, DeviceType.Camera],
|
|
10928
|
+
exposesDeviceSettings: true,
|
|
10910
10929
|
methods: {},
|
|
10911
10930
|
events: {
|
|
10912
10931
|
/**
|
|
@@ -17258,6 +17277,14 @@ var ConfigEntrySchema = object({
|
|
|
17258
17277
|
value: unknown(),
|
|
17259
17278
|
description: string().optional()
|
|
17260
17279
|
});
|
|
17280
|
+
var DeviceLinkModeSchema = _enum(["auto", "manual"]);
|
|
17281
|
+
/** One resolved linked device — the compact projection consumers need. */
|
|
17282
|
+
var LinkedDeviceSchema = object({
|
|
17283
|
+
deviceId: number(),
|
|
17284
|
+
name: string(),
|
|
17285
|
+
location: string().nullable(),
|
|
17286
|
+
features: array(string())
|
|
17287
|
+
});
|
|
17261
17288
|
var SavedDeviceRowSchema = object({
|
|
17262
17289
|
/** Numeric id reserved at allocateDeviceId time. */
|
|
17263
17290
|
id: number(),
|
|
@@ -17479,7 +17506,10 @@ method(object({
|
|
|
17479
17506
|
}), _void(), {
|
|
17480
17507
|
kind: "mutation",
|
|
17481
17508
|
auth: "admin"
|
|
17482
|
-
}), 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() }),
|
|
17509
|
+
}), 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({
|
|
17510
|
+
mode: DeviceLinkModeSchema,
|
|
17511
|
+
devices: array(LinkedDeviceSchema)
|
|
17512
|
+
})), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
|
|
17483
17513
|
deviceId: number(),
|
|
17484
17514
|
values: record(string(), unknown())
|
|
17485
17515
|
}), object({ success: literal(true) }), {
|
|
@@ -18748,6 +18778,61 @@ var EventKindSchema = _enum([
|
|
|
18748
18778
|
"object",
|
|
18749
18779
|
"audio"
|
|
18750
18780
|
]);
|
|
18781
|
+
/**
|
|
18782
|
+
* Spatial filter for `listTracks` — the rect + polygon variants of the shared
|
|
18783
|
+
* MaskShape vocabulary (see `mask-shape.ts`). Coordinates are NORMALIZED 0..1
|
|
18784
|
+
* of the camera frame (top-left origin), matching the drawing-plane editor.
|
|
18785
|
+
*/
|
|
18786
|
+
var TrackZoneFilterSchema = discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
|
|
18787
|
+
/** Closed icon vocabulary so clients render a known glyph per kind. */
|
|
18788
|
+
var EventKindIconSchema = _enum([
|
|
18789
|
+
"motion",
|
|
18790
|
+
"audio",
|
|
18791
|
+
"person",
|
|
18792
|
+
"vehicle",
|
|
18793
|
+
"animal",
|
|
18794
|
+
"door",
|
|
18795
|
+
"pir",
|
|
18796
|
+
"smoke",
|
|
18797
|
+
"water",
|
|
18798
|
+
"button",
|
|
18799
|
+
"generic"
|
|
18800
|
+
]);
|
|
18801
|
+
var EventKindCategorySchema = _enum([
|
|
18802
|
+
"motion",
|
|
18803
|
+
"audio",
|
|
18804
|
+
"detection",
|
|
18805
|
+
"sensor",
|
|
18806
|
+
"custom"
|
|
18807
|
+
]);
|
|
18808
|
+
var EventKindDescriptorSchema = object({
|
|
18809
|
+
/** Stable kind id (e.g. 'motion', 'person', 'contact'). */
|
|
18810
|
+
kind: string(),
|
|
18811
|
+
label: string(),
|
|
18812
|
+
/** Hex color for timeline/legend rendering. */
|
|
18813
|
+
color: string(),
|
|
18814
|
+
icon: EventKindIconSchema,
|
|
18815
|
+
category: EventKindCategorySchema,
|
|
18816
|
+
/** Which cap + device contributes this kind. For built-ins the camera
|
|
18817
|
+
* itself; for sensor kinds the LINKED source device. */
|
|
18818
|
+
source: object({
|
|
18819
|
+
capName: string(),
|
|
18820
|
+
deviceId: number()
|
|
18821
|
+
})
|
|
18822
|
+
});
|
|
18823
|
+
var SensorEventSchema = object({
|
|
18824
|
+
id: string(),
|
|
18825
|
+
/** The CAMERA the event is attributed to (a sensor linked to N cameras
|
|
18826
|
+
* yields N rows, one per camera). */
|
|
18827
|
+
deviceId: number(),
|
|
18828
|
+
/** The linked sensor device whose state changed. */
|
|
18829
|
+
sourceDeviceId: number(),
|
|
18830
|
+
/** Event kind id — matches an `EventKindDescriptor.kind`. */
|
|
18831
|
+
kind: string(),
|
|
18832
|
+
/** Snapshot of the sensor cap's runtime-state slice at the change. */
|
|
18833
|
+
value: record(string(), unknown()).nullable(),
|
|
18834
|
+
timestamp: number()
|
|
18835
|
+
});
|
|
18751
18836
|
var TrackPositionSchema = object({
|
|
18752
18837
|
x: number(),
|
|
18753
18838
|
y: number(),
|
|
@@ -18761,6 +18846,30 @@ var TrackSnapshotSchema = object({
|
|
|
18761
18846
|
mediaKey: string()
|
|
18762
18847
|
});
|
|
18763
18848
|
/**
|
|
18849
|
+
* Normalized 0..1 trajectory envelope (min/max over every position bbox,
|
|
18850
|
+
* divided by the track's detection-frame dims), computed at persist time.
|
|
18851
|
+
* Absent when the frame dims were unknown when the track was persisted
|
|
18852
|
+
* (legacy rows / dims-less sources) and on active (in-RAM) tracks.
|
|
18853
|
+
*/
|
|
18854
|
+
var TrackEnvelopeSchema = object({
|
|
18855
|
+
minX: number(),
|
|
18856
|
+
minY: number(),
|
|
18857
|
+
maxX: number(),
|
|
18858
|
+
maxY: number()
|
|
18859
|
+
});
|
|
18860
|
+
/**
|
|
18861
|
+
* Row projection for track list queries. `full` (default) returns the
|
|
18862
|
+
* complete Track including the frame-rate `positions[]` history and the
|
|
18863
|
+
* `snapshots[]` references — megabytes across a page of tracks. `slim`
|
|
18864
|
+
* keeps every scalar the list surfaces actually render (ids, class(es),
|
|
18865
|
+
* label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
|
|
18866
|
+
* zonesVisited, bestEventId, envelope) and returns `positions` /
|
|
18867
|
+
* `snapshots` as EMPTY arrays — detail views re-fetch the full row via
|
|
18868
|
+
* `getTrack`. Mirrors the event-store `projection` convention
|
|
18869
|
+
* (`getObjectEvents` et al.).
|
|
18870
|
+
*/
|
|
18871
|
+
var TrackProjectionSchema = _enum(["full", "slim"]);
|
|
18872
|
+
/**
|
|
18764
18873
|
* One audio-classification label heard on the track's camera while the
|
|
18765
18874
|
* track was alive, aggregated per label. An "episode" is one persisted
|
|
18766
18875
|
* audio event (the confident-classification path: score ≥ the device's
|
|
@@ -18811,7 +18920,11 @@ var TrackSchema = object({
|
|
|
18811
18920
|
/** Audio-classification labels heard on the camera during the track's
|
|
18812
18921
|
* life (score ≥ device `classificationMinScore`), aggregated per label.
|
|
18813
18922
|
* Absent on legacy rows / tracks with no confident audio. */
|
|
18814
|
-
audioLabels: array(TrackAudioLabelSchema).readonly().optional()
|
|
18923
|
+
audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
|
|
18924
|
+
/** Normalized 0..1 trajectory envelope (see {@link TrackEnvelopeSchema}).
|
|
18925
|
+
* Populated from the persisted envelope columns on historical reads;
|
|
18926
|
+
* absent on legacy rows, dims-less tracks and active (in-RAM) tracks. */
|
|
18927
|
+
envelope: TrackEnvelopeSchema.optional()
|
|
18815
18928
|
});
|
|
18816
18929
|
var BaseEventFields = {
|
|
18817
18930
|
id: string(),
|
|
@@ -18921,11 +19034,13 @@ var MediaFileSchema = object({
|
|
|
18921
19034
|
sizeBytes: number(),
|
|
18922
19035
|
timestamp: number()
|
|
18923
19036
|
});
|
|
19037
|
+
var DEFAULT_EVENT_QUERY_LIMIT = 1e3;
|
|
19038
|
+
var MAX_EVENT_QUERY_LIMIT = 5e3;
|
|
18924
19039
|
var DeviceEventQueryInput = object({
|
|
18925
19040
|
deviceId: number(),
|
|
18926
19041
|
since: number().optional(),
|
|
18927
19042
|
until: number().optional(),
|
|
18928
|
-
limit: number().int().min(1).max(
|
|
19043
|
+
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT),
|
|
18929
19044
|
/** `slim` drops heavy JSON fields (regions/bbox/zones) and carries an
|
|
18930
19045
|
* optional `mediaUrl` (populated by B5). `full` (default) keeps today's
|
|
18931
19046
|
* exact behaviour. Callers may omit this field — the store defaults to
|
|
@@ -18933,6 +19048,27 @@ var DeviceEventQueryInput = object({
|
|
|
18933
19048
|
projection: _enum(["full", "slim"]).optional()
|
|
18934
19049
|
});
|
|
18935
19050
|
var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
|
|
19051
|
+
var RecentTracksQueryInput = object({
|
|
19052
|
+
/** Devices to merge. An empty array yields `{ tracks: [], nextCursor: null }`. */
|
|
19053
|
+
deviceIds: array(number()),
|
|
19054
|
+
/** Window lower bound on `lastSeen` (inclusive). */
|
|
19055
|
+
since: number().optional(),
|
|
19056
|
+
/** Window upper bound on `lastSeen` (inclusive). */
|
|
19057
|
+
until: number().optional(),
|
|
19058
|
+
/** Page size. Default 200, max 1000. */
|
|
19059
|
+
limit: number().int().min(1).max(1e3).default(200),
|
|
19060
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`.
|
|
19061
|
+
* Encodes the (lastSeen, trackId) sort position — treat as opaque. */
|
|
19062
|
+
cursor: string().optional(),
|
|
19063
|
+
/** See {@link TrackProjectionSchema}. Default `full`. */
|
|
19064
|
+
projection: TrackProjectionSchema.optional()
|
|
19065
|
+
});
|
|
19066
|
+
var RecentTracksPageSchema = object({
|
|
19067
|
+
/** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
|
|
19068
|
+
tracks: array(TrackSchema).readonly(),
|
|
19069
|
+
/** Cursor for the next page, or null when this page is the last. */
|
|
19070
|
+
nextCursor: string().nullable()
|
|
19071
|
+
});
|
|
18936
19072
|
var KeyEventQueryInput = object({
|
|
18937
19073
|
deviceId: number(),
|
|
18938
19074
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
@@ -19015,11 +19151,25 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19015
19151
|
deviceId: number(),
|
|
19016
19152
|
since: number().optional(),
|
|
19017
19153
|
until: number().optional(),
|
|
19018
|
-
limit: number().optional()
|
|
19019
|
-
|
|
19154
|
+
limit: number().optional(),
|
|
19155
|
+
/** Spatial filter — only tracks whose trajectory intersects the zone
|
|
19156
|
+
* (normalized 0..1 rect or polygon). SQL-prefiltered on the persisted
|
|
19157
|
+
* envelope columns, then precisely tested per position. Tracks with
|
|
19158
|
+
* an unknown envelope (no frame dims at persist time) always match. */
|
|
19159
|
+
zone: TrackZoneFilterSchema.optional(),
|
|
19160
|
+
/** See {@link TrackProjectionSchema}. Default `full` (backward
|
|
19161
|
+
* compatible — omitting the field keeps today's exact behaviour). */
|
|
19162
|
+
projection: TrackProjectionSchema.optional()
|
|
19163
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
|
|
19020
19164
|
kind: "mutation",
|
|
19021
19165
|
auth: "admin"
|
|
19022
|
-
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(
|
|
19166
|
+
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({
|
|
19167
|
+
deviceId: number(),
|
|
19168
|
+
since: number().optional(),
|
|
19169
|
+
until: number().optional(),
|
|
19170
|
+
kinds: array(string()).optional(),
|
|
19171
|
+
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
|
|
19172
|
+
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
|
|
19023
19173
|
deviceId: number(),
|
|
19024
19174
|
since: number(),
|
|
19025
19175
|
until: number(),
|
|
@@ -22271,7 +22421,12 @@ var RecordingStorageUsageSchema = object({
|
|
|
22271
22421
|
/**
|
|
22272
22422
|
* Result of locating footage at a wall-clock instant for one device/profile.
|
|
22273
22423
|
* `segment` carries the covering segment's window; `gap` reports the forward
|
|
22274
|
-
* nearest covered edge (`null` past the end of footage / when none exists)
|
|
22424
|
+
* nearest covered edge (`null` past the end of footage / when none exists)
|
|
22425
|
+
* and the backward covered edge `prevEndMs` (exclusive end of the nearest
|
|
22426
|
+
* footage behind the epoch; `null` when none — optional so older providers
|
|
22427
|
+
* that omit it stay valid). `prevEndMs` lets a backward frame-step hop the
|
|
22428
|
+
* small inter-segment cracks (durMs under-covers the span to the next
|
|
22429
|
+
* startMs by ~11-17 ms) instead of no-opping at a segment head.
|
|
22275
22430
|
*/
|
|
22276
22431
|
var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
|
|
22277
22432
|
kind: literal("segment"),
|
|
@@ -22280,7 +22435,8 @@ var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
|
|
|
22280
22435
|
bytes: number()
|
|
22281
22436
|
}), object({
|
|
22282
22437
|
kind: literal("gap"),
|
|
22283
|
-
nearestEdgeMs: number().nullable()
|
|
22438
|
+
nearestEdgeMs: number().nullable(),
|
|
22439
|
+
prevEndMs: number().nullable().optional()
|
|
22284
22440
|
})]);
|
|
22285
22441
|
/** Raw bytes of one finalized footage segment (read off disk on the recording node). */
|
|
22286
22442
|
var ReadSegmentBytesResultSchema = object({ data: _instanceof(Uint8Array) });
|
|
@@ -23862,6 +24018,12 @@ Object.freeze({
|
|
|
23862
24018
|
addonId: null,
|
|
23863
24019
|
access: "view"
|
|
23864
24020
|
},
|
|
24021
|
+
"deviceManager.getLinkedDevices": {
|
|
24022
|
+
capName: "device-manager",
|
|
24023
|
+
capScope: "system",
|
|
24024
|
+
addonId: null,
|
|
24025
|
+
access: "view"
|
|
24026
|
+
},
|
|
23865
24027
|
"deviceManager.getRoleDisplayDefaults": {
|
|
23866
24028
|
capName: "device-manager",
|
|
23867
24029
|
capScope: "system",
|
|
@@ -25416,6 +25578,12 @@ Object.freeze({
|
|
|
25416
25578
|
addonId: null,
|
|
25417
25579
|
access: "view"
|
|
25418
25580
|
},
|
|
25581
|
+
"pipelineAnalytics.getSensorEvents": {
|
|
25582
|
+
capName: "pipeline-analytics",
|
|
25583
|
+
capScope: "device",
|
|
25584
|
+
addonId: null,
|
|
25585
|
+
access: "view"
|
|
25586
|
+
},
|
|
25419
25587
|
"pipelineAnalytics.getTrack": {
|
|
25420
25588
|
capName: "pipeline-analytics",
|
|
25421
25589
|
capScope: "device",
|
|
@@ -25428,6 +25596,18 @@ Object.freeze({
|
|
|
25428
25596
|
addonId: null,
|
|
25429
25597
|
access: "view"
|
|
25430
25598
|
},
|
|
25599
|
+
"pipelineAnalytics.listEventKinds": {
|
|
25600
|
+
capName: "pipeline-analytics",
|
|
25601
|
+
capScope: "device",
|
|
25602
|
+
addonId: null,
|
|
25603
|
+
access: "view"
|
|
25604
|
+
},
|
|
25605
|
+
"pipelineAnalytics.listRecentTracks": {
|
|
25606
|
+
capName: "pipeline-analytics",
|
|
25607
|
+
capScope: "device",
|
|
25608
|
+
addonId: null,
|
|
25609
|
+
access: "view"
|
|
25610
|
+
},
|
|
25431
25611
|
"pipelineAnalytics.listTracks": {
|
|
25432
25612
|
capName: "pipeline-analytics",
|
|
25433
25613
|
capScope: "device",
|