@camstack/addon-provider-rademacher 0.1.9 → 0.1.10
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
|
@@ -984,7 +984,7 @@ var Rademacher = class {
|
|
|
984
984
|
}
|
|
985
985
|
};
|
|
986
986
|
//#endregion
|
|
987
|
-
//#region ../types/dist/event-category-
|
|
987
|
+
//#region ../types/dist/event-category-H4AVePnn.mjs
|
|
988
988
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
989
989
|
EventCategory["SystemBoot"] = "system.boot";
|
|
990
990
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -1134,6 +1134,9 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
1134
1134
|
EventCategory["RecordingSegmentWritten"] = "recording.segment.written";
|
|
1135
1135
|
EventCategory["RecordingPolicyFallback"] = "recording.policy.fallback";
|
|
1136
1136
|
EventCategory["RecordingRetentionCompleted"] = "recording.retention.completed";
|
|
1137
|
+
/** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
|
|
1138
|
+
* thumb is a scrub gap the recorder's keyframe backfill covers. */
|
|
1139
|
+
EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
|
|
1137
1140
|
EventCategory["DetectionEvent"] = "detection.event";
|
|
1138
1141
|
EventCategory["SessionTrackNew"] = "session.track.new";
|
|
1139
1142
|
EventCategory["SessionTrackExpired"] = "session.track.expired";
|
|
@@ -11781,10 +11784,23 @@ var deviceDiscoveryCapability = {
|
|
|
11781
11784
|
}
|
|
11782
11785
|
};
|
|
11783
11786
|
/**
|
|
11784
|
-
* Doorbell button cap.
|
|
11785
|
-
*
|
|
11786
|
-
*
|
|
11787
|
-
*
|
|
11787
|
+
* Doorbell button cap. Two kinds of providers coexist behind this cap
|
|
11788
|
+
* name (same pattern as `snapshot`):
|
|
11789
|
+
*
|
|
11790
|
+
* - **Native** providers: registered per-device by device-driver
|
|
11791
|
+
* addons via `ctx.registerNativeCap` — either on a
|
|
11792
|
+
* `DeviceType.Button` accessory with `role: DeviceRole.Doorbell`,
|
|
11793
|
+
* or directly on the camera (Reolink registers at camera level).
|
|
11794
|
+
* Emits an `onPressed` event every time the firmware pushes a
|
|
11795
|
+
* ring; status tracks the last press and a pressCount since start
|
|
11796
|
+
* (diagnostic).
|
|
11797
|
+
*
|
|
11798
|
+
* - **Wrapper** provider: the `virtual-doorbell` system builtin
|
|
11799
|
+
* (`@camstack/system/builtins/doorbell`). Turns ANY binary-ish
|
|
11800
|
+
* device (contact / switch / event-emitter …) into a doorbell for
|
|
11801
|
+
* a camera. `defaultActive: false` — the operator explicitly binds
|
|
11802
|
+
* it per camera in the device-bindings UI, then picks the source
|
|
11803
|
+
* device + trigger in the per-device settings.
|
|
11788
11804
|
*
|
|
11789
11805
|
* The DeviceEventPropagator re-emits `onPressed` on the camera parent
|
|
11790
11806
|
* — subscribers listening at the camera level receive ring events
|
|
@@ -11805,7 +11821,10 @@ var doorbellCapability = {
|
|
|
11805
11821
|
scope: "device",
|
|
11806
11822
|
deviceNative: true,
|
|
11807
11823
|
mode: "singleton",
|
|
11808
|
-
|
|
11824
|
+
kind: "wrapper",
|
|
11825
|
+
defaultActive: false,
|
|
11826
|
+
deviceTypes: [DeviceType.Button, DeviceType.Camera],
|
|
11827
|
+
exposesDeviceSettings: true,
|
|
11809
11828
|
methods: {},
|
|
11810
11829
|
events: {
|
|
11811
11830
|
/**
|
|
@@ -18157,6 +18176,14 @@ var ConfigEntrySchema = object({
|
|
|
18157
18176
|
value: unknown(),
|
|
18158
18177
|
description: string().optional()
|
|
18159
18178
|
});
|
|
18179
|
+
var DeviceLinkModeSchema = _enum(["auto", "manual"]);
|
|
18180
|
+
/** One resolved linked device — the compact projection consumers need. */
|
|
18181
|
+
var LinkedDeviceSchema = object({
|
|
18182
|
+
deviceId: number(),
|
|
18183
|
+
name: string(),
|
|
18184
|
+
location: string().nullable(),
|
|
18185
|
+
features: array(string())
|
|
18186
|
+
});
|
|
18160
18187
|
var SavedDeviceRowSchema = object({
|
|
18161
18188
|
/** Numeric id reserved at allocateDeviceId time. */
|
|
18162
18189
|
id: number(),
|
|
@@ -18378,7 +18405,10 @@ method(object({
|
|
|
18378
18405
|
}), _void(), {
|
|
18379
18406
|
kind: "mutation",
|
|
18380
18407
|
auth: "admin"
|
|
18381
|
-
}), 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() }),
|
|
18408
|
+
}), 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({
|
|
18409
|
+
mode: DeviceLinkModeSchema,
|
|
18410
|
+
devices: array(LinkedDeviceSchema)
|
|
18411
|
+
})), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
|
|
18382
18412
|
deviceId: number(),
|
|
18383
18413
|
values: record(string(), unknown())
|
|
18384
18414
|
}), object({ success: literal(true) }), {
|
|
@@ -19647,6 +19677,61 @@ var EventKindSchema = _enum([
|
|
|
19647
19677
|
"object",
|
|
19648
19678
|
"audio"
|
|
19649
19679
|
]);
|
|
19680
|
+
/**
|
|
19681
|
+
* Spatial filter for `listTracks` — the rect + polygon variants of the shared
|
|
19682
|
+
* MaskShape vocabulary (see `mask-shape.ts`). Coordinates are NORMALIZED 0..1
|
|
19683
|
+
* of the camera frame (top-left origin), matching the drawing-plane editor.
|
|
19684
|
+
*/
|
|
19685
|
+
var TrackZoneFilterSchema = discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
|
|
19686
|
+
/** Closed icon vocabulary so clients render a known glyph per kind. */
|
|
19687
|
+
var EventKindIconSchema = _enum([
|
|
19688
|
+
"motion",
|
|
19689
|
+
"audio",
|
|
19690
|
+
"person",
|
|
19691
|
+
"vehicle",
|
|
19692
|
+
"animal",
|
|
19693
|
+
"door",
|
|
19694
|
+
"pir",
|
|
19695
|
+
"smoke",
|
|
19696
|
+
"water",
|
|
19697
|
+
"button",
|
|
19698
|
+
"generic"
|
|
19699
|
+
]);
|
|
19700
|
+
var EventKindCategorySchema = _enum([
|
|
19701
|
+
"motion",
|
|
19702
|
+
"audio",
|
|
19703
|
+
"detection",
|
|
19704
|
+
"sensor",
|
|
19705
|
+
"custom"
|
|
19706
|
+
]);
|
|
19707
|
+
var EventKindDescriptorSchema = object({
|
|
19708
|
+
/** Stable kind id (e.g. 'motion', 'person', 'contact'). */
|
|
19709
|
+
kind: string(),
|
|
19710
|
+
label: string(),
|
|
19711
|
+
/** Hex color for timeline/legend rendering. */
|
|
19712
|
+
color: string(),
|
|
19713
|
+
icon: EventKindIconSchema,
|
|
19714
|
+
category: EventKindCategorySchema,
|
|
19715
|
+
/** Which cap + device contributes this kind. For built-ins the camera
|
|
19716
|
+
* itself; for sensor kinds the LINKED source device. */
|
|
19717
|
+
source: object({
|
|
19718
|
+
capName: string(),
|
|
19719
|
+
deviceId: number()
|
|
19720
|
+
})
|
|
19721
|
+
});
|
|
19722
|
+
var SensorEventSchema = object({
|
|
19723
|
+
id: string(),
|
|
19724
|
+
/** The CAMERA the event is attributed to (a sensor linked to N cameras
|
|
19725
|
+
* yields N rows, one per camera). */
|
|
19726
|
+
deviceId: number(),
|
|
19727
|
+
/** The linked sensor device whose state changed. */
|
|
19728
|
+
sourceDeviceId: number(),
|
|
19729
|
+
/** Event kind id — matches an `EventKindDescriptor.kind`. */
|
|
19730
|
+
kind: string(),
|
|
19731
|
+
/** Snapshot of the sensor cap's runtime-state slice at the change. */
|
|
19732
|
+
value: record(string(), unknown()).nullable(),
|
|
19733
|
+
timestamp: number()
|
|
19734
|
+
});
|
|
19650
19735
|
var TrackPositionSchema = object({
|
|
19651
19736
|
x: number(),
|
|
19652
19737
|
y: number(),
|
|
@@ -19660,6 +19745,30 @@ var TrackSnapshotSchema = object({
|
|
|
19660
19745
|
mediaKey: string()
|
|
19661
19746
|
});
|
|
19662
19747
|
/**
|
|
19748
|
+
* Normalized 0..1 trajectory envelope (min/max over every position bbox,
|
|
19749
|
+
* divided by the track's detection-frame dims), computed at persist time.
|
|
19750
|
+
* Absent when the frame dims were unknown when the track was persisted
|
|
19751
|
+
* (legacy rows / dims-less sources) and on active (in-RAM) tracks.
|
|
19752
|
+
*/
|
|
19753
|
+
var TrackEnvelopeSchema = object({
|
|
19754
|
+
minX: number(),
|
|
19755
|
+
minY: number(),
|
|
19756
|
+
maxX: number(),
|
|
19757
|
+
maxY: number()
|
|
19758
|
+
});
|
|
19759
|
+
/**
|
|
19760
|
+
* Row projection for track list queries. `full` (default) returns the
|
|
19761
|
+
* complete Track including the frame-rate `positions[]` history and the
|
|
19762
|
+
* `snapshots[]` references — megabytes across a page of tracks. `slim`
|
|
19763
|
+
* keeps every scalar the list surfaces actually render (ids, class(es),
|
|
19764
|
+
* label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
|
|
19765
|
+
* zonesVisited, bestEventId, envelope) and returns `positions` /
|
|
19766
|
+
* `snapshots` as EMPTY arrays — detail views re-fetch the full row via
|
|
19767
|
+
* `getTrack`. Mirrors the event-store `projection` convention
|
|
19768
|
+
* (`getObjectEvents` et al.).
|
|
19769
|
+
*/
|
|
19770
|
+
var TrackProjectionSchema = _enum(["full", "slim"]);
|
|
19771
|
+
/**
|
|
19663
19772
|
* One audio-classification label heard on the track's camera while the
|
|
19664
19773
|
* track was alive, aggregated per label. An "episode" is one persisted
|
|
19665
19774
|
* audio event (the confident-classification path: score ≥ the device's
|
|
@@ -19710,7 +19819,11 @@ var TrackSchema = object({
|
|
|
19710
19819
|
/** Audio-classification labels heard on the camera during the track's
|
|
19711
19820
|
* life (score ≥ device `classificationMinScore`), aggregated per label.
|
|
19712
19821
|
* Absent on legacy rows / tracks with no confident audio. */
|
|
19713
|
-
audioLabels: array(TrackAudioLabelSchema).readonly().optional()
|
|
19822
|
+
audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
|
|
19823
|
+
/** Normalized 0..1 trajectory envelope (see {@link TrackEnvelopeSchema}).
|
|
19824
|
+
* Populated from the persisted envelope columns on historical reads;
|
|
19825
|
+
* absent on legacy rows, dims-less tracks and active (in-RAM) tracks. */
|
|
19826
|
+
envelope: TrackEnvelopeSchema.optional()
|
|
19714
19827
|
});
|
|
19715
19828
|
var BaseEventFields = {
|
|
19716
19829
|
id: string(),
|
|
@@ -19820,11 +19933,13 @@ var MediaFileSchema = object({
|
|
|
19820
19933
|
sizeBytes: number(),
|
|
19821
19934
|
timestamp: number()
|
|
19822
19935
|
});
|
|
19936
|
+
var DEFAULT_EVENT_QUERY_LIMIT = 1e3;
|
|
19937
|
+
var MAX_EVENT_QUERY_LIMIT = 5e3;
|
|
19823
19938
|
var DeviceEventQueryInput = object({
|
|
19824
19939
|
deviceId: number(),
|
|
19825
19940
|
since: number().optional(),
|
|
19826
19941
|
until: number().optional(),
|
|
19827
|
-
limit: number().int().min(1).max(
|
|
19942
|
+
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT),
|
|
19828
19943
|
/** `slim` drops heavy JSON fields (regions/bbox/zones) and carries an
|
|
19829
19944
|
* optional `mediaUrl` (populated by B5). `full` (default) keeps today's
|
|
19830
19945
|
* exact behaviour. Callers may omit this field — the store defaults to
|
|
@@ -19832,6 +19947,27 @@ var DeviceEventQueryInput = object({
|
|
|
19832
19947
|
projection: _enum(["full", "slim"]).optional()
|
|
19833
19948
|
});
|
|
19834
19949
|
var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
|
|
19950
|
+
var RecentTracksQueryInput = object({
|
|
19951
|
+
/** Devices to merge. An empty array yields `{ tracks: [], nextCursor: null }`. */
|
|
19952
|
+
deviceIds: array(number()),
|
|
19953
|
+
/** Window lower bound on `lastSeen` (inclusive). */
|
|
19954
|
+
since: number().optional(),
|
|
19955
|
+
/** Window upper bound on `lastSeen` (inclusive). */
|
|
19956
|
+
until: number().optional(),
|
|
19957
|
+
/** Page size. Default 200, max 1000. */
|
|
19958
|
+
limit: number().int().min(1).max(1e3).default(200),
|
|
19959
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`.
|
|
19960
|
+
* Encodes the (lastSeen, trackId) sort position — treat as opaque. */
|
|
19961
|
+
cursor: string().optional(),
|
|
19962
|
+
/** See {@link TrackProjectionSchema}. Default `full`. */
|
|
19963
|
+
projection: TrackProjectionSchema.optional()
|
|
19964
|
+
});
|
|
19965
|
+
var RecentTracksPageSchema = object({
|
|
19966
|
+
/** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
|
|
19967
|
+
tracks: array(TrackSchema).readonly(),
|
|
19968
|
+
/** Cursor for the next page, or null when this page is the last. */
|
|
19969
|
+
nextCursor: string().nullable()
|
|
19970
|
+
});
|
|
19835
19971
|
var KeyEventQueryInput = object({
|
|
19836
19972
|
deviceId: number(),
|
|
19837
19973
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
@@ -19914,11 +20050,25 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19914
20050
|
deviceId: number(),
|
|
19915
20051
|
since: number().optional(),
|
|
19916
20052
|
until: number().optional(),
|
|
19917
|
-
limit: number().optional()
|
|
19918
|
-
|
|
20053
|
+
limit: number().optional(),
|
|
20054
|
+
/** Spatial filter — only tracks whose trajectory intersects the zone
|
|
20055
|
+
* (normalized 0..1 rect or polygon). SQL-prefiltered on the persisted
|
|
20056
|
+
* envelope columns, then precisely tested per position. Tracks with
|
|
20057
|
+
* an unknown envelope (no frame dims at persist time) always match. */
|
|
20058
|
+
zone: TrackZoneFilterSchema.optional(),
|
|
20059
|
+
/** See {@link TrackProjectionSchema}. Default `full` (backward
|
|
20060
|
+
* compatible — omitting the field keeps today's exact behaviour). */
|
|
20061
|
+
projection: TrackProjectionSchema.optional()
|
|
20062
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
|
|
19919
20063
|
kind: "mutation",
|
|
19920
20064
|
auth: "admin"
|
|
19921
|
-
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(
|
|
20065
|
+
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({
|
|
20066
|
+
deviceId: number(),
|
|
20067
|
+
since: number().optional(),
|
|
20068
|
+
until: number().optional(),
|
|
20069
|
+
kinds: array(string()).optional(),
|
|
20070
|
+
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
|
|
20071
|
+
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
|
|
19922
20072
|
deviceId: number(),
|
|
19923
20073
|
since: number(),
|
|
19924
20074
|
until: number(),
|
|
@@ -23119,7 +23269,12 @@ var RecordingStorageUsageSchema = object({
|
|
|
23119
23269
|
/**
|
|
23120
23270
|
* Result of locating footage at a wall-clock instant for one device/profile.
|
|
23121
23271
|
* `segment` carries the covering segment's window; `gap` reports the forward
|
|
23122
|
-
* nearest covered edge (`null` past the end of footage / when none exists)
|
|
23272
|
+
* nearest covered edge (`null` past the end of footage / when none exists)
|
|
23273
|
+
* and the backward covered edge `prevEndMs` (exclusive end of the nearest
|
|
23274
|
+
* footage behind the epoch; `null` when none — optional so older providers
|
|
23275
|
+
* that omit it stay valid). `prevEndMs` lets a backward frame-step hop the
|
|
23276
|
+
* small inter-segment cracks (durMs under-covers the span to the next
|
|
23277
|
+
* startMs by ~11-17 ms) instead of no-opping at a segment head.
|
|
23123
23278
|
*/
|
|
23124
23279
|
var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
|
|
23125
23280
|
kind: literal("segment"),
|
|
@@ -23128,7 +23283,8 @@ var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
|
|
|
23128
23283
|
bytes: number()
|
|
23129
23284
|
}), object({
|
|
23130
23285
|
kind: literal("gap"),
|
|
23131
|
-
nearestEdgeMs: number().nullable()
|
|
23286
|
+
nearestEdgeMs: number().nullable(),
|
|
23287
|
+
prevEndMs: number().nullable().optional()
|
|
23132
23288
|
})]);
|
|
23133
23289
|
/** Raw bytes of one finalized footage segment (read off disk on the recording node). */
|
|
23134
23290
|
var ReadSegmentBytesResultSchema = object({ data: _instanceof(Uint8Array) });
|
|
@@ -24697,6 +24853,12 @@ Object.freeze({
|
|
|
24697
24853
|
addonId: null,
|
|
24698
24854
|
access: "view"
|
|
24699
24855
|
},
|
|
24856
|
+
"deviceManager.getLinkedDevices": {
|
|
24857
|
+
capName: "device-manager",
|
|
24858
|
+
capScope: "system",
|
|
24859
|
+
addonId: null,
|
|
24860
|
+
access: "view"
|
|
24861
|
+
},
|
|
24700
24862
|
"deviceManager.getRoleDisplayDefaults": {
|
|
24701
24863
|
capName: "device-manager",
|
|
24702
24864
|
capScope: "system",
|
|
@@ -26251,6 +26413,12 @@ Object.freeze({
|
|
|
26251
26413
|
addonId: null,
|
|
26252
26414
|
access: "view"
|
|
26253
26415
|
},
|
|
26416
|
+
"pipelineAnalytics.getSensorEvents": {
|
|
26417
|
+
capName: "pipeline-analytics",
|
|
26418
|
+
capScope: "device",
|
|
26419
|
+
addonId: null,
|
|
26420
|
+
access: "view"
|
|
26421
|
+
},
|
|
26254
26422
|
"pipelineAnalytics.getTrack": {
|
|
26255
26423
|
capName: "pipeline-analytics",
|
|
26256
26424
|
capScope: "device",
|
|
@@ -26263,6 +26431,18 @@ Object.freeze({
|
|
|
26263
26431
|
addonId: null,
|
|
26264
26432
|
access: "view"
|
|
26265
26433
|
},
|
|
26434
|
+
"pipelineAnalytics.listEventKinds": {
|
|
26435
|
+
capName: "pipeline-analytics",
|
|
26436
|
+
capScope: "device",
|
|
26437
|
+
addonId: null,
|
|
26438
|
+
access: "view"
|
|
26439
|
+
},
|
|
26440
|
+
"pipelineAnalytics.listRecentTracks": {
|
|
26441
|
+
capName: "pipeline-analytics",
|
|
26442
|
+
capScope: "device",
|
|
26443
|
+
addonId: null,
|
|
26444
|
+
access: "view"
|
|
26445
|
+
},
|
|
26266
26446
|
"pipelineAnalytics.listTracks": {
|
|
26267
26447
|
capName: "pipeline-analytics",
|
|
26268
26448
|
capScope: "device",
|
package/dist/addon.mjs
CHANGED
|
@@ -983,7 +983,7 @@ var Rademacher = class {
|
|
|
983
983
|
}
|
|
984
984
|
};
|
|
985
985
|
//#endregion
|
|
986
|
-
//#region ../types/dist/event-category-
|
|
986
|
+
//#region ../types/dist/event-category-H4AVePnn.mjs
|
|
987
987
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
988
988
|
EventCategory["SystemBoot"] = "system.boot";
|
|
989
989
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -1133,6 +1133,9 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
1133
1133
|
EventCategory["RecordingSegmentWritten"] = "recording.segment.written";
|
|
1134
1134
|
EventCategory["RecordingPolicyFallback"] = "recording.policy.fallback";
|
|
1135
1135
|
EventCategory["RecordingRetentionCompleted"] = "recording.retention.completed";
|
|
1136
|
+
/** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
|
|
1137
|
+
* thumb is a scrub gap the recorder's keyframe backfill covers. */
|
|
1138
|
+
EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
|
|
1136
1139
|
EventCategory["DetectionEvent"] = "detection.event";
|
|
1137
1140
|
EventCategory["SessionTrackNew"] = "session.track.new";
|
|
1138
1141
|
EventCategory["SessionTrackExpired"] = "session.track.expired";
|
|
@@ -11780,10 +11783,23 @@ var deviceDiscoveryCapability = {
|
|
|
11780
11783
|
}
|
|
11781
11784
|
};
|
|
11782
11785
|
/**
|
|
11783
|
-
* Doorbell button cap.
|
|
11784
|
-
*
|
|
11785
|
-
*
|
|
11786
|
-
*
|
|
11786
|
+
* Doorbell button cap. Two kinds of providers coexist behind this cap
|
|
11787
|
+
* name (same pattern as `snapshot`):
|
|
11788
|
+
*
|
|
11789
|
+
* - **Native** providers: registered per-device by device-driver
|
|
11790
|
+
* addons via `ctx.registerNativeCap` — either on a
|
|
11791
|
+
* `DeviceType.Button` accessory with `role: DeviceRole.Doorbell`,
|
|
11792
|
+
* or directly on the camera (Reolink registers at camera level).
|
|
11793
|
+
* Emits an `onPressed` event every time the firmware pushes a
|
|
11794
|
+
* ring; status tracks the last press and a pressCount since start
|
|
11795
|
+
* (diagnostic).
|
|
11796
|
+
*
|
|
11797
|
+
* - **Wrapper** provider: the `virtual-doorbell` system builtin
|
|
11798
|
+
* (`@camstack/system/builtins/doorbell`). Turns ANY binary-ish
|
|
11799
|
+
* device (contact / switch / event-emitter …) into a doorbell for
|
|
11800
|
+
* a camera. `defaultActive: false` — the operator explicitly binds
|
|
11801
|
+
* it per camera in the device-bindings UI, then picks the source
|
|
11802
|
+
* device + trigger in the per-device settings.
|
|
11787
11803
|
*
|
|
11788
11804
|
* The DeviceEventPropagator re-emits `onPressed` on the camera parent
|
|
11789
11805
|
* — subscribers listening at the camera level receive ring events
|
|
@@ -11804,7 +11820,10 @@ var doorbellCapability = {
|
|
|
11804
11820
|
scope: "device",
|
|
11805
11821
|
deviceNative: true,
|
|
11806
11822
|
mode: "singleton",
|
|
11807
|
-
|
|
11823
|
+
kind: "wrapper",
|
|
11824
|
+
defaultActive: false,
|
|
11825
|
+
deviceTypes: [DeviceType.Button, DeviceType.Camera],
|
|
11826
|
+
exposesDeviceSettings: true,
|
|
11808
11827
|
methods: {},
|
|
11809
11828
|
events: {
|
|
11810
11829
|
/**
|
|
@@ -18156,6 +18175,14 @@ var ConfigEntrySchema = object({
|
|
|
18156
18175
|
value: unknown(),
|
|
18157
18176
|
description: string().optional()
|
|
18158
18177
|
});
|
|
18178
|
+
var DeviceLinkModeSchema = _enum(["auto", "manual"]);
|
|
18179
|
+
/** One resolved linked device — the compact projection consumers need. */
|
|
18180
|
+
var LinkedDeviceSchema = object({
|
|
18181
|
+
deviceId: number(),
|
|
18182
|
+
name: string(),
|
|
18183
|
+
location: string().nullable(),
|
|
18184
|
+
features: array(string())
|
|
18185
|
+
});
|
|
18159
18186
|
var SavedDeviceRowSchema = object({
|
|
18160
18187
|
/** Numeric id reserved at allocateDeviceId time. */
|
|
18161
18188
|
id: number(),
|
|
@@ -18377,7 +18404,10 @@ method(object({
|
|
|
18377
18404
|
}), _void(), {
|
|
18378
18405
|
kind: "mutation",
|
|
18379
18406
|
auth: "admin"
|
|
18380
|
-
}), 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() }),
|
|
18407
|
+
}), 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({
|
|
18408
|
+
mode: DeviceLinkModeSchema,
|
|
18409
|
+
devices: array(LinkedDeviceSchema)
|
|
18410
|
+
})), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
|
|
18381
18411
|
deviceId: number(),
|
|
18382
18412
|
values: record(string(), unknown())
|
|
18383
18413
|
}), object({ success: literal(true) }), {
|
|
@@ -19646,6 +19676,61 @@ var EventKindSchema = _enum([
|
|
|
19646
19676
|
"object",
|
|
19647
19677
|
"audio"
|
|
19648
19678
|
]);
|
|
19679
|
+
/**
|
|
19680
|
+
* Spatial filter for `listTracks` — the rect + polygon variants of the shared
|
|
19681
|
+
* MaskShape vocabulary (see `mask-shape.ts`). Coordinates are NORMALIZED 0..1
|
|
19682
|
+
* of the camera frame (top-left origin), matching the drawing-plane editor.
|
|
19683
|
+
*/
|
|
19684
|
+
var TrackZoneFilterSchema = discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
|
|
19685
|
+
/** Closed icon vocabulary so clients render a known glyph per kind. */
|
|
19686
|
+
var EventKindIconSchema = _enum([
|
|
19687
|
+
"motion",
|
|
19688
|
+
"audio",
|
|
19689
|
+
"person",
|
|
19690
|
+
"vehicle",
|
|
19691
|
+
"animal",
|
|
19692
|
+
"door",
|
|
19693
|
+
"pir",
|
|
19694
|
+
"smoke",
|
|
19695
|
+
"water",
|
|
19696
|
+
"button",
|
|
19697
|
+
"generic"
|
|
19698
|
+
]);
|
|
19699
|
+
var EventKindCategorySchema = _enum([
|
|
19700
|
+
"motion",
|
|
19701
|
+
"audio",
|
|
19702
|
+
"detection",
|
|
19703
|
+
"sensor",
|
|
19704
|
+
"custom"
|
|
19705
|
+
]);
|
|
19706
|
+
var EventKindDescriptorSchema = object({
|
|
19707
|
+
/** Stable kind id (e.g. 'motion', 'person', 'contact'). */
|
|
19708
|
+
kind: string(),
|
|
19709
|
+
label: string(),
|
|
19710
|
+
/** Hex color for timeline/legend rendering. */
|
|
19711
|
+
color: string(),
|
|
19712
|
+
icon: EventKindIconSchema,
|
|
19713
|
+
category: EventKindCategorySchema,
|
|
19714
|
+
/** Which cap + device contributes this kind. For built-ins the camera
|
|
19715
|
+
* itself; for sensor kinds the LINKED source device. */
|
|
19716
|
+
source: object({
|
|
19717
|
+
capName: string(),
|
|
19718
|
+
deviceId: number()
|
|
19719
|
+
})
|
|
19720
|
+
});
|
|
19721
|
+
var SensorEventSchema = object({
|
|
19722
|
+
id: string(),
|
|
19723
|
+
/** The CAMERA the event is attributed to (a sensor linked to N cameras
|
|
19724
|
+
* yields N rows, one per camera). */
|
|
19725
|
+
deviceId: number(),
|
|
19726
|
+
/** The linked sensor device whose state changed. */
|
|
19727
|
+
sourceDeviceId: number(),
|
|
19728
|
+
/** Event kind id — matches an `EventKindDescriptor.kind`. */
|
|
19729
|
+
kind: string(),
|
|
19730
|
+
/** Snapshot of the sensor cap's runtime-state slice at the change. */
|
|
19731
|
+
value: record(string(), unknown()).nullable(),
|
|
19732
|
+
timestamp: number()
|
|
19733
|
+
});
|
|
19649
19734
|
var TrackPositionSchema = object({
|
|
19650
19735
|
x: number(),
|
|
19651
19736
|
y: number(),
|
|
@@ -19659,6 +19744,30 @@ var TrackSnapshotSchema = object({
|
|
|
19659
19744
|
mediaKey: string()
|
|
19660
19745
|
});
|
|
19661
19746
|
/**
|
|
19747
|
+
* Normalized 0..1 trajectory envelope (min/max over every position bbox,
|
|
19748
|
+
* divided by the track's detection-frame dims), computed at persist time.
|
|
19749
|
+
* Absent when the frame dims were unknown when the track was persisted
|
|
19750
|
+
* (legacy rows / dims-less sources) and on active (in-RAM) tracks.
|
|
19751
|
+
*/
|
|
19752
|
+
var TrackEnvelopeSchema = object({
|
|
19753
|
+
minX: number(),
|
|
19754
|
+
minY: number(),
|
|
19755
|
+
maxX: number(),
|
|
19756
|
+
maxY: number()
|
|
19757
|
+
});
|
|
19758
|
+
/**
|
|
19759
|
+
* Row projection for track list queries. `full` (default) returns the
|
|
19760
|
+
* complete Track including the frame-rate `positions[]` history and the
|
|
19761
|
+
* `snapshots[]` references — megabytes across a page of tracks. `slim`
|
|
19762
|
+
* keeps every scalar the list surfaces actually render (ids, class(es),
|
|
19763
|
+
* label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
|
|
19764
|
+
* zonesVisited, bestEventId, envelope) and returns `positions` /
|
|
19765
|
+
* `snapshots` as EMPTY arrays — detail views re-fetch the full row via
|
|
19766
|
+
* `getTrack`. Mirrors the event-store `projection` convention
|
|
19767
|
+
* (`getObjectEvents` et al.).
|
|
19768
|
+
*/
|
|
19769
|
+
var TrackProjectionSchema = _enum(["full", "slim"]);
|
|
19770
|
+
/**
|
|
19662
19771
|
* One audio-classification label heard on the track's camera while the
|
|
19663
19772
|
* track was alive, aggregated per label. An "episode" is one persisted
|
|
19664
19773
|
* audio event (the confident-classification path: score ≥ the device's
|
|
@@ -19709,7 +19818,11 @@ var TrackSchema = object({
|
|
|
19709
19818
|
/** Audio-classification labels heard on the camera during the track's
|
|
19710
19819
|
* life (score ≥ device `classificationMinScore`), aggregated per label.
|
|
19711
19820
|
* Absent on legacy rows / tracks with no confident audio. */
|
|
19712
|
-
audioLabels: array(TrackAudioLabelSchema).readonly().optional()
|
|
19821
|
+
audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
|
|
19822
|
+
/** Normalized 0..1 trajectory envelope (see {@link TrackEnvelopeSchema}).
|
|
19823
|
+
* Populated from the persisted envelope columns on historical reads;
|
|
19824
|
+
* absent on legacy rows, dims-less tracks and active (in-RAM) tracks. */
|
|
19825
|
+
envelope: TrackEnvelopeSchema.optional()
|
|
19713
19826
|
});
|
|
19714
19827
|
var BaseEventFields = {
|
|
19715
19828
|
id: string(),
|
|
@@ -19819,11 +19932,13 @@ var MediaFileSchema = object({
|
|
|
19819
19932
|
sizeBytes: number(),
|
|
19820
19933
|
timestamp: number()
|
|
19821
19934
|
});
|
|
19935
|
+
var DEFAULT_EVENT_QUERY_LIMIT = 1e3;
|
|
19936
|
+
var MAX_EVENT_QUERY_LIMIT = 5e3;
|
|
19822
19937
|
var DeviceEventQueryInput = object({
|
|
19823
19938
|
deviceId: number(),
|
|
19824
19939
|
since: number().optional(),
|
|
19825
19940
|
until: number().optional(),
|
|
19826
|
-
limit: number().int().min(1).max(
|
|
19941
|
+
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT),
|
|
19827
19942
|
/** `slim` drops heavy JSON fields (regions/bbox/zones) and carries an
|
|
19828
19943
|
* optional `mediaUrl` (populated by B5). `full` (default) keeps today's
|
|
19829
19944
|
* exact behaviour. Callers may omit this field — the store defaults to
|
|
@@ -19831,6 +19946,27 @@ var DeviceEventQueryInput = object({
|
|
|
19831
19946
|
projection: _enum(["full", "slim"]).optional()
|
|
19832
19947
|
});
|
|
19833
19948
|
var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
|
|
19949
|
+
var RecentTracksQueryInput = object({
|
|
19950
|
+
/** Devices to merge. An empty array yields `{ tracks: [], nextCursor: null }`. */
|
|
19951
|
+
deviceIds: array(number()),
|
|
19952
|
+
/** Window lower bound on `lastSeen` (inclusive). */
|
|
19953
|
+
since: number().optional(),
|
|
19954
|
+
/** Window upper bound on `lastSeen` (inclusive). */
|
|
19955
|
+
until: number().optional(),
|
|
19956
|
+
/** Page size. Default 200, max 1000. */
|
|
19957
|
+
limit: number().int().min(1).max(1e3).default(200),
|
|
19958
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`.
|
|
19959
|
+
* Encodes the (lastSeen, trackId) sort position — treat as opaque. */
|
|
19960
|
+
cursor: string().optional(),
|
|
19961
|
+
/** See {@link TrackProjectionSchema}. Default `full`. */
|
|
19962
|
+
projection: TrackProjectionSchema.optional()
|
|
19963
|
+
});
|
|
19964
|
+
var RecentTracksPageSchema = object({
|
|
19965
|
+
/** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
|
|
19966
|
+
tracks: array(TrackSchema).readonly(),
|
|
19967
|
+
/** Cursor for the next page, or null when this page is the last. */
|
|
19968
|
+
nextCursor: string().nullable()
|
|
19969
|
+
});
|
|
19834
19970
|
var KeyEventQueryInput = object({
|
|
19835
19971
|
deviceId: number(),
|
|
19836
19972
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
@@ -19913,11 +20049,25 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19913
20049
|
deviceId: number(),
|
|
19914
20050
|
since: number().optional(),
|
|
19915
20051
|
until: number().optional(),
|
|
19916
|
-
limit: number().optional()
|
|
19917
|
-
|
|
20052
|
+
limit: number().optional(),
|
|
20053
|
+
/** Spatial filter — only tracks whose trajectory intersects the zone
|
|
20054
|
+
* (normalized 0..1 rect or polygon). SQL-prefiltered on the persisted
|
|
20055
|
+
* envelope columns, then precisely tested per position. Tracks with
|
|
20056
|
+
* an unknown envelope (no frame dims at persist time) always match. */
|
|
20057
|
+
zone: TrackZoneFilterSchema.optional(),
|
|
20058
|
+
/** See {@link TrackProjectionSchema}. Default `full` (backward
|
|
20059
|
+
* compatible — omitting the field keeps today's exact behaviour). */
|
|
20060
|
+
projection: TrackProjectionSchema.optional()
|
|
20061
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
|
|
19918
20062
|
kind: "mutation",
|
|
19919
20063
|
auth: "admin"
|
|
19920
|
-
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(
|
|
20064
|
+
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({
|
|
20065
|
+
deviceId: number(),
|
|
20066
|
+
since: number().optional(),
|
|
20067
|
+
until: number().optional(),
|
|
20068
|
+
kinds: array(string()).optional(),
|
|
20069
|
+
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
|
|
20070
|
+
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
|
|
19921
20071
|
deviceId: number(),
|
|
19922
20072
|
since: number(),
|
|
19923
20073
|
until: number(),
|
|
@@ -23118,7 +23268,12 @@ var RecordingStorageUsageSchema = object({
|
|
|
23118
23268
|
/**
|
|
23119
23269
|
* Result of locating footage at a wall-clock instant for one device/profile.
|
|
23120
23270
|
* `segment` carries the covering segment's window; `gap` reports the forward
|
|
23121
|
-
* nearest covered edge (`null` past the end of footage / when none exists)
|
|
23271
|
+
* nearest covered edge (`null` past the end of footage / when none exists)
|
|
23272
|
+
* and the backward covered edge `prevEndMs` (exclusive end of the nearest
|
|
23273
|
+
* footage behind the epoch; `null` when none — optional so older providers
|
|
23274
|
+
* that omit it stay valid). `prevEndMs` lets a backward frame-step hop the
|
|
23275
|
+
* small inter-segment cracks (durMs under-covers the span to the next
|
|
23276
|
+
* startMs by ~11-17 ms) instead of no-opping at a segment head.
|
|
23122
23277
|
*/
|
|
23123
23278
|
var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
|
|
23124
23279
|
kind: literal("segment"),
|
|
@@ -23127,7 +23282,8 @@ var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
|
|
|
23127
23282
|
bytes: number()
|
|
23128
23283
|
}), object({
|
|
23129
23284
|
kind: literal("gap"),
|
|
23130
|
-
nearestEdgeMs: number().nullable()
|
|
23285
|
+
nearestEdgeMs: number().nullable(),
|
|
23286
|
+
prevEndMs: number().nullable().optional()
|
|
23131
23287
|
})]);
|
|
23132
23288
|
/** Raw bytes of one finalized footage segment (read off disk on the recording node). */
|
|
23133
23289
|
var ReadSegmentBytesResultSchema = object({ data: _instanceof(Uint8Array) });
|
|
@@ -24696,6 +24852,12 @@ Object.freeze({
|
|
|
24696
24852
|
addonId: null,
|
|
24697
24853
|
access: "view"
|
|
24698
24854
|
},
|
|
24855
|
+
"deviceManager.getLinkedDevices": {
|
|
24856
|
+
capName: "device-manager",
|
|
24857
|
+
capScope: "system",
|
|
24858
|
+
addonId: null,
|
|
24859
|
+
access: "view"
|
|
24860
|
+
},
|
|
24699
24861
|
"deviceManager.getRoleDisplayDefaults": {
|
|
24700
24862
|
capName: "device-manager",
|
|
24701
24863
|
capScope: "system",
|
|
@@ -26250,6 +26412,12 @@ Object.freeze({
|
|
|
26250
26412
|
addonId: null,
|
|
26251
26413
|
access: "view"
|
|
26252
26414
|
},
|
|
26415
|
+
"pipelineAnalytics.getSensorEvents": {
|
|
26416
|
+
capName: "pipeline-analytics",
|
|
26417
|
+
capScope: "device",
|
|
26418
|
+
addonId: null,
|
|
26419
|
+
access: "view"
|
|
26420
|
+
},
|
|
26253
26421
|
"pipelineAnalytics.getTrack": {
|
|
26254
26422
|
capName: "pipeline-analytics",
|
|
26255
26423
|
capScope: "device",
|
|
@@ -26262,6 +26430,18 @@ Object.freeze({
|
|
|
26262
26430
|
addonId: null,
|
|
26263
26431
|
access: "view"
|
|
26264
26432
|
},
|
|
26433
|
+
"pipelineAnalytics.listEventKinds": {
|
|
26434
|
+
capName: "pipeline-analytics",
|
|
26435
|
+
capScope: "device",
|
|
26436
|
+
addonId: null,
|
|
26437
|
+
access: "view"
|
|
26438
|
+
},
|
|
26439
|
+
"pipelineAnalytics.listRecentTracks": {
|
|
26440
|
+
capName: "pipeline-analytics",
|
|
26441
|
+
capScope: "device",
|
|
26442
|
+
addonId: null,
|
|
26443
|
+
access: "view"
|
|
26444
|
+
},
|
|
26265
26445
|
"pipelineAnalytics.listTracks": {
|
|
26266
26446
|
capName: "pipeline-analytics",
|
|
26267
26447
|
capScope: "device",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-provider-rademacher",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
4
4
|
"description": "Rademacher HomePilot device-provider addon for CamStack — wraps the @apocaliss92/noderademacher local-hub client (roller shutters over the cover cap)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|