@camstack/addon-provider-homeassistant 1.1.27 → 1.1.28
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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
let node_crypto = require("node:crypto");
|
|
3
3
|
let node_zlib = require("node:zlib");
|
|
4
|
-
//#region ../types/dist/event-category-
|
|
4
|
+
//#region ../types/dist/event-category-H4AVePnn.mjs
|
|
5
5
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
6
6
|
EventCategory["SystemBoot"] = "system.boot";
|
|
7
7
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -151,6 +151,9 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
151
151
|
EventCategory["RecordingSegmentWritten"] = "recording.segment.written";
|
|
152
152
|
EventCategory["RecordingPolicyFallback"] = "recording.policy.fallback";
|
|
153
153
|
EventCategory["RecordingRetentionCompleted"] = "recording.retention.completed";
|
|
154
|
+
/** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
|
|
155
|
+
* thumb is a scrub gap the recorder's keyframe backfill covers. */
|
|
156
|
+
EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
|
|
154
157
|
EventCategory["DetectionEvent"] = "detection.event";
|
|
155
158
|
EventCategory["SessionTrackNew"] = "session.track.new";
|
|
156
159
|
EventCategory["SessionTrackExpired"] = "session.track.expired";
|
|
@@ -11139,10 +11142,23 @@ var deviceDiscoveryCapability = {
|
|
|
11139
11142
|
}
|
|
11140
11143
|
};
|
|
11141
11144
|
/**
|
|
11142
|
-
* Doorbell button cap.
|
|
11143
|
-
*
|
|
11144
|
-
*
|
|
11145
|
-
*
|
|
11145
|
+
* Doorbell button cap. Two kinds of providers coexist behind this cap
|
|
11146
|
+
* name (same pattern as `snapshot`):
|
|
11147
|
+
*
|
|
11148
|
+
* - **Native** providers: registered per-device by device-driver
|
|
11149
|
+
* addons via `ctx.registerNativeCap` — either on a
|
|
11150
|
+
* `DeviceType.Button` accessory with `role: DeviceRole.Doorbell`,
|
|
11151
|
+
* or directly on the camera (Reolink registers at camera level).
|
|
11152
|
+
* Emits an `onPressed` event every time the firmware pushes a
|
|
11153
|
+
* ring; status tracks the last press and a pressCount since start
|
|
11154
|
+
* (diagnostic).
|
|
11155
|
+
*
|
|
11156
|
+
* - **Wrapper** provider: the `virtual-doorbell` system builtin
|
|
11157
|
+
* (`@camstack/system/builtins/doorbell`). Turns ANY binary-ish
|
|
11158
|
+
* device (contact / switch / event-emitter …) into a doorbell for
|
|
11159
|
+
* a camera. `defaultActive: false` — the operator explicitly binds
|
|
11160
|
+
* it per camera in the device-bindings UI, then picks the source
|
|
11161
|
+
* device + trigger in the per-device settings.
|
|
11146
11162
|
*
|
|
11147
11163
|
* The DeviceEventPropagator re-emits `onPressed` on the camera parent
|
|
11148
11164
|
* — subscribers listening at the camera level receive ring events
|
|
@@ -11163,7 +11179,10 @@ var doorbellCapability = {
|
|
|
11163
11179
|
scope: "device",
|
|
11164
11180
|
deviceNative: true,
|
|
11165
11181
|
mode: "singleton",
|
|
11166
|
-
|
|
11182
|
+
kind: "wrapper",
|
|
11183
|
+
defaultActive: false,
|
|
11184
|
+
deviceTypes: [DeviceType.Button, DeviceType.Camera],
|
|
11185
|
+
exposesDeviceSettings: true,
|
|
11167
11186
|
methods: {},
|
|
11168
11187
|
events: {
|
|
11169
11188
|
/**
|
|
@@ -17600,6 +17619,14 @@ var ConfigEntrySchema = object({
|
|
|
17600
17619
|
value: unknown(),
|
|
17601
17620
|
description: string().optional()
|
|
17602
17621
|
});
|
|
17622
|
+
var DeviceLinkModeSchema = _enum(["auto", "manual"]);
|
|
17623
|
+
/** One resolved linked device — the compact projection consumers need. */
|
|
17624
|
+
var LinkedDeviceSchema = object({
|
|
17625
|
+
deviceId: number(),
|
|
17626
|
+
name: string(),
|
|
17627
|
+
location: string().nullable(),
|
|
17628
|
+
features: array(string())
|
|
17629
|
+
});
|
|
17603
17630
|
var SavedDeviceRowSchema = object({
|
|
17604
17631
|
/** Numeric id reserved at allocateDeviceId time. */
|
|
17605
17632
|
id: number(),
|
|
@@ -17821,7 +17848,10 @@ method(object({
|
|
|
17821
17848
|
}), _void(), {
|
|
17822
17849
|
kind: "mutation",
|
|
17823
17850
|
auth: "admin"
|
|
17824
|
-
}), 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() }),
|
|
17851
|
+
}), 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({
|
|
17852
|
+
mode: DeviceLinkModeSchema,
|
|
17853
|
+
devices: array(LinkedDeviceSchema)
|
|
17854
|
+
})), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
|
|
17825
17855
|
deviceId: number(),
|
|
17826
17856
|
values: record(string(), unknown())
|
|
17827
17857
|
}), object({ success: literal(true) }), {
|
|
@@ -19104,6 +19134,61 @@ var EventKindSchema = _enum([
|
|
|
19104
19134
|
"object",
|
|
19105
19135
|
"audio"
|
|
19106
19136
|
]);
|
|
19137
|
+
/**
|
|
19138
|
+
* Spatial filter for `listTracks` — the rect + polygon variants of the shared
|
|
19139
|
+
* MaskShape vocabulary (see `mask-shape.ts`). Coordinates are NORMALIZED 0..1
|
|
19140
|
+
* of the camera frame (top-left origin), matching the drawing-plane editor.
|
|
19141
|
+
*/
|
|
19142
|
+
var TrackZoneFilterSchema = discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
|
|
19143
|
+
/** Closed icon vocabulary so clients render a known glyph per kind. */
|
|
19144
|
+
var EventKindIconSchema = _enum([
|
|
19145
|
+
"motion",
|
|
19146
|
+
"audio",
|
|
19147
|
+
"person",
|
|
19148
|
+
"vehicle",
|
|
19149
|
+
"animal",
|
|
19150
|
+
"door",
|
|
19151
|
+
"pir",
|
|
19152
|
+
"smoke",
|
|
19153
|
+
"water",
|
|
19154
|
+
"button",
|
|
19155
|
+
"generic"
|
|
19156
|
+
]);
|
|
19157
|
+
var EventKindCategorySchema = _enum([
|
|
19158
|
+
"motion",
|
|
19159
|
+
"audio",
|
|
19160
|
+
"detection",
|
|
19161
|
+
"sensor",
|
|
19162
|
+
"custom"
|
|
19163
|
+
]);
|
|
19164
|
+
var EventKindDescriptorSchema = object({
|
|
19165
|
+
/** Stable kind id (e.g. 'motion', 'person', 'contact'). */
|
|
19166
|
+
kind: string(),
|
|
19167
|
+
label: string(),
|
|
19168
|
+
/** Hex color for timeline/legend rendering. */
|
|
19169
|
+
color: string(),
|
|
19170
|
+
icon: EventKindIconSchema,
|
|
19171
|
+
category: EventKindCategorySchema,
|
|
19172
|
+
/** Which cap + device contributes this kind. For built-ins the camera
|
|
19173
|
+
* itself; for sensor kinds the LINKED source device. */
|
|
19174
|
+
source: object({
|
|
19175
|
+
capName: string(),
|
|
19176
|
+
deviceId: number()
|
|
19177
|
+
})
|
|
19178
|
+
});
|
|
19179
|
+
var SensorEventSchema = object({
|
|
19180
|
+
id: string(),
|
|
19181
|
+
/** The CAMERA the event is attributed to (a sensor linked to N cameras
|
|
19182
|
+
* yields N rows, one per camera). */
|
|
19183
|
+
deviceId: number(),
|
|
19184
|
+
/** The linked sensor device whose state changed. */
|
|
19185
|
+
sourceDeviceId: number(),
|
|
19186
|
+
/** Event kind id — matches an `EventKindDescriptor.kind`. */
|
|
19187
|
+
kind: string(),
|
|
19188
|
+
/** Snapshot of the sensor cap's runtime-state slice at the change. */
|
|
19189
|
+
value: record(string(), unknown()).nullable(),
|
|
19190
|
+
timestamp: number()
|
|
19191
|
+
});
|
|
19107
19192
|
var TrackPositionSchema = object({
|
|
19108
19193
|
x: number(),
|
|
19109
19194
|
y: number(),
|
|
@@ -19117,6 +19202,30 @@ var TrackSnapshotSchema = object({
|
|
|
19117
19202
|
mediaKey: string()
|
|
19118
19203
|
});
|
|
19119
19204
|
/**
|
|
19205
|
+
* Normalized 0..1 trajectory envelope (min/max over every position bbox,
|
|
19206
|
+
* divided by the track's detection-frame dims), computed at persist time.
|
|
19207
|
+
* Absent when the frame dims were unknown when the track was persisted
|
|
19208
|
+
* (legacy rows / dims-less sources) and on active (in-RAM) tracks.
|
|
19209
|
+
*/
|
|
19210
|
+
var TrackEnvelopeSchema = object({
|
|
19211
|
+
minX: number(),
|
|
19212
|
+
minY: number(),
|
|
19213
|
+
maxX: number(),
|
|
19214
|
+
maxY: number()
|
|
19215
|
+
});
|
|
19216
|
+
/**
|
|
19217
|
+
* Row projection for track list queries. `full` (default) returns the
|
|
19218
|
+
* complete Track including the frame-rate `positions[]` history and the
|
|
19219
|
+
* `snapshots[]` references — megabytes across a page of tracks. `slim`
|
|
19220
|
+
* keeps every scalar the list surfaces actually render (ids, class(es),
|
|
19221
|
+
* label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
|
|
19222
|
+
* zonesVisited, bestEventId, envelope) and returns `positions` /
|
|
19223
|
+
* `snapshots` as EMPTY arrays — detail views re-fetch the full row via
|
|
19224
|
+
* `getTrack`. Mirrors the event-store `projection` convention
|
|
19225
|
+
* (`getObjectEvents` et al.).
|
|
19226
|
+
*/
|
|
19227
|
+
var TrackProjectionSchema = _enum(["full", "slim"]);
|
|
19228
|
+
/**
|
|
19120
19229
|
* One audio-classification label heard on the track's camera while the
|
|
19121
19230
|
* track was alive, aggregated per label. An "episode" is one persisted
|
|
19122
19231
|
* audio event (the confident-classification path: score ≥ the device's
|
|
@@ -19167,7 +19276,11 @@ var TrackSchema = object({
|
|
|
19167
19276
|
/** Audio-classification labels heard on the camera during the track's
|
|
19168
19277
|
* life (score ≥ device `classificationMinScore`), aggregated per label.
|
|
19169
19278
|
* Absent on legacy rows / tracks with no confident audio. */
|
|
19170
|
-
audioLabels: array(TrackAudioLabelSchema).readonly().optional()
|
|
19279
|
+
audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
|
|
19280
|
+
/** Normalized 0..1 trajectory envelope (see {@link TrackEnvelopeSchema}).
|
|
19281
|
+
* Populated from the persisted envelope columns on historical reads;
|
|
19282
|
+
* absent on legacy rows, dims-less tracks and active (in-RAM) tracks. */
|
|
19283
|
+
envelope: TrackEnvelopeSchema.optional()
|
|
19171
19284
|
});
|
|
19172
19285
|
var BaseEventFields = {
|
|
19173
19286
|
id: string(),
|
|
@@ -19277,11 +19390,13 @@ var MediaFileSchema = object({
|
|
|
19277
19390
|
sizeBytes: number(),
|
|
19278
19391
|
timestamp: number()
|
|
19279
19392
|
});
|
|
19393
|
+
var DEFAULT_EVENT_QUERY_LIMIT = 1e3;
|
|
19394
|
+
var MAX_EVENT_QUERY_LIMIT = 5e3;
|
|
19280
19395
|
var DeviceEventQueryInput = object({
|
|
19281
19396
|
deviceId: number(),
|
|
19282
19397
|
since: number().optional(),
|
|
19283
19398
|
until: number().optional(),
|
|
19284
|
-
limit: number().int().min(1).max(
|
|
19399
|
+
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT),
|
|
19285
19400
|
/** `slim` drops heavy JSON fields (regions/bbox/zones) and carries an
|
|
19286
19401
|
* optional `mediaUrl` (populated by B5). `full` (default) keeps today's
|
|
19287
19402
|
* exact behaviour. Callers may omit this field — the store defaults to
|
|
@@ -19289,6 +19404,27 @@ var DeviceEventQueryInput = object({
|
|
|
19289
19404
|
projection: _enum(["full", "slim"]).optional()
|
|
19290
19405
|
});
|
|
19291
19406
|
var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
|
|
19407
|
+
var RecentTracksQueryInput = object({
|
|
19408
|
+
/** Devices to merge. An empty array yields `{ tracks: [], nextCursor: null }`. */
|
|
19409
|
+
deviceIds: array(number()),
|
|
19410
|
+
/** Window lower bound on `lastSeen` (inclusive). */
|
|
19411
|
+
since: number().optional(),
|
|
19412
|
+
/** Window upper bound on `lastSeen` (inclusive). */
|
|
19413
|
+
until: number().optional(),
|
|
19414
|
+
/** Page size. Default 200, max 1000. */
|
|
19415
|
+
limit: number().int().min(1).max(1e3).default(200),
|
|
19416
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`.
|
|
19417
|
+
* Encodes the (lastSeen, trackId) sort position — treat as opaque. */
|
|
19418
|
+
cursor: string().optional(),
|
|
19419
|
+
/** See {@link TrackProjectionSchema}. Default `full`. */
|
|
19420
|
+
projection: TrackProjectionSchema.optional()
|
|
19421
|
+
});
|
|
19422
|
+
var RecentTracksPageSchema = object({
|
|
19423
|
+
/** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
|
|
19424
|
+
tracks: array(TrackSchema).readonly(),
|
|
19425
|
+
/** Cursor for the next page, or null when this page is the last. */
|
|
19426
|
+
nextCursor: string().nullable()
|
|
19427
|
+
});
|
|
19292
19428
|
var KeyEventQueryInput = object({
|
|
19293
19429
|
deviceId: number(),
|
|
19294
19430
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
@@ -19371,11 +19507,25 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19371
19507
|
deviceId: number(),
|
|
19372
19508
|
since: number().optional(),
|
|
19373
19509
|
until: number().optional(),
|
|
19374
|
-
limit: number().optional()
|
|
19375
|
-
|
|
19510
|
+
limit: number().optional(),
|
|
19511
|
+
/** Spatial filter — only tracks whose trajectory intersects the zone
|
|
19512
|
+
* (normalized 0..1 rect or polygon). SQL-prefiltered on the persisted
|
|
19513
|
+
* envelope columns, then precisely tested per position. Tracks with
|
|
19514
|
+
* an unknown envelope (no frame dims at persist time) always match. */
|
|
19515
|
+
zone: TrackZoneFilterSchema.optional(),
|
|
19516
|
+
/** See {@link TrackProjectionSchema}. Default `full` (backward
|
|
19517
|
+
* compatible — omitting the field keeps today's exact behaviour). */
|
|
19518
|
+
projection: TrackProjectionSchema.optional()
|
|
19519
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
|
|
19376
19520
|
kind: "mutation",
|
|
19377
19521
|
auth: "admin"
|
|
19378
|
-
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(
|
|
19522
|
+
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({
|
|
19523
|
+
deviceId: number(),
|
|
19524
|
+
since: number().optional(),
|
|
19525
|
+
until: number().optional(),
|
|
19526
|
+
kinds: array(string()).optional(),
|
|
19527
|
+
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
|
|
19528
|
+
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
|
|
19379
19529
|
deviceId: number(),
|
|
19380
19530
|
since: number(),
|
|
19381
19531
|
until: number(),
|
|
@@ -22665,7 +22815,12 @@ var RecordingStorageUsageSchema = object({
|
|
|
22665
22815
|
/**
|
|
22666
22816
|
* Result of locating footage at a wall-clock instant for one device/profile.
|
|
22667
22817
|
* `segment` carries the covering segment's window; `gap` reports the forward
|
|
22668
|
-
* nearest covered edge (`null` past the end of footage / when none exists)
|
|
22818
|
+
* nearest covered edge (`null` past the end of footage / when none exists)
|
|
22819
|
+
* and the backward covered edge `prevEndMs` (exclusive end of the nearest
|
|
22820
|
+
* footage behind the epoch; `null` when none — optional so older providers
|
|
22821
|
+
* that omit it stay valid). `prevEndMs` lets a backward frame-step hop the
|
|
22822
|
+
* small inter-segment cracks (durMs under-covers the span to the next
|
|
22823
|
+
* startMs by ~11-17 ms) instead of no-opping at a segment head.
|
|
22669
22824
|
*/
|
|
22670
22825
|
var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
|
|
22671
22826
|
kind: literal("segment"),
|
|
@@ -22674,7 +22829,8 @@ var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
|
|
|
22674
22829
|
bytes: number()
|
|
22675
22830
|
}), object({
|
|
22676
22831
|
kind: literal("gap"),
|
|
22677
|
-
nearestEdgeMs: number().nullable()
|
|
22832
|
+
nearestEdgeMs: number().nullable(),
|
|
22833
|
+
prevEndMs: number().nullable().optional()
|
|
22678
22834
|
})]);
|
|
22679
22835
|
/** Raw bytes of one finalized footage segment (read off disk on the recording node). */
|
|
22680
22836
|
var ReadSegmentBytesResultSchema = object({ data: _instanceof(Uint8Array) });
|
|
@@ -24243,6 +24399,12 @@ Object.freeze({
|
|
|
24243
24399
|
addonId: null,
|
|
24244
24400
|
access: "view"
|
|
24245
24401
|
},
|
|
24402
|
+
"deviceManager.getLinkedDevices": {
|
|
24403
|
+
capName: "device-manager",
|
|
24404
|
+
capScope: "system",
|
|
24405
|
+
addonId: null,
|
|
24406
|
+
access: "view"
|
|
24407
|
+
},
|
|
24246
24408
|
"deviceManager.getRoleDisplayDefaults": {
|
|
24247
24409
|
capName: "device-manager",
|
|
24248
24410
|
capScope: "system",
|
|
@@ -25797,6 +25959,12 @@ Object.freeze({
|
|
|
25797
25959
|
addonId: null,
|
|
25798
25960
|
access: "view"
|
|
25799
25961
|
},
|
|
25962
|
+
"pipelineAnalytics.getSensorEvents": {
|
|
25963
|
+
capName: "pipeline-analytics",
|
|
25964
|
+
capScope: "device",
|
|
25965
|
+
addonId: null,
|
|
25966
|
+
access: "view"
|
|
25967
|
+
},
|
|
25800
25968
|
"pipelineAnalytics.getTrack": {
|
|
25801
25969
|
capName: "pipeline-analytics",
|
|
25802
25970
|
capScope: "device",
|
|
@@ -25809,6 +25977,18 @@ Object.freeze({
|
|
|
25809
25977
|
addonId: null,
|
|
25810
25978
|
access: "view"
|
|
25811
25979
|
},
|
|
25980
|
+
"pipelineAnalytics.listEventKinds": {
|
|
25981
|
+
capName: "pipeline-analytics",
|
|
25982
|
+
capScope: "device",
|
|
25983
|
+
addonId: null,
|
|
25984
|
+
access: "view"
|
|
25985
|
+
},
|
|
25986
|
+
"pipelineAnalytics.listRecentTracks": {
|
|
25987
|
+
capName: "pipeline-analytics",
|
|
25988
|
+
capScope: "device",
|
|
25989
|
+
addonId: null,
|
|
25990
|
+
access: "view"
|
|
25991
|
+
},
|
|
25812
25992
|
"pipelineAnalytics.listTracks": {
|
|
25813
25993
|
capName: "pipeline-analytics",
|
|
25814
25994
|
capScope: "device",
|
package/dist/addon.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { brotliCompressSync, deflateSync, gzipSync } from "node:zlib";
|
|
3
|
-
//#region ../types/dist/event-category-
|
|
3
|
+
//#region ../types/dist/event-category-H4AVePnn.mjs
|
|
4
4
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
5
5
|
EventCategory["SystemBoot"] = "system.boot";
|
|
6
6
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -150,6 +150,9 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
150
150
|
EventCategory["RecordingSegmentWritten"] = "recording.segment.written";
|
|
151
151
|
EventCategory["RecordingPolicyFallback"] = "recording.policy.fallback";
|
|
152
152
|
EventCategory["RecordingRetentionCompleted"] = "recording.retention.completed";
|
|
153
|
+
/** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
|
|
154
|
+
* thumb is a scrub gap the recorder's keyframe backfill covers. */
|
|
155
|
+
EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
|
|
153
156
|
EventCategory["DetectionEvent"] = "detection.event";
|
|
154
157
|
EventCategory["SessionTrackNew"] = "session.track.new";
|
|
155
158
|
EventCategory["SessionTrackExpired"] = "session.track.expired";
|
|
@@ -11138,10 +11141,23 @@ var deviceDiscoveryCapability = {
|
|
|
11138
11141
|
}
|
|
11139
11142
|
};
|
|
11140
11143
|
/**
|
|
11141
|
-
* Doorbell button cap.
|
|
11142
|
-
*
|
|
11143
|
-
*
|
|
11144
|
-
*
|
|
11144
|
+
* Doorbell button cap. Two kinds of providers coexist behind this cap
|
|
11145
|
+
* name (same pattern as `snapshot`):
|
|
11146
|
+
*
|
|
11147
|
+
* - **Native** providers: registered per-device by device-driver
|
|
11148
|
+
* addons via `ctx.registerNativeCap` — either on a
|
|
11149
|
+
* `DeviceType.Button` accessory with `role: DeviceRole.Doorbell`,
|
|
11150
|
+
* or directly on the camera (Reolink registers at camera level).
|
|
11151
|
+
* Emits an `onPressed` event every time the firmware pushes a
|
|
11152
|
+
* ring; status tracks the last press and a pressCount since start
|
|
11153
|
+
* (diagnostic).
|
|
11154
|
+
*
|
|
11155
|
+
* - **Wrapper** provider: the `virtual-doorbell` system builtin
|
|
11156
|
+
* (`@camstack/system/builtins/doorbell`). Turns ANY binary-ish
|
|
11157
|
+
* device (contact / switch / event-emitter …) into a doorbell for
|
|
11158
|
+
* a camera. `defaultActive: false` — the operator explicitly binds
|
|
11159
|
+
* it per camera in the device-bindings UI, then picks the source
|
|
11160
|
+
* device + trigger in the per-device settings.
|
|
11145
11161
|
*
|
|
11146
11162
|
* The DeviceEventPropagator re-emits `onPressed` on the camera parent
|
|
11147
11163
|
* — subscribers listening at the camera level receive ring events
|
|
@@ -11162,7 +11178,10 @@ var doorbellCapability = {
|
|
|
11162
11178
|
scope: "device",
|
|
11163
11179
|
deviceNative: true,
|
|
11164
11180
|
mode: "singleton",
|
|
11165
|
-
|
|
11181
|
+
kind: "wrapper",
|
|
11182
|
+
defaultActive: false,
|
|
11183
|
+
deviceTypes: [DeviceType.Button, DeviceType.Camera],
|
|
11184
|
+
exposesDeviceSettings: true,
|
|
11166
11185
|
methods: {},
|
|
11167
11186
|
events: {
|
|
11168
11187
|
/**
|
|
@@ -17599,6 +17618,14 @@ var ConfigEntrySchema = object({
|
|
|
17599
17618
|
value: unknown(),
|
|
17600
17619
|
description: string().optional()
|
|
17601
17620
|
});
|
|
17621
|
+
var DeviceLinkModeSchema = _enum(["auto", "manual"]);
|
|
17622
|
+
/** One resolved linked device — the compact projection consumers need. */
|
|
17623
|
+
var LinkedDeviceSchema = object({
|
|
17624
|
+
deviceId: number(),
|
|
17625
|
+
name: string(),
|
|
17626
|
+
location: string().nullable(),
|
|
17627
|
+
features: array(string())
|
|
17628
|
+
});
|
|
17602
17629
|
var SavedDeviceRowSchema = object({
|
|
17603
17630
|
/** Numeric id reserved at allocateDeviceId time. */
|
|
17604
17631
|
id: number(),
|
|
@@ -17820,7 +17847,10 @@ method(object({
|
|
|
17820
17847
|
}), _void(), {
|
|
17821
17848
|
kind: "mutation",
|
|
17822
17849
|
auth: "admin"
|
|
17823
|
-
}), 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() }),
|
|
17850
|
+
}), 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({
|
|
17851
|
+
mode: DeviceLinkModeSchema,
|
|
17852
|
+
devices: array(LinkedDeviceSchema)
|
|
17853
|
+
})), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
|
|
17824
17854
|
deviceId: number(),
|
|
17825
17855
|
values: record(string(), unknown())
|
|
17826
17856
|
}), object({ success: literal(true) }), {
|
|
@@ -19103,6 +19133,61 @@ var EventKindSchema = _enum([
|
|
|
19103
19133
|
"object",
|
|
19104
19134
|
"audio"
|
|
19105
19135
|
]);
|
|
19136
|
+
/**
|
|
19137
|
+
* Spatial filter for `listTracks` — the rect + polygon variants of the shared
|
|
19138
|
+
* MaskShape vocabulary (see `mask-shape.ts`). Coordinates are NORMALIZED 0..1
|
|
19139
|
+
* of the camera frame (top-left origin), matching the drawing-plane editor.
|
|
19140
|
+
*/
|
|
19141
|
+
var TrackZoneFilterSchema = discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
|
|
19142
|
+
/** Closed icon vocabulary so clients render a known glyph per kind. */
|
|
19143
|
+
var EventKindIconSchema = _enum([
|
|
19144
|
+
"motion",
|
|
19145
|
+
"audio",
|
|
19146
|
+
"person",
|
|
19147
|
+
"vehicle",
|
|
19148
|
+
"animal",
|
|
19149
|
+
"door",
|
|
19150
|
+
"pir",
|
|
19151
|
+
"smoke",
|
|
19152
|
+
"water",
|
|
19153
|
+
"button",
|
|
19154
|
+
"generic"
|
|
19155
|
+
]);
|
|
19156
|
+
var EventKindCategorySchema = _enum([
|
|
19157
|
+
"motion",
|
|
19158
|
+
"audio",
|
|
19159
|
+
"detection",
|
|
19160
|
+
"sensor",
|
|
19161
|
+
"custom"
|
|
19162
|
+
]);
|
|
19163
|
+
var EventKindDescriptorSchema = object({
|
|
19164
|
+
/** Stable kind id (e.g. 'motion', 'person', 'contact'). */
|
|
19165
|
+
kind: string(),
|
|
19166
|
+
label: string(),
|
|
19167
|
+
/** Hex color for timeline/legend rendering. */
|
|
19168
|
+
color: string(),
|
|
19169
|
+
icon: EventKindIconSchema,
|
|
19170
|
+
category: EventKindCategorySchema,
|
|
19171
|
+
/** Which cap + device contributes this kind. For built-ins the camera
|
|
19172
|
+
* itself; for sensor kinds the LINKED source device. */
|
|
19173
|
+
source: object({
|
|
19174
|
+
capName: string(),
|
|
19175
|
+
deviceId: number()
|
|
19176
|
+
})
|
|
19177
|
+
});
|
|
19178
|
+
var SensorEventSchema = object({
|
|
19179
|
+
id: string(),
|
|
19180
|
+
/** The CAMERA the event is attributed to (a sensor linked to N cameras
|
|
19181
|
+
* yields N rows, one per camera). */
|
|
19182
|
+
deviceId: number(),
|
|
19183
|
+
/** The linked sensor device whose state changed. */
|
|
19184
|
+
sourceDeviceId: number(),
|
|
19185
|
+
/** Event kind id — matches an `EventKindDescriptor.kind`. */
|
|
19186
|
+
kind: string(),
|
|
19187
|
+
/** Snapshot of the sensor cap's runtime-state slice at the change. */
|
|
19188
|
+
value: record(string(), unknown()).nullable(),
|
|
19189
|
+
timestamp: number()
|
|
19190
|
+
});
|
|
19106
19191
|
var TrackPositionSchema = object({
|
|
19107
19192
|
x: number(),
|
|
19108
19193
|
y: number(),
|
|
@@ -19116,6 +19201,30 @@ var TrackSnapshotSchema = object({
|
|
|
19116
19201
|
mediaKey: string()
|
|
19117
19202
|
});
|
|
19118
19203
|
/**
|
|
19204
|
+
* Normalized 0..1 trajectory envelope (min/max over every position bbox,
|
|
19205
|
+
* divided by the track's detection-frame dims), computed at persist time.
|
|
19206
|
+
* Absent when the frame dims were unknown when the track was persisted
|
|
19207
|
+
* (legacy rows / dims-less sources) and on active (in-RAM) tracks.
|
|
19208
|
+
*/
|
|
19209
|
+
var TrackEnvelopeSchema = object({
|
|
19210
|
+
minX: number(),
|
|
19211
|
+
minY: number(),
|
|
19212
|
+
maxX: number(),
|
|
19213
|
+
maxY: number()
|
|
19214
|
+
});
|
|
19215
|
+
/**
|
|
19216
|
+
* Row projection for track list queries. `full` (default) returns the
|
|
19217
|
+
* complete Track including the frame-rate `positions[]` history and the
|
|
19218
|
+
* `snapshots[]` references — megabytes across a page of tracks. `slim`
|
|
19219
|
+
* keeps every scalar the list surfaces actually render (ids, class(es),
|
|
19220
|
+
* label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
|
|
19221
|
+
* zonesVisited, bestEventId, envelope) and returns `positions` /
|
|
19222
|
+
* `snapshots` as EMPTY arrays — detail views re-fetch the full row via
|
|
19223
|
+
* `getTrack`. Mirrors the event-store `projection` convention
|
|
19224
|
+
* (`getObjectEvents` et al.).
|
|
19225
|
+
*/
|
|
19226
|
+
var TrackProjectionSchema = _enum(["full", "slim"]);
|
|
19227
|
+
/**
|
|
19119
19228
|
* One audio-classification label heard on the track's camera while the
|
|
19120
19229
|
* track was alive, aggregated per label. An "episode" is one persisted
|
|
19121
19230
|
* audio event (the confident-classification path: score ≥ the device's
|
|
@@ -19166,7 +19275,11 @@ var TrackSchema = object({
|
|
|
19166
19275
|
/** Audio-classification labels heard on the camera during the track's
|
|
19167
19276
|
* life (score ≥ device `classificationMinScore`), aggregated per label.
|
|
19168
19277
|
* Absent on legacy rows / tracks with no confident audio. */
|
|
19169
|
-
audioLabels: array(TrackAudioLabelSchema).readonly().optional()
|
|
19278
|
+
audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
|
|
19279
|
+
/** Normalized 0..1 trajectory envelope (see {@link TrackEnvelopeSchema}).
|
|
19280
|
+
* Populated from the persisted envelope columns on historical reads;
|
|
19281
|
+
* absent on legacy rows, dims-less tracks and active (in-RAM) tracks. */
|
|
19282
|
+
envelope: TrackEnvelopeSchema.optional()
|
|
19170
19283
|
});
|
|
19171
19284
|
var BaseEventFields = {
|
|
19172
19285
|
id: string(),
|
|
@@ -19276,11 +19389,13 @@ var MediaFileSchema = object({
|
|
|
19276
19389
|
sizeBytes: number(),
|
|
19277
19390
|
timestamp: number()
|
|
19278
19391
|
});
|
|
19392
|
+
var DEFAULT_EVENT_QUERY_LIMIT = 1e3;
|
|
19393
|
+
var MAX_EVENT_QUERY_LIMIT = 5e3;
|
|
19279
19394
|
var DeviceEventQueryInput = object({
|
|
19280
19395
|
deviceId: number(),
|
|
19281
19396
|
since: number().optional(),
|
|
19282
19397
|
until: number().optional(),
|
|
19283
|
-
limit: number().int().min(1).max(
|
|
19398
|
+
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT),
|
|
19284
19399
|
/** `slim` drops heavy JSON fields (regions/bbox/zones) and carries an
|
|
19285
19400
|
* optional `mediaUrl` (populated by B5). `full` (default) keeps today's
|
|
19286
19401
|
* exact behaviour. Callers may omit this field — the store defaults to
|
|
@@ -19288,6 +19403,27 @@ var DeviceEventQueryInput = object({
|
|
|
19288
19403
|
projection: _enum(["full", "slim"]).optional()
|
|
19289
19404
|
});
|
|
19290
19405
|
var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
|
|
19406
|
+
var RecentTracksQueryInput = object({
|
|
19407
|
+
/** Devices to merge. An empty array yields `{ tracks: [], nextCursor: null }`. */
|
|
19408
|
+
deviceIds: array(number()),
|
|
19409
|
+
/** Window lower bound on `lastSeen` (inclusive). */
|
|
19410
|
+
since: number().optional(),
|
|
19411
|
+
/** Window upper bound on `lastSeen` (inclusive). */
|
|
19412
|
+
until: number().optional(),
|
|
19413
|
+
/** Page size. Default 200, max 1000. */
|
|
19414
|
+
limit: number().int().min(1).max(1e3).default(200),
|
|
19415
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`.
|
|
19416
|
+
* Encodes the (lastSeen, trackId) sort position — treat as opaque. */
|
|
19417
|
+
cursor: string().optional(),
|
|
19418
|
+
/** See {@link TrackProjectionSchema}. Default `full`. */
|
|
19419
|
+
projection: TrackProjectionSchema.optional()
|
|
19420
|
+
});
|
|
19421
|
+
var RecentTracksPageSchema = object({
|
|
19422
|
+
/** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
|
|
19423
|
+
tracks: array(TrackSchema).readonly(),
|
|
19424
|
+
/** Cursor for the next page, or null when this page is the last. */
|
|
19425
|
+
nextCursor: string().nullable()
|
|
19426
|
+
});
|
|
19291
19427
|
var KeyEventQueryInput = object({
|
|
19292
19428
|
deviceId: number(),
|
|
19293
19429
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
@@ -19370,11 +19506,25 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19370
19506
|
deviceId: number(),
|
|
19371
19507
|
since: number().optional(),
|
|
19372
19508
|
until: number().optional(),
|
|
19373
|
-
limit: number().optional()
|
|
19374
|
-
|
|
19509
|
+
limit: number().optional(),
|
|
19510
|
+
/** Spatial filter — only tracks whose trajectory intersects the zone
|
|
19511
|
+
* (normalized 0..1 rect or polygon). SQL-prefiltered on the persisted
|
|
19512
|
+
* envelope columns, then precisely tested per position. Tracks with
|
|
19513
|
+
* an unknown envelope (no frame dims at persist time) always match. */
|
|
19514
|
+
zone: TrackZoneFilterSchema.optional(),
|
|
19515
|
+
/** See {@link TrackProjectionSchema}. Default `full` (backward
|
|
19516
|
+
* compatible — omitting the field keeps today's exact behaviour). */
|
|
19517
|
+
projection: TrackProjectionSchema.optional()
|
|
19518
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
|
|
19375
19519
|
kind: "mutation",
|
|
19376
19520
|
auth: "admin"
|
|
19377
|
-
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(
|
|
19521
|
+
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({
|
|
19522
|
+
deviceId: number(),
|
|
19523
|
+
since: number().optional(),
|
|
19524
|
+
until: number().optional(),
|
|
19525
|
+
kinds: array(string()).optional(),
|
|
19526
|
+
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
|
|
19527
|
+
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
|
|
19378
19528
|
deviceId: number(),
|
|
19379
19529
|
since: number(),
|
|
19380
19530
|
until: number(),
|
|
@@ -22664,7 +22814,12 @@ var RecordingStorageUsageSchema = object({
|
|
|
22664
22814
|
/**
|
|
22665
22815
|
* Result of locating footage at a wall-clock instant for one device/profile.
|
|
22666
22816
|
* `segment` carries the covering segment's window; `gap` reports the forward
|
|
22667
|
-
* nearest covered edge (`null` past the end of footage / when none exists)
|
|
22817
|
+
* nearest covered edge (`null` past the end of footage / when none exists)
|
|
22818
|
+
* and the backward covered edge `prevEndMs` (exclusive end of the nearest
|
|
22819
|
+
* footage behind the epoch; `null` when none — optional so older providers
|
|
22820
|
+
* that omit it stay valid). `prevEndMs` lets a backward frame-step hop the
|
|
22821
|
+
* small inter-segment cracks (durMs under-covers the span to the next
|
|
22822
|
+
* startMs by ~11-17 ms) instead of no-opping at a segment head.
|
|
22668
22823
|
*/
|
|
22669
22824
|
var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
|
|
22670
22825
|
kind: literal("segment"),
|
|
@@ -22673,7 +22828,8 @@ var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
|
|
|
22673
22828
|
bytes: number()
|
|
22674
22829
|
}), object({
|
|
22675
22830
|
kind: literal("gap"),
|
|
22676
|
-
nearestEdgeMs: number().nullable()
|
|
22831
|
+
nearestEdgeMs: number().nullable(),
|
|
22832
|
+
prevEndMs: number().nullable().optional()
|
|
22677
22833
|
})]);
|
|
22678
22834
|
/** Raw bytes of one finalized footage segment (read off disk on the recording node). */
|
|
22679
22835
|
var ReadSegmentBytesResultSchema = object({ data: _instanceof(Uint8Array) });
|
|
@@ -24242,6 +24398,12 @@ Object.freeze({
|
|
|
24242
24398
|
addonId: null,
|
|
24243
24399
|
access: "view"
|
|
24244
24400
|
},
|
|
24401
|
+
"deviceManager.getLinkedDevices": {
|
|
24402
|
+
capName: "device-manager",
|
|
24403
|
+
capScope: "system",
|
|
24404
|
+
addonId: null,
|
|
24405
|
+
access: "view"
|
|
24406
|
+
},
|
|
24245
24407
|
"deviceManager.getRoleDisplayDefaults": {
|
|
24246
24408
|
capName: "device-manager",
|
|
24247
24409
|
capScope: "system",
|
|
@@ -25796,6 +25958,12 @@ Object.freeze({
|
|
|
25796
25958
|
addonId: null,
|
|
25797
25959
|
access: "view"
|
|
25798
25960
|
},
|
|
25961
|
+
"pipelineAnalytics.getSensorEvents": {
|
|
25962
|
+
capName: "pipeline-analytics",
|
|
25963
|
+
capScope: "device",
|
|
25964
|
+
addonId: null,
|
|
25965
|
+
access: "view"
|
|
25966
|
+
},
|
|
25799
25967
|
"pipelineAnalytics.getTrack": {
|
|
25800
25968
|
capName: "pipeline-analytics",
|
|
25801
25969
|
capScope: "device",
|
|
@@ -25808,6 +25976,18 @@ Object.freeze({
|
|
|
25808
25976
|
addonId: null,
|
|
25809
25977
|
access: "view"
|
|
25810
25978
|
},
|
|
25979
|
+
"pipelineAnalytics.listEventKinds": {
|
|
25980
|
+
capName: "pipeline-analytics",
|
|
25981
|
+
capScope: "device",
|
|
25982
|
+
addonId: null,
|
|
25983
|
+
access: "view"
|
|
25984
|
+
},
|
|
25985
|
+
"pipelineAnalytics.listRecentTracks": {
|
|
25986
|
+
capName: "pipeline-analytics",
|
|
25987
|
+
capScope: "device",
|
|
25988
|
+
addonId: null,
|
|
25989
|
+
access: "view"
|
|
25990
|
+
},
|
|
25811
25991
|
"pipelineAnalytics.listTracks": {
|
|
25812
25992
|
capName: "pipeline-analytics",
|
|
25813
25993
|
capScope: "device",
|