@camstack/addon-provider-dreo 0.2.116 → 0.2.117
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 +892 -325
- package/dist/addon.mjs +892 -325
- package/package.json +1 -3
package/dist/addon.js
CHANGED
|
@@ -35,7 +35,7 @@ var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["modu
|
|
|
35
35
|
//#endregion
|
|
36
36
|
let crypto$1 = require("crypto");
|
|
37
37
|
let events = require("events");
|
|
38
|
-
//#region ../types/dist/event-category-
|
|
38
|
+
//#region ../types/dist/event-category-BGmz_oxW.mjs
|
|
39
39
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
40
40
|
EventCategory["SystemBoot"] = "system.boot";
|
|
41
41
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -568,6 +568,15 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
568
568
|
*/
|
|
569
569
|
EventCategory["PipelineAudioInferenceResult"] = "pipeline.audio-inference-result";
|
|
570
570
|
EventCategory["DetectionPhaseTransition"] = "detection.phase-transition";
|
|
571
|
+
/**
|
|
572
|
+
* A camera provider's RAW onboard motion push (D673): the `MotionOnMotionChanged`
|
|
573
|
+
* data shape without `triggeredBy`, built by `providerMotionEvent`. Its one
|
|
574
|
+
* consumer is the orchestrator's camera-sensors bridge, which re-emits the
|
|
575
|
+
* camera's EFFECTIVE onboard motion as `MotionOnMotionChanged` (a pass-through
|
|
576
|
+
* for a camera with no attached sensor). Providers must not emit
|
|
577
|
+
* `MotionOnMotionChanged` themselves; `scripts/check-onboard-motion-emitters.ts`
|
|
578
|
+
* keeps it so (camera-grid is a named, deferred exception).
|
|
579
|
+
*/
|
|
571
580
|
EventCategory["ProviderMotion"] = "provider.motion";
|
|
572
581
|
EventCategory["ProviderDetection"] = "provider.detection";
|
|
573
582
|
EventCategory["EnrichmentEmbeddingStored"] = "enrichment.embedding.stored";
|
|
@@ -5406,7 +5415,7 @@ var ZodIssueCode = {
|
|
|
5406
5415
|
var ZodFirstPartyTypeKind;
|
|
5407
5416
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5408
5417
|
//#endregion
|
|
5409
|
-
//#region ../types/dist/sleep-
|
|
5418
|
+
//#region ../types/dist/sleep-CDCONfkt.mjs
|
|
5410
5419
|
/**
|
|
5411
5420
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5412
5421
|
* window to float samples (D455).
|
|
@@ -7449,7 +7458,7 @@ function errMsg(err) {
|
|
|
7449
7458
|
return String(err);
|
|
7450
7459
|
}
|
|
7451
7460
|
//#endregion
|
|
7452
|
-
//#region ../types/dist/composition-
|
|
7461
|
+
//#region ../types/dist/composition-Bzr7GwgP.mjs
|
|
7453
7462
|
/**
|
|
7454
7463
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
7455
7464
|
*
|
|
@@ -7503,21 +7512,20 @@ function portable(target) {
|
|
|
7503
7512
|
}
|
|
7504
7513
|
portable("linux64"), portable("linuxarm64"), portable("macarm64"), portable("mac64");
|
|
7505
7514
|
/**
|
|
7506
|
-
*
|
|
7507
|
-
*
|
|
7515
|
+
* THE table "which boolean of this device type counts as HIGH", and the
|
|
7516
|
+
* pure evaluator of its EDGE.
|
|
7508
7517
|
*
|
|
7509
|
-
*
|
|
7510
|
-
*
|
|
7511
|
-
*
|
|
7512
|
-
*
|
|
7513
|
-
*
|
|
7514
|
-
*
|
|
7515
|
-
* SPOSTA qui e il doorbell la ri-esporta.
|
|
7518
|
+
* ONE table for everyone who asks "is this device HIGH?": the
|
|
7519
|
+
* recorder's `RecordingTriggers.sensorDeviceIds` trigger, the post-analysis
|
|
7520
|
+
* sensor markers, the orchestrator's camera-sensors bridge and
|
|
7521
|
+
* the sources of a composite doorbell (`doorbellFeatureSources`, D671).
|
|
7522
|
+
* A second copy would diverge at the first cap added, and the symptom — "the
|
|
7523
|
+
* sensor rings the doorbell but does not record" — is exactly D62.
|
|
7516
7524
|
*
|
|
7517
|
-
* ⚠
|
|
7518
|
-
*
|
|
7519
|
-
*
|
|
7520
|
-
*
|
|
7525
|
+
* ⚠ NOT `DEVICE_STATE_READERS` (`catalogs/device-state-vocabulary.ts`), and the
|
|
7526
|
+
* two must not be unified: that one answers "what is the state WORD for a
|
|
7527
|
+
* rule" (and includes `presence`, `cover`, `alarm-panel`), this one "which
|
|
7528
|
+
* boolean's EDGE counts". Deliberately different vocabularies.
|
|
7521
7529
|
*/
|
|
7522
7530
|
/**
|
|
7523
7531
|
* Known binary / switch source caps → the boolean slice field whose
|
|
@@ -9126,22 +9134,22 @@ var CLASS_MAP_MACRO_TARGETS = [
|
|
|
9126
9134
|
"package"
|
|
9127
9135
|
];
|
|
9128
9136
|
/**
|
|
9129
|
-
*
|
|
9130
|
-
*
|
|
9137
|
+
* The FIRST-LEVEL macro classes: those an object detector emits and that
|
|
9138
|
+
* an operator can select.
|
|
9131
9139
|
*
|
|
9132
|
-
*
|
|
9140
|
+
* They are the three offered by the `object-detection` step
|
|
9133
9141
|
* (`addon-pipeline/src/detection-pipeline/registry/step-definitions.ts`,
|
|
9134
|
-
* `enabledMacroClasses`). `package`
|
|
9135
|
-
* `MACRO_LABELS` —
|
|
9136
|
-
* `package-detection`,
|
|
9137
|
-
*
|
|
9142
|
+
* `enabledMacroClasses`). `package` is in {@link CLASS_MAP_MACRO_TARGETS} and in
|
|
9143
|
+
* `MACRO_LABELS` — it is a true macro — but NOT here: it belongs to the step
|
|
9144
|
+
* `package-detection`, whose enablement is driven by zones, and offering the
|
|
9145
|
+
* same word twice has already made an operator turn on the COCO proxy
|
|
9138
9146
|
* (suitcase/backpack/handbag) lasciando spento il detector dedicato.
|
|
9139
9147
|
*
|
|
9140
|
-
*
|
|
9141
|
-
*
|
|
9142
|
-
* (`types/detection.ts`);
|
|
9143
|
-
* (`RecordingTriggers.objectClasses`)
|
|
9144
|
-
*
|
|
9148
|
+
* ONE list. Before today the same three were hand-written in the step's offer
|
|
9149
|
+
* and a second time as the union `FirstLevelMacro`
|
|
9150
|
+
* (`types/detection.ts`); a third copy for the recording trigger
|
|
9151
|
+
* (`RecordingTriggers.objectClasses`) would have made the later divergence
|
|
9152
|
+
* invisible.
|
|
9145
9153
|
*/
|
|
9146
9154
|
var FIRST_LEVEL_MACRO_CLASSES = [
|
|
9147
9155
|
"person",
|
|
@@ -9206,17 +9214,17 @@ var RecordingStorageModeSchema = _enum([
|
|
|
9206
9214
|
"on-device-decision"
|
|
9207
9215
|
]);
|
|
9208
9216
|
/**
|
|
9209
|
-
*
|
|
9210
|
-
*
|
|
9217
|
+
* The macro classes that can open a recording window — the same
|
|
9218
|
+
* three offered by the `object-detection` step, from ONE list
|
|
9211
9219
|
* ({@link FIRST_LEVEL_MACRO_CLASSES}).
|
|
9212
9220
|
*/
|
|
9213
9221
|
var RecordingObjectTriggerClassSchema = _enum(FIRST_LEVEL_MACRO_CLASSES);
|
|
9214
9222
|
/**
|
|
9215
|
-
* True
|
|
9223
|
+
* True when `values` does not repeat an element.
|
|
9216
9224
|
*
|
|
9217
|
-
*
|
|
9218
|
-
*
|
|
9219
|
-
*
|
|
9225
|
+
* A duplicate is not harmless: every entry of `objectClasses` / `sensorDeviceIds`
|
|
9226
|
+
* becomes a SOURCE in `bandTriggerSources`, and the same source twice
|
|
9227
|
+
* would count its windows twice in `segmentMissedByMs`.
|
|
9220
9228
|
*/
|
|
9221
9229
|
var noDuplicates = (values) => new Set(values).size === values.length;
|
|
9222
9230
|
/** Which detectors trigger an `events`-mode band. */
|
|
@@ -9224,34 +9232,34 @@ var RecordingTriggersSchema = object({
|
|
|
9224
9232
|
motion: boolean().optional(),
|
|
9225
9233
|
audioThresholdDbfs: number().optional(),
|
|
9226
9234
|
/**
|
|
9227
|
-
*
|
|
9228
|
-
*
|
|
9229
|
-
*
|
|
9230
|
-
*
|
|
9235
|
+
* The macro classes whose detection opens a window. ABSENT = the source
|
|
9236
|
+
* is not listened to; an EMPTY array is rejected, because "events band, object
|
|
9237
|
+
* trigger on, no class" is the same shape "enabled and records
|
|
9238
|
+
* nothing, forever" that `eventsBandCanEverDemand` is written against.
|
|
9231
9239
|
*
|
|
9232
|
-
*
|
|
9233
|
-
*
|
|
9234
|
-
* `minConfidence<Macro>`
|
|
9235
|
-
* (`source: 'onboard'`)
|
|
9236
|
-
*
|
|
9240
|
+
* The signal read is ALREADY FILTERED: only `source: 'pipeline'` detections, i.e.
|
|
9241
|
+
* those that went through `enabledMacroClasses`, the
|
|
9242
|
+
* `minConfidence<Macro>` and the full-frame guard. The camera's onboard AI
|
|
9243
|
+
* (`source: 'onboard'`) goes through none of those gates and does NOT open
|
|
9244
|
+
* windows — see `recorder/object-trigger.ts`.
|
|
9237
9245
|
*/
|
|
9238
9246
|
objectClasses: array(RecordingObjectTriggerClassSchema).min(1).refine(noDuplicates, { message: "objectClasses must not repeat a class" }).optional(),
|
|
9239
9247
|
/**
|
|
9240
|
-
*
|
|
9241
|
-
*
|
|
9248
|
+
* The LINKED devices whose RISING EDGE opens a window. Absent = the source
|
|
9249
|
+
* is not listened to; an empty array is rejected for the same reason as
|
|
9242
9250
|
* `objectClasses`.
|
|
9243
9251
|
*
|
|
9244
|
-
*
|
|
9245
|
-
*
|
|
9246
|
-
*
|
|
9247
|
-
*
|
|
9248
|
-
* device (D12) —
|
|
9252
|
+
* These are SOURCE device ids, not cameras: the band names them, so the
|
|
9253
|
+
* hot path (`DeviceStateChanged`, at bus rate across the whole fleet)
|
|
9254
|
+
* does no RPC. The OFFER from which the operator picks them is another question, and
|
|
9255
|
+
* is resolved with `deviceManager.getLinkedDevices` + `getBindingsBatch` per
|
|
9256
|
+
* device (D12) — never a global list of caps.
|
|
9249
9257
|
*
|
|
9250
|
-
*
|
|
9251
|
-
* `SOURCE_CAP_ACTIVE_FIELD` (`catalogs/sensor-active-state.ts`)
|
|
9252
|
-
*
|
|
9253
|
-
*
|
|
9254
|
-
*
|
|
9258
|
+
* What "high" means depends on the device TYPE and is not decided here:
|
|
9259
|
+
* `SOURCE_CAP_ACTIVE_FIELD` (`catalogs/sensor-active-state.ts`) is THE table,
|
|
9260
|
+
* the same one as the composite doorbell (D671). And it is the EDGE, not
|
|
9261
|
+
* the level: a contact found already open at runner restart does not
|
|
9262
|
+
* record.
|
|
9255
9263
|
*/
|
|
9256
9264
|
sensorDeviceIds: array(number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional()
|
|
9257
9265
|
});
|
|
@@ -10328,7 +10336,7 @@ var DecoderSessionConfigSchema = object({
|
|
|
10328
10336
|
* - **VALUE** — at which level, for which scope, until when. That stays ONE
|
|
10329
10337
|
* thing: the logging settings document on the `system` cap. Two authorities
|
|
10330
10338
|
* over the values is the exact defect
|
|
10331
|
-
* `docs/design/plans/2026-08-26-
|
|
10339
|
+
* `docs/design/plans/2026-08-26-per-component-logging.md` was written to
|
|
10332
10340
|
* remove; re-introducing it from the cure side would be grotesque.
|
|
10333
10341
|
*
|
|
10334
10342
|
* Nothing in this file reads a clock, an env var or a store. The registry is
|
|
@@ -12039,7 +12047,7 @@ var BrokerStatusEnum = _enum([
|
|
|
12039
12047
|
"unreachable",
|
|
12040
12048
|
"error"
|
|
12041
12049
|
]);
|
|
12042
|
-
var BrokerInfoSchema
|
|
12050
|
+
var BrokerInfoSchema = object({
|
|
12043
12051
|
/** Stable broker id. Persisted; survives addon restarts. */
|
|
12044
12052
|
id: string(),
|
|
12045
12053
|
/** Addon id of the provider that OWNS this broker.
|
|
@@ -12172,7 +12180,7 @@ var GetStateInputSchema = object({
|
|
|
12172
12180
|
* HA: entity_id (returns the cached entity state). */
|
|
12173
12181
|
key: string()
|
|
12174
12182
|
});
|
|
12175
|
-
method(ListInputSchema, array(BrokerInfoSchema
|
|
12183
|
+
method(ListInputSchema, array(BrokerInfoSchema)), method(GetInputSchema, BrokerInfoSchema.nullable()), method(_void(), array(BrokerProviderInfoSchema), { auth: "admin" }), method(AddInputSchema, AddResultSchema, {
|
|
12176
12184
|
kind: "mutation",
|
|
12177
12185
|
auth: "admin"
|
|
12178
12186
|
}), method(RemoveInputSchema, _void(), {
|
|
@@ -13883,7 +13891,7 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
|
|
|
13883
13891
|
*
|
|
13884
13892
|
* ⚠ An earlier version of this comment blamed Zod stripping, and that
|
|
13885
13893
|
* was wrong — corrected 2026-08-26 after the hop map
|
|
13886
|
-
* (`docs/design/2026-08-26-
|
|
13894
|
+
* (`docs/design/2026-08-26-topic-hop-map.md`) traced the path.
|
|
13887
13895
|
* There is **no Zod parse at all** between the door and the engine: the
|
|
13888
13896
|
* dispatcher forwards the payload verbatim and UDS carries it whole. A
|
|
13889
13897
|
* field declared here reaches `SqliteSettingsBackend` either way.
|
|
@@ -14763,7 +14771,17 @@ var SiteZoneSchema = object({
|
|
|
14763
14771
|
var ProviderStatusSchema = object({
|
|
14764
14772
|
connected: boolean(),
|
|
14765
14773
|
deviceCount: number(),
|
|
14766
|
-
error: string().optional()
|
|
14774
|
+
error: string().optional(),
|
|
14775
|
+
/**
|
|
14776
|
+
* `'orchestrator'`: this provider writes NO camera's `motion` runtime slice
|
|
14777
|
+
* — the orchestrator is its only writer (D696). Set by `BaseDeviceProvider`,
|
|
14778
|
+
* which every provider bundles, so only a provider BUILT from D696-amended
|
|
14779
|
+
* code says it. ABSENT means an older provider that may still write it (raw
|
|
14780
|
+
* VMD writes, a boot seed), and the orchestrator's provider gate keeps that
|
|
14781
|
+
* provider's cameras unwritten (`camera-sensors/motion-slice-provider-gate.ts`)
|
|
14782
|
+
* — the provider twin of the runner's `getLocalLoad().motionSliceWriter`.
|
|
14783
|
+
*/
|
|
14784
|
+
motionSliceWriter: literal("orchestrator").optional()
|
|
14767
14785
|
});
|
|
14768
14786
|
object({
|
|
14769
14787
|
externalId: string(),
|
|
@@ -15642,109 +15660,10 @@ method(object({
|
|
|
15642
15660
|
deviceIds: array(number()).readonly(),
|
|
15643
15661
|
caps: array(string()).readonly().optional()
|
|
15644
15662
|
}), record(string(), record(string(), unknown().nullable())));
|
|
15645
|
-
|
|
15646
|
-
|
|
15647
|
-
* name (same pattern as `snapshot`):
|
|
15648
|
-
*
|
|
15649
|
-
* - **Native** providers: registered per-device by device-driver
|
|
15650
|
-
* addons via `ctx.registerNativeCap` — either on a
|
|
15651
|
-
* `DeviceType.Button` accessory with `role: DeviceRole.Doorbell`,
|
|
15652
|
-
* or directly on the camera (Reolink registers at camera level).
|
|
15653
|
-
* Emits an `onPressed` event every time the firmware pushes a
|
|
15654
|
-
* ring; status tracks the last press and a pressCount since start
|
|
15655
|
-
* (diagnostic).
|
|
15656
|
-
*
|
|
15657
|
-
* - **Wrapper** provider: the `virtual-doorbell` system builtin
|
|
15658
|
-
* (`@camstack/system/builtins/doorbell`). Turns ANY binary-ish
|
|
15659
|
-
* device (contact / switch / event-emitter …) into a doorbell for
|
|
15660
|
-
* a camera. `defaultActive: false` — the operator explicitly binds
|
|
15661
|
-
* it per camera in the device-bindings UI, then picks the source
|
|
15662
|
-
* device + trigger in the per-device settings.
|
|
15663
|
-
*
|
|
15664
|
-
* The DeviceEventPropagator re-emits `onPressed` on the camera parent
|
|
15665
|
-
* — subscribers listening at the camera level receive ring events
|
|
15666
|
-
* with `via[]` populated. No code on the parent needed.
|
|
15667
|
-
*/
|
|
15668
|
-
var DoorbellStatusSchema = object({
|
|
15669
|
-
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
15670
|
-
lastPressedAt: number().nullable(),
|
|
15671
|
-
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
15672
|
-
pressCountSinceStart: number()
|
|
15673
|
-
});
|
|
15674
|
-
var DoorbellPressEventSchema = object({
|
|
15675
|
-
deviceId: number(),
|
|
15676
|
-
timestamp: number()
|
|
15677
|
-
});
|
|
15678
|
-
/**
|
|
15679
|
-
* The `doorbell-source` extension slot's editable value (D648): the camera's
|
|
15680
|
-
* virtual-doorbell trigger devices, exactly what the wrapper's
|
|
15681
|
-
* `doorbellSources` persists (as `{ deviceId }` records).
|
|
15682
|
-
*/
|
|
15683
|
-
var DoorbellSourceSlotValueSchema = object({ deviceIds: array(number().int().positive()) });
|
|
15684
|
-
/**
|
|
15685
|
-
* The `doorbell-source` slot — which devices ring this camera's VIRTUAL
|
|
15686
|
-
* doorbell, owned by the `virtual-doorbell` wrapper over its
|
|
15687
|
-
* `doorbellSources` store (D648). A source rings when one of its
|
|
15688
|
-
* `SOURCE_CAPS` rises. Whether the wrapper is bound to the camera at all is a
|
|
15689
|
-
* different authority (`deviceManager.setWrapperActive`, D62) — the slot
|
|
15690
|
-
* reports it, it never writes it.
|
|
15691
|
-
*/
|
|
15692
|
-
var DOORBELL_SOURCE_SLOT = {
|
|
15693
|
-
id: "doorbell-source",
|
|
15694
|
-
label: "Doorbell trigger devices",
|
|
15695
|
-
description: "Any of these becoming active rings this camera's virtual doorbell: a binary sensor when it goes active, a switch when it turns on.",
|
|
15696
|
-
shape: "association",
|
|
15697
|
-
hostDeviceTypes: [DeviceType.Camera],
|
|
15698
|
-
sourceCaps: SOURCE_CAPS,
|
|
15699
|
-
cardinality: "many",
|
|
15700
|
-
value: DoorbellSourceSlotValueSchema
|
|
15701
|
-
};
|
|
15702
|
-
var doorbellCapability = {
|
|
15703
|
-
name: "doorbell",
|
|
15704
|
-
scope: "device",
|
|
15705
|
-
deviceNative: true,
|
|
15706
|
-
mode: "singleton",
|
|
15707
|
-
kind: "wrapper",
|
|
15708
|
-
defaultActive: false,
|
|
15709
|
-
deviceTypes: [DeviceType.Button, DeviceType.Camera],
|
|
15710
|
-
extensionSlots: [DOORBELL_SOURCE_SLOT],
|
|
15711
|
-
methods: {},
|
|
15712
|
-
events: {
|
|
15713
|
-
/**
|
|
15714
|
-
* Fires once per physical press. Reolink delivers via Baichuan
|
|
15715
|
-
* push (`ReolinkSimpleEvent.type === 'doorbell'`). There is no
|
|
15716
|
-
* release/duration — it's a pulse.
|
|
15717
|
-
*/
|
|
15718
|
-
onPressed: {
|
|
15719
|
-
data: DoorbellPressEventSchema,
|
|
15720
|
-
fromState: {
|
|
15721
|
-
field: "lastPressedAt",
|
|
15722
|
-
on: "advance"
|
|
15723
|
-
}
|
|
15724
|
-
} },
|
|
15725
|
-
status: {
|
|
15726
|
-
schema: DoorbellStatusSchema,
|
|
15727
|
-
kind: "push"
|
|
15728
|
-
},
|
|
15729
|
-
/**
|
|
15730
|
-
* Runtime-state slice — last press timestamp + lifetime press count.
|
|
15731
|
-
* Mirrored by the kernel and readable via
|
|
15732
|
-
* `device.state.doorbell.value`. UIs can show "last ring 5m ago"
|
|
15733
|
-
* without subscribing.
|
|
15734
|
-
*/
|
|
15735
|
-
runtimeState: DoorbellStatusSchema,
|
|
15736
|
-
/**
|
|
15737
|
-
* Runtime-state durability: **restored** — a monotonic accumulator: the slice IS the record. `lastPressedAt` is content here, not a clock, so it is deliberately NOT volatile.
|
|
15738
|
-
*
|
|
15739
|
-
* See `RuntimeStateDurability`. Enforced by
|
|
15740
|
-
* `scripts/check-runtime-state-durability.ts`.
|
|
15741
|
-
*/
|
|
15742
|
-
durability: "restored"
|
|
15743
|
-
};
|
|
15744
|
-
var ExtensionSlotIdSchema = _enum(["doorbell-source", "linked-devices"]);
|
|
15745
|
-
DeviceType.Camera, DeviceType.Camera;
|
|
15663
|
+
var ExtensionSlotIdSchema = _enum(["linked-devices"]);
|
|
15664
|
+
DeviceType.Camera;
|
|
15746
15665
|
/** A slot's editable value, discriminated on `slot`. */
|
|
15747
|
-
var ExtensionSlotValueSchema = discriminatedUnion("slot", [
|
|
15666
|
+
var ExtensionSlotValueSchema = discriminatedUnion("slot", [LinkedDevicesSlotValueSchema.extend({ slot: literal("linked-devices") })]);
|
|
15748
15667
|
DeviceType.Camera;
|
|
15749
15668
|
var ExtensionSourceAvailabilitySchema = discriminatedUnion("state", [object({ state: literal("ok") }), object({
|
|
15750
15669
|
state: literal("unreachable"),
|
|
@@ -15781,10 +15700,11 @@ var ExtensionSlotSourceSchema = object({
|
|
|
15781
15700
|
});
|
|
15782
15701
|
/**
|
|
15783
15702
|
* A DIFFERENT authority that gates whether the slot's sources do anything —
|
|
15784
|
-
* reported read-only, named, never written through this contract (D62).
|
|
15785
|
-
*
|
|
15786
|
-
*
|
|
15787
|
-
* `unknown` means the gate could
|
|
15703
|
+
* reported read-only, named, never written through this contract (D62) — e.g.
|
|
15704
|
+
* a slot whose sources act only while a wrapper is bound to the host, a
|
|
15705
|
+
* binding that belongs to `deviceManager.setWrapperActive`. No slot reports
|
|
15706
|
+
* one today (`linked-devices` answers `null`). `unknown` means the gate could
|
|
15707
|
+
* not be read; it is not "inactive" (D315).
|
|
15788
15708
|
*/
|
|
15789
15709
|
var ExtensionSlotActivationSchema = object({
|
|
15790
15710
|
state: _enum([
|
|
@@ -15800,7 +15720,7 @@ var ExtensionSlotRowSchema = discriminatedUnion("state", [object({
|
|
|
15800
15720
|
/** `<source>:<slotId>` — the routing key for `listCandidates` / `setSlot`. */
|
|
15801
15721
|
slotRef: string(),
|
|
15802
15722
|
slot: ExtensionSlotIdSchema,
|
|
15803
|
-
/** Names the store written (D62), e.g. `
|
|
15723
|
+
/** Names the store written (D62), e.g. `device-manager:_linkedDeviceIds`. */
|
|
15804
15724
|
authority: string(),
|
|
15805
15725
|
activation: ExtensionSlotActivationSchema.nullable(),
|
|
15806
15726
|
value: ExtensionSlotValueSchema,
|
|
@@ -16078,7 +15998,7 @@ method(object({
|
|
|
16078
15998
|
* per-device window, `KeyFrameCaptureLog`, `bumpCropMetric`. Every one of them
|
|
16079
15999
|
* ends in a log line, and a log line is the thing the operator asked to stop
|
|
16080
16000
|
* needing: *"possiamo armare questi errori intanto? Così al prossimo giro
|
|
16081
|
-
* ricontrolliamo tutti questi punti"
|
|
16001
|
+
* ricontrolliamo tutti questi punti"* [can we instrument these errors in the meantime? That way next round we recheck all these points]. Reading them meant grepping Loki and
|
|
16082
16002
|
* hand-correlating timestamps, which is how a 22% thumbnail gap and a 3-hour
|
|
16083
16003
|
* media blackout were both diagnosed. The counters stay; this is where they can
|
|
16084
16004
|
* be READ.
|
|
@@ -17454,7 +17374,7 @@ var BrokerStatusSchema$1 = _enum([
|
|
|
17454
17374
|
"unreachable",
|
|
17455
17375
|
"tls-error"
|
|
17456
17376
|
]);
|
|
17457
|
-
var BrokerInfoSchema = object({
|
|
17377
|
+
var BrokerInfoSchema$1 = object({
|
|
17458
17378
|
id: string(),
|
|
17459
17379
|
name: string(),
|
|
17460
17380
|
url: string(),
|
|
@@ -17517,7 +17437,7 @@ var StatusSchema = object({
|
|
|
17517
17437
|
brokerCount: number(),
|
|
17518
17438
|
embeddedRunning: boolean()
|
|
17519
17439
|
});
|
|
17520
|
-
method(_void(), array(BrokerInfoSchema)), method(IdInputSchema, BrokerConnectionDetailsSchema, { auth: "admin" }), method(AddBrokerInputSchema, AddBrokerResultSchema, {
|
|
17440
|
+
method(_void(), array(BrokerInfoSchema$1)), method(IdInputSchema, BrokerConnectionDetailsSchema, { auth: "admin" }), method(AddBrokerInputSchema, AddBrokerResultSchema, {
|
|
17521
17441
|
kind: "mutation",
|
|
17522
17442
|
auth: "admin"
|
|
17523
17443
|
}), method(IdInputSchema, _void(), {
|
|
@@ -19731,78 +19651,16 @@ var NcRuleInputSchema = object({
|
|
|
19731
19651
|
*/
|
|
19732
19652
|
confirm: NcConfirmSchema.optional(),
|
|
19733
19653
|
/**
|
|
19734
|
-
*
|
|
19735
|
-
*
|
|
19736
|
-
*
|
|
19737
|
-
*
|
|
19738
|
-
*
|
|
19739
|
-
*
|
|
19740
|
-
*
|
|
19741
|
-
*
|
|
19742
|
-
*
|
|
19743
|
-
* Only two honest answers exist, and this flag picks between them. It has
|
|
19744
|
-
* effect ONLY on a rule that declares a recognition scope
|
|
19745
|
-
* ({@link NcConditions.identities} or {@link NcConditions.plates}) — on any
|
|
19746
|
-
* other rule there is nothing to wait for and the flag is inert.
|
|
19747
|
-
*
|
|
19748
|
-
* | value | what happens |
|
|
19749
|
-
* | --- | --- |
|
|
19750
|
-
* | `true` | the rule stops firing on the object event and fires at TRACK CLOSE instead, once, with the name — later, and complete |
|
|
19751
|
-
* | absent / `false` | it fires at once WITHOUT the name, and if recognition lands before the track closes a SECOND, "…is Gianluca" notification follows (one per track, per rule, per target) |
|
|
19752
|
-
*
|
|
19753
|
-
* `.optional()` and deliberately NOT `.default()`: a Zod default does not run
|
|
19754
|
-
* on the addon cap path, and absent has to keep meaning exactly what every
|
|
19755
|
-
* rule authored before this field meant.
|
|
19756
|
-
*
|
|
19757
|
-
* The cost of `true` is stated here because the editor states it too: a rule
|
|
19758
|
-
* that waits also inherits track-close SEMANTICS — its `zones` condition
|
|
19759
|
-
* tests every zone the track visited and a `crossing` condition can no longer
|
|
19760
|
-
* be satisfied, because a closed track carries no crossing.
|
|
19654
|
+
* IMMEDIATE GROUPED (D692): the first matching subject opens a window of this many
|
|
19655
|
+
* seconds; the rule sends ONE message when the window closes — early, once every
|
|
19656
|
+
* subject in it is final, never before {@link NC_GROUPING_MIN_SEC} — naming everybody
|
|
19657
|
+
* the rule matched, with one mosaic tile per subject.
|
|
19658
|
+
* Absent = plain immediate (one message per track, at the first match).
|
|
19659
|
+
* Only an `immediate` DETECTION rule may carry it (`ruleGroupingApplies`, enforced on
|
|
19660
|
+
* save by the hub's grouping guard). `.optional()`, never `.default()`: the addon cap
|
|
19661
|
+
* path does not run Zod defaults.
|
|
19761
19662
|
*/
|
|
19762
|
-
|
|
19763
|
-
/**
|
|
19764
|
-
* GROUP a burst of subjects into ONE notification that grows.
|
|
19765
|
-
*
|
|
19766
|
-
* Seconds of quiet after the last matching subject before the burst is
|
|
19767
|
-
* considered over. While it is open, the first subject enqueues immediately —
|
|
19768
|
-
* **exactly as today, with no added latency** — and every real growth (a new
|
|
19769
|
-
* subject, or a name confirmed on one already in it) REPLACES that
|
|
19770
|
-
* notification with an updated one naming everybody. The push carries the
|
|
19771
|
-
* group's own coalescing tag, so the phone replaces rather than stacks.
|
|
19772
|
-
*
|
|
19773
|
-
* `0` / absent = off, and off is today's behaviour byte for byte.
|
|
19774
|
-
*
|
|
19775
|
-
* ### Why an idle cutoff and not a window
|
|
19776
|
-
*
|
|
19777
|
-
* The measured seven-person arrival on device 590 spans 110 s with every
|
|
19778
|
-
* internal gap under 30 s. A 12 s fixed window cuts it into three groups; an
|
|
19779
|
-
* idle cutoff holds it as one and ends it when the arrival actually ends.
|
|
19780
|
-
* 30 s is a widely shipped value for the same decision.
|
|
19781
|
-
*
|
|
19782
|
-
* ### What it replaces
|
|
19783
|
-
*
|
|
19784
|
-
* The blind cooldown, which collapses a burst by DISCARDING it. Measured on
|
|
19785
|
-
* device 615 / *Persona su Uscio* over six days: 116 qualifying tracks → 74
|
|
19786
|
-
* notifications, **44 (37.9%) suppressed outright**, 23 of them overlapping a
|
|
19787
|
-
* track that did fire and 7 carrying a confirmed identity nobody heard about.
|
|
19788
|
-
* A group collapses the same volume by MERGING, so the cooldown becomes a
|
|
19789
|
-
* budget over GROUPS — which is what it always meant — and a growth is never
|
|
19790
|
-
* throttled by the window its own first member spent.
|
|
19791
|
-
*
|
|
19792
|
-
* ### Interaction with {@link waitForEnhancement}
|
|
19793
|
-
*
|
|
19794
|
-
* They compose, and the order matters. `waitForEnhancement` defers the rule to
|
|
19795
|
-
* TRACK CLOSE, so with both set the group is opened by the first member to
|
|
19796
|
-
* CLOSE — already carrying its name — and grows as later members close. That
|
|
19797
|
-
* is later, and complete. With grouping alone the group opens on the first
|
|
19798
|
-
* object event and picks up names as they are confirmed, through the growth
|
|
19799
|
-
* path. Neither combination fires twice for one subject.
|
|
19800
|
-
*
|
|
19801
|
-
* `.optional()` and deliberately NOT `.default()`: a Zod default does not run
|
|
19802
|
-
* on the addon cap path, so absent must keep meaning what it meant before this
|
|
19803
|
-
* field existed.
|
|
19804
|
-
*/
|
|
19805
|
-
groupIdleSec: number().int().min(0).max(600).optional()
|
|
19663
|
+
groupingSec: number().int().min(5).max(60).optional()
|
|
19806
19664
|
});
|
|
19807
19665
|
/**
|
|
19808
19666
|
* Partial patch for `updateRule` — any subset of the input fields, plus the
|
|
@@ -19850,9 +19708,10 @@ var NcRuleClearableKeySchema = _enum([
|
|
|
19850
19708
|
"targetUsers",
|
|
19851
19709
|
"snoozeOptions",
|
|
19852
19710
|
"snoozeAllowGlobal",
|
|
19853
|
-
"waitForEnhancement",
|
|
19854
19711
|
"actions",
|
|
19855
19712
|
"confirm",
|
|
19713
|
+
"groupingSec",
|
|
19714
|
+
"waitForEnhancement",
|
|
19856
19715
|
"groupIdleSec"
|
|
19857
19716
|
]);
|
|
19858
19717
|
var NcRuleUpdateInputSchema = object({
|
|
@@ -19874,9 +19733,25 @@ var NcRuleSchema = NcRuleInputSchema.extend({
|
|
|
19874
19733
|
*/
|
|
19875
19734
|
disabledTargetIds: array(string()).default([])
|
|
19876
19735
|
});
|
|
19736
|
+
/**
|
|
19737
|
+
* The state-summary SECTIONS (D647 / D698): the D637 kind groups that report a
|
|
19738
|
+
* still-true state. `backups-exports` and `alarm` are not sections — a completed
|
|
19739
|
+
* job is not an open state, and the alarm stays instant.
|
|
19740
|
+
*/
|
|
19741
|
+
var NcStateSummarySectionIdSchema = _enum([
|
|
19742
|
+
"device-state",
|
|
19743
|
+
"streams",
|
|
19744
|
+
"battery",
|
|
19745
|
+
"consumables",
|
|
19746
|
+
"tanks",
|
|
19747
|
+
"detection-blind",
|
|
19748
|
+
"nodes",
|
|
19749
|
+
"addons",
|
|
19750
|
+
"updates"
|
|
19751
|
+
]);
|
|
19877
19752
|
/** One section of a previewed state summary. `unavailable` = its state could not be read. */
|
|
19878
19753
|
var NcStateSummaryPreviewSectionSchema = object({
|
|
19879
|
-
id:
|
|
19754
|
+
id: NcStateSummarySectionIdSchema,
|
|
19880
19755
|
status: _enum(["read", "unavailable"]),
|
|
19881
19756
|
items: number().int().nonnegative(),
|
|
19882
19757
|
reason: string().optional()
|
|
@@ -19886,7 +19761,7 @@ var NcStateSummaryPreviewSectionSchema = object({
|
|
|
19886
19761
|
* a `rule` split (no `section`), one section's on a `section` split.
|
|
19887
19762
|
*/
|
|
19888
19763
|
var NcStateSummaryPreviewRowSchema = object({
|
|
19889
|
-
section:
|
|
19764
|
+
section: NcStateSummarySectionIdSchema.optional(),
|
|
19890
19765
|
/** The section's name on a per-section row; every reported section's, joined, on a combined one. */
|
|
19891
19766
|
title: string(),
|
|
19892
19767
|
text: string(),
|
|
@@ -20323,6 +20198,29 @@ object({
|
|
|
20323
20198
|
firstAt: number(),
|
|
20324
20199
|
lastAt: number()
|
|
20325
20200
|
});
|
|
20201
|
+
var NC_ALARM_TRIGGERED_MAX_SEC = 3600;
|
|
20202
|
+
var NcAlarmDelaySecSchema = number().int().min(0).max(600);
|
|
20203
|
+
var NcAlarmTriggeredSecSchema = number().int().min(0).max(NC_ALARM_TRIGGERED_MAX_SEC);
|
|
20204
|
+
var uniqueModes = (entries) => new Set(entries.map((e) => e.mode)).size === entries.length;
|
|
20205
|
+
var NcAlarmModeDelaysListSchema = array(object({
|
|
20206
|
+
mode: AlarmArmModeSchema,
|
|
20207
|
+
exitDelaySec: NcAlarmDelaySecSchema.optional(),
|
|
20208
|
+
entryDelaySec: NcAlarmDelaySecSchema.optional(),
|
|
20209
|
+
triggeredDurationSec: NcAlarmTriggeredSecSchema.optional()
|
|
20210
|
+
})).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
|
|
20211
|
+
var NcAlarmModeDelaysEditListSchema = array(object({
|
|
20212
|
+
mode: AlarmArmModeSchema,
|
|
20213
|
+
exitDelaySec: NcAlarmDelaySecSchema.nullable().optional(),
|
|
20214
|
+
entryDelaySec: NcAlarmDelaySecSchema.nullable().optional(),
|
|
20215
|
+
triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional()
|
|
20216
|
+
})).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
|
|
20217
|
+
/** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
|
|
20218
|
+
var NcAlarmNonBlockingEditSchema = object({
|
|
20219
|
+
mode: AlarmArmModeSchema,
|
|
20220
|
+
deviceId: number().int().positive(),
|
|
20221
|
+
/** true = on the list (may be open, does not block); false = off the list (blocks). */
|
|
20222
|
+
nonBlocking: boolean()
|
|
20223
|
+
});
|
|
20326
20224
|
/**
|
|
20327
20225
|
* The per-mode lists, at most one per mode. Two lists for one mode have no
|
|
20328
20226
|
* meaning a reader could agree on (union? the last one?), so they are refused
|
|
@@ -20331,10 +20229,10 @@ object({
|
|
|
20331
20229
|
var NcAlarmNonBlockingListSchema = array(object({
|
|
20332
20230
|
mode: AlarmArmModeSchema,
|
|
20333
20231
|
deviceIds: array(number().int()).max(200)
|
|
20334
|
-
})).max(8).refine(
|
|
20232
|
+
})).max(8).refine(uniqueModes, { message: "nonBlocking: at most one list per arm mode" });
|
|
20335
20233
|
/**
|
|
20336
|
-
* The three durations
|
|
20337
|
-
* transitions, and which openings each mode tolerates.
|
|
20234
|
+
* The three durations — global, and per mode since D697 — the panel's state
|
|
20235
|
+
* machine runs on, who hears about its transitions, and which openings each mode tolerates.
|
|
20338
20236
|
*
|
|
20339
20237
|
* They live on the NOTIFICATION-RULES cap, not on `alarm-panel`, on purpose:
|
|
20340
20238
|
* `alarm-panel` is `deviceNative` and its other provider mirrors somebody
|
|
@@ -20344,15 +20242,15 @@ var NcAlarmNonBlockingListSchema = array(object({
|
|
|
20344
20242
|
*/
|
|
20345
20243
|
var NcAlarmSettingsSchema = object({
|
|
20346
20244
|
/** Grace period between arming and the mode taking effect. 0 = immediate. */
|
|
20347
|
-
exitDelaySec:
|
|
20245
|
+
exitDelaySec: NcAlarmDelaySecSchema,
|
|
20348
20246
|
/** Grace period between a trigger and the alarm firing. 0 = immediate. */
|
|
20349
|
-
entryDelaySec:
|
|
20247
|
+
entryDelaySec: NcAlarmDelaySecSchema,
|
|
20350
20248
|
/**
|
|
20351
20249
|
* How long `triggered` lasts before the panel re-arms itself.
|
|
20352
20250
|
* **0 = until an operator disarms it** — the behaviour before this field
|
|
20353
20251
|
* existed, and therefore what an untouched install keeps doing.
|
|
20354
20252
|
*/
|
|
20355
|
-
triggeredDurationSec:
|
|
20253
|
+
triggeredDurationSec: NcAlarmTriggeredSecSchema,
|
|
20356
20254
|
/**
|
|
20357
20255
|
* Deprecated by D630 — every transition is announced. Parsed, never read;
|
|
20358
20256
|
* remove after one release. Optional so an older admin's patch (which still
|
|
@@ -20375,17 +20273,30 @@ var NcAlarmSettingsSchema = object({
|
|
|
20375
20273
|
* per mode is meaningful. Defaulted to `[]` so a blob stored before D630
|
|
20376
20274
|
* parses as "every opening blocks" — the behaviour it was written under.
|
|
20377
20275
|
*/
|
|
20378
|
-
nonBlocking: NcAlarmNonBlockingListSchema.default([])
|
|
20276
|
+
nonBlocking: NcAlarmNonBlockingListSchema.default([]),
|
|
20277
|
+
/**
|
|
20278
|
+
* Per arm mode, the delays that mode OVERRIDES (D697). A mode with no entry, or an entry
|
|
20279
|
+
* without a field, uses the global value above — so `[]`, the default, is exactly the
|
|
20280
|
+
* behaviour of a blob stored before this field existed. Read through `resolveModeDelays`.
|
|
20281
|
+
*/
|
|
20282
|
+
modeDelays: NcAlarmModeDelaysListSchema.default([])
|
|
20379
20283
|
});
|
|
20380
20284
|
/**
|
|
20381
20285
|
* Every field optional — a tab edits one control at a time.
|
|
20382
20286
|
*
|
|
20383
|
-
* `nonBlocking`
|
|
20384
|
-
* remove an inner `.default()`, so a patch that never
|
|
20385
|
-
* parse to `
|
|
20386
|
-
* (the same trap {@link NcRulePatchSchema} documents).
|
|
20287
|
+
* `nonBlocking` and `modeDelays` are re-declared WITHOUT their defaults:
|
|
20288
|
+
* `.partial()` does not remove an inner `.default()`, so a patch that never
|
|
20289
|
+
* named the field would parse to `[]` and wipe every mode's list on an
|
|
20290
|
+
* unrelated edit (the same trap {@link NcRulePatchSchema} documents). Here
|
|
20291
|
+
* `modeDelays` means EDITS, not the stored overrides.
|
|
20387
20292
|
*/
|
|
20388
|
-
var NcAlarmSettingsPatchSchema = NcAlarmSettingsSchema.extend({
|
|
20293
|
+
var NcAlarmSettingsPatchSchema = NcAlarmSettingsSchema.extend({
|
|
20294
|
+
nonBlocking: NcAlarmNonBlockingListSchema,
|
|
20295
|
+
/** Per-mode, per-field edits — NOT the whole list (see NcAlarmModeDelaysEditSchema). */
|
|
20296
|
+
modeDelays: NcAlarmModeDelaysEditListSchema,
|
|
20297
|
+
/** ONE membership change; the panel applies it to the list it holds at its turn. */
|
|
20298
|
+
nonBlockingEdit: NcAlarmNonBlockingEditSchema
|
|
20299
|
+
}).partial().refine((p) => p.nonBlocking === void 0 || p.nonBlockingEdit === void 0, { message: "nonBlocking and nonBlockingEdit are exclusive — send the whole lists or one edit" });
|
|
20389
20300
|
/**
|
|
20390
20301
|
* What one arm mode actually arms, DERIVED from the enabled rules gated on it.
|
|
20391
20302
|
* Never authored, never stored — see `alarm-mode-coverage.ts` for why a stored
|
|
@@ -20485,6 +20396,28 @@ var NcAlarmConfigSchema = object({
|
|
|
20485
20396
|
*/
|
|
20486
20397
|
live: NcAlarmLiveSchema.optional()
|
|
20487
20398
|
});
|
|
20399
|
+
var NcAlarmSensorReadingSchema = _enum([
|
|
20400
|
+
"open",
|
|
20401
|
+
"closed",
|
|
20402
|
+
"unknown",
|
|
20403
|
+
"not-opening"
|
|
20404
|
+
]);
|
|
20405
|
+
/** One device's state as the alarm reads it — the classifier the arm check uses. */
|
|
20406
|
+
var NcAlarmSensorStateSchema = object({
|
|
20407
|
+
deviceId: number().int().positive(),
|
|
20408
|
+
reading: NcAlarmSensorReadingSchema,
|
|
20409
|
+
/** The word as read (`open`, `closed`, `unlocked`, `stopped`, …); null when unknown / not an opening. */
|
|
20410
|
+
state: string().nullable(),
|
|
20411
|
+
/** Why `unknown`: the read failed, or the slice holds no word its cap defines (a placeholder included). */
|
|
20412
|
+
unknownWhy: _enum(["read-failed", "unknown-word"]).nullable(),
|
|
20413
|
+
/** The device manager's liveness as the centre mirrors it; null = not known. */
|
|
20414
|
+
online: boolean().nullable()
|
|
20415
|
+
});
|
|
20416
|
+
var NcAlarmSensorsInputSchema = object({ deviceIds: array(number().int().positive()).max(500) });
|
|
20417
|
+
var NcAlarmSensorsSchema = object({
|
|
20418
|
+
sensors: array(NcAlarmSensorStateSchema),
|
|
20419
|
+
readAt: number().int().nonnegative()
|
|
20420
|
+
});
|
|
20488
20421
|
/**
|
|
20489
20422
|
* ONE rule's demand on ONE camera's clip ring.
|
|
20490
20423
|
*
|
|
@@ -20575,7 +20508,7 @@ method(object({}), object({ rules: array(NcRuleSchema) }), { auth: "admin" }), m
|
|
|
20575
20508
|
}), method(object({}), NcAlarmConfigSchema, { auth: "admin" }), method(object({ patch: NcAlarmSettingsPatchSchema }), NcAlarmConfigSchema, {
|
|
20576
20509
|
kind: "mutation",
|
|
20577
20510
|
auth: "admin"
|
|
20578
|
-
});
|
|
20511
|
+
}), method(NcAlarmSensorsInputSchema, NcAlarmSensorsSchema, { auth: "admin" });
|
|
20579
20512
|
/**
|
|
20580
20513
|
* Zod schemas for persisted record types.
|
|
20581
20514
|
*
|
|
@@ -20922,12 +20855,26 @@ var CameraSensorRefSchema = object({
|
|
|
20922
20855
|
function cameraSensorRefKey(ref) {
|
|
20923
20856
|
return `${ref.addonId}/${ref.stableId}`;
|
|
20924
20857
|
}
|
|
20925
|
-
/**
|
|
20926
|
-
|
|
20927
|
-
|
|
20928
|
-
|
|
20929
|
-
|
|
20930
|
-
|
|
20858
|
+
/**
|
|
20859
|
+
* A sensor's mode (D673). `in-addition`: its motion is the camera's motion too.
|
|
20860
|
+
* `replace`: its motion is the camera's, and while one is READY the camera's
|
|
20861
|
+
* own motion no longer counts on its own. `confirm`: while one is READY the
|
|
20862
|
+
* camera's own motion counts only while a confirm sensor is active — with or
|
|
20863
|
+
* without a replace sensor (spec C2, the controller's ruling on Q1).
|
|
20864
|
+
*/
|
|
20865
|
+
var CameraSensorModeSchema = _enum([
|
|
20866
|
+
"in-addition",
|
|
20867
|
+
"confirm",
|
|
20868
|
+
"replace"
|
|
20869
|
+
]);
|
|
20870
|
+
/** A stored sensor with no mode — every CS-1 row — is in addition. */
|
|
20871
|
+
var DEFAULT_CAMERA_SENSOR_MODE = "in-addition";
|
|
20872
|
+
/**
|
|
20873
|
+
* A camera's attached sensors. A CS-1 row carried an envelope
|
|
20874
|
+
* `mode: 'in-addition'`: `z.object` drops it on parse, and the PARSED value is
|
|
20875
|
+
* what the write stores (D672 rule 3), so it is never written again.
|
|
20876
|
+
*/
|
|
20877
|
+
var CameraSensorsConfigSchema = object({ sensors: array(CameraSensorRefSchema.extend({ mode: CameraSensorModeSchema.default(DEFAULT_CAMERA_SENSOR_MODE) })).min(1).max(8) }).superRefine((value, ctx) => {
|
|
20931
20878
|
const seen = /* @__PURE__ */ new Set();
|
|
20932
20879
|
value.sensors.forEach((ref, index) => {
|
|
20933
20880
|
const key = cameraSensorRefKey(ref);
|
|
@@ -20939,39 +20886,41 @@ var CameraSensorsConfigSchema = object({
|
|
|
20939
20886
|
seen.add(key);
|
|
20940
20887
|
});
|
|
20941
20888
|
});
|
|
20942
|
-
|
|
20889
|
+
/** Every attachment names its mode; an older orchestrator that does not is in addition. */
|
|
20890
|
+
var AttachmentFields = {
|
|
20943
20891
|
addonId: string(),
|
|
20944
|
-
stableId: string()
|
|
20892
|
+
stableId: string(),
|
|
20893
|
+
mode: CameraSensorModeSchema.default(DEFAULT_CAMERA_SENSOR_MODE)
|
|
20945
20894
|
};
|
|
20946
20895
|
var CameraSensorAttachmentSchema = discriminatedUnion("state", [
|
|
20947
20896
|
object({
|
|
20948
|
-
...
|
|
20897
|
+
...AttachmentFields,
|
|
20949
20898
|
state: literal("ready"),
|
|
20950
20899
|
deviceId: number(),
|
|
20951
20900
|
name: string(),
|
|
20952
20901
|
caps: array(string()).readonly()
|
|
20953
20902
|
}),
|
|
20954
20903
|
object({
|
|
20955
|
-
...
|
|
20904
|
+
...AttachmentFields,
|
|
20956
20905
|
state: literal("offline"),
|
|
20957
20906
|
deviceId: number(),
|
|
20958
20907
|
name: string(),
|
|
20959
20908
|
reason: _enum(["offline", "disabled"])
|
|
20960
20909
|
}),
|
|
20961
20910
|
object({
|
|
20962
|
-
...
|
|
20911
|
+
...AttachmentFields,
|
|
20963
20912
|
state: literal("missing"),
|
|
20964
20913
|
reason: string()
|
|
20965
20914
|
}),
|
|
20966
20915
|
object({
|
|
20967
|
-
...
|
|
20916
|
+
...AttachmentFields,
|
|
20968
20917
|
state: literal("unsupported"),
|
|
20969
20918
|
deviceId: number(),
|
|
20970
20919
|
name: string(),
|
|
20971
20920
|
reason: string()
|
|
20972
20921
|
}),
|
|
20973
20922
|
object({
|
|
20974
|
-
...
|
|
20923
|
+
...AttachmentFields,
|
|
20975
20924
|
state: literal("unreadable"),
|
|
20976
20925
|
reason: string()
|
|
20977
20926
|
})
|
|
@@ -20984,17 +20933,49 @@ var CameraSensorAttachmentSchema = discriminatedUnion("state", [
|
|
|
20984
20933
|
* say.
|
|
20985
20934
|
*/
|
|
20986
20935
|
var CameraSensorsNotForwardedSchema = _enum(["onboard-not-listed", "no-active-detection"]);
|
|
20936
|
+
/** Whether the camera's OWN motion counts on its own (D673 C2), from its READY sensors (C3). */
|
|
20937
|
+
var CameraOwnMotionSchema = _enum([
|
|
20938
|
+
"always",
|
|
20939
|
+
"when-confirmed",
|
|
20940
|
+
"never"
|
|
20941
|
+
]);
|
|
20942
|
+
/** Confirm / Replace cannot suppress this camera's motion: its provider still emits it directly (D673 C13). */
|
|
20943
|
+
var CameraSensorsNotEnforcedSchema = _enum(["provider-not-split"]);
|
|
20944
|
+
/**
|
|
20945
|
+
* The camera's OWN onboard motion (D696): the raw input the bridge combines,
|
|
20946
|
+
* never the effective value. The camera's `motion` slice is the effective one,
|
|
20947
|
+
* so a view of the camera's own row reads this.
|
|
20948
|
+
* - `atMs`: when the bridge received the camera's last own edge.
|
|
20949
|
+
* - `detected`: evaluated WHEN THE STATUS IS ASKED — the last edge said `true`
|
|
20950
|
+
* AND it is younger than the window the bridge counts the camera's own motion
|
|
20951
|
+
* for (`motionCooldownMs`, floored at two sustain ticks). A camera that never
|
|
20952
|
+
* sends a clear (heartbeats only) therefore reads `false` once no push came
|
|
20953
|
+
* within the window; a status read is a snapshot, so a live view re-asks.
|
|
20954
|
+
* Absent = this orchestrator has not received the camera's own motion since it
|
|
20955
|
+
* started (unknown, never "quiet"), or an orchestrator older than D696.
|
|
20956
|
+
*/
|
|
20957
|
+
var CameraRawLevelSchema = object({
|
|
20958
|
+
detected: boolean(),
|
|
20959
|
+
atMs: number()
|
|
20960
|
+
});
|
|
20987
20961
|
var CameraSensorsStatusSchema = discriminatedUnion("state", [
|
|
20988
|
-
object({
|
|
20962
|
+
object({
|
|
20963
|
+
state: literal("not-configured"),
|
|
20964
|
+
cameraLevel: CameraRawLevelSchema.optional()
|
|
20965
|
+
}),
|
|
20989
20966
|
object({
|
|
20990
20967
|
state: literal("unreadable"),
|
|
20991
|
-
reason: string()
|
|
20968
|
+
reason: string(),
|
|
20969
|
+
cameraLevel: CameraRawLevelSchema.optional()
|
|
20992
20970
|
}),
|
|
20993
20971
|
object({
|
|
20994
20972
|
state: literal("configured"),
|
|
20995
|
-
|
|
20973
|
+
cameraLevel: CameraRawLevelSchema.optional(),
|
|
20996
20974
|
sensors: array(CameraSensorAttachmentSchema).readonly(),
|
|
20997
|
-
|
|
20975
|
+
/** Absent = an orchestrator older than CS-2: it does not say (D315). */
|
|
20976
|
+
cameraMotion: CameraOwnMotionSchema.optional(),
|
|
20977
|
+
notForwarded: CameraSensorsNotForwardedSchema.optional(),
|
|
20978
|
+
notEnforced: CameraSensorsNotEnforcedSchema.optional()
|
|
20998
20979
|
})
|
|
20999
20980
|
]);
|
|
21000
20981
|
Object.freeze({
|
|
@@ -21679,14 +21660,14 @@ var TrackSchema = object({
|
|
|
21679
21660
|
* `derive-returned-null tile=standin`,
|
|
21680
21661
|
* `native-tile tile=native no-key-frame-at-close`, …) written at close and
|
|
21681
21662
|
* CLEARED by the late-keyFrame upgrade when a native tile lands after all.
|
|
21682
|
-
* The operator-facing answer to "perché manca l'immagine?" on a track whose
|
|
21663
|
+
* The operator-facing answer to "perché manca l'immagine?" [why is the image missing?] on a track whose
|
|
21683
21664
|
* tile is a face/plate stand-in, a raster crop, or an icon.
|
|
21684
21665
|
*
|
|
21685
21666
|
* **`no-key-frame-at-close` (D400).** The line used to be written ONLY when
|
|
21686
21667
|
* the TILE ranked below native, so a track whose thumbnail landed natively
|
|
21687
21668
|
* while its key frame missed carried no reason at all — three of the four
|
|
21688
21669
|
* `MISSING_KEYFRAME` tracks in the 2026-09-07 operator audit were exactly
|
|
21689
|
-
* that shape, and their "niente ultimo" had no cause anywhere on the row.
|
|
21670
|
+
* that shape, and their "niente ultimo" [no last frame] had no cause anywhere on the row.
|
|
21690
21671
|
* The key frame is the head of a cascade (`keyFrame ⇒ keyFrameSmall ⇒ the
|
|
21691
21672
|
* lastFrame copy source`), so its absence is now on this line whatever the
|
|
21692
21673
|
* tile ended up being.
|
|
@@ -21773,7 +21754,7 @@ var MotionEventSchema = object({
|
|
|
21773
21754
|
/**
|
|
21774
21755
|
* Ms offsets from `timestamp` (the episode's own first rising edge, so the
|
|
21775
21756
|
* first entry is always `0`) of every genuine off→on transition the
|
|
21776
|
-
* episode saw — "ogni evento on si deve salvare" (D475). NOT one entry per
|
|
21757
|
+
* episode saw — "ogni evento on si deve salvare" [every ON event must be saved] (D475). NOT one entry per
|
|
21777
21758
|
* push: a firmware source that keepalives at ~1 Hz for the whole burst
|
|
21778
21759
|
* (Reolink, Hikvision) produces exactly one edge; a source that reports an
|
|
21779
21760
|
* explicit `false` mid-episode and then resumes before the quiet window
|
|
@@ -22297,6 +22278,7 @@ var KeyEventSchema = object({
|
|
|
22297
22278
|
bestEventId: string(),
|
|
22298
22279
|
/** Track lifetime in ms (lastSeen - firstSeen). */
|
|
22299
22280
|
windowMs: number().optional(),
|
|
22281
|
+
audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
|
|
22300
22282
|
...TrackFlagFields,
|
|
22301
22283
|
...TrackRetrainFields
|
|
22302
22284
|
});
|
|
@@ -24225,8 +24207,10 @@ var RunnerCameraConfigSchema = object({
|
|
|
24225
24207
|
* - `analyzer`: ML/frame-diff motion detection (motion-wasm or other
|
|
24226
24208
|
* analyzer providers) running on decoded frames in this runner.
|
|
24227
24209
|
* - `onboard`: camera-native motion pushes (Reolink Baichuan, ONVIF
|
|
24228
|
-
* analytics). The provider emits ProviderMotion
|
|
24229
|
-
*
|
|
24210
|
+
* analytics). The provider emits its raw push as `ProviderMotion`
|
|
24211
|
+
* (D673); the orchestrator's camera-sensors bridge re-emits the camera's
|
|
24212
|
+
* effective motion as `MotionOnMotionChanged`, which is what reaches
|
|
24213
|
+
* `reportMotion`.
|
|
24230
24214
|
*/
|
|
24231
24215
|
motionSources: MotionSourcesSchema.default(["analyzer"]),
|
|
24232
24216
|
/**
|
|
@@ -24403,7 +24387,15 @@ var RunnerLocalLoadSchema = object({
|
|
|
24403
24387
|
hasGpu: boolean(),
|
|
24404
24388
|
inferenceBackend: string().optional(),
|
|
24405
24389
|
cpuCores: number().optional()
|
|
24406
|
-
})
|
|
24390
|
+
}),
|
|
24391
|
+
/**
|
|
24392
|
+
* Who writes a camera's `motion` runtime slice (D696). `'orchestrator'`: this
|
|
24393
|
+
* runner never writes it. ABSENT = a runner older than D696, which still
|
|
24394
|
+
* writes the slice from its phase machine; the orchestrator does not write
|
|
24395
|
+
* while any runner node is absent-or-unanswered, so one slice never has two
|
|
24396
|
+
* writers.
|
|
24397
|
+
*/
|
|
24398
|
+
motionSliceWriter: literal("orchestrator").optional()
|
|
24407
24399
|
});
|
|
24408
24400
|
/**
|
|
24409
24401
|
* Aggregate runtime metrics for the runner's whole local pool. Mirrors the
|
|
@@ -27068,7 +27060,7 @@ var ClipPlaybackSchema = object({
|
|
|
27068
27060
|
* **One authorised yes is one wake.** `next-natural` — take the clip the next
|
|
27069
27061
|
* time the camera is awake for its own reasons — is deliberately not a member:
|
|
27070
27062
|
* it was proposed, it is free on the battery, and the operator declined it on
|
|
27071
|
-
* 2026-09-20 (*"Quando un export viene richiesto si sveglia la camera."
|
|
27063
|
+
* 2026-09-20 (*"Quando un export viene richiesto si sveglia la camera."* [When an export is requested the camera wakes up],
|
|
27072
27064
|
* D558 "Considered and not taken").
|
|
27073
27065
|
*/
|
|
27074
27066
|
var ClipWakeSchema = _enum(["authorised"]);
|
|
@@ -27329,7 +27321,7 @@ DeviceType.Camera, method(object({
|
|
|
27329
27321
|
* It replaced `sources?: string[]`, a VIEW filter over source ids that
|
|
27330
27322
|
* assumed the answer was a fan-out over everything a camera has. The
|
|
27331
27323
|
* operator settled otherwise on 2026-09-20 — *"l'utilizzatore è uno
|
|
27332
|
-
* solo"* — so the list is asked of one provider at a time and there is
|
|
27324
|
+
* solo"* [there is only one user] — so the list is asked of one provider at a time and there is
|
|
27333
27325
|
* nothing to filter out of it.
|
|
27334
27326
|
*/
|
|
27335
27327
|
provider: string().min(1)
|
|
@@ -29932,6 +29924,70 @@ onStatusChanged: { data: object({
|
|
|
29932
29924
|
* whether persisting is worth a SQLite commit. */
|
|
29933
29925
|
volatileStateFields: ["lastChangedAt"]
|
|
29934
29926
|
};
|
|
29927
|
+
var DoorbellStatusSchema = object({
|
|
29928
|
+
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
29929
|
+
lastPressedAt: number().nullable(),
|
|
29930
|
+
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
29931
|
+
pressCountSinceStart: number()
|
|
29932
|
+
});
|
|
29933
|
+
var DoorbellPressEventSchema = object({
|
|
29934
|
+
deviceId: number(),
|
|
29935
|
+
timestamp: number()
|
|
29936
|
+
});
|
|
29937
|
+
/**
|
|
29938
|
+
* Doorbell button cap. Two kinds of provider serve it, and to every consumer
|
|
29939
|
+
* they are the same cap:
|
|
29940
|
+
*
|
|
29941
|
+
* - **Native** providers, registered per device by a driver addon through
|
|
29942
|
+
* `ctx.registerNativeCap` — a `DeviceType.Button` accessory with
|
|
29943
|
+
* `role: DeviceRole.Doorbell`, or the camera itself (Reolink registers at
|
|
29944
|
+
* camera level). They emit `onPressed` on every firmware ring.
|
|
29945
|
+
* - **A composed doorbell** (D670, D671): a camera's customization gives it
|
|
29946
|
+
* the cap, its `lastPressedAt` rising from the sources the operator
|
|
29947
|
+
* assigned in Customize → Doorbell, and the composer emits `onPressed`
|
|
29948
|
+
* from that field's advance (`fromState`).
|
|
29949
|
+
*
|
|
29950
|
+
* The DeviceEventPropagator re-emits `onPressed` on the camera parent.
|
|
29951
|
+
*/
|
|
29952
|
+
var doorbellCapability = {
|
|
29953
|
+
name: "doorbell",
|
|
29954
|
+
scope: "device",
|
|
29955
|
+
deviceNative: true,
|
|
29956
|
+
mode: "singleton",
|
|
29957
|
+
deviceTypes: [DeviceType.Button, DeviceType.Camera],
|
|
29958
|
+
methods: {},
|
|
29959
|
+
events: {
|
|
29960
|
+
/**
|
|
29961
|
+
* Fires once per physical press. Reolink delivers via Baichuan
|
|
29962
|
+
* push (`ReolinkSimpleEvent.type === 'doorbell'`). There is no
|
|
29963
|
+
* release/duration — it's a pulse.
|
|
29964
|
+
*/
|
|
29965
|
+
onPressed: {
|
|
29966
|
+
data: DoorbellPressEventSchema,
|
|
29967
|
+
fromState: {
|
|
29968
|
+
field: "lastPressedAt",
|
|
29969
|
+
on: "advance"
|
|
29970
|
+
}
|
|
29971
|
+
} },
|
|
29972
|
+
status: {
|
|
29973
|
+
schema: DoorbellStatusSchema,
|
|
29974
|
+
kind: "push"
|
|
29975
|
+
},
|
|
29976
|
+
/**
|
|
29977
|
+
* Runtime-state slice — last press timestamp + lifetime press count.
|
|
29978
|
+
* Mirrored by the kernel and readable via
|
|
29979
|
+
* `device.state.doorbell.value`. UIs can show "last ring 5m ago"
|
|
29980
|
+
* without subscribing.
|
|
29981
|
+
*/
|
|
29982
|
+
runtimeState: DoorbellStatusSchema,
|
|
29983
|
+
/**
|
|
29984
|
+
* Runtime-state durability: **restored** — a monotonic accumulator: the slice IS the record. `lastPressedAt` is content here, not a clock, so it is deliberately NOT volatile.
|
|
29985
|
+
*
|
|
29986
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
29987
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
29988
|
+
*/
|
|
29989
|
+
durability: "restored"
|
|
29990
|
+
};
|
|
29935
29991
|
/**
|
|
29936
29992
|
* Enum-state sensor — a string value picked from a finite option set.
|
|
29937
29993
|
* Drives HA `sensor` entries with `state_class: enum` (HVAC action
|
|
@@ -32076,9 +32132,9 @@ var MotionStatusSchema = object({
|
|
|
32076
32132
|
/** Ms epoch of the last detected-true observation. Null if never detected. */
|
|
32077
32133
|
lastDetectedAt: number().nullable(),
|
|
32078
32134
|
/**
|
|
32079
|
-
* `MOTION_CLOSE_AFTER_MS` while `detected: true` on a `Camera` device
|
|
32080
|
-
* `null` while false and on every `Sensor`
|
|
32081
|
-
* constant's doc for the one-authority rule.
|
|
32135
|
+
* `MOTION_CLOSE_AFTER_MS` while `detected: true` on a `Camera` device (the
|
|
32136
|
+
* orchestrator writes it, D696), `null` while false and on every `Sensor`
|
|
32137
|
+
* device (D475) — see that constant's doc for the one-authority rule.
|
|
32082
32138
|
*
|
|
32083
32139
|
* ## Reading this field still arms nothing
|
|
32084
32140
|
*
|
|
@@ -32096,34 +32152,31 @@ var MotionStatusSchema = object({
|
|
|
32096
32152
|
* `addon-export-alexa/src/motion-clear-hold.ts` and
|
|
32097
32153
|
* `addon-export-hap`'s `RESET_DEBOUNCE_MS` both do.
|
|
32098
32154
|
*
|
|
32099
|
-
* ## Who writes it
|
|
32100
|
-
*
|
|
32101
|
-
* - **Cameras** — the
|
|
32102
|
-
*
|
|
32103
|
-
* `
|
|
32104
|
-
* `
|
|
32105
|
-
*
|
|
32106
|
-
*
|
|
32107
|
-
* a
|
|
32108
|
-
*
|
|
32109
|
-
*
|
|
32110
|
-
*
|
|
32111
|
-
*
|
|
32112
|
-
*
|
|
32113
|
-
*
|
|
32114
|
-
*
|
|
32115
|
-
*
|
|
32116
|
-
*
|
|
32117
|
-
* `
|
|
32118
|
-
*
|
|
32119
|
-
*
|
|
32120
|
-
*
|
|
32121
|
-
*
|
|
32122
|
-
*
|
|
32123
|
-
*
|
|
32124
|
-
* This predates D475 and is not fixed there: the fix touches every
|
|
32125
|
-
* camera provider. Recorded in D475's Consequences. Do not restore the
|
|
32126
|
-
* "sole writer" wording without also removing the other writers.
|
|
32155
|
+
* ## Who writes it (D696)
|
|
32156
|
+
*
|
|
32157
|
+
* - **Cameras** — the orchestrator, and nothing else. It writes the camera's
|
|
32158
|
+
* EFFECTIVE motion (`addon-pipeline-orchestrator`
|
|
32159
|
+
* `camera-sensors/motion-slice.ts`), alongside the effective
|
|
32160
|
+
* `MotionOnMotionChanged` it emits or receives: the camera-sensors bridge
|
|
32161
|
+
* for a split camera, an unsplit emitter's direct event, the analyzer and
|
|
32162
|
+
* device activity, as the camera's `motionSources` counts them. A source
|
|
32163
|
+
* that never sends a clear falls one window after its last `true`.
|
|
32164
|
+
* `lastDetectedAt` moves only on an effective rise. No camera provider
|
|
32165
|
+
* writes this slice (not even a boot seed), and neither does the runner's
|
|
32166
|
+
* phase machine: its phase is "a session is attached" for every on-motion
|
|
32167
|
+
* session, not motion, and it now has its own `DetectionPhaseTransition`.
|
|
32168
|
+
* A provider's `isDetected` answers from the hub's slice.
|
|
32169
|
+
* - **Sensors** (Home Assistant binary sensors, Homematic, Matter, Alexa
|
|
32170
|
+
* imports) — the provider pushes both edges itself, from the upstream
|
|
32171
|
+
* system's own state change. That is the sensor's own fact.
|
|
32172
|
+
*
|
|
32173
|
+
* `scripts/check-onboard-motion-emitters.ts` refuses any other writer of a
|
|
32174
|
+
* `motion` slice; each sensor writer is a named exemption.
|
|
32175
|
+
*
|
|
32176
|
+
* This replaces the D475 §4 rule ("the phase machine is the sole writer").
|
|
32177
|
+
* That rule was never true: Hikvision and Amcrest wrote the slice raw beside
|
|
32178
|
+
* it, every provider seeded it at boot, and every session left it
|
|
32179
|
+
* `detected: true` after its detach.
|
|
32127
32180
|
*/
|
|
32128
32181
|
autoClearAfterMs: number().nullable()
|
|
32129
32182
|
});
|
|
@@ -32195,11 +32248,12 @@ onMotionChanged: { data: MotionOnMotionChangedDataSchema } },
|
|
|
32195
32248
|
*/
|
|
32196
32249
|
runtimeState: MotionStatusSchema,
|
|
32197
32250
|
/**
|
|
32198
|
-
* Runtime-state durability: **session** —
|
|
32251
|
+
* Runtime-state durability: **session** — the writer of this slice
|
|
32199
32252
|
* writes only on an EDGE, so a restored `detected: true` would stay
|
|
32200
32253
|
* frozen until the next one instead of being corrected. The next edge
|
|
32201
|
-
* re-publishes the real state
|
|
32202
|
-
*
|
|
32254
|
+
* re-publishes the real state, and the orchestrator re-publishes every
|
|
32255
|
+
* camera when it starts writing (D696; on who writes it, see
|
|
32256
|
+
* `autoClearAfterMs` above).
|
|
32203
32257
|
*
|
|
32204
32258
|
* See `RuntimeStateDurability`. Enforced by
|
|
32205
32259
|
* `scripts/check-runtime-state-durability.ts`.
|
|
@@ -34582,8 +34636,7 @@ var ptzAutotrackCapability = {
|
|
|
34582
34636
|
deviceNative: true,
|
|
34583
34637
|
mode: "singleton",
|
|
34584
34638
|
/**
|
|
34585
|
-
* Two kinds of provider behind one name, the same shape `snapshot`
|
|
34586
|
-
* `doorbell` use:
|
|
34639
|
+
* Two kinds of provider behind one name, the same shape `snapshot` uses:
|
|
34587
34640
|
*
|
|
34588
34641
|
* - **Native**: the camera's own firmware autotrack, registered per device by
|
|
34589
34642
|
* the driver when the probe says it exists (Reolink: yes; Hikvision:
|
|
@@ -34591,7 +34644,7 @@ var ptzAutotrackCapability = {
|
|
|
34591
34644
|
* - **Wrapper**: the emulated implementation (`@camstack/system`'s `autotrack` builtin),
|
|
34592
34645
|
* which follows a subject with `ptz.move` pulses driven by the detection
|
|
34593
34646
|
* pipeline. `defaultActive: false` — the operator binds it per camera in
|
|
34594
|
-
* the bindings UI
|
|
34647
|
+
* the bindings UI.
|
|
34595
34648
|
*
|
|
34596
34649
|
* The binding chooses WHICH implementation answers; `setEnabled` stays the
|
|
34597
34650
|
* one switch for the function either way. A camera never has both driving its
|
|
@@ -35266,7 +35319,7 @@ var ReadGopBytesResultSchema = object({
|
|
|
35266
35319
|
/**
|
|
35267
35320
|
* A time WINDOW of one finalized segment, cut by byte range — the multi-GOP
|
|
35268
35321
|
* twin of {@link ReadGopBytesResultSchema}'s single instant. Built for the
|
|
35269
|
-
* replay clip's `recording` source (`docs/design/plans/2026-08-26-replay-
|
|
35322
|
+
* replay clip's `recording` source (`docs/design/plans/2026-08-26-clip-replay-on-pipeline.md`):
|
|
35270
35323
|
* a replay needs several seconds of native pixels, not one frame.
|
|
35271
35324
|
*
|
|
35272
35325
|
* `ok.data` is standalone-demuxable, same as a GOP read. `ok.reachesRequestedEnd`
|
|
@@ -38630,6 +38683,7 @@ var zoneRulesCapability = {
|
|
|
38630
38683
|
*/
|
|
38631
38684
|
durability: "restored"
|
|
38632
38685
|
};
|
|
38686
|
+
SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
|
|
38633
38687
|
/**
|
|
38634
38688
|
* Accessory device helpers — shared across drivers.
|
|
38635
38689
|
*
|
|
@@ -39689,13 +39743,14 @@ var BaseDeviceProvider = class extends BaseAddon {
|
|
|
39689
39743
|
async getStatus() {
|
|
39690
39744
|
const all = await this.ctx.kernel.devices?.getAll() ?? [];
|
|
39691
39745
|
const summary = this.restoreFailureSummary();
|
|
39692
|
-
|
|
39746
|
+
const base = {
|
|
39693
39747
|
connected: true,
|
|
39694
|
-
deviceCount: all.length
|
|
39748
|
+
deviceCount: all.length,
|
|
39749
|
+
motionSliceWriter: "orchestrator"
|
|
39695
39750
|
};
|
|
39751
|
+
if (summary === null) return base;
|
|
39696
39752
|
return {
|
|
39697
|
-
|
|
39698
|
-
deviceCount: all.length,
|
|
39753
|
+
...base,
|
|
39699
39754
|
error: summary
|
|
39700
39755
|
};
|
|
39701
39756
|
}
|
|
@@ -45131,6 +45186,12 @@ Object.freeze({
|
|
|
45131
45186
|
addonId: null,
|
|
45132
45187
|
access: "view"
|
|
45133
45188
|
},
|
|
45189
|
+
"notificationRules.getAlarmSensors": {
|
|
45190
|
+
capName: "notification-rules",
|
|
45191
|
+
capScope: "system",
|
|
45192
|
+
addonId: null,
|
|
45193
|
+
access: "view"
|
|
45194
|
+
},
|
|
45134
45195
|
"notificationRules.getClipRetentionAsks": {
|
|
45135
45196
|
capName: "notification-rules",
|
|
45136
45197
|
capScope: "system",
|
|
@@ -48709,6 +48770,11 @@ Object.freeze({
|
|
|
48709
48770
|
}
|
|
48710
48771
|
});
|
|
48711
48772
|
Object.freeze({
|
|
48773
|
+
"accessories.getStatus": [{
|
|
48774
|
+
name: "deviceId",
|
|
48775
|
+
form: "single",
|
|
48776
|
+
optional: false
|
|
48777
|
+
}],
|
|
48712
48778
|
"accessories.setChildHidden": [{
|
|
48713
48779
|
name: "childDeviceId",
|
|
48714
48780
|
form: "single",
|
|
@@ -48728,6 +48794,11 @@ Object.freeze({
|
|
|
48728
48794
|
form: "single",
|
|
48729
48795
|
optional: false
|
|
48730
48796
|
}],
|
|
48797
|
+
"airQualitySensor.getStatus": [{
|
|
48798
|
+
name: "deviceId",
|
|
48799
|
+
form: "single",
|
|
48800
|
+
optional: false
|
|
48801
|
+
}],
|
|
48731
48802
|
"alarmPanel.arm": [{
|
|
48732
48803
|
name: "deviceId",
|
|
48733
48804
|
form: "single",
|
|
@@ -48738,11 +48809,36 @@ Object.freeze({
|
|
|
48738
48809
|
form: "single",
|
|
48739
48810
|
optional: false
|
|
48740
48811
|
}],
|
|
48812
|
+
"alarmPanel.getStatus": [{
|
|
48813
|
+
name: "deviceId",
|
|
48814
|
+
form: "single",
|
|
48815
|
+
optional: false
|
|
48816
|
+
}],
|
|
48741
48817
|
"alarmPanel.trigger": [{
|
|
48742
48818
|
name: "deviceId",
|
|
48743
48819
|
form: "single",
|
|
48744
48820
|
optional: false
|
|
48745
48821
|
}],
|
|
48822
|
+
"ambientLightSensor.getStatus": [{
|
|
48823
|
+
name: "deviceId",
|
|
48824
|
+
form: "single",
|
|
48825
|
+
optional: false
|
|
48826
|
+
}],
|
|
48827
|
+
"audioAnalysis.applyDeviceSettingsPatch": [{
|
|
48828
|
+
name: "deviceId",
|
|
48829
|
+
form: "single",
|
|
48830
|
+
optional: false
|
|
48831
|
+
}],
|
|
48832
|
+
"audioAnalysis.getDeviceLiveContribution": [{
|
|
48833
|
+
name: "deviceId",
|
|
48834
|
+
form: "single",
|
|
48835
|
+
optional: false
|
|
48836
|
+
}],
|
|
48837
|
+
"audioAnalysis.getDeviceSettingsContribution": [{
|
|
48838
|
+
name: "deviceId",
|
|
48839
|
+
form: "single",
|
|
48840
|
+
optional: false
|
|
48841
|
+
}],
|
|
48746
48842
|
"audioAnalysis.resolveDeviceSettings": [{
|
|
48747
48843
|
name: "deviceId",
|
|
48748
48844
|
form: "single",
|
|
@@ -48783,16 +48879,36 @@ Object.freeze({
|
|
|
48783
48879
|
form: "single",
|
|
48784
48880
|
optional: false
|
|
48785
48881
|
}],
|
|
48882
|
+
"automationControl.getStatus": [{
|
|
48883
|
+
name: "deviceId",
|
|
48884
|
+
form: "single",
|
|
48885
|
+
optional: false
|
|
48886
|
+
}],
|
|
48786
48887
|
"automationControl.trigger": [{
|
|
48787
48888
|
name: "deviceId",
|
|
48788
48889
|
form: "single",
|
|
48789
48890
|
optional: false
|
|
48790
48891
|
}],
|
|
48892
|
+
"battery.getStatus": [{
|
|
48893
|
+
name: "deviceId",
|
|
48894
|
+
form: "single",
|
|
48895
|
+
optional: false
|
|
48896
|
+
}],
|
|
48791
48897
|
"battery.wakeForStream": [{
|
|
48792
48898
|
name: "deviceId",
|
|
48793
48899
|
form: "single",
|
|
48794
48900
|
optional: false
|
|
48795
48901
|
}],
|
|
48902
|
+
"binary.getStatus": [{
|
|
48903
|
+
name: "deviceId",
|
|
48904
|
+
form: "single",
|
|
48905
|
+
optional: false
|
|
48906
|
+
}],
|
|
48907
|
+
"brightness.getStatus": [{
|
|
48908
|
+
name: "deviceId",
|
|
48909
|
+
form: "single",
|
|
48910
|
+
optional: false
|
|
48911
|
+
}],
|
|
48796
48912
|
"brightness.setBrightness": [{
|
|
48797
48913
|
name: "deviceId",
|
|
48798
48914
|
form: "single",
|
|
@@ -48808,6 +48924,26 @@ Object.freeze({
|
|
|
48808
48924
|
form: "single",
|
|
48809
48925
|
optional: false
|
|
48810
48926
|
}],
|
|
48927
|
+
"cameraCredentials.getStatus": [{
|
|
48928
|
+
name: "deviceId",
|
|
48929
|
+
form: "single",
|
|
48930
|
+
optional: false
|
|
48931
|
+
}],
|
|
48932
|
+
"cameraGridLayout.applyDeviceSettingsPatch": [{
|
|
48933
|
+
name: "deviceId",
|
|
48934
|
+
form: "single",
|
|
48935
|
+
optional: false
|
|
48936
|
+
}],
|
|
48937
|
+
"cameraGridLayout.getDeviceLiveContribution": [{
|
|
48938
|
+
name: "deviceId",
|
|
48939
|
+
form: "single",
|
|
48940
|
+
optional: false
|
|
48941
|
+
}],
|
|
48942
|
+
"cameraGridLayout.getDeviceSettingsContribution": [{
|
|
48943
|
+
name: "deviceId",
|
|
48944
|
+
form: "single",
|
|
48945
|
+
optional: false
|
|
48946
|
+
}],
|
|
48811
48947
|
"cameraGridLayout.getLayout": [{
|
|
48812
48948
|
name: "deviceId",
|
|
48813
48949
|
form: "single",
|
|
@@ -48823,6 +48959,21 @@ Object.freeze({
|
|
|
48823
48959
|
form: "single",
|
|
48824
48960
|
optional: false
|
|
48825
48961
|
}],
|
|
48962
|
+
"cameraPipelineConfig.applyDeviceSettingsPatch": [{
|
|
48963
|
+
name: "deviceId",
|
|
48964
|
+
form: "single",
|
|
48965
|
+
optional: false
|
|
48966
|
+
}],
|
|
48967
|
+
"cameraPipelineConfig.getDeviceLiveContribution": [{
|
|
48968
|
+
name: "deviceId",
|
|
48969
|
+
form: "single",
|
|
48970
|
+
optional: false
|
|
48971
|
+
}],
|
|
48972
|
+
"cameraPipelineConfig.getDeviceSettingsContribution": [{
|
|
48973
|
+
name: "deviceId",
|
|
48974
|
+
form: "single",
|
|
48975
|
+
optional: false
|
|
48976
|
+
}],
|
|
48826
48977
|
"cameraStreams.getBrokerStreams": [{
|
|
48827
48978
|
name: "deviceId",
|
|
48828
48979
|
form: "single",
|
|
@@ -48848,6 +48999,16 @@ Object.freeze({
|
|
|
48848
48999
|
form: "single",
|
|
48849
49000
|
optional: false
|
|
48850
49001
|
}],
|
|
49002
|
+
"carbonMonoxide.getStatus": [{
|
|
49003
|
+
name: "deviceId",
|
|
49004
|
+
form: "single",
|
|
49005
|
+
optional: false
|
|
49006
|
+
}],
|
|
49007
|
+
"climateControl.getStatus": [{
|
|
49008
|
+
name: "deviceId",
|
|
49009
|
+
form: "single",
|
|
49010
|
+
optional: false
|
|
49011
|
+
}],
|
|
48851
49012
|
"climateControl.setFanMode": [{
|
|
48852
49013
|
name: "deviceId",
|
|
48853
49014
|
form: "single",
|
|
@@ -48888,16 +49049,41 @@ Object.freeze({
|
|
|
48888
49049
|
form: "single",
|
|
48889
49050
|
optional: false
|
|
48890
49051
|
}],
|
|
49052
|
+
"color.getStatus": [{
|
|
49053
|
+
name: "deviceId",
|
|
49054
|
+
form: "single",
|
|
49055
|
+
optional: false
|
|
49056
|
+
}],
|
|
48891
49057
|
"color.setColor": [{
|
|
48892
49058
|
name: "deviceId",
|
|
48893
49059
|
form: "single",
|
|
48894
49060
|
optional: false
|
|
48895
49061
|
}],
|
|
49062
|
+
"connectivity.getStatus": [{
|
|
49063
|
+
name: "deviceId",
|
|
49064
|
+
form: "single",
|
|
49065
|
+
optional: false
|
|
49066
|
+
}],
|
|
49067
|
+
"consumables.getStatus": [{
|
|
49068
|
+
name: "deviceId",
|
|
49069
|
+
form: "single",
|
|
49070
|
+
optional: false
|
|
49071
|
+
}],
|
|
48896
49072
|
"consumables.reset": [{
|
|
48897
49073
|
name: "deviceId",
|
|
48898
49074
|
form: "single",
|
|
48899
49075
|
optional: false
|
|
48900
49076
|
}],
|
|
49077
|
+
"contact.getStatus": [{
|
|
49078
|
+
name: "deviceId",
|
|
49079
|
+
form: "single",
|
|
49080
|
+
optional: false
|
|
49081
|
+
}],
|
|
49082
|
+
"control.getStatus": [{
|
|
49083
|
+
name: "deviceId",
|
|
49084
|
+
form: "single",
|
|
49085
|
+
optional: false
|
|
49086
|
+
}],
|
|
48901
49087
|
"control.setValue": [{
|
|
48902
49088
|
name: "deviceId",
|
|
48903
49089
|
form: "single",
|
|
@@ -48908,6 +49094,11 @@ Object.freeze({
|
|
|
48908
49094
|
form: "single",
|
|
48909
49095
|
optional: false
|
|
48910
49096
|
}],
|
|
49097
|
+
"cover.getStatus": [{
|
|
49098
|
+
name: "deviceId",
|
|
49099
|
+
form: "single",
|
|
49100
|
+
optional: false
|
|
49101
|
+
}],
|
|
48911
49102
|
"cover.open": [{
|
|
48912
49103
|
name: "deviceId",
|
|
48913
49104
|
form: "single",
|
|
@@ -48933,6 +49124,11 @@ Object.freeze({
|
|
|
48933
49124
|
form: "single",
|
|
48934
49125
|
optional: false
|
|
48935
49126
|
}],
|
|
49127
|
+
"dayNight.getStatus": [{
|
|
49128
|
+
name: "deviceId",
|
|
49129
|
+
form: "single",
|
|
49130
|
+
optional: false
|
|
49131
|
+
}],
|
|
48936
49132
|
"dayNight.setSettings": [{
|
|
48937
49133
|
name: "deviceId",
|
|
48938
49134
|
form: "single",
|
|
@@ -48943,11 +49139,31 @@ Object.freeze({
|
|
|
48943
49139
|
form: "single",
|
|
48944
49140
|
optional: true
|
|
48945
49141
|
}],
|
|
49142
|
+
"detectionPipeline.applyDeviceSettingsPatch": [{
|
|
49143
|
+
name: "deviceId",
|
|
49144
|
+
form: "single",
|
|
49145
|
+
optional: false
|
|
49146
|
+
}],
|
|
49147
|
+
"detectionPipeline.getDeviceLiveContribution": [{
|
|
49148
|
+
name: "deviceId",
|
|
49149
|
+
form: "single",
|
|
49150
|
+
optional: false
|
|
49151
|
+
}],
|
|
49152
|
+
"detectionPipeline.getDeviceSettingsContribution": [{
|
|
49153
|
+
name: "deviceId",
|
|
49154
|
+
form: "single",
|
|
49155
|
+
optional: false
|
|
49156
|
+
}],
|
|
48946
49157
|
"deviceAdminLink.getAdminLink": [{
|
|
48947
49158
|
name: "deviceId",
|
|
48948
49159
|
form: "single",
|
|
48949
49160
|
optional: false
|
|
48950
49161
|
}],
|
|
49162
|
+
"deviceAdoption.getStatus": [{
|
|
49163
|
+
name: "deviceId",
|
|
49164
|
+
form: "single",
|
|
49165
|
+
optional: false
|
|
49166
|
+
}],
|
|
48951
49167
|
"deviceAdoption.release": [{
|
|
48952
49168
|
name: "camDeviceId",
|
|
48953
49169
|
form: "single",
|
|
@@ -48963,6 +49179,11 @@ Object.freeze({
|
|
|
48963
49179
|
form: "single",
|
|
48964
49180
|
optional: false
|
|
48965
49181
|
}],
|
|
49182
|
+
"deviceDiscovery.getStatus": [{
|
|
49183
|
+
name: "deviceId",
|
|
49184
|
+
form: "single",
|
|
49185
|
+
optional: false
|
|
49186
|
+
}],
|
|
48966
49187
|
"deviceDiscovery.listDiscovered": [{
|
|
48967
49188
|
name: "deviceId",
|
|
48968
49189
|
form: "single",
|
|
@@ -48982,6 +49203,21 @@ Object.freeze({
|
|
|
48982
49203
|
form: "single",
|
|
48983
49204
|
optional: false
|
|
48984
49205
|
}],
|
|
49206
|
+
"deviceExport.applyDeviceSettingsPatch": [{
|
|
49207
|
+
name: "deviceId",
|
|
49208
|
+
form: "single",
|
|
49209
|
+
optional: false
|
|
49210
|
+
}],
|
|
49211
|
+
"deviceExport.getDeviceLiveContribution": [{
|
|
49212
|
+
name: "deviceId",
|
|
49213
|
+
form: "single",
|
|
49214
|
+
optional: false
|
|
49215
|
+
}],
|
|
49216
|
+
"deviceExport.getDeviceSettingsContribution": [{
|
|
49217
|
+
name: "deviceId",
|
|
49218
|
+
form: "single",
|
|
49219
|
+
optional: false
|
|
49220
|
+
}],
|
|
48985
49221
|
"deviceExtension.listCandidates": [{
|
|
48986
49222
|
name: "deviceId",
|
|
48987
49223
|
form: "single",
|
|
@@ -49330,6 +49566,26 @@ Object.freeze({
|
|
|
49330
49566
|
form: "single",
|
|
49331
49567
|
optional: false
|
|
49332
49568
|
}],
|
|
49569
|
+
"deviceStatus.getStatus": [{
|
|
49570
|
+
name: "deviceId",
|
|
49571
|
+
form: "single",
|
|
49572
|
+
optional: false
|
|
49573
|
+
}],
|
|
49574
|
+
"doorbell.getStatus": [{
|
|
49575
|
+
name: "deviceId",
|
|
49576
|
+
form: "single",
|
|
49577
|
+
optional: false
|
|
49578
|
+
}],
|
|
49579
|
+
"enumSensor.getStatus": [{
|
|
49580
|
+
name: "deviceId",
|
|
49581
|
+
form: "single",
|
|
49582
|
+
optional: false
|
|
49583
|
+
}],
|
|
49584
|
+
"eventEmitter.getStatus": [{
|
|
49585
|
+
name: "deviceId",
|
|
49586
|
+
form: "single",
|
|
49587
|
+
optional: false
|
|
49588
|
+
}],
|
|
49333
49589
|
"faceGallery.getFaceByTrack": [{
|
|
49334
49590
|
name: "deviceId",
|
|
49335
49591
|
form: "single",
|
|
@@ -49344,6 +49600,11 @@ Object.freeze({
|
|
|
49344
49600
|
form: "array",
|
|
49345
49601
|
optional: true
|
|
49346
49602
|
}],
|
|
49603
|
+
"fanControl.getStatus": [{
|
|
49604
|
+
name: "deviceId",
|
|
49605
|
+
form: "single",
|
|
49606
|
+
optional: false
|
|
49607
|
+
}],
|
|
49347
49608
|
"fanControl.setDirection": [{
|
|
49348
49609
|
name: "deviceId",
|
|
49349
49610
|
form: "single",
|
|
@@ -49364,6 +49625,26 @@ Object.freeze({
|
|
|
49364
49625
|
form: "single",
|
|
49365
49626
|
optional: false
|
|
49366
49627
|
}],
|
|
49628
|
+
"featureProbe.getStatus": [{
|
|
49629
|
+
name: "deviceId",
|
|
49630
|
+
form: "single",
|
|
49631
|
+
optional: false
|
|
49632
|
+
}],
|
|
49633
|
+
"flood.getStatus": [{
|
|
49634
|
+
name: "deviceId",
|
|
49635
|
+
form: "single",
|
|
49636
|
+
optional: false
|
|
49637
|
+
}],
|
|
49638
|
+
"gas.getStatus": [{
|
|
49639
|
+
name: "deviceId",
|
|
49640
|
+
form: "single",
|
|
49641
|
+
optional: false
|
|
49642
|
+
}],
|
|
49643
|
+
"humidifier.getStatus": [{
|
|
49644
|
+
name: "deviceId",
|
|
49645
|
+
form: "single",
|
|
49646
|
+
optional: false
|
|
49647
|
+
}],
|
|
49367
49648
|
"humidifier.setMode": [{
|
|
49368
49649
|
name: "deviceId",
|
|
49369
49650
|
form: "single",
|
|
@@ -49379,11 +49660,26 @@ Object.freeze({
|
|
|
49379
49660
|
form: "single",
|
|
49380
49661
|
optional: false
|
|
49381
49662
|
}],
|
|
49663
|
+
"humiditySensor.getStatus": [{
|
|
49664
|
+
name: "deviceId",
|
|
49665
|
+
form: "single",
|
|
49666
|
+
optional: false
|
|
49667
|
+
}],
|
|
49668
|
+
"image.getStatus": [{
|
|
49669
|
+
name: "deviceId",
|
|
49670
|
+
form: "single",
|
|
49671
|
+
optional: false
|
|
49672
|
+
}],
|
|
49382
49673
|
"imageSettings.getOptions": [{
|
|
49383
49674
|
name: "deviceId",
|
|
49384
49675
|
form: "single",
|
|
49385
49676
|
optional: false
|
|
49386
49677
|
}],
|
|
49678
|
+
"imageSettings.getStatus": [{
|
|
49679
|
+
name: "deviceId",
|
|
49680
|
+
form: "single",
|
|
49681
|
+
optional: false
|
|
49682
|
+
}],
|
|
49387
49683
|
"imageSettings.setSettings": [{
|
|
49388
49684
|
name: "deviceId",
|
|
49389
49685
|
form: "single",
|
|
@@ -49394,6 +49690,11 @@ Object.freeze({
|
|
|
49394
49690
|
form: "single",
|
|
49395
49691
|
optional: false
|
|
49396
49692
|
}],
|
|
49693
|
+
"intercom.getStatus": [{
|
|
49694
|
+
name: "deviceId",
|
|
49695
|
+
form: "single",
|
|
49696
|
+
optional: false
|
|
49697
|
+
}],
|
|
49397
49698
|
"intercom.handleAnswer": [{
|
|
49398
49699
|
name: "deviceId",
|
|
49399
49700
|
form: "single",
|
|
@@ -49424,6 +49725,11 @@ Object.freeze({
|
|
|
49424
49725
|
form: "single",
|
|
49425
49726
|
optional: false
|
|
49426
49727
|
}],
|
|
49728
|
+
"lawnMowerControl.getStatus": [{
|
|
49729
|
+
name: "deviceId",
|
|
49730
|
+
form: "single",
|
|
49731
|
+
optional: false
|
|
49732
|
+
}],
|
|
49427
49733
|
"lawnMowerControl.pause": [{
|
|
49428
49734
|
name: "deviceId",
|
|
49429
49735
|
form: "single",
|
|
@@ -49434,6 +49740,11 @@ Object.freeze({
|
|
|
49434
49740
|
form: "single",
|
|
49435
49741
|
optional: false
|
|
49436
49742
|
}],
|
|
49743
|
+
"lockControl.getStatus": [{
|
|
49744
|
+
name: "deviceId",
|
|
49745
|
+
form: "single",
|
|
49746
|
+
optional: false
|
|
49747
|
+
}],
|
|
49437
49748
|
"lockControl.lock": [{
|
|
49438
49749
|
name: "deviceId",
|
|
49439
49750
|
form: "single",
|
|
@@ -49449,6 +49760,11 @@ Object.freeze({
|
|
|
49449
49760
|
form: "single",
|
|
49450
49761
|
optional: false
|
|
49451
49762
|
}],
|
|
49763
|
+
"mediaPlayer.getStatus": [{
|
|
49764
|
+
name: "deviceId",
|
|
49765
|
+
form: "single",
|
|
49766
|
+
optional: false
|
|
49767
|
+
}],
|
|
49452
49768
|
"mediaPlayer.next": [{
|
|
49453
49769
|
name: "deviceId",
|
|
49454
49770
|
form: "single",
|
|
@@ -49509,6 +49825,11 @@ Object.freeze({
|
|
|
49509
49825
|
form: "single",
|
|
49510
49826
|
optional: false
|
|
49511
49827
|
}],
|
|
49828
|
+
"motion.getStatus": [{
|
|
49829
|
+
name: "deviceId",
|
|
49830
|
+
form: "single",
|
|
49831
|
+
optional: false
|
|
49832
|
+
}],
|
|
49512
49833
|
"motion.isDetected": [{
|
|
49513
49834
|
name: "deviceId",
|
|
49514
49835
|
form: "single",
|
|
@@ -49519,11 +49840,31 @@ Object.freeze({
|
|
|
49519
49840
|
form: "single",
|
|
49520
49841
|
optional: false
|
|
49521
49842
|
}],
|
|
49843
|
+
"motionDetection.applyDeviceSettingsPatch": [{
|
|
49844
|
+
name: "deviceId",
|
|
49845
|
+
form: "single",
|
|
49846
|
+
optional: false
|
|
49847
|
+
}],
|
|
49848
|
+
"motionDetection.getDeviceLiveContribution": [{
|
|
49849
|
+
name: "deviceId",
|
|
49850
|
+
form: "single",
|
|
49851
|
+
optional: false
|
|
49852
|
+
}],
|
|
49853
|
+
"motionDetection.getDeviceSettingsContribution": [{
|
|
49854
|
+
name: "deviceId",
|
|
49855
|
+
form: "single",
|
|
49856
|
+
optional: false
|
|
49857
|
+
}],
|
|
49522
49858
|
"motionDetection.removeCamera": [{
|
|
49523
49859
|
name: "deviceId",
|
|
49524
49860
|
form: "single",
|
|
49525
49861
|
optional: false
|
|
49526
49862
|
}],
|
|
49863
|
+
"motionTrigger.getStatus": [{
|
|
49864
|
+
name: "deviceId",
|
|
49865
|
+
form: "single",
|
|
49866
|
+
optional: false
|
|
49867
|
+
}],
|
|
49527
49868
|
"motionTrigger.setMotionTrigger": [{
|
|
49528
49869
|
name: "deviceId",
|
|
49529
49870
|
form: "single",
|
|
@@ -49534,6 +49875,11 @@ Object.freeze({
|
|
|
49534
49875
|
form: "single",
|
|
49535
49876
|
optional: false
|
|
49536
49877
|
}],
|
|
49878
|
+
"motionZones.getStatus": [{
|
|
49879
|
+
name: "deviceId",
|
|
49880
|
+
form: "single",
|
|
49881
|
+
optional: false
|
|
49882
|
+
}],
|
|
49537
49883
|
"motionZones.setZone": [{
|
|
49538
49884
|
name: "deviceId",
|
|
49539
49885
|
form: "single",
|
|
@@ -49544,6 +49890,11 @@ Object.freeze({
|
|
|
49544
49890
|
form: "single",
|
|
49545
49891
|
optional: false
|
|
49546
49892
|
}],
|
|
49893
|
+
"nativeObjectDetection.getStatus": [{
|
|
49894
|
+
name: "deviceId",
|
|
49895
|
+
form: "single",
|
|
49896
|
+
optional: false
|
|
49897
|
+
}],
|
|
49547
49898
|
"nativeObjectDetection.setEnabled": [{
|
|
49548
49899
|
name: "deviceId",
|
|
49549
49900
|
form: "single",
|
|
@@ -49559,6 +49910,11 @@ Object.freeze({
|
|
|
49559
49910
|
form: "single",
|
|
49560
49911
|
optional: false
|
|
49561
49912
|
}],
|
|
49913
|
+
"navigation.getStatus": [{
|
|
49914
|
+
name: "deviceId",
|
|
49915
|
+
form: "single",
|
|
49916
|
+
optional: false
|
|
49917
|
+
}],
|
|
49562
49918
|
"navigation.goToPoint": [{
|
|
49563
49919
|
name: "deviceId",
|
|
49564
49920
|
form: "single",
|
|
@@ -49604,6 +49960,11 @@ Object.freeze({
|
|
|
49604
49960
|
form: "single",
|
|
49605
49961
|
optional: false
|
|
49606
49962
|
}],
|
|
49963
|
+
"networkLink.getStatus": [{
|
|
49964
|
+
name: "deviceId",
|
|
49965
|
+
form: "single",
|
|
49966
|
+
optional: false
|
|
49967
|
+
}],
|
|
49607
49968
|
"networkQuality.getDeviceStats": [{
|
|
49608
49969
|
name: "deviceId",
|
|
49609
49970
|
form: "single",
|
|
@@ -49614,6 +49975,11 @@ Object.freeze({
|
|
|
49614
49975
|
form: "single",
|
|
49615
49976
|
optional: false
|
|
49616
49977
|
}],
|
|
49978
|
+
"notificationRules.getAlarmSensors": [{
|
|
49979
|
+
name: "deviceIds",
|
|
49980
|
+
form: "array",
|
|
49981
|
+
optional: false
|
|
49982
|
+
}],
|
|
49617
49983
|
"notificationRules.setDeviceMuted": [{
|
|
49618
49984
|
name: "deviceId",
|
|
49619
49985
|
form: "single",
|
|
@@ -49624,11 +49990,26 @@ Object.freeze({
|
|
|
49624
49990
|
form: "single",
|
|
49625
49991
|
optional: false
|
|
49626
49992
|
}],
|
|
49993
|
+
"notifier.getStatus": [{
|
|
49994
|
+
name: "deviceId",
|
|
49995
|
+
form: "single",
|
|
49996
|
+
optional: false
|
|
49997
|
+
}],
|
|
49627
49998
|
"notifier.send": [{
|
|
49628
49999
|
name: "deviceId",
|
|
49629
50000
|
form: "single",
|
|
49630
50001
|
optional: false
|
|
49631
50002
|
}],
|
|
50003
|
+
"numericSensor.getStatus": [{
|
|
50004
|
+
name: "deviceId",
|
|
50005
|
+
form: "single",
|
|
50006
|
+
optional: false
|
|
50007
|
+
}],
|
|
50008
|
+
"osd.getStatus": [{
|
|
50009
|
+
name: "deviceId",
|
|
50010
|
+
form: "single",
|
|
50011
|
+
optional: false
|
|
50012
|
+
}],
|
|
49632
50013
|
"osd.setOverlay": [{
|
|
49633
50014
|
name: "deviceId",
|
|
49634
50015
|
form: "single",
|
|
@@ -49688,6 +50069,11 @@ Object.freeze({
|
|
|
49688
50069
|
form: "single",
|
|
49689
50070
|
optional: false
|
|
49690
50071
|
}],
|
|
50072
|
+
"petFeeder.getStatus": [{
|
|
50073
|
+
name: "deviceId",
|
|
50074
|
+
form: "single",
|
|
50075
|
+
optional: false
|
|
50076
|
+
}],
|
|
49691
50077
|
"petFeeder.markFoodReplenished": [{
|
|
49692
50078
|
name: "deviceId",
|
|
49693
50079
|
form: "single",
|
|
@@ -49723,6 +50109,11 @@ Object.freeze({
|
|
|
49723
50109
|
form: "single",
|
|
49724
50110
|
optional: false
|
|
49725
50111
|
}],
|
|
50112
|
+
"pipelineAnalytics.applyDeviceSettingsPatch": [{
|
|
50113
|
+
name: "deviceId",
|
|
50114
|
+
form: "single",
|
|
50115
|
+
optional: false
|
|
50116
|
+
}],
|
|
49726
50117
|
"pipelineAnalytics.clearTrackRelation": [{
|
|
49727
50118
|
name: "deviceId",
|
|
49728
50119
|
form: "single",
|
|
@@ -49763,6 +50154,16 @@ Object.freeze({
|
|
|
49763
50154
|
form: "single",
|
|
49764
50155
|
optional: false
|
|
49765
50156
|
}],
|
|
50157
|
+
"pipelineAnalytics.getDeviceLiveContribution": [{
|
|
50158
|
+
name: "deviceId",
|
|
50159
|
+
form: "single",
|
|
50160
|
+
optional: false
|
|
50161
|
+
}],
|
|
50162
|
+
"pipelineAnalytics.getDeviceSettingsContribution": [{
|
|
50163
|
+
name: "deviceId",
|
|
50164
|
+
form: "single",
|
|
50165
|
+
optional: false
|
|
50166
|
+
}],
|
|
49766
50167
|
"pipelineAnalytics.getEventDensity": [{
|
|
49767
50168
|
name: "deviceId",
|
|
49768
50169
|
form: "single",
|
|
@@ -49978,6 +50379,11 @@ Object.freeze({
|
|
|
49978
50379
|
form: "single",
|
|
49979
50380
|
optional: true
|
|
49980
50381
|
}],
|
|
50382
|
+
"pipelineOrchestrator.applyDeviceSettingsPatch": [{
|
|
50383
|
+
name: "deviceId",
|
|
50384
|
+
form: "single",
|
|
50385
|
+
optional: false
|
|
50386
|
+
}],
|
|
49981
50387
|
"pipelineOrchestrator.assignAudio": [{
|
|
49982
50388
|
name: "deviceId",
|
|
49983
50389
|
form: "single",
|
|
@@ -50023,6 +50429,16 @@ Object.freeze({
|
|
|
50023
50429
|
form: "single",
|
|
50024
50430
|
optional: false
|
|
50025
50431
|
}],
|
|
50432
|
+
"pipelineOrchestrator.getDeviceLiveContribution": [{
|
|
50433
|
+
name: "deviceId",
|
|
50434
|
+
form: "single",
|
|
50435
|
+
optional: false
|
|
50436
|
+
}],
|
|
50437
|
+
"pipelineOrchestrator.getDeviceSettingsContribution": [{
|
|
50438
|
+
name: "deviceId",
|
|
50439
|
+
form: "single",
|
|
50440
|
+
optional: false
|
|
50441
|
+
}],
|
|
50026
50442
|
"pipelineOrchestrator.getPipelineAssignment": [{
|
|
50027
50443
|
name: "deviceId",
|
|
50028
50444
|
form: "single",
|
|
@@ -50143,11 +50559,31 @@ Object.freeze({
|
|
|
50143
50559
|
form: "single",
|
|
50144
50560
|
optional: true
|
|
50145
50561
|
}],
|
|
50562
|
+
"powerMeter.getStatus": [{
|
|
50563
|
+
name: "deviceId",
|
|
50564
|
+
form: "single",
|
|
50565
|
+
optional: false
|
|
50566
|
+
}],
|
|
50567
|
+
"presence.getStatus": [{
|
|
50568
|
+
name: "deviceId",
|
|
50569
|
+
form: "single",
|
|
50570
|
+
optional: false
|
|
50571
|
+
}],
|
|
50572
|
+
"pressureSensor.getStatus": [{
|
|
50573
|
+
name: "deviceId",
|
|
50574
|
+
form: "single",
|
|
50575
|
+
optional: false
|
|
50576
|
+
}],
|
|
50146
50577
|
"privacyMask.getOptions": [{
|
|
50147
50578
|
name: "deviceId",
|
|
50148
50579
|
form: "single",
|
|
50149
50580
|
optional: false
|
|
50150
50581
|
}],
|
|
50582
|
+
"privacyMask.getStatus": [{
|
|
50583
|
+
name: "deviceId",
|
|
50584
|
+
form: "single",
|
|
50585
|
+
optional: false
|
|
50586
|
+
}],
|
|
50151
50587
|
"privacyMask.setAudioEnabled": [{
|
|
50152
50588
|
name: "deviceId",
|
|
50153
50589
|
form: "single",
|
|
@@ -50198,6 +50634,11 @@ Object.freeze({
|
|
|
50198
50634
|
form: "single",
|
|
50199
50635
|
optional: false
|
|
50200
50636
|
}],
|
|
50637
|
+
"ptz.getStatus": [{
|
|
50638
|
+
name: "deviceId",
|
|
50639
|
+
form: "single",
|
|
50640
|
+
optional: false
|
|
50641
|
+
}],
|
|
50201
50642
|
"ptz.goHome": [{
|
|
50202
50643
|
name: "deviceId",
|
|
50203
50644
|
form: "single",
|
|
@@ -50288,6 +50729,11 @@ Object.freeze({
|
|
|
50288
50729
|
form: "single",
|
|
50289
50730
|
optional: false
|
|
50290
50731
|
}],
|
|
50732
|
+
"recordingArchive.applyDeviceSettingsPatch": [{
|
|
50733
|
+
name: "deviceId",
|
|
50734
|
+
form: "single",
|
|
50735
|
+
optional: false
|
|
50736
|
+
}],
|
|
50291
50737
|
"recordingArchive.deleteFootprint": [{
|
|
50292
50738
|
name: "deviceId",
|
|
50293
50739
|
form: "single",
|
|
@@ -50308,6 +50754,21 @@ Object.freeze({
|
|
|
50308
50754
|
form: "single",
|
|
50309
50755
|
optional: false
|
|
50310
50756
|
}],
|
|
50757
|
+
"recordingArchive.getDeviceLiveContribution": [{
|
|
50758
|
+
name: "deviceId",
|
|
50759
|
+
form: "single",
|
|
50760
|
+
optional: false
|
|
50761
|
+
}],
|
|
50762
|
+
"recordingArchive.getDeviceSettingsContribution": [{
|
|
50763
|
+
name: "deviceId",
|
|
50764
|
+
form: "single",
|
|
50765
|
+
optional: false
|
|
50766
|
+
}],
|
|
50767
|
+
"recordingArchive.getStatus": [{
|
|
50768
|
+
name: "deviceId",
|
|
50769
|
+
form: "single",
|
|
50770
|
+
optional: false
|
|
50771
|
+
}],
|
|
50311
50772
|
"recordingArchive.listOpsLog": [{
|
|
50312
50773
|
name: "deviceId",
|
|
50313
50774
|
form: "single",
|
|
@@ -50393,6 +50854,11 @@ Object.freeze({
|
|
|
50393
50854
|
form: "single",
|
|
50394
50855
|
optional: false
|
|
50395
50856
|
}],
|
|
50857
|
+
"recordingOnboard.getStatus": [{
|
|
50858
|
+
name: "deviceId",
|
|
50859
|
+
form: "single",
|
|
50860
|
+
optional: false
|
|
50861
|
+
}],
|
|
50396
50862
|
"recordingOnboard.setSettings": [{
|
|
50397
50863
|
name: "deviceId",
|
|
50398
50864
|
form: "single",
|
|
@@ -50423,6 +50889,11 @@ Object.freeze({
|
|
|
50423
50889
|
form: "single",
|
|
50424
50890
|
optional: false
|
|
50425
50891
|
}],
|
|
50892
|
+
"sceneMonitor.getStatus": [{
|
|
50893
|
+
name: "deviceId",
|
|
50894
|
+
form: "single",
|
|
50895
|
+
optional: false
|
|
50896
|
+
}],
|
|
50426
50897
|
"sceneMonitor.listScenes": [{
|
|
50427
50898
|
name: "deviceId",
|
|
50428
50899
|
form: "single",
|
|
@@ -50448,6 +50919,11 @@ Object.freeze({
|
|
|
50448
50919
|
form: "single",
|
|
50449
50920
|
optional: false
|
|
50450
50921
|
}],
|
|
50922
|
+
"scriptRunner.getStatus": [{
|
|
50923
|
+
name: "deviceId",
|
|
50924
|
+
form: "single",
|
|
50925
|
+
optional: false
|
|
50926
|
+
}],
|
|
50451
50927
|
"scriptRunner.run": [{
|
|
50452
50928
|
name: "deviceId",
|
|
50453
50929
|
form: "single",
|
|
@@ -50458,11 +50934,31 @@ Object.freeze({
|
|
|
50458
50934
|
form: "single",
|
|
50459
50935
|
optional: false
|
|
50460
50936
|
}],
|
|
50937
|
+
"smoke.getStatus": [{
|
|
50938
|
+
name: "deviceId",
|
|
50939
|
+
form: "single",
|
|
50940
|
+
optional: false
|
|
50941
|
+
}],
|
|
50942
|
+
"snapshot.applyDeviceSettingsPatch": [{
|
|
50943
|
+
name: "deviceId",
|
|
50944
|
+
form: "single",
|
|
50945
|
+
optional: false
|
|
50946
|
+
}],
|
|
50461
50947
|
"snapshot.getDebugState": [{
|
|
50462
50948
|
name: "deviceId",
|
|
50463
50949
|
form: "single",
|
|
50464
50950
|
optional: false
|
|
50465
50951
|
}],
|
|
50952
|
+
"snapshot.getDeviceLiveContribution": [{
|
|
50953
|
+
name: "deviceId",
|
|
50954
|
+
form: "single",
|
|
50955
|
+
optional: false
|
|
50956
|
+
}],
|
|
50957
|
+
"snapshot.getDeviceSettingsContribution": [{
|
|
50958
|
+
name: "deviceId",
|
|
50959
|
+
form: "single",
|
|
50960
|
+
optional: false
|
|
50961
|
+
}],
|
|
50466
50962
|
"snapshot.getSnapshot": [{
|
|
50467
50963
|
name: "deviceId",
|
|
50468
50964
|
form: "single",
|
|
@@ -50479,6 +50975,11 @@ Object.freeze({
|
|
|
50479
50975
|
form: "array",
|
|
50480
50976
|
optional: false
|
|
50481
50977
|
}],
|
|
50978
|
+
"snapshot.getStatus": [{
|
|
50979
|
+
name: "deviceId",
|
|
50980
|
+
form: "single",
|
|
50981
|
+
optional: false
|
|
50982
|
+
}],
|
|
50482
50983
|
"snapshot.invalidateCache": [{
|
|
50483
50984
|
name: "deviceId",
|
|
50484
50985
|
form: "single",
|
|
@@ -50489,6 +50990,11 @@ Object.freeze({
|
|
|
50489
50990
|
form: "single",
|
|
50490
50991
|
optional: false
|
|
50491
50992
|
}],
|
|
50993
|
+
"streamBroker.applyDeviceSettingsPatch": [{
|
|
50994
|
+
name: "deviceId",
|
|
50995
|
+
form: "single",
|
|
50996
|
+
optional: false
|
|
50997
|
+
}],
|
|
50492
50998
|
"streamBroker.assignProfile": [{
|
|
50493
50999
|
name: "deviceId",
|
|
50494
51000
|
form: "single",
|
|
@@ -50504,6 +51010,16 @@ Object.freeze({
|
|
|
50504
51010
|
form: "single",
|
|
50505
51011
|
optional: false
|
|
50506
51012
|
}],
|
|
51013
|
+
"streamBroker.getDeviceLiveContribution": [{
|
|
51014
|
+
name: "deviceId",
|
|
51015
|
+
form: "single",
|
|
51016
|
+
optional: false
|
|
51017
|
+
}],
|
|
51018
|
+
"streamBroker.getDeviceSettingsContribution": [{
|
|
51019
|
+
name: "deviceId",
|
|
51020
|
+
form: "single",
|
|
51021
|
+
optional: false
|
|
51022
|
+
}],
|
|
50507
51023
|
"streamBroker.getStreamWithCodec": [{
|
|
50508
51024
|
name: "deviceId",
|
|
50509
51025
|
form: "single",
|
|
@@ -50564,16 +51080,46 @@ Object.freeze({
|
|
|
50564
51080
|
form: "single",
|
|
50565
51081
|
optional: false
|
|
50566
51082
|
}],
|
|
51083
|
+
"streamParams.getStatus": [{
|
|
51084
|
+
name: "deviceId",
|
|
51085
|
+
form: "single",
|
|
51086
|
+
optional: false
|
|
51087
|
+
}],
|
|
50567
51088
|
"streamParams.setProfile": [{
|
|
50568
51089
|
name: "deviceId",
|
|
50569
51090
|
form: "single",
|
|
50570
51091
|
optional: false
|
|
50571
51092
|
}],
|
|
51093
|
+
"switch.getStatus": [{
|
|
51094
|
+
name: "deviceId",
|
|
51095
|
+
form: "single",
|
|
51096
|
+
optional: false
|
|
51097
|
+
}],
|
|
50572
51098
|
"switch.setState": [{
|
|
50573
51099
|
name: "deviceId",
|
|
50574
51100
|
form: "single",
|
|
50575
51101
|
optional: false
|
|
50576
51102
|
}],
|
|
51103
|
+
"tamper.getStatus": [{
|
|
51104
|
+
name: "deviceId",
|
|
51105
|
+
form: "single",
|
|
51106
|
+
optional: false
|
|
51107
|
+
}],
|
|
51108
|
+
"temperatureSensor.getStatus": [{
|
|
51109
|
+
name: "deviceId",
|
|
51110
|
+
form: "single",
|
|
51111
|
+
optional: false
|
|
51112
|
+
}],
|
|
51113
|
+
"update.getStatus": [{
|
|
51114
|
+
name: "deviceId",
|
|
51115
|
+
form: "single",
|
|
51116
|
+
optional: false
|
|
51117
|
+
}],
|
|
51118
|
+
"vacuumControl.getStatus": [{
|
|
51119
|
+
name: "deviceId",
|
|
51120
|
+
form: "single",
|
|
51121
|
+
optional: false
|
|
51122
|
+
}],
|
|
50577
51123
|
"vacuumControl.locate": [{
|
|
50578
51124
|
name: "deviceId",
|
|
50579
51125
|
form: "single",
|
|
@@ -50609,6 +51155,11 @@ Object.freeze({
|
|
|
50609
51155
|
form: "single",
|
|
50610
51156
|
optional: false
|
|
50611
51157
|
}],
|
|
51158
|
+
"valve.getStatus": [{
|
|
51159
|
+
name: "deviceId",
|
|
51160
|
+
form: "single",
|
|
51161
|
+
optional: false
|
|
51162
|
+
}],
|
|
50612
51163
|
"valve.open": [{
|
|
50613
51164
|
name: "deviceId",
|
|
50614
51165
|
form: "single",
|
|
@@ -50624,6 +51175,11 @@ Object.freeze({
|
|
|
50624
51175
|
form: "single",
|
|
50625
51176
|
optional: false
|
|
50626
51177
|
}],
|
|
51178
|
+
"vibration.getStatus": [{
|
|
51179
|
+
name: "deviceId",
|
|
51180
|
+
form: "single",
|
|
51181
|
+
optional: false
|
|
51182
|
+
}],
|
|
50627
51183
|
"videoclips.dialClipStream": [{
|
|
50628
51184
|
name: "deviceId",
|
|
50629
51185
|
form: "single",
|
|
@@ -50659,6 +51215,11 @@ Object.freeze({
|
|
|
50659
51215
|
form: "single",
|
|
50660
51216
|
optional: false
|
|
50661
51217
|
}],
|
|
51218
|
+
"waterHeater.getStatus": [{
|
|
51219
|
+
name: "deviceId",
|
|
51220
|
+
form: "single",
|
|
51221
|
+
optional: false
|
|
51222
|
+
}],
|
|
50662
51223
|
"waterHeater.setAway": [{
|
|
50663
51224
|
name: "deviceId",
|
|
50664
51225
|
form: "single",
|
|
@@ -50674,6 +51235,11 @@ Object.freeze({
|
|
|
50674
51235
|
form: "single",
|
|
50675
51236
|
optional: false
|
|
50676
51237
|
}],
|
|
51238
|
+
"weather.getStatus": [{
|
|
51239
|
+
name: "deviceId",
|
|
51240
|
+
form: "single",
|
|
51241
|
+
optional: false
|
|
51242
|
+
}],
|
|
50677
51243
|
"webrtcSession.addIceCandidate": [{
|
|
50678
51244
|
name: "deviceId",
|
|
50679
51245
|
form: "single",
|
|
@@ -51411,7 +51977,7 @@ var PreviewTextField = string().max(200);
|
|
|
51411
51977
|
* Whether the notification's preview is a STILL or a short animation.
|
|
51412
51978
|
*
|
|
51413
51979
|
* The operator's ask, verbatim: *"inviato come gif o video (come per le altre
|
|
51414
|
-
* rule)"* — the other rules already offer an animated preview, and a ten-hour
|
|
51980
|
+
* rule)"* [sent as a gif or video (as for the other rules)] — the other rules already offer an animated preview, and a ten-hour
|
|
51415
51981
|
* night reads better as three seconds of motion than as one frame of it. Both
|
|
51416
51982
|
* modes get the SAME treatment (blurred frame, large centred title); `'gif'`
|
|
51417
51983
|
* simply applies it to a dozen frames sampled across the render and assembles
|
|
@@ -51549,6 +52115,7 @@ TimelapseRuleInputSchema.extend({
|
|
|
51549
52115
|
createdAt: number(),
|
|
51550
52116
|
updatedAt: number()
|
|
51551
52117
|
});
|
|
52118
|
+
MotionOnMotionChangedDataSchema.omit({ triggeredBy: true });
|
|
51552
52119
|
object({
|
|
51553
52120
|
/**
|
|
51554
52121
|
* Fraction of the box's own size added on EACH side before cutting.
|