@camstack/addon-provider-homematic 1.1.22 → 1.1.23
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
|
@@ -8,7 +8,7 @@ let http = require("http");
|
|
|
8
8
|
let crypto$1 = require("crypto");
|
|
9
9
|
let fs_promises = require("fs/promises");
|
|
10
10
|
let path = require("path");
|
|
11
|
-
//#region ../types/dist/event-category-
|
|
11
|
+
//#region ../types/dist/event-category-H4AVePnn.mjs
|
|
12
12
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
13
13
|
EventCategory["SystemBoot"] = "system.boot";
|
|
14
14
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -158,6 +158,9 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
158
158
|
EventCategory["RecordingSegmentWritten"] = "recording.segment.written";
|
|
159
159
|
EventCategory["RecordingPolicyFallback"] = "recording.policy.fallback";
|
|
160
160
|
EventCategory["RecordingRetentionCompleted"] = "recording.retention.completed";
|
|
161
|
+
/** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
|
|
162
|
+
* thumb is a scrub gap the recorder's keyframe backfill covers. */
|
|
163
|
+
EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
|
|
161
164
|
EventCategory["DetectionEvent"] = "detection.event";
|
|
162
165
|
EventCategory["SessionTrackNew"] = "session.track.new";
|
|
163
166
|
EventCategory["SessionTrackExpired"] = "session.track.expired";
|
|
@@ -10805,10 +10808,23 @@ var deviceDiscoveryCapability = {
|
|
|
10805
10808
|
}
|
|
10806
10809
|
};
|
|
10807
10810
|
/**
|
|
10808
|
-
* Doorbell button cap.
|
|
10809
|
-
*
|
|
10810
|
-
*
|
|
10811
|
-
*
|
|
10811
|
+
* Doorbell button cap. Two kinds of providers coexist behind this cap
|
|
10812
|
+
* name (same pattern as `snapshot`):
|
|
10813
|
+
*
|
|
10814
|
+
* - **Native** providers: registered per-device by device-driver
|
|
10815
|
+
* addons via `ctx.registerNativeCap` — either on a
|
|
10816
|
+
* `DeviceType.Button` accessory with `role: DeviceRole.Doorbell`,
|
|
10817
|
+
* or directly on the camera (Reolink registers at camera level).
|
|
10818
|
+
* Emits an `onPressed` event every time the firmware pushes a
|
|
10819
|
+
* ring; status tracks the last press and a pressCount since start
|
|
10820
|
+
* (diagnostic).
|
|
10821
|
+
*
|
|
10822
|
+
* - **Wrapper** provider: the `virtual-doorbell` system builtin
|
|
10823
|
+
* (`@camstack/system/builtins/doorbell`). Turns ANY binary-ish
|
|
10824
|
+
* device (contact / switch / event-emitter …) into a doorbell for
|
|
10825
|
+
* a camera. `defaultActive: false` — the operator explicitly binds
|
|
10826
|
+
* it per camera in the device-bindings UI, then picks the source
|
|
10827
|
+
* device + trigger in the per-device settings.
|
|
10812
10828
|
*
|
|
10813
10829
|
* The DeviceEventPropagator re-emits `onPressed` on the camera parent
|
|
10814
10830
|
* — subscribers listening at the camera level receive ring events
|
|
@@ -10829,7 +10845,10 @@ var doorbellCapability = {
|
|
|
10829
10845
|
scope: "device",
|
|
10830
10846
|
deviceNative: true,
|
|
10831
10847
|
mode: "singleton",
|
|
10832
|
-
|
|
10848
|
+
kind: "wrapper",
|
|
10849
|
+
defaultActive: false,
|
|
10850
|
+
deviceTypes: [DeviceType.Button, DeviceType.Camera],
|
|
10851
|
+
exposesDeviceSettings: true,
|
|
10833
10852
|
methods: {},
|
|
10834
10853
|
events: {
|
|
10835
10854
|
/**
|
|
@@ -17247,6 +17266,14 @@ var ConfigEntrySchema = object({
|
|
|
17247
17266
|
value: unknown(),
|
|
17248
17267
|
description: string().optional()
|
|
17249
17268
|
});
|
|
17269
|
+
var DeviceLinkModeSchema = _enum(["auto", "manual"]);
|
|
17270
|
+
/** One resolved linked device — the compact projection consumers need. */
|
|
17271
|
+
var LinkedDeviceSchema = object({
|
|
17272
|
+
deviceId: number(),
|
|
17273
|
+
name: string(),
|
|
17274
|
+
location: string().nullable(),
|
|
17275
|
+
features: array(string())
|
|
17276
|
+
});
|
|
17250
17277
|
var SavedDeviceRowSchema = object({
|
|
17251
17278
|
/** Numeric id reserved at allocateDeviceId time. */
|
|
17252
17279
|
id: number(),
|
|
@@ -17468,7 +17495,10 @@ method(object({
|
|
|
17468
17495
|
}), _void(), {
|
|
17469
17496
|
kind: "mutation",
|
|
17470
17497
|
auth: "admin"
|
|
17471
|
-
}), 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() }),
|
|
17498
|
+
}), 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({
|
|
17499
|
+
mode: DeviceLinkModeSchema,
|
|
17500
|
+
devices: array(LinkedDeviceSchema)
|
|
17501
|
+
})), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
|
|
17472
17502
|
deviceId: number(),
|
|
17473
17503
|
values: record(string(), unknown())
|
|
17474
17504
|
}), object({ success: literal(true) }), {
|
|
@@ -18737,6 +18767,61 @@ var EventKindSchema = _enum([
|
|
|
18737
18767
|
"object",
|
|
18738
18768
|
"audio"
|
|
18739
18769
|
]);
|
|
18770
|
+
/**
|
|
18771
|
+
* Spatial filter for `listTracks` — the rect + polygon variants of the shared
|
|
18772
|
+
* MaskShape vocabulary (see `mask-shape.ts`). Coordinates are NORMALIZED 0..1
|
|
18773
|
+
* of the camera frame (top-left origin), matching the drawing-plane editor.
|
|
18774
|
+
*/
|
|
18775
|
+
var TrackZoneFilterSchema = discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
|
|
18776
|
+
/** Closed icon vocabulary so clients render a known glyph per kind. */
|
|
18777
|
+
var EventKindIconSchema = _enum([
|
|
18778
|
+
"motion",
|
|
18779
|
+
"audio",
|
|
18780
|
+
"person",
|
|
18781
|
+
"vehicle",
|
|
18782
|
+
"animal",
|
|
18783
|
+
"door",
|
|
18784
|
+
"pir",
|
|
18785
|
+
"smoke",
|
|
18786
|
+
"water",
|
|
18787
|
+
"button",
|
|
18788
|
+
"generic"
|
|
18789
|
+
]);
|
|
18790
|
+
var EventKindCategorySchema = _enum([
|
|
18791
|
+
"motion",
|
|
18792
|
+
"audio",
|
|
18793
|
+
"detection",
|
|
18794
|
+
"sensor",
|
|
18795
|
+
"custom"
|
|
18796
|
+
]);
|
|
18797
|
+
var EventKindDescriptorSchema = object({
|
|
18798
|
+
/** Stable kind id (e.g. 'motion', 'person', 'contact'). */
|
|
18799
|
+
kind: string(),
|
|
18800
|
+
label: string(),
|
|
18801
|
+
/** Hex color for timeline/legend rendering. */
|
|
18802
|
+
color: string(),
|
|
18803
|
+
icon: EventKindIconSchema,
|
|
18804
|
+
category: EventKindCategorySchema,
|
|
18805
|
+
/** Which cap + device contributes this kind. For built-ins the camera
|
|
18806
|
+
* itself; for sensor kinds the LINKED source device. */
|
|
18807
|
+
source: object({
|
|
18808
|
+
capName: string(),
|
|
18809
|
+
deviceId: number()
|
|
18810
|
+
})
|
|
18811
|
+
});
|
|
18812
|
+
var SensorEventSchema = object({
|
|
18813
|
+
id: string(),
|
|
18814
|
+
/** The CAMERA the event is attributed to (a sensor linked to N cameras
|
|
18815
|
+
* yields N rows, one per camera). */
|
|
18816
|
+
deviceId: number(),
|
|
18817
|
+
/** The linked sensor device whose state changed. */
|
|
18818
|
+
sourceDeviceId: number(),
|
|
18819
|
+
/** Event kind id — matches an `EventKindDescriptor.kind`. */
|
|
18820
|
+
kind: string(),
|
|
18821
|
+
/** Snapshot of the sensor cap's runtime-state slice at the change. */
|
|
18822
|
+
value: record(string(), unknown()).nullable(),
|
|
18823
|
+
timestamp: number()
|
|
18824
|
+
});
|
|
18740
18825
|
var TrackPositionSchema = object({
|
|
18741
18826
|
x: number(),
|
|
18742
18827
|
y: number(),
|
|
@@ -18750,6 +18835,30 @@ var TrackSnapshotSchema = object({
|
|
|
18750
18835
|
mediaKey: string()
|
|
18751
18836
|
});
|
|
18752
18837
|
/**
|
|
18838
|
+
* Normalized 0..1 trajectory envelope (min/max over every position bbox,
|
|
18839
|
+
* divided by the track's detection-frame dims), computed at persist time.
|
|
18840
|
+
* Absent when the frame dims were unknown when the track was persisted
|
|
18841
|
+
* (legacy rows / dims-less sources) and on active (in-RAM) tracks.
|
|
18842
|
+
*/
|
|
18843
|
+
var TrackEnvelopeSchema = object({
|
|
18844
|
+
minX: number(),
|
|
18845
|
+
minY: number(),
|
|
18846
|
+
maxX: number(),
|
|
18847
|
+
maxY: number()
|
|
18848
|
+
});
|
|
18849
|
+
/**
|
|
18850
|
+
* Row projection for track list queries. `full` (default) returns the
|
|
18851
|
+
* complete Track including the frame-rate `positions[]` history and the
|
|
18852
|
+
* `snapshots[]` references — megabytes across a page of tracks. `slim`
|
|
18853
|
+
* keeps every scalar the list surfaces actually render (ids, class(es),
|
|
18854
|
+
* label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
|
|
18855
|
+
* zonesVisited, bestEventId, envelope) and returns `positions` /
|
|
18856
|
+
* `snapshots` as EMPTY arrays — detail views re-fetch the full row via
|
|
18857
|
+
* `getTrack`. Mirrors the event-store `projection` convention
|
|
18858
|
+
* (`getObjectEvents` et al.).
|
|
18859
|
+
*/
|
|
18860
|
+
var TrackProjectionSchema = _enum(["full", "slim"]);
|
|
18861
|
+
/**
|
|
18753
18862
|
* One audio-classification label heard on the track's camera while the
|
|
18754
18863
|
* track was alive, aggregated per label. An "episode" is one persisted
|
|
18755
18864
|
* audio event (the confident-classification path: score ≥ the device's
|
|
@@ -18800,7 +18909,11 @@ var TrackSchema = object({
|
|
|
18800
18909
|
/** Audio-classification labels heard on the camera during the track's
|
|
18801
18910
|
* life (score ≥ device `classificationMinScore`), aggregated per label.
|
|
18802
18911
|
* Absent on legacy rows / tracks with no confident audio. */
|
|
18803
|
-
audioLabels: array(TrackAudioLabelSchema).readonly().optional()
|
|
18912
|
+
audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
|
|
18913
|
+
/** Normalized 0..1 trajectory envelope (see {@link TrackEnvelopeSchema}).
|
|
18914
|
+
* Populated from the persisted envelope columns on historical reads;
|
|
18915
|
+
* absent on legacy rows, dims-less tracks and active (in-RAM) tracks. */
|
|
18916
|
+
envelope: TrackEnvelopeSchema.optional()
|
|
18804
18917
|
});
|
|
18805
18918
|
var BaseEventFields = {
|
|
18806
18919
|
id: string(),
|
|
@@ -18910,11 +19023,13 @@ var MediaFileSchema = object({
|
|
|
18910
19023
|
sizeBytes: number(),
|
|
18911
19024
|
timestamp: number()
|
|
18912
19025
|
});
|
|
19026
|
+
var DEFAULT_EVENT_QUERY_LIMIT = 1e3;
|
|
19027
|
+
var MAX_EVENT_QUERY_LIMIT = 5e3;
|
|
18913
19028
|
var DeviceEventQueryInput = object({
|
|
18914
19029
|
deviceId: number(),
|
|
18915
19030
|
since: number().optional(),
|
|
18916
19031
|
until: number().optional(),
|
|
18917
|
-
limit: number().int().min(1).max(
|
|
19032
|
+
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT),
|
|
18918
19033
|
/** `slim` drops heavy JSON fields (regions/bbox/zones) and carries an
|
|
18919
19034
|
* optional `mediaUrl` (populated by B5). `full` (default) keeps today's
|
|
18920
19035
|
* exact behaviour. Callers may omit this field — the store defaults to
|
|
@@ -18922,6 +19037,27 @@ var DeviceEventQueryInput = object({
|
|
|
18922
19037
|
projection: _enum(["full", "slim"]).optional()
|
|
18923
19038
|
});
|
|
18924
19039
|
var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
|
|
19040
|
+
var RecentTracksQueryInput = object({
|
|
19041
|
+
/** Devices to merge. An empty array yields `{ tracks: [], nextCursor: null }`. */
|
|
19042
|
+
deviceIds: array(number()),
|
|
19043
|
+
/** Window lower bound on `lastSeen` (inclusive). */
|
|
19044
|
+
since: number().optional(),
|
|
19045
|
+
/** Window upper bound on `lastSeen` (inclusive). */
|
|
19046
|
+
until: number().optional(),
|
|
19047
|
+
/** Page size. Default 200, max 1000. */
|
|
19048
|
+
limit: number().int().min(1).max(1e3).default(200),
|
|
19049
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`.
|
|
19050
|
+
* Encodes the (lastSeen, trackId) sort position — treat as opaque. */
|
|
19051
|
+
cursor: string().optional(),
|
|
19052
|
+
/** See {@link TrackProjectionSchema}. Default `full`. */
|
|
19053
|
+
projection: TrackProjectionSchema.optional()
|
|
19054
|
+
});
|
|
19055
|
+
var RecentTracksPageSchema = object({
|
|
19056
|
+
/** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
|
|
19057
|
+
tracks: array(TrackSchema).readonly(),
|
|
19058
|
+
/** Cursor for the next page, or null when this page is the last. */
|
|
19059
|
+
nextCursor: string().nullable()
|
|
19060
|
+
});
|
|
18925
19061
|
var KeyEventQueryInput = object({
|
|
18926
19062
|
deviceId: number(),
|
|
18927
19063
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
@@ -19004,11 +19140,25 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19004
19140
|
deviceId: number(),
|
|
19005
19141
|
since: number().optional(),
|
|
19006
19142
|
until: number().optional(),
|
|
19007
|
-
limit: number().optional()
|
|
19008
|
-
|
|
19143
|
+
limit: number().optional(),
|
|
19144
|
+
/** Spatial filter — only tracks whose trajectory intersects the zone
|
|
19145
|
+
* (normalized 0..1 rect or polygon). SQL-prefiltered on the persisted
|
|
19146
|
+
* envelope columns, then precisely tested per position. Tracks with
|
|
19147
|
+
* an unknown envelope (no frame dims at persist time) always match. */
|
|
19148
|
+
zone: TrackZoneFilterSchema.optional(),
|
|
19149
|
+
/** See {@link TrackProjectionSchema}. Default `full` (backward
|
|
19150
|
+
* compatible — omitting the field keeps today's exact behaviour). */
|
|
19151
|
+
projection: TrackProjectionSchema.optional()
|
|
19152
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
|
|
19009
19153
|
kind: "mutation",
|
|
19010
19154
|
auth: "admin"
|
|
19011
|
-
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(
|
|
19155
|
+
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({
|
|
19156
|
+
deviceId: number(),
|
|
19157
|
+
since: number().optional(),
|
|
19158
|
+
until: number().optional(),
|
|
19159
|
+
kinds: array(string()).optional(),
|
|
19160
|
+
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
|
|
19161
|
+
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
|
|
19012
19162
|
deviceId: number(),
|
|
19013
19163
|
since: number(),
|
|
19014
19164
|
until: number(),
|
|
@@ -22209,7 +22359,12 @@ var RecordingStorageUsageSchema = object({
|
|
|
22209
22359
|
/**
|
|
22210
22360
|
* Result of locating footage at a wall-clock instant for one device/profile.
|
|
22211
22361
|
* `segment` carries the covering segment's window; `gap` reports the forward
|
|
22212
|
-
* nearest covered edge (`null` past the end of footage / when none exists)
|
|
22362
|
+
* nearest covered edge (`null` past the end of footage / when none exists)
|
|
22363
|
+
* and the backward covered edge `prevEndMs` (exclusive end of the nearest
|
|
22364
|
+
* footage behind the epoch; `null` when none — optional so older providers
|
|
22365
|
+
* that omit it stay valid). `prevEndMs` lets a backward frame-step hop the
|
|
22366
|
+
* small inter-segment cracks (durMs under-covers the span to the next
|
|
22367
|
+
* startMs by ~11-17 ms) instead of no-opping at a segment head.
|
|
22213
22368
|
*/
|
|
22214
22369
|
var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
|
|
22215
22370
|
kind: literal("segment"),
|
|
@@ -22218,7 +22373,8 @@ var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
|
|
|
22218
22373
|
bytes: number()
|
|
22219
22374
|
}), object({
|
|
22220
22375
|
kind: literal("gap"),
|
|
22221
|
-
nearestEdgeMs: number().nullable()
|
|
22376
|
+
nearestEdgeMs: number().nullable(),
|
|
22377
|
+
prevEndMs: number().nullable().optional()
|
|
22222
22378
|
})]);
|
|
22223
22379
|
/** Raw bytes of one finalized footage segment (read off disk on the recording node). */
|
|
22224
22380
|
var ReadSegmentBytesResultSchema = object({ data: _instanceof(Uint8Array) });
|
|
@@ -23787,6 +23943,12 @@ Object.freeze({
|
|
|
23787
23943
|
addonId: null,
|
|
23788
23944
|
access: "view"
|
|
23789
23945
|
},
|
|
23946
|
+
"deviceManager.getLinkedDevices": {
|
|
23947
|
+
capName: "device-manager",
|
|
23948
|
+
capScope: "system",
|
|
23949
|
+
addonId: null,
|
|
23950
|
+
access: "view"
|
|
23951
|
+
},
|
|
23790
23952
|
"deviceManager.getRoleDisplayDefaults": {
|
|
23791
23953
|
capName: "device-manager",
|
|
23792
23954
|
capScope: "system",
|
|
@@ -25341,6 +25503,12 @@ Object.freeze({
|
|
|
25341
25503
|
addonId: null,
|
|
25342
25504
|
access: "view"
|
|
25343
25505
|
},
|
|
25506
|
+
"pipelineAnalytics.getSensorEvents": {
|
|
25507
|
+
capName: "pipeline-analytics",
|
|
25508
|
+
capScope: "device",
|
|
25509
|
+
addonId: null,
|
|
25510
|
+
access: "view"
|
|
25511
|
+
},
|
|
25344
25512
|
"pipelineAnalytics.getTrack": {
|
|
25345
25513
|
capName: "pipeline-analytics",
|
|
25346
25514
|
capScope: "device",
|
|
@@ -25353,6 +25521,18 @@ Object.freeze({
|
|
|
25353
25521
|
addonId: null,
|
|
25354
25522
|
access: "view"
|
|
25355
25523
|
},
|
|
25524
|
+
"pipelineAnalytics.listEventKinds": {
|
|
25525
|
+
capName: "pipeline-analytics",
|
|
25526
|
+
capScope: "device",
|
|
25527
|
+
addonId: null,
|
|
25528
|
+
access: "view"
|
|
25529
|
+
},
|
|
25530
|
+
"pipelineAnalytics.listRecentTracks": {
|
|
25531
|
+
capName: "pipeline-analytics",
|
|
25532
|
+
capScope: "device",
|
|
25533
|
+
addonId: null,
|
|
25534
|
+
access: "view"
|
|
25535
|
+
},
|
|
25356
25536
|
"pipelineAnalytics.listTracks": {
|
|
25357
25537
|
capName: "pipeline-analytics",
|
|
25358
25538
|
capScope: "device",
|
package/dist/addon.mjs
CHANGED
|
@@ -9,7 +9,7 @@ import { join } from "path";
|
|
|
9
9
|
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
|
|
10
10
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
11
11
|
//#endregion
|
|
12
|
-
//#region ../types/dist/event-category-
|
|
12
|
+
//#region ../types/dist/event-category-H4AVePnn.mjs
|
|
13
13
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
14
14
|
EventCategory["SystemBoot"] = "system.boot";
|
|
15
15
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -159,6 +159,9 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
159
159
|
EventCategory["RecordingSegmentWritten"] = "recording.segment.written";
|
|
160
160
|
EventCategory["RecordingPolicyFallback"] = "recording.policy.fallback";
|
|
161
161
|
EventCategory["RecordingRetentionCompleted"] = "recording.retention.completed";
|
|
162
|
+
/** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
|
|
163
|
+
* thumb is a scrub gap the recorder's keyframe backfill covers. */
|
|
164
|
+
EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
|
|
162
165
|
EventCategory["DetectionEvent"] = "detection.event";
|
|
163
166
|
EventCategory["SessionTrackNew"] = "session.track.new";
|
|
164
167
|
EventCategory["SessionTrackExpired"] = "session.track.expired";
|
|
@@ -10806,10 +10809,23 @@ var deviceDiscoveryCapability = {
|
|
|
10806
10809
|
}
|
|
10807
10810
|
};
|
|
10808
10811
|
/**
|
|
10809
|
-
* Doorbell button cap.
|
|
10810
|
-
*
|
|
10811
|
-
*
|
|
10812
|
-
*
|
|
10812
|
+
* Doorbell button cap. Two kinds of providers coexist behind this cap
|
|
10813
|
+
* name (same pattern as `snapshot`):
|
|
10814
|
+
*
|
|
10815
|
+
* - **Native** providers: registered per-device by device-driver
|
|
10816
|
+
* addons via `ctx.registerNativeCap` — either on a
|
|
10817
|
+
* `DeviceType.Button` accessory with `role: DeviceRole.Doorbell`,
|
|
10818
|
+
* or directly on the camera (Reolink registers at camera level).
|
|
10819
|
+
* Emits an `onPressed` event every time the firmware pushes a
|
|
10820
|
+
* ring; status tracks the last press and a pressCount since start
|
|
10821
|
+
* (diagnostic).
|
|
10822
|
+
*
|
|
10823
|
+
* - **Wrapper** provider: the `virtual-doorbell` system builtin
|
|
10824
|
+
* (`@camstack/system/builtins/doorbell`). Turns ANY binary-ish
|
|
10825
|
+
* device (contact / switch / event-emitter …) into a doorbell for
|
|
10826
|
+
* a camera. `defaultActive: false` — the operator explicitly binds
|
|
10827
|
+
* it per camera in the device-bindings UI, then picks the source
|
|
10828
|
+
* device + trigger in the per-device settings.
|
|
10813
10829
|
*
|
|
10814
10830
|
* The DeviceEventPropagator re-emits `onPressed` on the camera parent
|
|
10815
10831
|
* — subscribers listening at the camera level receive ring events
|
|
@@ -10830,7 +10846,10 @@ var doorbellCapability = {
|
|
|
10830
10846
|
scope: "device",
|
|
10831
10847
|
deviceNative: true,
|
|
10832
10848
|
mode: "singleton",
|
|
10833
|
-
|
|
10849
|
+
kind: "wrapper",
|
|
10850
|
+
defaultActive: false,
|
|
10851
|
+
deviceTypes: [DeviceType.Button, DeviceType.Camera],
|
|
10852
|
+
exposesDeviceSettings: true,
|
|
10834
10853
|
methods: {},
|
|
10835
10854
|
events: {
|
|
10836
10855
|
/**
|
|
@@ -17248,6 +17267,14 @@ var ConfigEntrySchema = object({
|
|
|
17248
17267
|
value: unknown(),
|
|
17249
17268
|
description: string().optional()
|
|
17250
17269
|
});
|
|
17270
|
+
var DeviceLinkModeSchema = _enum(["auto", "manual"]);
|
|
17271
|
+
/** One resolved linked device — the compact projection consumers need. */
|
|
17272
|
+
var LinkedDeviceSchema = object({
|
|
17273
|
+
deviceId: number(),
|
|
17274
|
+
name: string(),
|
|
17275
|
+
location: string().nullable(),
|
|
17276
|
+
features: array(string())
|
|
17277
|
+
});
|
|
17251
17278
|
var SavedDeviceRowSchema = object({
|
|
17252
17279
|
/** Numeric id reserved at allocateDeviceId time. */
|
|
17253
17280
|
id: number(),
|
|
@@ -17469,7 +17496,10 @@ method(object({
|
|
|
17469
17496
|
}), _void(), {
|
|
17470
17497
|
kind: "mutation",
|
|
17471
17498
|
auth: "admin"
|
|
17472
|
-
}), 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() }),
|
|
17499
|
+
}), 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({
|
|
17500
|
+
mode: DeviceLinkModeSchema,
|
|
17501
|
+
devices: array(LinkedDeviceSchema)
|
|
17502
|
+
})), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
|
|
17473
17503
|
deviceId: number(),
|
|
17474
17504
|
values: record(string(), unknown())
|
|
17475
17505
|
}), object({ success: literal(true) }), {
|
|
@@ -18738,6 +18768,61 @@ var EventKindSchema = _enum([
|
|
|
18738
18768
|
"object",
|
|
18739
18769
|
"audio"
|
|
18740
18770
|
]);
|
|
18771
|
+
/**
|
|
18772
|
+
* Spatial filter for `listTracks` — the rect + polygon variants of the shared
|
|
18773
|
+
* MaskShape vocabulary (see `mask-shape.ts`). Coordinates are NORMALIZED 0..1
|
|
18774
|
+
* of the camera frame (top-left origin), matching the drawing-plane editor.
|
|
18775
|
+
*/
|
|
18776
|
+
var TrackZoneFilterSchema = discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
|
|
18777
|
+
/** Closed icon vocabulary so clients render a known glyph per kind. */
|
|
18778
|
+
var EventKindIconSchema = _enum([
|
|
18779
|
+
"motion",
|
|
18780
|
+
"audio",
|
|
18781
|
+
"person",
|
|
18782
|
+
"vehicle",
|
|
18783
|
+
"animal",
|
|
18784
|
+
"door",
|
|
18785
|
+
"pir",
|
|
18786
|
+
"smoke",
|
|
18787
|
+
"water",
|
|
18788
|
+
"button",
|
|
18789
|
+
"generic"
|
|
18790
|
+
]);
|
|
18791
|
+
var EventKindCategorySchema = _enum([
|
|
18792
|
+
"motion",
|
|
18793
|
+
"audio",
|
|
18794
|
+
"detection",
|
|
18795
|
+
"sensor",
|
|
18796
|
+
"custom"
|
|
18797
|
+
]);
|
|
18798
|
+
var EventKindDescriptorSchema = object({
|
|
18799
|
+
/** Stable kind id (e.g. 'motion', 'person', 'contact'). */
|
|
18800
|
+
kind: string(),
|
|
18801
|
+
label: string(),
|
|
18802
|
+
/** Hex color for timeline/legend rendering. */
|
|
18803
|
+
color: string(),
|
|
18804
|
+
icon: EventKindIconSchema,
|
|
18805
|
+
category: EventKindCategorySchema,
|
|
18806
|
+
/** Which cap + device contributes this kind. For built-ins the camera
|
|
18807
|
+
* itself; for sensor kinds the LINKED source device. */
|
|
18808
|
+
source: object({
|
|
18809
|
+
capName: string(),
|
|
18810
|
+
deviceId: number()
|
|
18811
|
+
})
|
|
18812
|
+
});
|
|
18813
|
+
var SensorEventSchema = object({
|
|
18814
|
+
id: string(),
|
|
18815
|
+
/** The CAMERA the event is attributed to (a sensor linked to N cameras
|
|
18816
|
+
* yields N rows, one per camera). */
|
|
18817
|
+
deviceId: number(),
|
|
18818
|
+
/** The linked sensor device whose state changed. */
|
|
18819
|
+
sourceDeviceId: number(),
|
|
18820
|
+
/** Event kind id — matches an `EventKindDescriptor.kind`. */
|
|
18821
|
+
kind: string(),
|
|
18822
|
+
/** Snapshot of the sensor cap's runtime-state slice at the change. */
|
|
18823
|
+
value: record(string(), unknown()).nullable(),
|
|
18824
|
+
timestamp: number()
|
|
18825
|
+
});
|
|
18741
18826
|
var TrackPositionSchema = object({
|
|
18742
18827
|
x: number(),
|
|
18743
18828
|
y: number(),
|
|
@@ -18751,6 +18836,30 @@ var TrackSnapshotSchema = object({
|
|
|
18751
18836
|
mediaKey: string()
|
|
18752
18837
|
});
|
|
18753
18838
|
/**
|
|
18839
|
+
* Normalized 0..1 trajectory envelope (min/max over every position bbox,
|
|
18840
|
+
* divided by the track's detection-frame dims), computed at persist time.
|
|
18841
|
+
* Absent when the frame dims were unknown when the track was persisted
|
|
18842
|
+
* (legacy rows / dims-less sources) and on active (in-RAM) tracks.
|
|
18843
|
+
*/
|
|
18844
|
+
var TrackEnvelopeSchema = object({
|
|
18845
|
+
minX: number(),
|
|
18846
|
+
minY: number(),
|
|
18847
|
+
maxX: number(),
|
|
18848
|
+
maxY: number()
|
|
18849
|
+
});
|
|
18850
|
+
/**
|
|
18851
|
+
* Row projection for track list queries. `full` (default) returns the
|
|
18852
|
+
* complete Track including the frame-rate `positions[]` history and the
|
|
18853
|
+
* `snapshots[]` references — megabytes across a page of tracks. `slim`
|
|
18854
|
+
* keeps every scalar the list surfaces actually render (ids, class(es),
|
|
18855
|
+
* label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
|
|
18856
|
+
* zonesVisited, bestEventId, envelope) and returns `positions` /
|
|
18857
|
+
* `snapshots` as EMPTY arrays — detail views re-fetch the full row via
|
|
18858
|
+
* `getTrack`. Mirrors the event-store `projection` convention
|
|
18859
|
+
* (`getObjectEvents` et al.).
|
|
18860
|
+
*/
|
|
18861
|
+
var TrackProjectionSchema = _enum(["full", "slim"]);
|
|
18862
|
+
/**
|
|
18754
18863
|
* One audio-classification label heard on the track's camera while the
|
|
18755
18864
|
* track was alive, aggregated per label. An "episode" is one persisted
|
|
18756
18865
|
* audio event (the confident-classification path: score ≥ the device's
|
|
@@ -18801,7 +18910,11 @@ var TrackSchema = object({
|
|
|
18801
18910
|
/** Audio-classification labels heard on the camera during the track's
|
|
18802
18911
|
* life (score ≥ device `classificationMinScore`), aggregated per label.
|
|
18803
18912
|
* Absent on legacy rows / tracks with no confident audio. */
|
|
18804
|
-
audioLabels: array(TrackAudioLabelSchema).readonly().optional()
|
|
18913
|
+
audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
|
|
18914
|
+
/** Normalized 0..1 trajectory envelope (see {@link TrackEnvelopeSchema}).
|
|
18915
|
+
* Populated from the persisted envelope columns on historical reads;
|
|
18916
|
+
* absent on legacy rows, dims-less tracks and active (in-RAM) tracks. */
|
|
18917
|
+
envelope: TrackEnvelopeSchema.optional()
|
|
18805
18918
|
});
|
|
18806
18919
|
var BaseEventFields = {
|
|
18807
18920
|
id: string(),
|
|
@@ -18911,11 +19024,13 @@ var MediaFileSchema = object({
|
|
|
18911
19024
|
sizeBytes: number(),
|
|
18912
19025
|
timestamp: number()
|
|
18913
19026
|
});
|
|
19027
|
+
var DEFAULT_EVENT_QUERY_LIMIT = 1e3;
|
|
19028
|
+
var MAX_EVENT_QUERY_LIMIT = 5e3;
|
|
18914
19029
|
var DeviceEventQueryInput = object({
|
|
18915
19030
|
deviceId: number(),
|
|
18916
19031
|
since: number().optional(),
|
|
18917
19032
|
until: number().optional(),
|
|
18918
|
-
limit: number().int().min(1).max(
|
|
19033
|
+
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT),
|
|
18919
19034
|
/** `slim` drops heavy JSON fields (regions/bbox/zones) and carries an
|
|
18920
19035
|
* optional `mediaUrl` (populated by B5). `full` (default) keeps today's
|
|
18921
19036
|
* exact behaviour. Callers may omit this field — the store defaults to
|
|
@@ -18923,6 +19038,27 @@ var DeviceEventQueryInput = object({
|
|
|
18923
19038
|
projection: _enum(["full", "slim"]).optional()
|
|
18924
19039
|
});
|
|
18925
19040
|
var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
|
|
19041
|
+
var RecentTracksQueryInput = object({
|
|
19042
|
+
/** Devices to merge. An empty array yields `{ tracks: [], nextCursor: null }`. */
|
|
19043
|
+
deviceIds: array(number()),
|
|
19044
|
+
/** Window lower bound on `lastSeen` (inclusive). */
|
|
19045
|
+
since: number().optional(),
|
|
19046
|
+
/** Window upper bound on `lastSeen` (inclusive). */
|
|
19047
|
+
until: number().optional(),
|
|
19048
|
+
/** Page size. Default 200, max 1000. */
|
|
19049
|
+
limit: number().int().min(1).max(1e3).default(200),
|
|
19050
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`.
|
|
19051
|
+
* Encodes the (lastSeen, trackId) sort position — treat as opaque. */
|
|
19052
|
+
cursor: string().optional(),
|
|
19053
|
+
/** See {@link TrackProjectionSchema}. Default `full`. */
|
|
19054
|
+
projection: TrackProjectionSchema.optional()
|
|
19055
|
+
});
|
|
19056
|
+
var RecentTracksPageSchema = object({
|
|
19057
|
+
/** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
|
|
19058
|
+
tracks: array(TrackSchema).readonly(),
|
|
19059
|
+
/** Cursor for the next page, or null when this page is the last. */
|
|
19060
|
+
nextCursor: string().nullable()
|
|
19061
|
+
});
|
|
18926
19062
|
var KeyEventQueryInput = object({
|
|
18927
19063
|
deviceId: number(),
|
|
18928
19064
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
@@ -19005,11 +19141,25 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19005
19141
|
deviceId: number(),
|
|
19006
19142
|
since: number().optional(),
|
|
19007
19143
|
until: number().optional(),
|
|
19008
|
-
limit: number().optional()
|
|
19009
|
-
|
|
19144
|
+
limit: number().optional(),
|
|
19145
|
+
/** Spatial filter — only tracks whose trajectory intersects the zone
|
|
19146
|
+
* (normalized 0..1 rect or polygon). SQL-prefiltered on the persisted
|
|
19147
|
+
* envelope columns, then precisely tested per position. Tracks with
|
|
19148
|
+
* an unknown envelope (no frame dims at persist time) always match. */
|
|
19149
|
+
zone: TrackZoneFilterSchema.optional(),
|
|
19150
|
+
/** See {@link TrackProjectionSchema}. Default `full` (backward
|
|
19151
|
+
* compatible — omitting the field keeps today's exact behaviour). */
|
|
19152
|
+
projection: TrackProjectionSchema.optional()
|
|
19153
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
|
|
19010
19154
|
kind: "mutation",
|
|
19011
19155
|
auth: "admin"
|
|
19012
|
-
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(
|
|
19156
|
+
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({
|
|
19157
|
+
deviceId: number(),
|
|
19158
|
+
since: number().optional(),
|
|
19159
|
+
until: number().optional(),
|
|
19160
|
+
kinds: array(string()).optional(),
|
|
19161
|
+
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
|
|
19162
|
+
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
|
|
19013
19163
|
deviceId: number(),
|
|
19014
19164
|
since: number(),
|
|
19015
19165
|
until: number(),
|
|
@@ -22210,7 +22360,12 @@ var RecordingStorageUsageSchema = object({
|
|
|
22210
22360
|
/**
|
|
22211
22361
|
* Result of locating footage at a wall-clock instant for one device/profile.
|
|
22212
22362
|
* `segment` carries the covering segment's window; `gap` reports the forward
|
|
22213
|
-
* nearest covered edge (`null` past the end of footage / when none exists)
|
|
22363
|
+
* nearest covered edge (`null` past the end of footage / when none exists)
|
|
22364
|
+
* and the backward covered edge `prevEndMs` (exclusive end of the nearest
|
|
22365
|
+
* footage behind the epoch; `null` when none — optional so older providers
|
|
22366
|
+
* that omit it stay valid). `prevEndMs` lets a backward frame-step hop the
|
|
22367
|
+
* small inter-segment cracks (durMs under-covers the span to the next
|
|
22368
|
+
* startMs by ~11-17 ms) instead of no-opping at a segment head.
|
|
22214
22369
|
*/
|
|
22215
22370
|
var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
|
|
22216
22371
|
kind: literal("segment"),
|
|
@@ -22219,7 +22374,8 @@ var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
|
|
|
22219
22374
|
bytes: number()
|
|
22220
22375
|
}), object({
|
|
22221
22376
|
kind: literal("gap"),
|
|
22222
|
-
nearestEdgeMs: number().nullable()
|
|
22377
|
+
nearestEdgeMs: number().nullable(),
|
|
22378
|
+
prevEndMs: number().nullable().optional()
|
|
22223
22379
|
})]);
|
|
22224
22380
|
/** Raw bytes of one finalized footage segment (read off disk on the recording node). */
|
|
22225
22381
|
var ReadSegmentBytesResultSchema = object({ data: _instanceof(Uint8Array) });
|
|
@@ -23788,6 +23944,12 @@ Object.freeze({
|
|
|
23788
23944
|
addonId: null,
|
|
23789
23945
|
access: "view"
|
|
23790
23946
|
},
|
|
23947
|
+
"deviceManager.getLinkedDevices": {
|
|
23948
|
+
capName: "device-manager",
|
|
23949
|
+
capScope: "system",
|
|
23950
|
+
addonId: null,
|
|
23951
|
+
access: "view"
|
|
23952
|
+
},
|
|
23791
23953
|
"deviceManager.getRoleDisplayDefaults": {
|
|
23792
23954
|
capName: "device-manager",
|
|
23793
23955
|
capScope: "system",
|
|
@@ -25342,6 +25504,12 @@ Object.freeze({
|
|
|
25342
25504
|
addonId: null,
|
|
25343
25505
|
access: "view"
|
|
25344
25506
|
},
|
|
25507
|
+
"pipelineAnalytics.getSensorEvents": {
|
|
25508
|
+
capName: "pipeline-analytics",
|
|
25509
|
+
capScope: "device",
|
|
25510
|
+
addonId: null,
|
|
25511
|
+
access: "view"
|
|
25512
|
+
},
|
|
25345
25513
|
"pipelineAnalytics.getTrack": {
|
|
25346
25514
|
capName: "pipeline-analytics",
|
|
25347
25515
|
capScope: "device",
|
|
@@ -25354,6 +25522,18 @@ Object.freeze({
|
|
|
25354
25522
|
addonId: null,
|
|
25355
25523
|
access: "view"
|
|
25356
25524
|
},
|
|
25525
|
+
"pipelineAnalytics.listEventKinds": {
|
|
25526
|
+
capName: "pipeline-analytics",
|
|
25527
|
+
capScope: "device",
|
|
25528
|
+
addonId: null,
|
|
25529
|
+
access: "view"
|
|
25530
|
+
},
|
|
25531
|
+
"pipelineAnalytics.listRecentTracks": {
|
|
25532
|
+
capName: "pipeline-analytics",
|
|
25533
|
+
capScope: "device",
|
|
25534
|
+
addonId: null,
|
|
25535
|
+
access: "view"
|
|
25536
|
+
},
|
|
25357
25537
|
"pipelineAnalytics.listTracks": {
|
|
25358
25538
|
capName: "pipeline-analytics",
|
|
25359
25539
|
capScope: "device",
|
package/package.json
CHANGED