@camstack/addon-provider-rademacher 0.2.47 → 0.2.48
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 +246 -2
- package/dist/addon.mjs +246 -2
- package/package.json +1 -1
package/dist/addon.js
CHANGED
|
@@ -9003,6 +9003,20 @@ var RelocateJobSchema = object({
|
|
|
9003
9003
|
* in its row, not in its name, so `MediaRelocateEngine` never reconciles one.
|
|
9004
9004
|
*/
|
|
9005
9005
|
rowsReconciled: number().int().nonnegative().optional(),
|
|
9006
|
+
/**
|
|
9007
|
+
* Rows this run FORGOT because the file they name is not on disk.
|
|
9008
|
+
*
|
|
9009
|
+
* The mover derived the path from the row's own fields and `stat`ed it; an
|
|
9010
|
+
* ENOENT there is a per-path confirmation that the segment is gone (D296),
|
|
9011
|
+
* and the durable row is dropped through the same channel eviction uses. It
|
|
9012
|
+
* is reported for the same reason `rowsReconciled` is: this is a durable
|
|
9013
|
+
* mutation nobody asked for, and a migration that quietly erases hour rows is
|
|
9014
|
+
* the same failure as one that quietly skips them (D295).
|
|
9015
|
+
*
|
|
9016
|
+
* The production drain of 2026-08-30 would have reported 11 074 here — the
|
|
9017
|
+
* ledger claimed 5.65 GB of footage that no longer existed.
|
|
9018
|
+
*/
|
|
9019
|
+
rowsForgotten: number().int().nonnegative().optional(),
|
|
9006
9020
|
startedAt: number(),
|
|
9007
9021
|
finishedAt: number().nullable(),
|
|
9008
9022
|
error: string().nullable()
|
|
@@ -9366,6 +9380,91 @@ var RelocateResidueSchema = object({
|
|
|
9366
9380
|
segments: number().int().nonnegative(),
|
|
9367
9381
|
bytes: number().int().nonnegative()
|
|
9368
9382
|
}).nullable();
|
|
9383
|
+
/**
|
|
9384
|
+
* Ask one location whether its durable hour rows describe the disk — the walk
|
|
9385
|
+
* (D319).
|
|
9386
|
+
*
|
|
9387
|
+
* `apply` DEFAULTS TO FALSE and that default is the product: the operator's
|
|
9388
|
+
* missing tool is the question, and the dry run is how they sanity-check the
|
|
9389
|
+
* destructive run before authorising it.
|
|
9390
|
+
*/
|
|
9391
|
+
var LedgerWalkInputSchema = object({
|
|
9392
|
+
locationId: string().min(1),
|
|
9393
|
+
/** Forget the confirmed-absent rows, rather than only counting them. */
|
|
9394
|
+
apply: boolean().optional(),
|
|
9395
|
+
/** Narrow to one camera. */
|
|
9396
|
+
deviceId: number().int().positive().optional(),
|
|
9397
|
+
/** Narrow to these recording profiles; empty/absent = every profile. */
|
|
9398
|
+
profiles: array(string().min(1)).optional()
|
|
9399
|
+
});
|
|
9400
|
+
/** Why a whole walk did nothing. Every one leaves the ledger untouched. */
|
|
9401
|
+
var LedgerWalkRefusalSchema = _enum([
|
|
9402
|
+
"location-unknown",
|
|
9403
|
+
"source-writable",
|
|
9404
|
+
"no-ledger",
|
|
9405
|
+
"archive-unreadable",
|
|
9406
|
+
"anchor-absent",
|
|
9407
|
+
"anchor-unreadable",
|
|
9408
|
+
"anchor-moved"
|
|
9409
|
+
]);
|
|
9410
|
+
_enum([
|
|
9411
|
+
"live-tail",
|
|
9412
|
+
"listing-error",
|
|
9413
|
+
"path-mismatch",
|
|
9414
|
+
"durable-refused"
|
|
9415
|
+
]);
|
|
9416
|
+
/** Every skip reason, always present, always a number — so a reason that never
|
|
9417
|
+
* fired reports as zero rather than absent and the report shape is constant
|
|
9418
|
+
* between passes. Spelled out rather than `z.record` for exactly that. */
|
|
9419
|
+
var LedgerWalkSkipCountsSchema = object({
|
|
9420
|
+
"live-tail": number().int().nonnegative(),
|
|
9421
|
+
"listing-error": number().int().nonnegative(),
|
|
9422
|
+
"path-mismatch": number().int().nonnegative(),
|
|
9423
|
+
"durable-refused": number().int().nonnegative()
|
|
9424
|
+
});
|
|
9425
|
+
/** One camera's share of a walk, so a report names cameras and not rows. */
|
|
9426
|
+
var LedgerWalkDeviceReportSchema = object({
|
|
9427
|
+
deviceId: number().int(),
|
|
9428
|
+
hoursWalked: number().int().nonnegative(),
|
|
9429
|
+
hoursMissing: number().int().nonnegative(),
|
|
9430
|
+
ghostSegments: number().int().nonnegative(),
|
|
9431
|
+
ghostBytes: number().int().nonnegative(),
|
|
9432
|
+
forgottenSegments: number().int().nonnegative(),
|
|
9433
|
+
orphanFiles: number().int().nonnegative()
|
|
9434
|
+
});
|
|
9435
|
+
/**
|
|
9436
|
+
* What one walk claimed, listed, found and (only when armed) forgot.
|
|
9437
|
+
*
|
|
9438
|
+
* `archiveSegments` is the **M** and `segmentsClaimed` the **N** (D295), so a
|
|
9439
|
+
* walk that saw a fraction of the location is visible in its own report rather
|
|
9440
|
+
* than in the absence of one.
|
|
9441
|
+
*/
|
|
9442
|
+
var LedgerWalkReportSchema = object({
|
|
9443
|
+
locationId: string(),
|
|
9444
|
+
applied: boolean(),
|
|
9445
|
+
refused: LedgerWalkRefusalSchema.nullable(),
|
|
9446
|
+
archiveSegments: number().int().nonnegative().nullable(),
|
|
9447
|
+
archiveBytes: number().int().nonnegative().nullable(),
|
|
9448
|
+
hoursClaimed: number().int().nonnegative(),
|
|
9449
|
+
hoursWalked: number().int().nonnegative(),
|
|
9450
|
+
hoursMissing: number().int().nonnegative(),
|
|
9451
|
+
/** `readdir` calls issued — the cost, stated in the unit that is paid. */
|
|
9452
|
+
listings: number().int().nonnegative(),
|
|
9453
|
+
segmentsClaimed: number().int().nonnegative(),
|
|
9454
|
+
ghostSegments: number().int().nonnegative(),
|
|
9455
|
+
ghostBytes: number().int().nonnegative(),
|
|
9456
|
+
ghostHoursWhole: number().int().nonnegative(),
|
|
9457
|
+
forgottenSegments: number().int().nonnegative(),
|
|
9458
|
+
forgottenBytes: number().int().nonnegative(),
|
|
9459
|
+
/** Files under a claimed hour that no durable row names. Never deleted. */
|
|
9460
|
+
orphanFiles: number().int().nonnegative(),
|
|
9461
|
+
orphanSample: array(string()).readonly(),
|
|
9462
|
+
hoursSkipped: number().int().nonnegative(),
|
|
9463
|
+
skippedByReason: LedgerWalkSkipCountsSchema,
|
|
9464
|
+
/** The walk stopped at its per-pass hour bound with claims unwalked. */
|
|
9465
|
+
bounded: boolean(),
|
|
9466
|
+
byDevice: array(LedgerWalkDeviceReportSchema).readonly()
|
|
9467
|
+
});
|
|
9369
9468
|
/** How many rows a media pass would still act on against a given target — the
|
|
9370
9469
|
* media lane's denominator AND its residue, from ONE derivation so the two can
|
|
9371
9470
|
* never disagree. `null` = the count could not be taken. */
|
|
@@ -19981,13 +20080,15 @@ var ListGroupsPageSchema = object({
|
|
|
19981
20080
|
groups: array(AnalyticsGroupRecordSchema).readonly(),
|
|
19982
20081
|
nextCursor: string().nullable()
|
|
19983
20082
|
});
|
|
20083
|
+
var KEY_EVENTS_DEFAULT_LIMIT = 50;
|
|
20084
|
+
var KEY_EVENTS_MAX_LIMIT = 200;
|
|
19984
20085
|
var KeyEventQueryInput = object({
|
|
19985
20086
|
deviceId: number(),
|
|
19986
20087
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
19987
20088
|
since: number(),
|
|
19988
20089
|
/** Window upper bound (track firstSeen ≤ until). */
|
|
19989
20090
|
until: number(),
|
|
19990
|
-
limit: number().int().min(1).max(
|
|
20091
|
+
limit: number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
19991
20092
|
/** Drop tracks scoring below this importance. */
|
|
19992
20093
|
minImportance: number().min(0).max(1).optional(),
|
|
19993
20094
|
/** Restrict to a single class (e.g. 'person'). */
|
|
@@ -20009,6 +20110,32 @@ var KeyEventSchema = object({
|
|
|
20009
20110
|
...TrackFlagFields,
|
|
20010
20111
|
...TrackRetrainFields
|
|
20011
20112
|
});
|
|
20113
|
+
/** `getKeyEvents`' window and filters, asked of a SET of cameras at once. */
|
|
20114
|
+
var KeyEventBatchQueryInput = object({
|
|
20115
|
+
deviceIds: array(number()).min(1).max(200),
|
|
20116
|
+
since: number(),
|
|
20117
|
+
until: number(),
|
|
20118
|
+
/** Applied PER CAMERA, exactly as `getKeyEvents.limit` is — never a total
|
|
20119
|
+
* across the set, which would let a busy camera starve a quiet one of its
|
|
20120
|
+
* rows and change what the merged feed contains. */
|
|
20121
|
+
limit: number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
20122
|
+
minImportance: number().min(0).max(1).optional(),
|
|
20123
|
+
classFilter: string().optional()
|
|
20124
|
+
});
|
|
20125
|
+
/**
|
|
20126
|
+
* One camera's key events in a batch answer.
|
|
20127
|
+
*
|
|
20128
|
+
* The row exists for every requested id. `getKeyEvents` degrades to `[]` on
|
|
20129
|
+
* error rather than throwing, so a camera whose store read failed and one with
|
|
20130
|
+
* no events in the window were ALREADY indistinguishable per camera — the
|
|
20131
|
+
* batch does not make that worse, and the row keeps the deviceId the single
|
|
20132
|
+
* method's output never carried (the caller used to stamp it from the fan-out
|
|
20133
|
+
* key, which only worked because there was one query per camera).
|
|
20134
|
+
*/
|
|
20135
|
+
var KeyEventsForDeviceSchema = object({
|
|
20136
|
+
deviceId: number(),
|
|
20137
|
+
events: array(KeyEventSchema).readonly()
|
|
20138
|
+
});
|
|
20012
20139
|
object({
|
|
20013
20140
|
trackId: string(),
|
|
20014
20141
|
className: string(),
|
|
@@ -20278,7 +20405,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20278
20405
|
until: number().optional(),
|
|
20279
20406
|
kinds: array(string()).optional(),
|
|
20280
20407
|
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
|
|
20281
|
-
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
|
|
20408
|
+
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(KeyEventBatchQueryInput, array(KeyEventsForDeviceSchema).readonly()), method(object({
|
|
20282
20409
|
deviceId: number(),
|
|
20283
20410
|
since: number(),
|
|
20284
20411
|
until: number(),
|
|
@@ -29645,6 +29772,9 @@ method(object({
|
|
|
29645
29772
|
}), method(RelocateResidueInputSchema, RelocateResidueSchema, {
|
|
29646
29773
|
kind: "query",
|
|
29647
29774
|
auth: "admin"
|
|
29775
|
+
}), method(LedgerWalkInputSchema, LedgerWalkReportSchema, {
|
|
29776
|
+
kind: "mutation",
|
|
29777
|
+
auth: "admin"
|
|
29648
29778
|
}), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
|
|
29649
29779
|
kind: "mutation",
|
|
29650
29780
|
auth: "admin"
|
|
@@ -30036,6 +30166,25 @@ var SceneMonitorStatusSchema = object({
|
|
|
30036
30166
|
monitors: array(SceneMonitorSchema),
|
|
30037
30167
|
lastFetchedAt: number()
|
|
30038
30168
|
});
|
|
30169
|
+
/**
|
|
30170
|
+
* One camera's row in a `listScenesBatch` answer.
|
|
30171
|
+
*
|
|
30172
|
+
* `status` is NULLABLE and the nullability is the whole point. `scene-monitor`
|
|
30173
|
+
* is a `defaultActive` wrapper, so every camera is asked; a camera whose
|
|
30174
|
+
* provider is absent (pipeline-analytics not deployed, the post-processing node
|
|
30175
|
+
* down) cannot answer, and that is not the same fact as a camera with no scenes
|
|
30176
|
+
* configured. Fanned out per camera the difference was visible — one query
|
|
30177
|
+
* errored while the others resolved — and a batch that returned only the rows
|
|
30178
|
+
* it managed would have destroyed it, silently, by making an unreachable camera
|
|
30179
|
+
* indistinguishable from one that answered `monitors: []`.
|
|
30180
|
+
*
|
|
30181
|
+
* So: EVERY requested deviceId gets a row. `status: null` means "this camera
|
|
30182
|
+
* could not be read"; `status.monitors: []` means "read, and it has none".
|
|
30183
|
+
*/
|
|
30184
|
+
var SceneMonitorStatusForDeviceSchema = object({
|
|
30185
|
+
deviceId: number(),
|
|
30186
|
+
status: SceneMonitorStatusSchema.nullable()
|
|
30187
|
+
});
|
|
30039
30188
|
var sceneMonitorCapability = {
|
|
30040
30189
|
name: "scene-monitor",
|
|
30041
30190
|
scope: "device",
|
|
@@ -30045,6 +30194,22 @@ var sceneMonitorCapability = {
|
|
|
30045
30194
|
deviceTypes: [DeviceType.Camera],
|
|
30046
30195
|
methods: {
|
|
30047
30196
|
listScenes: method(object({ deviceId: number() }), SceneMonitorStatusSchema),
|
|
30197
|
+
/**
|
|
30198
|
+
* The same answer, for a SET of cameras, in one round trip.
|
|
30199
|
+
*
|
|
30200
|
+
* `/scenes` renders every camera and re-reads them on a 30s safety-net
|
|
30201
|
+
* poll behind the push slice. Fanned out client-side that was one query
|
|
30202
|
+
* per camera — 29 round trips through the browser, the hub and the
|
|
30203
|
+
* post-analysis runner every 30 seconds to read an in-memory map the
|
|
30204
|
+
* owner had already merged. The work is unchanged (`statusFor` per
|
|
30205
|
+
* device, all in-process at the owner); what collapses is the transport.
|
|
30206
|
+
*
|
|
30207
|
+
* A camera that cannot answer still gets a row, with `status: null` —
|
|
30208
|
+
* see {@link SceneMonitorStatusForDeviceSchema}. Never fewer rows than
|
|
30209
|
+
* ids: a caller that asked for twenty-nine and got twenty-seven cannot
|
|
30210
|
+
* tell which two are missing, or that any are.
|
|
30211
|
+
*/
|
|
30212
|
+
listScenesBatch: method(object({ deviceIds: array(number()).min(1).max(200) }), array(SceneMonitorStatusForDeviceSchema).readonly()),
|
|
30048
30213
|
createScene: method(object({
|
|
30049
30214
|
deviceId: number(),
|
|
30050
30215
|
label: string(),
|
|
@@ -31880,6 +32045,27 @@ var CameraOccupancySnapshotSchema = object({
|
|
|
31880
32045
|
stationaryObjects: array(StationaryObjectSchema).readonly().optional()
|
|
31881
32046
|
});
|
|
31882
32047
|
/**
|
|
32048
|
+
* One camera's row in a `getCurrentSnapshotBatch` answer.
|
|
32049
|
+
*
|
|
32050
|
+
* THREE outcomes, and the single-camera method could only express two of them
|
|
32051
|
+
* because `snapshot: null` was already spoken for:
|
|
32052
|
+
*
|
|
32053
|
+
* - `read: 'read'`, `snapshot` present — the live occupancy reading.
|
|
32054
|
+
* - `read: 'read'`, `snapshot: null` — read, and this camera has no reading
|
|
32055
|
+
* yet: no frame since boot, and no parked-object registry to hydrate from.
|
|
32056
|
+
* - `read: 'unreadable'` — the owner could not answer for this
|
|
32057
|
+
* camera. `snapshot` is null, and it does NOT mean "nothing parked here".
|
|
32058
|
+
*
|
|
32059
|
+
* Collapsing the last two is the failure this field exists to prevent: a
|
|
32060
|
+
* hydration that threw would otherwise render as an empty Stationary section,
|
|
32061
|
+
* which is a definite claim about a camera nobody could read.
|
|
32062
|
+
*/
|
|
32063
|
+
var CameraOccupancySnapshotForDeviceSchema = object({
|
|
32064
|
+
deviceId: number(),
|
|
32065
|
+
read: _enum(["read", "unreadable"]),
|
|
32066
|
+
snapshot: CameraOccupancySnapshotSchema.nullable()
|
|
32067
|
+
});
|
|
32068
|
+
/**
|
|
31883
32069
|
* Time-series resolution. The history methods return one bucket per
|
|
31884
32070
|
* step over the requested range. Smaller resolutions cost more
|
|
31885
32071
|
* memory + bandwidth; bound to discrete steps so caller cannot ask
|
|
@@ -31936,6 +32122,20 @@ var zoneAnalyticsCapability = {
|
|
|
31936
32122
|
* (no inference result emitted since boot or since binding was
|
|
31937
32123
|
* activated). */
|
|
31938
32124
|
getCurrentSnapshot: method(object({ deviceId: number() }), CameraOccupancySnapshotSchema.nullable()),
|
|
32125
|
+
/**
|
|
32126
|
+
* The same snapshot, for a SET of cameras, in one round trip.
|
|
32127
|
+
*
|
|
32128
|
+
* The Events page's Stationary section polls this every 15s for every
|
|
32129
|
+
* selected camera. Fanned out client-side that is one query per camera to
|
|
32130
|
+
* read a `Map.get` at the owner — the answer costs nothing, the round trip
|
|
32131
|
+
* costs everything. Batched, N transports become one and the per-device
|
|
32132
|
+
* work is unchanged.
|
|
32133
|
+
*
|
|
32134
|
+
* Every requested deviceId gets a row, tagged `read` — see
|
|
32135
|
+
* {@link CameraOccupancySnapshotForDeviceSchema}. A camera the owner could
|
|
32136
|
+
* not answer for is `'unreadable'`, never an empty reading.
|
|
32137
|
+
*/
|
|
32138
|
+
getCurrentSnapshotBatch: method(object({ deviceIds: array(number()).min(1).max(200) }), array(CameraOccupancySnapshotForDeviceSchema).readonly()),
|
|
31939
32139
|
/** Time-series object count inside one zone. `className` optional —
|
|
31940
32140
|
* omit to count every class in the zone. */
|
|
31941
32141
|
getZoneHistory: method(object({
|
|
@@ -36357,6 +36557,12 @@ Object.freeze({
|
|
|
36357
36557
|
addonId: null,
|
|
36358
36558
|
access: "view"
|
|
36359
36559
|
},
|
|
36560
|
+
"pipelineAnalytics.getKeyEventsBatch": {
|
|
36561
|
+
capName: "pipeline-analytics",
|
|
36562
|
+
capScope: "device",
|
|
36563
|
+
addonId: null,
|
|
36564
|
+
access: "view"
|
|
36565
|
+
},
|
|
36360
36566
|
"pipelineAnalytics.getMotionEvents": {
|
|
36361
36567
|
capName: "pipeline-analytics",
|
|
36362
36568
|
capScope: "device",
|
|
@@ -37533,6 +37739,12 @@ Object.freeze({
|
|
|
37533
37739
|
addonId: null,
|
|
37534
37740
|
access: "view"
|
|
37535
37741
|
},
|
|
37742
|
+
"recording.reconcileLedgerAgainstDisk": {
|
|
37743
|
+
capName: "recording",
|
|
37744
|
+
capScope: "system",
|
|
37745
|
+
addonId: null,
|
|
37746
|
+
access: "create"
|
|
37747
|
+
},
|
|
37536
37748
|
"recording.refreshStorageLocationsForMigration": {
|
|
37537
37749
|
capName: "recording",
|
|
37538
37750
|
capScope: "system",
|
|
@@ -37659,6 +37871,12 @@ Object.freeze({
|
|
|
37659
37871
|
addonId: null,
|
|
37660
37872
|
access: "view"
|
|
37661
37873
|
},
|
|
37874
|
+
"sceneMonitor.listScenesBatch": {
|
|
37875
|
+
capName: "scene-monitor",
|
|
37876
|
+
capScope: "device",
|
|
37877
|
+
addonId: null,
|
|
37878
|
+
access: "view"
|
|
37879
|
+
},
|
|
37662
37880
|
"sceneMonitor.recheckNow": {
|
|
37663
37881
|
capName: "scene-monitor",
|
|
37664
37882
|
capScope: "device",
|
|
@@ -39015,6 +39233,12 @@ Object.freeze({
|
|
|
39015
39233
|
addonId: null,
|
|
39016
39234
|
access: "view"
|
|
39017
39235
|
},
|
|
39236
|
+
"zoneAnalytics.getCurrentSnapshotBatch": {
|
|
39237
|
+
capName: "zone-analytics",
|
|
39238
|
+
capScope: "device",
|
|
39239
|
+
addonId: null,
|
|
39240
|
+
access: "view"
|
|
39241
|
+
},
|
|
39018
39242
|
"zoneAnalytics.getUnzonedHistory": {
|
|
39019
39243
|
capName: "zone-analytics",
|
|
39020
39244
|
capScope: "device",
|
|
@@ -40019,6 +40243,11 @@ Object.freeze({
|
|
|
40019
40243
|
form: "single",
|
|
40020
40244
|
optional: false
|
|
40021
40245
|
}],
|
|
40246
|
+
"pipelineAnalytics.getKeyEventsBatch": [{
|
|
40247
|
+
name: "deviceIds",
|
|
40248
|
+
form: "array",
|
|
40249
|
+
optional: false
|
|
40250
|
+
}],
|
|
40022
40251
|
"pipelineAnalytics.getMotionEvents": [{
|
|
40023
40252
|
name: "deviceId",
|
|
40024
40253
|
form: "single",
|
|
@@ -40459,6 +40688,11 @@ Object.freeze({
|
|
|
40459
40688
|
form: "single",
|
|
40460
40689
|
optional: false
|
|
40461
40690
|
}],
|
|
40691
|
+
"recording.reconcileLedgerAgainstDisk": [{
|
|
40692
|
+
name: "deviceId",
|
|
40693
|
+
form: "single",
|
|
40694
|
+
optional: true
|
|
40695
|
+
}],
|
|
40462
40696
|
"recording.relocateFootage": [{
|
|
40463
40697
|
name: "deviceId",
|
|
40464
40698
|
form: "single",
|
|
@@ -40524,6 +40758,11 @@ Object.freeze({
|
|
|
40524
40758
|
form: "single",
|
|
40525
40759
|
optional: false
|
|
40526
40760
|
}],
|
|
40761
|
+
"sceneMonitor.listScenesBatch": [{
|
|
40762
|
+
name: "deviceIds",
|
|
40763
|
+
form: "array",
|
|
40764
|
+
optional: false
|
|
40765
|
+
}],
|
|
40527
40766
|
"sceneMonitor.recheckNow": [{
|
|
40528
40767
|
name: "deviceId",
|
|
40529
40768
|
form: "single",
|
|
@@ -40785,6 +41024,11 @@ Object.freeze({
|
|
|
40785
41024
|
form: "single",
|
|
40786
41025
|
optional: false
|
|
40787
41026
|
}],
|
|
41027
|
+
"zoneAnalytics.getCurrentSnapshotBatch": [{
|
|
41028
|
+
name: "deviceIds",
|
|
41029
|
+
form: "array",
|
|
41030
|
+
optional: false
|
|
41031
|
+
}],
|
|
40788
41032
|
"zoneAnalytics.getUnzonedHistory": [{
|
|
40789
41033
|
name: "deviceId",
|
|
40790
41034
|
form: "single",
|
package/dist/addon.mjs
CHANGED
|
@@ -9002,6 +9002,20 @@ var RelocateJobSchema = object({
|
|
|
9002
9002
|
* in its row, not in its name, so `MediaRelocateEngine` never reconciles one.
|
|
9003
9003
|
*/
|
|
9004
9004
|
rowsReconciled: number().int().nonnegative().optional(),
|
|
9005
|
+
/**
|
|
9006
|
+
* Rows this run FORGOT because the file they name is not on disk.
|
|
9007
|
+
*
|
|
9008
|
+
* The mover derived the path from the row's own fields and `stat`ed it; an
|
|
9009
|
+
* ENOENT there is a per-path confirmation that the segment is gone (D296),
|
|
9010
|
+
* and the durable row is dropped through the same channel eviction uses. It
|
|
9011
|
+
* is reported for the same reason `rowsReconciled` is: this is a durable
|
|
9012
|
+
* mutation nobody asked for, and a migration that quietly erases hour rows is
|
|
9013
|
+
* the same failure as one that quietly skips them (D295).
|
|
9014
|
+
*
|
|
9015
|
+
* The production drain of 2026-08-30 would have reported 11 074 here — the
|
|
9016
|
+
* ledger claimed 5.65 GB of footage that no longer existed.
|
|
9017
|
+
*/
|
|
9018
|
+
rowsForgotten: number().int().nonnegative().optional(),
|
|
9005
9019
|
startedAt: number(),
|
|
9006
9020
|
finishedAt: number().nullable(),
|
|
9007
9021
|
error: string().nullable()
|
|
@@ -9365,6 +9379,91 @@ var RelocateResidueSchema = object({
|
|
|
9365
9379
|
segments: number().int().nonnegative(),
|
|
9366
9380
|
bytes: number().int().nonnegative()
|
|
9367
9381
|
}).nullable();
|
|
9382
|
+
/**
|
|
9383
|
+
* Ask one location whether its durable hour rows describe the disk — the walk
|
|
9384
|
+
* (D319).
|
|
9385
|
+
*
|
|
9386
|
+
* `apply` DEFAULTS TO FALSE and that default is the product: the operator's
|
|
9387
|
+
* missing tool is the question, and the dry run is how they sanity-check the
|
|
9388
|
+
* destructive run before authorising it.
|
|
9389
|
+
*/
|
|
9390
|
+
var LedgerWalkInputSchema = object({
|
|
9391
|
+
locationId: string().min(1),
|
|
9392
|
+
/** Forget the confirmed-absent rows, rather than only counting them. */
|
|
9393
|
+
apply: boolean().optional(),
|
|
9394
|
+
/** Narrow to one camera. */
|
|
9395
|
+
deviceId: number().int().positive().optional(),
|
|
9396
|
+
/** Narrow to these recording profiles; empty/absent = every profile. */
|
|
9397
|
+
profiles: array(string().min(1)).optional()
|
|
9398
|
+
});
|
|
9399
|
+
/** Why a whole walk did nothing. Every one leaves the ledger untouched. */
|
|
9400
|
+
var LedgerWalkRefusalSchema = _enum([
|
|
9401
|
+
"location-unknown",
|
|
9402
|
+
"source-writable",
|
|
9403
|
+
"no-ledger",
|
|
9404
|
+
"archive-unreadable",
|
|
9405
|
+
"anchor-absent",
|
|
9406
|
+
"anchor-unreadable",
|
|
9407
|
+
"anchor-moved"
|
|
9408
|
+
]);
|
|
9409
|
+
_enum([
|
|
9410
|
+
"live-tail",
|
|
9411
|
+
"listing-error",
|
|
9412
|
+
"path-mismatch",
|
|
9413
|
+
"durable-refused"
|
|
9414
|
+
]);
|
|
9415
|
+
/** Every skip reason, always present, always a number — so a reason that never
|
|
9416
|
+
* fired reports as zero rather than absent and the report shape is constant
|
|
9417
|
+
* between passes. Spelled out rather than `z.record` for exactly that. */
|
|
9418
|
+
var LedgerWalkSkipCountsSchema = object({
|
|
9419
|
+
"live-tail": number().int().nonnegative(),
|
|
9420
|
+
"listing-error": number().int().nonnegative(),
|
|
9421
|
+
"path-mismatch": number().int().nonnegative(),
|
|
9422
|
+
"durable-refused": number().int().nonnegative()
|
|
9423
|
+
});
|
|
9424
|
+
/** One camera's share of a walk, so a report names cameras and not rows. */
|
|
9425
|
+
var LedgerWalkDeviceReportSchema = object({
|
|
9426
|
+
deviceId: number().int(),
|
|
9427
|
+
hoursWalked: number().int().nonnegative(),
|
|
9428
|
+
hoursMissing: number().int().nonnegative(),
|
|
9429
|
+
ghostSegments: number().int().nonnegative(),
|
|
9430
|
+
ghostBytes: number().int().nonnegative(),
|
|
9431
|
+
forgottenSegments: number().int().nonnegative(),
|
|
9432
|
+
orphanFiles: number().int().nonnegative()
|
|
9433
|
+
});
|
|
9434
|
+
/**
|
|
9435
|
+
* What one walk claimed, listed, found and (only when armed) forgot.
|
|
9436
|
+
*
|
|
9437
|
+
* `archiveSegments` is the **M** and `segmentsClaimed` the **N** (D295), so a
|
|
9438
|
+
* walk that saw a fraction of the location is visible in its own report rather
|
|
9439
|
+
* than in the absence of one.
|
|
9440
|
+
*/
|
|
9441
|
+
var LedgerWalkReportSchema = object({
|
|
9442
|
+
locationId: string(),
|
|
9443
|
+
applied: boolean(),
|
|
9444
|
+
refused: LedgerWalkRefusalSchema.nullable(),
|
|
9445
|
+
archiveSegments: number().int().nonnegative().nullable(),
|
|
9446
|
+
archiveBytes: number().int().nonnegative().nullable(),
|
|
9447
|
+
hoursClaimed: number().int().nonnegative(),
|
|
9448
|
+
hoursWalked: number().int().nonnegative(),
|
|
9449
|
+
hoursMissing: number().int().nonnegative(),
|
|
9450
|
+
/** `readdir` calls issued — the cost, stated in the unit that is paid. */
|
|
9451
|
+
listings: number().int().nonnegative(),
|
|
9452
|
+
segmentsClaimed: number().int().nonnegative(),
|
|
9453
|
+
ghostSegments: number().int().nonnegative(),
|
|
9454
|
+
ghostBytes: number().int().nonnegative(),
|
|
9455
|
+
ghostHoursWhole: number().int().nonnegative(),
|
|
9456
|
+
forgottenSegments: number().int().nonnegative(),
|
|
9457
|
+
forgottenBytes: number().int().nonnegative(),
|
|
9458
|
+
/** Files under a claimed hour that no durable row names. Never deleted. */
|
|
9459
|
+
orphanFiles: number().int().nonnegative(),
|
|
9460
|
+
orphanSample: array(string()).readonly(),
|
|
9461
|
+
hoursSkipped: number().int().nonnegative(),
|
|
9462
|
+
skippedByReason: LedgerWalkSkipCountsSchema,
|
|
9463
|
+
/** The walk stopped at its per-pass hour bound with claims unwalked. */
|
|
9464
|
+
bounded: boolean(),
|
|
9465
|
+
byDevice: array(LedgerWalkDeviceReportSchema).readonly()
|
|
9466
|
+
});
|
|
9368
9467
|
/** How many rows a media pass would still act on against a given target — the
|
|
9369
9468
|
* media lane's denominator AND its residue, from ONE derivation so the two can
|
|
9370
9469
|
* never disagree. `null` = the count could not be taken. */
|
|
@@ -19980,13 +20079,15 @@ var ListGroupsPageSchema = object({
|
|
|
19980
20079
|
groups: array(AnalyticsGroupRecordSchema).readonly(),
|
|
19981
20080
|
nextCursor: string().nullable()
|
|
19982
20081
|
});
|
|
20082
|
+
var KEY_EVENTS_DEFAULT_LIMIT = 50;
|
|
20083
|
+
var KEY_EVENTS_MAX_LIMIT = 200;
|
|
19983
20084
|
var KeyEventQueryInput = object({
|
|
19984
20085
|
deviceId: number(),
|
|
19985
20086
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
19986
20087
|
since: number(),
|
|
19987
20088
|
/** Window upper bound (track firstSeen ≤ until). */
|
|
19988
20089
|
until: number(),
|
|
19989
|
-
limit: number().int().min(1).max(
|
|
20090
|
+
limit: number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
19990
20091
|
/** Drop tracks scoring below this importance. */
|
|
19991
20092
|
minImportance: number().min(0).max(1).optional(),
|
|
19992
20093
|
/** Restrict to a single class (e.g. 'person'). */
|
|
@@ -20008,6 +20109,32 @@ var KeyEventSchema = object({
|
|
|
20008
20109
|
...TrackFlagFields,
|
|
20009
20110
|
...TrackRetrainFields
|
|
20010
20111
|
});
|
|
20112
|
+
/** `getKeyEvents`' window and filters, asked of a SET of cameras at once. */
|
|
20113
|
+
var KeyEventBatchQueryInput = object({
|
|
20114
|
+
deviceIds: array(number()).min(1).max(200),
|
|
20115
|
+
since: number(),
|
|
20116
|
+
until: number(),
|
|
20117
|
+
/** Applied PER CAMERA, exactly as `getKeyEvents.limit` is — never a total
|
|
20118
|
+
* across the set, which would let a busy camera starve a quiet one of its
|
|
20119
|
+
* rows and change what the merged feed contains. */
|
|
20120
|
+
limit: number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
20121
|
+
minImportance: number().min(0).max(1).optional(),
|
|
20122
|
+
classFilter: string().optional()
|
|
20123
|
+
});
|
|
20124
|
+
/**
|
|
20125
|
+
* One camera's key events in a batch answer.
|
|
20126
|
+
*
|
|
20127
|
+
* The row exists for every requested id. `getKeyEvents` degrades to `[]` on
|
|
20128
|
+
* error rather than throwing, so a camera whose store read failed and one with
|
|
20129
|
+
* no events in the window were ALREADY indistinguishable per camera — the
|
|
20130
|
+
* batch does not make that worse, and the row keeps the deviceId the single
|
|
20131
|
+
* method's output never carried (the caller used to stamp it from the fan-out
|
|
20132
|
+
* key, which only worked because there was one query per camera).
|
|
20133
|
+
*/
|
|
20134
|
+
var KeyEventsForDeviceSchema = object({
|
|
20135
|
+
deviceId: number(),
|
|
20136
|
+
events: array(KeyEventSchema).readonly()
|
|
20137
|
+
});
|
|
20011
20138
|
object({
|
|
20012
20139
|
trackId: string(),
|
|
20013
20140
|
className: string(),
|
|
@@ -20277,7 +20404,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20277
20404
|
until: number().optional(),
|
|
20278
20405
|
kinds: array(string()).optional(),
|
|
20279
20406
|
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
|
|
20280
|
-
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
|
|
20407
|
+
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(KeyEventBatchQueryInput, array(KeyEventsForDeviceSchema).readonly()), method(object({
|
|
20281
20408
|
deviceId: number(),
|
|
20282
20409
|
since: number(),
|
|
20283
20410
|
until: number(),
|
|
@@ -29644,6 +29771,9 @@ method(object({
|
|
|
29644
29771
|
}), method(RelocateResidueInputSchema, RelocateResidueSchema, {
|
|
29645
29772
|
kind: "query",
|
|
29646
29773
|
auth: "admin"
|
|
29774
|
+
}), method(LedgerWalkInputSchema, LedgerWalkReportSchema, {
|
|
29775
|
+
kind: "mutation",
|
|
29776
|
+
auth: "admin"
|
|
29647
29777
|
}), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
|
|
29648
29778
|
kind: "mutation",
|
|
29649
29779
|
auth: "admin"
|
|
@@ -30035,6 +30165,25 @@ var SceneMonitorStatusSchema = object({
|
|
|
30035
30165
|
monitors: array(SceneMonitorSchema),
|
|
30036
30166
|
lastFetchedAt: number()
|
|
30037
30167
|
});
|
|
30168
|
+
/**
|
|
30169
|
+
* One camera's row in a `listScenesBatch` answer.
|
|
30170
|
+
*
|
|
30171
|
+
* `status` is NULLABLE and the nullability is the whole point. `scene-monitor`
|
|
30172
|
+
* is a `defaultActive` wrapper, so every camera is asked; a camera whose
|
|
30173
|
+
* provider is absent (pipeline-analytics not deployed, the post-processing node
|
|
30174
|
+
* down) cannot answer, and that is not the same fact as a camera with no scenes
|
|
30175
|
+
* configured. Fanned out per camera the difference was visible — one query
|
|
30176
|
+
* errored while the others resolved — and a batch that returned only the rows
|
|
30177
|
+
* it managed would have destroyed it, silently, by making an unreachable camera
|
|
30178
|
+
* indistinguishable from one that answered `monitors: []`.
|
|
30179
|
+
*
|
|
30180
|
+
* So: EVERY requested deviceId gets a row. `status: null` means "this camera
|
|
30181
|
+
* could not be read"; `status.monitors: []` means "read, and it has none".
|
|
30182
|
+
*/
|
|
30183
|
+
var SceneMonitorStatusForDeviceSchema = object({
|
|
30184
|
+
deviceId: number(),
|
|
30185
|
+
status: SceneMonitorStatusSchema.nullable()
|
|
30186
|
+
});
|
|
30038
30187
|
var sceneMonitorCapability = {
|
|
30039
30188
|
name: "scene-monitor",
|
|
30040
30189
|
scope: "device",
|
|
@@ -30044,6 +30193,22 @@ var sceneMonitorCapability = {
|
|
|
30044
30193
|
deviceTypes: [DeviceType.Camera],
|
|
30045
30194
|
methods: {
|
|
30046
30195
|
listScenes: method(object({ deviceId: number() }), SceneMonitorStatusSchema),
|
|
30196
|
+
/**
|
|
30197
|
+
* The same answer, for a SET of cameras, in one round trip.
|
|
30198
|
+
*
|
|
30199
|
+
* `/scenes` renders every camera and re-reads them on a 30s safety-net
|
|
30200
|
+
* poll behind the push slice. Fanned out client-side that was one query
|
|
30201
|
+
* per camera — 29 round trips through the browser, the hub and the
|
|
30202
|
+
* post-analysis runner every 30 seconds to read an in-memory map the
|
|
30203
|
+
* owner had already merged. The work is unchanged (`statusFor` per
|
|
30204
|
+
* device, all in-process at the owner); what collapses is the transport.
|
|
30205
|
+
*
|
|
30206
|
+
* A camera that cannot answer still gets a row, with `status: null` —
|
|
30207
|
+
* see {@link SceneMonitorStatusForDeviceSchema}. Never fewer rows than
|
|
30208
|
+
* ids: a caller that asked for twenty-nine and got twenty-seven cannot
|
|
30209
|
+
* tell which two are missing, or that any are.
|
|
30210
|
+
*/
|
|
30211
|
+
listScenesBatch: method(object({ deviceIds: array(number()).min(1).max(200) }), array(SceneMonitorStatusForDeviceSchema).readonly()),
|
|
30047
30212
|
createScene: method(object({
|
|
30048
30213
|
deviceId: number(),
|
|
30049
30214
|
label: string(),
|
|
@@ -31879,6 +32044,27 @@ var CameraOccupancySnapshotSchema = object({
|
|
|
31879
32044
|
stationaryObjects: array(StationaryObjectSchema).readonly().optional()
|
|
31880
32045
|
});
|
|
31881
32046
|
/**
|
|
32047
|
+
* One camera's row in a `getCurrentSnapshotBatch` answer.
|
|
32048
|
+
*
|
|
32049
|
+
* THREE outcomes, and the single-camera method could only express two of them
|
|
32050
|
+
* because `snapshot: null` was already spoken for:
|
|
32051
|
+
*
|
|
32052
|
+
* - `read: 'read'`, `snapshot` present — the live occupancy reading.
|
|
32053
|
+
* - `read: 'read'`, `snapshot: null` — read, and this camera has no reading
|
|
32054
|
+
* yet: no frame since boot, and no parked-object registry to hydrate from.
|
|
32055
|
+
* - `read: 'unreadable'` — the owner could not answer for this
|
|
32056
|
+
* camera. `snapshot` is null, and it does NOT mean "nothing parked here".
|
|
32057
|
+
*
|
|
32058
|
+
* Collapsing the last two is the failure this field exists to prevent: a
|
|
32059
|
+
* hydration that threw would otherwise render as an empty Stationary section,
|
|
32060
|
+
* which is a definite claim about a camera nobody could read.
|
|
32061
|
+
*/
|
|
32062
|
+
var CameraOccupancySnapshotForDeviceSchema = object({
|
|
32063
|
+
deviceId: number(),
|
|
32064
|
+
read: _enum(["read", "unreadable"]),
|
|
32065
|
+
snapshot: CameraOccupancySnapshotSchema.nullable()
|
|
32066
|
+
});
|
|
32067
|
+
/**
|
|
31882
32068
|
* Time-series resolution. The history methods return one bucket per
|
|
31883
32069
|
* step over the requested range. Smaller resolutions cost more
|
|
31884
32070
|
* memory + bandwidth; bound to discrete steps so caller cannot ask
|
|
@@ -31935,6 +32121,20 @@ var zoneAnalyticsCapability = {
|
|
|
31935
32121
|
* (no inference result emitted since boot or since binding was
|
|
31936
32122
|
* activated). */
|
|
31937
32123
|
getCurrentSnapshot: method(object({ deviceId: number() }), CameraOccupancySnapshotSchema.nullable()),
|
|
32124
|
+
/**
|
|
32125
|
+
* The same snapshot, for a SET of cameras, in one round trip.
|
|
32126
|
+
*
|
|
32127
|
+
* The Events page's Stationary section polls this every 15s for every
|
|
32128
|
+
* selected camera. Fanned out client-side that is one query per camera to
|
|
32129
|
+
* read a `Map.get` at the owner — the answer costs nothing, the round trip
|
|
32130
|
+
* costs everything. Batched, N transports become one and the per-device
|
|
32131
|
+
* work is unchanged.
|
|
32132
|
+
*
|
|
32133
|
+
* Every requested deviceId gets a row, tagged `read` — see
|
|
32134
|
+
* {@link CameraOccupancySnapshotForDeviceSchema}. A camera the owner could
|
|
32135
|
+
* not answer for is `'unreadable'`, never an empty reading.
|
|
32136
|
+
*/
|
|
32137
|
+
getCurrentSnapshotBatch: method(object({ deviceIds: array(number()).min(1).max(200) }), array(CameraOccupancySnapshotForDeviceSchema).readonly()),
|
|
31938
32138
|
/** Time-series object count inside one zone. `className` optional —
|
|
31939
32139
|
* omit to count every class in the zone. */
|
|
31940
32140
|
getZoneHistory: method(object({
|
|
@@ -36356,6 +36556,12 @@ Object.freeze({
|
|
|
36356
36556
|
addonId: null,
|
|
36357
36557
|
access: "view"
|
|
36358
36558
|
},
|
|
36559
|
+
"pipelineAnalytics.getKeyEventsBatch": {
|
|
36560
|
+
capName: "pipeline-analytics",
|
|
36561
|
+
capScope: "device",
|
|
36562
|
+
addonId: null,
|
|
36563
|
+
access: "view"
|
|
36564
|
+
},
|
|
36359
36565
|
"pipelineAnalytics.getMotionEvents": {
|
|
36360
36566
|
capName: "pipeline-analytics",
|
|
36361
36567
|
capScope: "device",
|
|
@@ -37532,6 +37738,12 @@ Object.freeze({
|
|
|
37532
37738
|
addonId: null,
|
|
37533
37739
|
access: "view"
|
|
37534
37740
|
},
|
|
37741
|
+
"recording.reconcileLedgerAgainstDisk": {
|
|
37742
|
+
capName: "recording",
|
|
37743
|
+
capScope: "system",
|
|
37744
|
+
addonId: null,
|
|
37745
|
+
access: "create"
|
|
37746
|
+
},
|
|
37535
37747
|
"recording.refreshStorageLocationsForMigration": {
|
|
37536
37748
|
capName: "recording",
|
|
37537
37749
|
capScope: "system",
|
|
@@ -37658,6 +37870,12 @@ Object.freeze({
|
|
|
37658
37870
|
addonId: null,
|
|
37659
37871
|
access: "view"
|
|
37660
37872
|
},
|
|
37873
|
+
"sceneMonitor.listScenesBatch": {
|
|
37874
|
+
capName: "scene-monitor",
|
|
37875
|
+
capScope: "device",
|
|
37876
|
+
addonId: null,
|
|
37877
|
+
access: "view"
|
|
37878
|
+
},
|
|
37661
37879
|
"sceneMonitor.recheckNow": {
|
|
37662
37880
|
capName: "scene-monitor",
|
|
37663
37881
|
capScope: "device",
|
|
@@ -39014,6 +39232,12 @@ Object.freeze({
|
|
|
39014
39232
|
addonId: null,
|
|
39015
39233
|
access: "view"
|
|
39016
39234
|
},
|
|
39235
|
+
"zoneAnalytics.getCurrentSnapshotBatch": {
|
|
39236
|
+
capName: "zone-analytics",
|
|
39237
|
+
capScope: "device",
|
|
39238
|
+
addonId: null,
|
|
39239
|
+
access: "view"
|
|
39240
|
+
},
|
|
39017
39241
|
"zoneAnalytics.getUnzonedHistory": {
|
|
39018
39242
|
capName: "zone-analytics",
|
|
39019
39243
|
capScope: "device",
|
|
@@ -40018,6 +40242,11 @@ Object.freeze({
|
|
|
40018
40242
|
form: "single",
|
|
40019
40243
|
optional: false
|
|
40020
40244
|
}],
|
|
40245
|
+
"pipelineAnalytics.getKeyEventsBatch": [{
|
|
40246
|
+
name: "deviceIds",
|
|
40247
|
+
form: "array",
|
|
40248
|
+
optional: false
|
|
40249
|
+
}],
|
|
40021
40250
|
"pipelineAnalytics.getMotionEvents": [{
|
|
40022
40251
|
name: "deviceId",
|
|
40023
40252
|
form: "single",
|
|
@@ -40458,6 +40687,11 @@ Object.freeze({
|
|
|
40458
40687
|
form: "single",
|
|
40459
40688
|
optional: false
|
|
40460
40689
|
}],
|
|
40690
|
+
"recording.reconcileLedgerAgainstDisk": [{
|
|
40691
|
+
name: "deviceId",
|
|
40692
|
+
form: "single",
|
|
40693
|
+
optional: true
|
|
40694
|
+
}],
|
|
40461
40695
|
"recording.relocateFootage": [{
|
|
40462
40696
|
name: "deviceId",
|
|
40463
40697
|
form: "single",
|
|
@@ -40523,6 +40757,11 @@ Object.freeze({
|
|
|
40523
40757
|
form: "single",
|
|
40524
40758
|
optional: false
|
|
40525
40759
|
}],
|
|
40760
|
+
"sceneMonitor.listScenesBatch": [{
|
|
40761
|
+
name: "deviceIds",
|
|
40762
|
+
form: "array",
|
|
40763
|
+
optional: false
|
|
40764
|
+
}],
|
|
40526
40765
|
"sceneMonitor.recheckNow": [{
|
|
40527
40766
|
name: "deviceId",
|
|
40528
40767
|
form: "single",
|
|
@@ -40784,6 +41023,11 @@ Object.freeze({
|
|
|
40784
41023
|
form: "single",
|
|
40785
41024
|
optional: false
|
|
40786
41025
|
}],
|
|
41026
|
+
"zoneAnalytics.getCurrentSnapshotBatch": [{
|
|
41027
|
+
name: "deviceIds",
|
|
41028
|
+
form: "array",
|
|
41029
|
+
optional: false
|
|
41030
|
+
}],
|
|
40787
41031
|
"zoneAnalytics.getUnzonedHistory": [{
|
|
40788
41032
|
name: "deviceId",
|
|
40789
41033
|
form: "single",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-provider-rademacher",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.48",
|
|
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",
|