@camstack/addon-matter-broker 0.1.20 → 0.1.21
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
|
@@ -13,7 +13,7 @@ let node_stream_promises = require("node:stream/promises");
|
|
|
13
13
|
let node_net = require("node:net");
|
|
14
14
|
let node_dgram = require("node:dgram");
|
|
15
15
|
node_dgram = require_esm.__toESM(node_dgram, 1);
|
|
16
|
-
//#region ../types/dist/event-category-
|
|
16
|
+
//#region ../types/dist/event-category-H4AVePnn.mjs
|
|
17
17
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
18
18
|
EventCategory["SystemBoot"] = "system.boot";
|
|
19
19
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -163,6 +163,9 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
163
163
|
EventCategory["RecordingSegmentWritten"] = "recording.segment.written";
|
|
164
164
|
EventCategory["RecordingPolicyFallback"] = "recording.policy.fallback";
|
|
165
165
|
EventCategory["RecordingRetentionCompleted"] = "recording.retention.completed";
|
|
166
|
+
/** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
|
|
167
|
+
* thumb is a scrub gap the recorder's keyframe backfill covers. */
|
|
168
|
+
EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
|
|
166
169
|
EventCategory["DetectionEvent"] = "detection.event";
|
|
167
170
|
EventCategory["SessionTrackNew"] = "session.track.new";
|
|
168
171
|
EventCategory["SessionTrackExpired"] = "session.track.expired";
|
|
@@ -10810,10 +10813,23 @@ var deviceDiscoveryCapability = {
|
|
|
10810
10813
|
}
|
|
10811
10814
|
};
|
|
10812
10815
|
/**
|
|
10813
|
-
* Doorbell button cap.
|
|
10814
|
-
*
|
|
10815
|
-
*
|
|
10816
|
-
*
|
|
10816
|
+
* Doorbell button cap. Two kinds of providers coexist behind this cap
|
|
10817
|
+
* name (same pattern as `snapshot`):
|
|
10818
|
+
*
|
|
10819
|
+
* - **Native** providers: registered per-device by device-driver
|
|
10820
|
+
* addons via `ctx.registerNativeCap` — either on a
|
|
10821
|
+
* `DeviceType.Button` accessory with `role: DeviceRole.Doorbell`,
|
|
10822
|
+
* or directly on the camera (Reolink registers at camera level).
|
|
10823
|
+
* Emits an `onPressed` event every time the firmware pushes a
|
|
10824
|
+
* ring; status tracks the last press and a pressCount since start
|
|
10825
|
+
* (diagnostic).
|
|
10826
|
+
*
|
|
10827
|
+
* - **Wrapper** provider: the `virtual-doorbell` system builtin
|
|
10828
|
+
* (`@camstack/system/builtins/doorbell`). Turns ANY binary-ish
|
|
10829
|
+
* device (contact / switch / event-emitter …) into a doorbell for
|
|
10830
|
+
* a camera. `defaultActive: false` — the operator explicitly binds
|
|
10831
|
+
* it per camera in the device-bindings UI, then picks the source
|
|
10832
|
+
* device + trigger in the per-device settings.
|
|
10817
10833
|
*
|
|
10818
10834
|
* The DeviceEventPropagator re-emits `onPressed` on the camera parent
|
|
10819
10835
|
* — subscribers listening at the camera level receive ring events
|
|
@@ -10834,7 +10850,10 @@ var doorbellCapability = {
|
|
|
10834
10850
|
scope: "device",
|
|
10835
10851
|
deviceNative: true,
|
|
10836
10852
|
mode: "singleton",
|
|
10837
|
-
|
|
10853
|
+
kind: "wrapper",
|
|
10854
|
+
defaultActive: false,
|
|
10855
|
+
deviceTypes: [DeviceType.Button, DeviceType.Camera],
|
|
10856
|
+
exposesDeviceSettings: true,
|
|
10838
10857
|
methods: {},
|
|
10839
10858
|
events: {
|
|
10840
10859
|
/**
|
|
@@ -17252,6 +17271,14 @@ var ConfigEntrySchema = object({
|
|
|
17252
17271
|
value: unknown(),
|
|
17253
17272
|
description: string$2().optional()
|
|
17254
17273
|
});
|
|
17274
|
+
var DeviceLinkModeSchema = _enum(["auto", "manual"]);
|
|
17275
|
+
/** One resolved linked device — the compact projection consumers need. */
|
|
17276
|
+
var LinkedDeviceSchema = object({
|
|
17277
|
+
deviceId: number(),
|
|
17278
|
+
name: string$2(),
|
|
17279
|
+
location: string$2().nullable(),
|
|
17280
|
+
features: array(string$2())
|
|
17281
|
+
});
|
|
17255
17282
|
var SavedDeviceRowSchema = object({
|
|
17256
17283
|
/** Numeric id reserved at allocateDeviceId time. */
|
|
17257
17284
|
id: number(),
|
|
@@ -17473,7 +17500,10 @@ method(object({
|
|
|
17473
17500
|
}), _void(), {
|
|
17474
17501
|
kind: "mutation",
|
|
17475
17502
|
auth: "admin"
|
|
17476
|
-
}), method(object({ addonId: string$2() }), array(SavedDeviceRowSchema)), method(object({ addonId: string$2().optional() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }),
|
|
17503
|
+
}), method(object({ addonId: string$2() }), array(SavedDeviceRowSchema)), method(object({ addonId: string$2().optional() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), object({
|
|
17504
|
+
mode: DeviceLinkModeSchema,
|
|
17505
|
+
devices: array(LinkedDeviceSchema)
|
|
17506
|
+
})), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
|
|
17477
17507
|
deviceId: number(),
|
|
17478
17508
|
values: record(string$2(), unknown())
|
|
17479
17509
|
}), object({ success: literal(true) }), {
|
|
@@ -18742,6 +18772,61 @@ var EventKindSchema = _enum([
|
|
|
18742
18772
|
"object",
|
|
18743
18773
|
"audio"
|
|
18744
18774
|
]);
|
|
18775
|
+
/**
|
|
18776
|
+
* Spatial filter for `listTracks` — the rect + polygon variants of the shared
|
|
18777
|
+
* MaskShape vocabulary (see `mask-shape.ts`). Coordinates are NORMALIZED 0..1
|
|
18778
|
+
* of the camera frame (top-left origin), matching the drawing-plane editor.
|
|
18779
|
+
*/
|
|
18780
|
+
var TrackZoneFilterSchema = discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
|
|
18781
|
+
/** Closed icon vocabulary so clients render a known glyph per kind. */
|
|
18782
|
+
var EventKindIconSchema = _enum([
|
|
18783
|
+
"motion",
|
|
18784
|
+
"audio",
|
|
18785
|
+
"person",
|
|
18786
|
+
"vehicle",
|
|
18787
|
+
"animal",
|
|
18788
|
+
"door",
|
|
18789
|
+
"pir",
|
|
18790
|
+
"smoke",
|
|
18791
|
+
"water",
|
|
18792
|
+
"button",
|
|
18793
|
+
"generic"
|
|
18794
|
+
]);
|
|
18795
|
+
var EventKindCategorySchema = _enum([
|
|
18796
|
+
"motion",
|
|
18797
|
+
"audio",
|
|
18798
|
+
"detection",
|
|
18799
|
+
"sensor",
|
|
18800
|
+
"custom"
|
|
18801
|
+
]);
|
|
18802
|
+
var EventKindDescriptorSchema = object({
|
|
18803
|
+
/** Stable kind id (e.g. 'motion', 'person', 'contact'). */
|
|
18804
|
+
kind: string$2(),
|
|
18805
|
+
label: string$2(),
|
|
18806
|
+
/** Hex color for timeline/legend rendering. */
|
|
18807
|
+
color: string$2(),
|
|
18808
|
+
icon: EventKindIconSchema,
|
|
18809
|
+
category: EventKindCategorySchema,
|
|
18810
|
+
/** Which cap + device contributes this kind. For built-ins the camera
|
|
18811
|
+
* itself; for sensor kinds the LINKED source device. */
|
|
18812
|
+
source: object({
|
|
18813
|
+
capName: string$2(),
|
|
18814
|
+
deviceId: number()
|
|
18815
|
+
})
|
|
18816
|
+
});
|
|
18817
|
+
var SensorEventSchema = object({
|
|
18818
|
+
id: string$2(),
|
|
18819
|
+
/** The CAMERA the event is attributed to (a sensor linked to N cameras
|
|
18820
|
+
* yields N rows, one per camera). */
|
|
18821
|
+
deviceId: number(),
|
|
18822
|
+
/** The linked sensor device whose state changed. */
|
|
18823
|
+
sourceDeviceId: number(),
|
|
18824
|
+
/** Event kind id — matches an `EventKindDescriptor.kind`. */
|
|
18825
|
+
kind: string$2(),
|
|
18826
|
+
/** Snapshot of the sensor cap's runtime-state slice at the change. */
|
|
18827
|
+
value: record(string$2(), unknown()).nullable(),
|
|
18828
|
+
timestamp: number()
|
|
18829
|
+
});
|
|
18745
18830
|
var TrackPositionSchema = object({
|
|
18746
18831
|
x: number(),
|
|
18747
18832
|
y: number(),
|
|
@@ -18755,6 +18840,30 @@ var TrackSnapshotSchema = object({
|
|
|
18755
18840
|
mediaKey: string$2()
|
|
18756
18841
|
});
|
|
18757
18842
|
/**
|
|
18843
|
+
* Normalized 0..1 trajectory envelope (min/max over every position bbox,
|
|
18844
|
+
* divided by the track's detection-frame dims), computed at persist time.
|
|
18845
|
+
* Absent when the frame dims were unknown when the track was persisted
|
|
18846
|
+
* (legacy rows / dims-less sources) and on active (in-RAM) tracks.
|
|
18847
|
+
*/
|
|
18848
|
+
var TrackEnvelopeSchema = object({
|
|
18849
|
+
minX: number(),
|
|
18850
|
+
minY: number(),
|
|
18851
|
+
maxX: number(),
|
|
18852
|
+
maxY: number()
|
|
18853
|
+
});
|
|
18854
|
+
/**
|
|
18855
|
+
* Row projection for track list queries. `full` (default) returns the
|
|
18856
|
+
* complete Track including the frame-rate `positions[]` history and the
|
|
18857
|
+
* `snapshots[]` references — megabytes across a page of tracks. `slim`
|
|
18858
|
+
* keeps every scalar the list surfaces actually render (ids, class(es),
|
|
18859
|
+
* label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
|
|
18860
|
+
* zonesVisited, bestEventId, envelope) and returns `positions` /
|
|
18861
|
+
* `snapshots` as EMPTY arrays — detail views re-fetch the full row via
|
|
18862
|
+
* `getTrack`. Mirrors the event-store `projection` convention
|
|
18863
|
+
* (`getObjectEvents` et al.).
|
|
18864
|
+
*/
|
|
18865
|
+
var TrackProjectionSchema = _enum(["full", "slim"]);
|
|
18866
|
+
/**
|
|
18758
18867
|
* One audio-classification label heard on the track's camera while the
|
|
18759
18868
|
* track was alive, aggregated per label. An "episode" is one persisted
|
|
18760
18869
|
* audio event (the confident-classification path: score ≥ the device's
|
|
@@ -18805,7 +18914,11 @@ var TrackSchema = object({
|
|
|
18805
18914
|
/** Audio-classification labels heard on the camera during the track's
|
|
18806
18915
|
* life (score ≥ device `classificationMinScore`), aggregated per label.
|
|
18807
18916
|
* Absent on legacy rows / tracks with no confident audio. */
|
|
18808
|
-
audioLabels: array(TrackAudioLabelSchema).readonly().optional()
|
|
18917
|
+
audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
|
|
18918
|
+
/** Normalized 0..1 trajectory envelope (see {@link TrackEnvelopeSchema}).
|
|
18919
|
+
* Populated from the persisted envelope columns on historical reads;
|
|
18920
|
+
* absent on legacy rows, dims-less tracks and active (in-RAM) tracks. */
|
|
18921
|
+
envelope: TrackEnvelopeSchema.optional()
|
|
18809
18922
|
});
|
|
18810
18923
|
var BaseEventFields = {
|
|
18811
18924
|
id: string$2(),
|
|
@@ -18915,11 +19028,13 @@ var MediaFileSchema = object({
|
|
|
18915
19028
|
sizeBytes: number(),
|
|
18916
19029
|
timestamp: number()
|
|
18917
19030
|
});
|
|
19031
|
+
var DEFAULT_EVENT_QUERY_LIMIT = 1e3;
|
|
19032
|
+
var MAX_EVENT_QUERY_LIMIT = 5e3;
|
|
18918
19033
|
var DeviceEventQueryInput = object({
|
|
18919
19034
|
deviceId: number(),
|
|
18920
19035
|
since: number().optional(),
|
|
18921
19036
|
until: number().optional(),
|
|
18922
|
-
limit: number().int().min(1).max(
|
|
19037
|
+
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT),
|
|
18923
19038
|
/** `slim` drops heavy JSON fields (regions/bbox/zones) and carries an
|
|
18924
19039
|
* optional `mediaUrl` (populated by B5). `full` (default) keeps today's
|
|
18925
19040
|
* exact behaviour. Callers may omit this field — the store defaults to
|
|
@@ -18927,6 +19042,27 @@ var DeviceEventQueryInput = object({
|
|
|
18927
19042
|
projection: _enum(["full", "slim"]).optional()
|
|
18928
19043
|
});
|
|
18929
19044
|
var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string$2().optional() });
|
|
19045
|
+
var RecentTracksQueryInput = object({
|
|
19046
|
+
/** Devices to merge. An empty array yields `{ tracks: [], nextCursor: null }`. */
|
|
19047
|
+
deviceIds: array(number()),
|
|
19048
|
+
/** Window lower bound on `lastSeen` (inclusive). */
|
|
19049
|
+
since: number().optional(),
|
|
19050
|
+
/** Window upper bound on `lastSeen` (inclusive). */
|
|
19051
|
+
until: number().optional(),
|
|
19052
|
+
/** Page size. Default 200, max 1000. */
|
|
19053
|
+
limit: number().int().min(1).max(1e3).default(200),
|
|
19054
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`.
|
|
19055
|
+
* Encodes the (lastSeen, trackId) sort position — treat as opaque. */
|
|
19056
|
+
cursor: string$2().optional(),
|
|
19057
|
+
/** See {@link TrackProjectionSchema}. Default `full`. */
|
|
19058
|
+
projection: TrackProjectionSchema.optional()
|
|
19059
|
+
});
|
|
19060
|
+
var RecentTracksPageSchema = object({
|
|
19061
|
+
/** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
|
|
19062
|
+
tracks: array(TrackSchema).readonly(),
|
|
19063
|
+
/** Cursor for the next page, or null when this page is the last. */
|
|
19064
|
+
nextCursor: string$2().nullable()
|
|
19065
|
+
});
|
|
18930
19066
|
var KeyEventQueryInput = object({
|
|
18931
19067
|
deviceId: number(),
|
|
18932
19068
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
@@ -19009,11 +19145,25 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19009
19145
|
deviceId: number(),
|
|
19010
19146
|
since: number().optional(),
|
|
19011
19147
|
until: number().optional(),
|
|
19012
|
-
limit: number().optional()
|
|
19013
|
-
|
|
19148
|
+
limit: number().optional(),
|
|
19149
|
+
/** Spatial filter — only tracks whose trajectory intersects the zone
|
|
19150
|
+
* (normalized 0..1 rect or polygon). SQL-prefiltered on the persisted
|
|
19151
|
+
* envelope columns, then precisely tested per position. Tracks with
|
|
19152
|
+
* an unknown envelope (no frame dims at persist time) always match. */
|
|
19153
|
+
zone: TrackZoneFilterSchema.optional(),
|
|
19154
|
+
/** See {@link TrackProjectionSchema}. Default `full` (backward
|
|
19155
|
+
* compatible — omitting the field keeps today's exact behaviour). */
|
|
19156
|
+
projection: TrackProjectionSchema.optional()
|
|
19157
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
|
|
19014
19158
|
kind: "mutation",
|
|
19015
19159
|
auth: "admin"
|
|
19016
|
-
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(
|
|
19160
|
+
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({
|
|
19161
|
+
deviceId: number(),
|
|
19162
|
+
since: number().optional(),
|
|
19163
|
+
until: number().optional(),
|
|
19164
|
+
kinds: array(string$2()).optional(),
|
|
19165
|
+
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
|
|
19166
|
+
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
|
|
19017
19167
|
deviceId: number(),
|
|
19018
19168
|
since: number(),
|
|
19019
19169
|
until: number(),
|
|
@@ -22231,7 +22381,12 @@ var RecordingStorageUsageSchema = object({
|
|
|
22231
22381
|
/**
|
|
22232
22382
|
* Result of locating footage at a wall-clock instant for one device/profile.
|
|
22233
22383
|
* `segment` carries the covering segment's window; `gap` reports the forward
|
|
22234
|
-
* nearest covered edge (`null` past the end of footage / when none exists)
|
|
22384
|
+
* nearest covered edge (`null` past the end of footage / when none exists)
|
|
22385
|
+
* and the backward covered edge `prevEndMs` (exclusive end of the nearest
|
|
22386
|
+
* footage behind the epoch; `null` when none — optional so older providers
|
|
22387
|
+
* that omit it stay valid). `prevEndMs` lets a backward frame-step hop the
|
|
22388
|
+
* small inter-segment cracks (durMs under-covers the span to the next
|
|
22389
|
+
* startMs by ~11-17 ms) instead of no-opping at a segment head.
|
|
22235
22390
|
*/
|
|
22236
22391
|
var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
|
|
22237
22392
|
kind: literal("segment"),
|
|
@@ -22240,7 +22395,8 @@ var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
|
|
|
22240
22395
|
bytes: number()
|
|
22241
22396
|
}), object({
|
|
22242
22397
|
kind: literal("gap"),
|
|
22243
|
-
nearestEdgeMs: number().nullable()
|
|
22398
|
+
nearestEdgeMs: number().nullable(),
|
|
22399
|
+
prevEndMs: number().nullable().optional()
|
|
22244
22400
|
})]);
|
|
22245
22401
|
/** Raw bytes of one finalized footage segment (read off disk on the recording node). */
|
|
22246
22402
|
var ReadSegmentBytesResultSchema = object({ data: _instanceof(Uint8Array) });
|
|
@@ -23809,6 +23965,12 @@ Object.freeze({
|
|
|
23809
23965
|
addonId: null,
|
|
23810
23966
|
access: "view"
|
|
23811
23967
|
},
|
|
23968
|
+
"deviceManager.getLinkedDevices": {
|
|
23969
|
+
capName: "device-manager",
|
|
23970
|
+
capScope: "system",
|
|
23971
|
+
addonId: null,
|
|
23972
|
+
access: "view"
|
|
23973
|
+
},
|
|
23812
23974
|
"deviceManager.getRoleDisplayDefaults": {
|
|
23813
23975
|
capName: "device-manager",
|
|
23814
23976
|
capScope: "system",
|
|
@@ -25363,6 +25525,12 @@ Object.freeze({
|
|
|
25363
25525
|
addonId: null,
|
|
25364
25526
|
access: "view"
|
|
25365
25527
|
},
|
|
25528
|
+
"pipelineAnalytics.getSensorEvents": {
|
|
25529
|
+
capName: "pipeline-analytics",
|
|
25530
|
+
capScope: "device",
|
|
25531
|
+
addonId: null,
|
|
25532
|
+
access: "view"
|
|
25533
|
+
},
|
|
25366
25534
|
"pipelineAnalytics.getTrack": {
|
|
25367
25535
|
capName: "pipeline-analytics",
|
|
25368
25536
|
capScope: "device",
|
|
@@ -25375,6 +25543,18 @@ Object.freeze({
|
|
|
25375
25543
|
addonId: null,
|
|
25376
25544
|
access: "view"
|
|
25377
25545
|
},
|
|
25546
|
+
"pipelineAnalytics.listEventKinds": {
|
|
25547
|
+
capName: "pipeline-analytics",
|
|
25548
|
+
capScope: "device",
|
|
25549
|
+
addonId: null,
|
|
25550
|
+
access: "view"
|
|
25551
|
+
},
|
|
25552
|
+
"pipelineAnalytics.listRecentTracks": {
|
|
25553
|
+
capName: "pipeline-analytics",
|
|
25554
|
+
capScope: "device",
|
|
25555
|
+
addonId: null,
|
|
25556
|
+
access: "view"
|
|
25557
|
+
},
|
|
25378
25558
|
"pipelineAnalytics.listTracks": {
|
|
25379
25559
|
capName: "pipeline-analytics",
|
|
25380
25560
|
capScope: "device",
|
package/dist/addon.mjs
CHANGED
|
@@ -11,7 +11,7 @@ import { networkInterfaces, tmpdir, uptime } from "node:os";
|
|
|
11
11
|
import { finished } from "node:stream/promises";
|
|
12
12
|
import { createConnection, createServer as createServer$2 } from "node:net";
|
|
13
13
|
import * as dgram from "node:dgram";
|
|
14
|
-
//#region ../types/dist/event-category-
|
|
14
|
+
//#region ../types/dist/event-category-H4AVePnn.mjs
|
|
15
15
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
16
16
|
EventCategory["SystemBoot"] = "system.boot";
|
|
17
17
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -161,6 +161,9 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
161
161
|
EventCategory["RecordingSegmentWritten"] = "recording.segment.written";
|
|
162
162
|
EventCategory["RecordingPolicyFallback"] = "recording.policy.fallback";
|
|
163
163
|
EventCategory["RecordingRetentionCompleted"] = "recording.retention.completed";
|
|
164
|
+
/** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
|
|
165
|
+
* thumb is a scrub gap the recorder's keyframe backfill covers. */
|
|
166
|
+
EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
|
|
164
167
|
EventCategory["DetectionEvent"] = "detection.event";
|
|
165
168
|
EventCategory["SessionTrackNew"] = "session.track.new";
|
|
166
169
|
EventCategory["SessionTrackExpired"] = "session.track.expired";
|
|
@@ -10808,10 +10811,23 @@ var deviceDiscoveryCapability = {
|
|
|
10808
10811
|
}
|
|
10809
10812
|
};
|
|
10810
10813
|
/**
|
|
10811
|
-
* Doorbell button cap.
|
|
10812
|
-
*
|
|
10813
|
-
*
|
|
10814
|
-
*
|
|
10814
|
+
* Doorbell button cap. Two kinds of providers coexist behind this cap
|
|
10815
|
+
* name (same pattern as `snapshot`):
|
|
10816
|
+
*
|
|
10817
|
+
* - **Native** providers: registered per-device by device-driver
|
|
10818
|
+
* addons via `ctx.registerNativeCap` — either on a
|
|
10819
|
+
* `DeviceType.Button` accessory with `role: DeviceRole.Doorbell`,
|
|
10820
|
+
* or directly on the camera (Reolink registers at camera level).
|
|
10821
|
+
* Emits an `onPressed` event every time the firmware pushes a
|
|
10822
|
+
* ring; status tracks the last press and a pressCount since start
|
|
10823
|
+
* (diagnostic).
|
|
10824
|
+
*
|
|
10825
|
+
* - **Wrapper** provider: the `virtual-doorbell` system builtin
|
|
10826
|
+
* (`@camstack/system/builtins/doorbell`). Turns ANY binary-ish
|
|
10827
|
+
* device (contact / switch / event-emitter …) into a doorbell for
|
|
10828
|
+
* a camera. `defaultActive: false` — the operator explicitly binds
|
|
10829
|
+
* it per camera in the device-bindings UI, then picks the source
|
|
10830
|
+
* device + trigger in the per-device settings.
|
|
10815
10831
|
*
|
|
10816
10832
|
* The DeviceEventPropagator re-emits `onPressed` on the camera parent
|
|
10817
10833
|
* — subscribers listening at the camera level receive ring events
|
|
@@ -10832,7 +10848,10 @@ var doorbellCapability = {
|
|
|
10832
10848
|
scope: "device",
|
|
10833
10849
|
deviceNative: true,
|
|
10834
10850
|
mode: "singleton",
|
|
10835
|
-
|
|
10851
|
+
kind: "wrapper",
|
|
10852
|
+
defaultActive: false,
|
|
10853
|
+
deviceTypes: [DeviceType.Button, DeviceType.Camera],
|
|
10854
|
+
exposesDeviceSettings: true,
|
|
10836
10855
|
methods: {},
|
|
10837
10856
|
events: {
|
|
10838
10857
|
/**
|
|
@@ -17250,6 +17269,14 @@ var ConfigEntrySchema = object({
|
|
|
17250
17269
|
value: unknown(),
|
|
17251
17270
|
description: string$2().optional()
|
|
17252
17271
|
});
|
|
17272
|
+
var DeviceLinkModeSchema = _enum(["auto", "manual"]);
|
|
17273
|
+
/** One resolved linked device — the compact projection consumers need. */
|
|
17274
|
+
var LinkedDeviceSchema = object({
|
|
17275
|
+
deviceId: number(),
|
|
17276
|
+
name: string$2(),
|
|
17277
|
+
location: string$2().nullable(),
|
|
17278
|
+
features: array(string$2())
|
|
17279
|
+
});
|
|
17253
17280
|
var SavedDeviceRowSchema = object({
|
|
17254
17281
|
/** Numeric id reserved at allocateDeviceId time. */
|
|
17255
17282
|
id: number(),
|
|
@@ -17471,7 +17498,10 @@ method(object({
|
|
|
17471
17498
|
}), _void(), {
|
|
17472
17499
|
kind: "mutation",
|
|
17473
17500
|
auth: "admin"
|
|
17474
|
-
}), method(object({ addonId: string$2() }), array(SavedDeviceRowSchema)), method(object({ addonId: string$2().optional() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }),
|
|
17501
|
+
}), method(object({ addonId: string$2() }), array(SavedDeviceRowSchema)), method(object({ addonId: string$2().optional() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), object({
|
|
17502
|
+
mode: DeviceLinkModeSchema,
|
|
17503
|
+
devices: array(LinkedDeviceSchema)
|
|
17504
|
+
})), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
|
|
17475
17505
|
deviceId: number(),
|
|
17476
17506
|
values: record(string$2(), unknown())
|
|
17477
17507
|
}), object({ success: literal(true) }), {
|
|
@@ -18740,6 +18770,61 @@ var EventKindSchema = _enum([
|
|
|
18740
18770
|
"object",
|
|
18741
18771
|
"audio"
|
|
18742
18772
|
]);
|
|
18773
|
+
/**
|
|
18774
|
+
* Spatial filter for `listTracks` — the rect + polygon variants of the shared
|
|
18775
|
+
* MaskShape vocabulary (see `mask-shape.ts`). Coordinates are NORMALIZED 0..1
|
|
18776
|
+
* of the camera frame (top-left origin), matching the drawing-plane editor.
|
|
18777
|
+
*/
|
|
18778
|
+
var TrackZoneFilterSchema = discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
|
|
18779
|
+
/** Closed icon vocabulary so clients render a known glyph per kind. */
|
|
18780
|
+
var EventKindIconSchema = _enum([
|
|
18781
|
+
"motion",
|
|
18782
|
+
"audio",
|
|
18783
|
+
"person",
|
|
18784
|
+
"vehicle",
|
|
18785
|
+
"animal",
|
|
18786
|
+
"door",
|
|
18787
|
+
"pir",
|
|
18788
|
+
"smoke",
|
|
18789
|
+
"water",
|
|
18790
|
+
"button",
|
|
18791
|
+
"generic"
|
|
18792
|
+
]);
|
|
18793
|
+
var EventKindCategorySchema = _enum([
|
|
18794
|
+
"motion",
|
|
18795
|
+
"audio",
|
|
18796
|
+
"detection",
|
|
18797
|
+
"sensor",
|
|
18798
|
+
"custom"
|
|
18799
|
+
]);
|
|
18800
|
+
var EventKindDescriptorSchema = object({
|
|
18801
|
+
/** Stable kind id (e.g. 'motion', 'person', 'contact'). */
|
|
18802
|
+
kind: string$2(),
|
|
18803
|
+
label: string$2(),
|
|
18804
|
+
/** Hex color for timeline/legend rendering. */
|
|
18805
|
+
color: string$2(),
|
|
18806
|
+
icon: EventKindIconSchema,
|
|
18807
|
+
category: EventKindCategorySchema,
|
|
18808
|
+
/** Which cap + device contributes this kind. For built-ins the camera
|
|
18809
|
+
* itself; for sensor kinds the LINKED source device. */
|
|
18810
|
+
source: object({
|
|
18811
|
+
capName: string$2(),
|
|
18812
|
+
deviceId: number()
|
|
18813
|
+
})
|
|
18814
|
+
});
|
|
18815
|
+
var SensorEventSchema = object({
|
|
18816
|
+
id: string$2(),
|
|
18817
|
+
/** The CAMERA the event is attributed to (a sensor linked to N cameras
|
|
18818
|
+
* yields N rows, one per camera). */
|
|
18819
|
+
deviceId: number(),
|
|
18820
|
+
/** The linked sensor device whose state changed. */
|
|
18821
|
+
sourceDeviceId: number(),
|
|
18822
|
+
/** Event kind id — matches an `EventKindDescriptor.kind`. */
|
|
18823
|
+
kind: string$2(),
|
|
18824
|
+
/** Snapshot of the sensor cap's runtime-state slice at the change. */
|
|
18825
|
+
value: record(string$2(), unknown()).nullable(),
|
|
18826
|
+
timestamp: number()
|
|
18827
|
+
});
|
|
18743
18828
|
var TrackPositionSchema = object({
|
|
18744
18829
|
x: number(),
|
|
18745
18830
|
y: number(),
|
|
@@ -18753,6 +18838,30 @@ var TrackSnapshotSchema = object({
|
|
|
18753
18838
|
mediaKey: string$2()
|
|
18754
18839
|
});
|
|
18755
18840
|
/**
|
|
18841
|
+
* Normalized 0..1 trajectory envelope (min/max over every position bbox,
|
|
18842
|
+
* divided by the track's detection-frame dims), computed at persist time.
|
|
18843
|
+
* Absent when the frame dims were unknown when the track was persisted
|
|
18844
|
+
* (legacy rows / dims-less sources) and on active (in-RAM) tracks.
|
|
18845
|
+
*/
|
|
18846
|
+
var TrackEnvelopeSchema = object({
|
|
18847
|
+
minX: number(),
|
|
18848
|
+
minY: number(),
|
|
18849
|
+
maxX: number(),
|
|
18850
|
+
maxY: number()
|
|
18851
|
+
});
|
|
18852
|
+
/**
|
|
18853
|
+
* Row projection for track list queries. `full` (default) returns the
|
|
18854
|
+
* complete Track including the frame-rate `positions[]` history and the
|
|
18855
|
+
* `snapshots[]` references — megabytes across a page of tracks. `slim`
|
|
18856
|
+
* keeps every scalar the list surfaces actually render (ids, class(es),
|
|
18857
|
+
* label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
|
|
18858
|
+
* zonesVisited, bestEventId, envelope) and returns `positions` /
|
|
18859
|
+
* `snapshots` as EMPTY arrays — detail views re-fetch the full row via
|
|
18860
|
+
* `getTrack`. Mirrors the event-store `projection` convention
|
|
18861
|
+
* (`getObjectEvents` et al.).
|
|
18862
|
+
*/
|
|
18863
|
+
var TrackProjectionSchema = _enum(["full", "slim"]);
|
|
18864
|
+
/**
|
|
18756
18865
|
* One audio-classification label heard on the track's camera while the
|
|
18757
18866
|
* track was alive, aggregated per label. An "episode" is one persisted
|
|
18758
18867
|
* audio event (the confident-classification path: score ≥ the device's
|
|
@@ -18803,7 +18912,11 @@ var TrackSchema = object({
|
|
|
18803
18912
|
/** Audio-classification labels heard on the camera during the track's
|
|
18804
18913
|
* life (score ≥ device `classificationMinScore`), aggregated per label.
|
|
18805
18914
|
* Absent on legacy rows / tracks with no confident audio. */
|
|
18806
|
-
audioLabels: array(TrackAudioLabelSchema).readonly().optional()
|
|
18915
|
+
audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
|
|
18916
|
+
/** Normalized 0..1 trajectory envelope (see {@link TrackEnvelopeSchema}).
|
|
18917
|
+
* Populated from the persisted envelope columns on historical reads;
|
|
18918
|
+
* absent on legacy rows, dims-less tracks and active (in-RAM) tracks. */
|
|
18919
|
+
envelope: TrackEnvelopeSchema.optional()
|
|
18807
18920
|
});
|
|
18808
18921
|
var BaseEventFields = {
|
|
18809
18922
|
id: string$2(),
|
|
@@ -18913,11 +19026,13 @@ var MediaFileSchema = object({
|
|
|
18913
19026
|
sizeBytes: number(),
|
|
18914
19027
|
timestamp: number()
|
|
18915
19028
|
});
|
|
19029
|
+
var DEFAULT_EVENT_QUERY_LIMIT = 1e3;
|
|
19030
|
+
var MAX_EVENT_QUERY_LIMIT = 5e3;
|
|
18916
19031
|
var DeviceEventQueryInput = object({
|
|
18917
19032
|
deviceId: number(),
|
|
18918
19033
|
since: number().optional(),
|
|
18919
19034
|
until: number().optional(),
|
|
18920
|
-
limit: number().int().min(1).max(
|
|
19035
|
+
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT),
|
|
18921
19036
|
/** `slim` drops heavy JSON fields (regions/bbox/zones) and carries an
|
|
18922
19037
|
* optional `mediaUrl` (populated by B5). `full` (default) keeps today's
|
|
18923
19038
|
* exact behaviour. Callers may omit this field — the store defaults to
|
|
@@ -18925,6 +19040,27 @@ var DeviceEventQueryInput = object({
|
|
|
18925
19040
|
projection: _enum(["full", "slim"]).optional()
|
|
18926
19041
|
});
|
|
18927
19042
|
var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string$2().optional() });
|
|
19043
|
+
var RecentTracksQueryInput = object({
|
|
19044
|
+
/** Devices to merge. An empty array yields `{ tracks: [], nextCursor: null }`. */
|
|
19045
|
+
deviceIds: array(number()),
|
|
19046
|
+
/** Window lower bound on `lastSeen` (inclusive). */
|
|
19047
|
+
since: number().optional(),
|
|
19048
|
+
/** Window upper bound on `lastSeen` (inclusive). */
|
|
19049
|
+
until: number().optional(),
|
|
19050
|
+
/** Page size. Default 200, max 1000. */
|
|
19051
|
+
limit: number().int().min(1).max(1e3).default(200),
|
|
19052
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`.
|
|
19053
|
+
* Encodes the (lastSeen, trackId) sort position — treat as opaque. */
|
|
19054
|
+
cursor: string$2().optional(),
|
|
19055
|
+
/** See {@link TrackProjectionSchema}. Default `full`. */
|
|
19056
|
+
projection: TrackProjectionSchema.optional()
|
|
19057
|
+
});
|
|
19058
|
+
var RecentTracksPageSchema = object({
|
|
19059
|
+
/** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
|
|
19060
|
+
tracks: array(TrackSchema).readonly(),
|
|
19061
|
+
/** Cursor for the next page, or null when this page is the last. */
|
|
19062
|
+
nextCursor: string$2().nullable()
|
|
19063
|
+
});
|
|
18928
19064
|
var KeyEventQueryInput = object({
|
|
18929
19065
|
deviceId: number(),
|
|
18930
19066
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
@@ -19007,11 +19143,25 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19007
19143
|
deviceId: number(),
|
|
19008
19144
|
since: number().optional(),
|
|
19009
19145
|
until: number().optional(),
|
|
19010
|
-
limit: number().optional()
|
|
19011
|
-
|
|
19146
|
+
limit: number().optional(),
|
|
19147
|
+
/** Spatial filter — only tracks whose trajectory intersects the zone
|
|
19148
|
+
* (normalized 0..1 rect or polygon). SQL-prefiltered on the persisted
|
|
19149
|
+
* envelope columns, then precisely tested per position. Tracks with
|
|
19150
|
+
* an unknown envelope (no frame dims at persist time) always match. */
|
|
19151
|
+
zone: TrackZoneFilterSchema.optional(),
|
|
19152
|
+
/** See {@link TrackProjectionSchema}. Default `full` (backward
|
|
19153
|
+
* compatible — omitting the field keeps today's exact behaviour). */
|
|
19154
|
+
projection: TrackProjectionSchema.optional()
|
|
19155
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
|
|
19012
19156
|
kind: "mutation",
|
|
19013
19157
|
auth: "admin"
|
|
19014
|
-
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(
|
|
19158
|
+
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({
|
|
19159
|
+
deviceId: number(),
|
|
19160
|
+
since: number().optional(),
|
|
19161
|
+
until: number().optional(),
|
|
19162
|
+
kinds: array(string$2()).optional(),
|
|
19163
|
+
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
|
|
19164
|
+
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
|
|
19015
19165
|
deviceId: number(),
|
|
19016
19166
|
since: number(),
|
|
19017
19167
|
until: number(),
|
|
@@ -22229,7 +22379,12 @@ var RecordingStorageUsageSchema = object({
|
|
|
22229
22379
|
/**
|
|
22230
22380
|
* Result of locating footage at a wall-clock instant for one device/profile.
|
|
22231
22381
|
* `segment` carries the covering segment's window; `gap` reports the forward
|
|
22232
|
-
* nearest covered edge (`null` past the end of footage / when none exists)
|
|
22382
|
+
* nearest covered edge (`null` past the end of footage / when none exists)
|
|
22383
|
+
* and the backward covered edge `prevEndMs` (exclusive end of the nearest
|
|
22384
|
+
* footage behind the epoch; `null` when none — optional so older providers
|
|
22385
|
+
* that omit it stay valid). `prevEndMs` lets a backward frame-step hop the
|
|
22386
|
+
* small inter-segment cracks (durMs under-covers the span to the next
|
|
22387
|
+
* startMs by ~11-17 ms) instead of no-opping at a segment head.
|
|
22233
22388
|
*/
|
|
22234
22389
|
var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
|
|
22235
22390
|
kind: literal("segment"),
|
|
@@ -22238,7 +22393,8 @@ var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
|
|
|
22238
22393
|
bytes: number()
|
|
22239
22394
|
}), object({
|
|
22240
22395
|
kind: literal("gap"),
|
|
22241
|
-
nearestEdgeMs: number().nullable()
|
|
22396
|
+
nearestEdgeMs: number().nullable(),
|
|
22397
|
+
prevEndMs: number().nullable().optional()
|
|
22242
22398
|
})]);
|
|
22243
22399
|
/** Raw bytes of one finalized footage segment (read off disk on the recording node). */
|
|
22244
22400
|
var ReadSegmentBytesResultSchema = object({ data: _instanceof(Uint8Array) });
|
|
@@ -23807,6 +23963,12 @@ Object.freeze({
|
|
|
23807
23963
|
addonId: null,
|
|
23808
23964
|
access: "view"
|
|
23809
23965
|
},
|
|
23966
|
+
"deviceManager.getLinkedDevices": {
|
|
23967
|
+
capName: "device-manager",
|
|
23968
|
+
capScope: "system",
|
|
23969
|
+
addonId: null,
|
|
23970
|
+
access: "view"
|
|
23971
|
+
},
|
|
23810
23972
|
"deviceManager.getRoleDisplayDefaults": {
|
|
23811
23973
|
capName: "device-manager",
|
|
23812
23974
|
capScope: "system",
|
|
@@ -25361,6 +25523,12 @@ Object.freeze({
|
|
|
25361
25523
|
addonId: null,
|
|
25362
25524
|
access: "view"
|
|
25363
25525
|
},
|
|
25526
|
+
"pipelineAnalytics.getSensorEvents": {
|
|
25527
|
+
capName: "pipeline-analytics",
|
|
25528
|
+
capScope: "device",
|
|
25529
|
+
addonId: null,
|
|
25530
|
+
access: "view"
|
|
25531
|
+
},
|
|
25364
25532
|
"pipelineAnalytics.getTrack": {
|
|
25365
25533
|
capName: "pipeline-analytics",
|
|
25366
25534
|
capScope: "device",
|
|
@@ -25373,6 +25541,18 @@ Object.freeze({
|
|
|
25373
25541
|
addonId: null,
|
|
25374
25542
|
access: "view"
|
|
25375
25543
|
},
|
|
25544
|
+
"pipelineAnalytics.listEventKinds": {
|
|
25545
|
+
capName: "pipeline-analytics",
|
|
25546
|
+
capScope: "device",
|
|
25547
|
+
addonId: null,
|
|
25548
|
+
access: "view"
|
|
25549
|
+
},
|
|
25550
|
+
"pipelineAnalytics.listRecentTracks": {
|
|
25551
|
+
capName: "pipeline-analytics",
|
|
25552
|
+
capScope: "device",
|
|
25553
|
+
addonId: null,
|
|
25554
|
+
access: "view"
|
|
25555
|
+
},
|
|
25376
25556
|
"pipelineAnalytics.listTracks": {
|
|
25377
25557
|
capName: "pipeline-analytics",
|
|
25378
25558
|
capScope: "device",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-matter-broker",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.21",
|
|
4
4
|
"description": "Matter broker addon for CamStack — owns a Matter fabric (commissioning + the long-lived controller) via the matter.js controller and brokers commissioned Matter nodes into CamStack",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|