@camstack/addon-terminal 0.1.122 → 0.1.123
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 +887 -321
- package/dist/addon.mjs +887 -321
- package/package.json +1 -3
package/dist/addon.js
CHANGED
|
@@ -31,7 +31,7 @@ let node_module = require("node:module");
|
|
|
31
31
|
let sharp = require("sharp");
|
|
32
32
|
sharp = __toESM(sharp);
|
|
33
33
|
let node_http = require("node:http");
|
|
34
|
-
//#region ../types/dist/event-category-
|
|
34
|
+
//#region ../types/dist/event-category-BGmz_oxW.mjs
|
|
35
35
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
36
36
|
EventCategory["SystemBoot"] = "system.boot";
|
|
37
37
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -564,6 +564,15 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
564
564
|
*/
|
|
565
565
|
EventCategory["PipelineAudioInferenceResult"] = "pipeline.audio-inference-result";
|
|
566
566
|
EventCategory["DetectionPhaseTransition"] = "detection.phase-transition";
|
|
567
|
+
/**
|
|
568
|
+
* A camera provider's RAW onboard motion push (D673): the `MotionOnMotionChanged`
|
|
569
|
+
* data shape without `triggeredBy`, built by `providerMotionEvent`. Its one
|
|
570
|
+
* consumer is the orchestrator's camera-sensors bridge, which re-emits the
|
|
571
|
+
* camera's EFFECTIVE onboard motion as `MotionOnMotionChanged` (a pass-through
|
|
572
|
+
* for a camera with no attached sensor). Providers must not emit
|
|
573
|
+
* `MotionOnMotionChanged` themselves; `scripts/check-onboard-motion-emitters.ts`
|
|
574
|
+
* keeps it so (camera-grid is a named, deferred exception).
|
|
575
|
+
*/
|
|
567
576
|
EventCategory["ProviderMotion"] = "provider.motion";
|
|
568
577
|
EventCategory["ProviderDetection"] = "provider.detection";
|
|
569
578
|
EventCategory["EnrichmentEmbeddingStored"] = "enrichment.embedding.stored";
|
|
@@ -5402,7 +5411,7 @@ var ZodIssueCode = {
|
|
|
5402
5411
|
var ZodFirstPartyTypeKind;
|
|
5403
5412
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5404
5413
|
//#endregion
|
|
5405
|
-
//#region ../types/dist/sleep-
|
|
5414
|
+
//#region ../types/dist/sleep-CDCONfkt.mjs
|
|
5406
5415
|
/**
|
|
5407
5416
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5408
5417
|
* window to float samples (D455).
|
|
@@ -7504,7 +7513,7 @@ function errMsg(err) {
|
|
|
7504
7513
|
return String(err);
|
|
7505
7514
|
}
|
|
7506
7515
|
//#endregion
|
|
7507
|
-
//#region ../types/dist/composition-
|
|
7516
|
+
//#region ../types/dist/composition-Bzr7GwgP.mjs
|
|
7508
7517
|
/**
|
|
7509
7518
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
7510
7519
|
*
|
|
@@ -7558,21 +7567,20 @@ function portable(target) {
|
|
|
7558
7567
|
}
|
|
7559
7568
|
portable("linux64"), portable("linuxarm64"), portable("macarm64"), portable("mac64");
|
|
7560
7569
|
/**
|
|
7561
|
-
*
|
|
7562
|
-
*
|
|
7570
|
+
* THE table "which boolean of this device type counts as HIGH", and the
|
|
7571
|
+
* pure evaluator of its EDGE.
|
|
7563
7572
|
*
|
|
7564
|
-
*
|
|
7565
|
-
*
|
|
7566
|
-
*
|
|
7567
|
-
*
|
|
7568
|
-
*
|
|
7569
|
-
*
|
|
7570
|
-
* SPOSTA qui e il doorbell la ri-esporta.
|
|
7573
|
+
* ONE table for everyone who asks "is this device HIGH?": the
|
|
7574
|
+
* recorder's `RecordingTriggers.sensorDeviceIds` trigger, the post-analysis
|
|
7575
|
+
* sensor markers, the orchestrator's camera-sensors bridge and
|
|
7576
|
+
* the sources of a composite doorbell (`doorbellFeatureSources`, D671).
|
|
7577
|
+
* A second copy would diverge at the first cap added, and the symptom — "the
|
|
7578
|
+
* sensor rings the doorbell but does not record" — is exactly D62.
|
|
7571
7579
|
*
|
|
7572
|
-
* ⚠
|
|
7573
|
-
*
|
|
7574
|
-
*
|
|
7575
|
-
*
|
|
7580
|
+
* ⚠ NOT `DEVICE_STATE_READERS` (`catalogs/device-state-vocabulary.ts`), and the
|
|
7581
|
+
* two must not be unified: that one answers "what is the state WORD for a
|
|
7582
|
+
* rule" (and includes `presence`, `cover`, `alarm-panel`), this one "which
|
|
7583
|
+
* boolean's EDGE counts". Deliberately different vocabularies.
|
|
7576
7584
|
*/
|
|
7577
7585
|
/**
|
|
7578
7586
|
* Known binary / switch source caps → the boolean slice field whose
|
|
@@ -9213,22 +9221,22 @@ var CLASS_MAP_MACRO_TARGETS = [
|
|
|
9213
9221
|
"package"
|
|
9214
9222
|
];
|
|
9215
9223
|
/**
|
|
9216
|
-
*
|
|
9217
|
-
*
|
|
9224
|
+
* The FIRST-LEVEL macro classes: those an object detector emits and that
|
|
9225
|
+
* an operator can select.
|
|
9218
9226
|
*
|
|
9219
|
-
*
|
|
9227
|
+
* They are the three offered by the `object-detection` step
|
|
9220
9228
|
* (`addon-pipeline/src/detection-pipeline/registry/step-definitions.ts`,
|
|
9221
|
-
* `enabledMacroClasses`). `package`
|
|
9222
|
-
* `MACRO_LABELS` —
|
|
9223
|
-
* `package-detection`,
|
|
9224
|
-
*
|
|
9229
|
+
* `enabledMacroClasses`). `package` is in {@link CLASS_MAP_MACRO_TARGETS} and in
|
|
9230
|
+
* `MACRO_LABELS` — it is a true macro — but NOT here: it belongs to the step
|
|
9231
|
+
* `package-detection`, whose enablement is driven by zones, and offering the
|
|
9232
|
+
* same word twice has already made an operator turn on the COCO proxy
|
|
9225
9233
|
* (suitcase/backpack/handbag) lasciando spento il detector dedicato.
|
|
9226
9234
|
*
|
|
9227
|
-
*
|
|
9228
|
-
*
|
|
9229
|
-
* (`types/detection.ts`);
|
|
9230
|
-
* (`RecordingTriggers.objectClasses`)
|
|
9231
|
-
*
|
|
9235
|
+
* ONE list. Before today the same three were hand-written in the step's offer
|
|
9236
|
+
* and a second time as the union `FirstLevelMacro`
|
|
9237
|
+
* (`types/detection.ts`); a third copy for the recording trigger
|
|
9238
|
+
* (`RecordingTriggers.objectClasses`) would have made the later divergence
|
|
9239
|
+
* invisible.
|
|
9232
9240
|
*/
|
|
9233
9241
|
var FIRST_LEVEL_MACRO_CLASSES = [
|
|
9234
9242
|
"person",
|
|
@@ -9293,17 +9301,17 @@ var RecordingStorageModeSchema = _enum([
|
|
|
9293
9301
|
"on-device-decision"
|
|
9294
9302
|
]);
|
|
9295
9303
|
/**
|
|
9296
|
-
*
|
|
9297
|
-
*
|
|
9304
|
+
* The macro classes that can open a recording window — the same
|
|
9305
|
+
* three offered by the `object-detection` step, from ONE list
|
|
9298
9306
|
* ({@link FIRST_LEVEL_MACRO_CLASSES}).
|
|
9299
9307
|
*/
|
|
9300
9308
|
var RecordingObjectTriggerClassSchema = _enum(FIRST_LEVEL_MACRO_CLASSES);
|
|
9301
9309
|
/**
|
|
9302
|
-
* True
|
|
9310
|
+
* True when `values` does not repeat an element.
|
|
9303
9311
|
*
|
|
9304
|
-
*
|
|
9305
|
-
*
|
|
9306
|
-
*
|
|
9312
|
+
* A duplicate is not harmless: every entry of `objectClasses` / `sensorDeviceIds`
|
|
9313
|
+
* becomes a SOURCE in `bandTriggerSources`, and the same source twice
|
|
9314
|
+
* would count its windows twice in `segmentMissedByMs`.
|
|
9307
9315
|
*/
|
|
9308
9316
|
var noDuplicates = (values) => new Set(values).size === values.length;
|
|
9309
9317
|
/** Which detectors trigger an `events`-mode band. */
|
|
@@ -9311,34 +9319,34 @@ var RecordingTriggersSchema = object({
|
|
|
9311
9319
|
motion: boolean().optional(),
|
|
9312
9320
|
audioThresholdDbfs: number().optional(),
|
|
9313
9321
|
/**
|
|
9314
|
-
*
|
|
9315
|
-
*
|
|
9316
|
-
*
|
|
9317
|
-
*
|
|
9322
|
+
* The macro classes whose detection opens a window. ABSENT = the source
|
|
9323
|
+
* is not listened to; an EMPTY array is rejected, because "events band, object
|
|
9324
|
+
* trigger on, no class" is the same shape "enabled and records
|
|
9325
|
+
* nothing, forever" that `eventsBandCanEverDemand` is written against.
|
|
9318
9326
|
*
|
|
9319
|
-
*
|
|
9320
|
-
*
|
|
9321
|
-
* `minConfidence<Macro>`
|
|
9322
|
-
* (`source: 'onboard'`)
|
|
9323
|
-
*
|
|
9327
|
+
* The signal read is ALREADY FILTERED: only `source: 'pipeline'` detections, i.e.
|
|
9328
|
+
* those that went through `enabledMacroClasses`, the
|
|
9329
|
+
* `minConfidence<Macro>` and the full-frame guard. The camera's onboard AI
|
|
9330
|
+
* (`source: 'onboard'`) goes through none of those gates and does NOT open
|
|
9331
|
+
* windows — see `recorder/object-trigger.ts`.
|
|
9324
9332
|
*/
|
|
9325
9333
|
objectClasses: array(RecordingObjectTriggerClassSchema).min(1).refine(noDuplicates, { message: "objectClasses must not repeat a class" }).optional(),
|
|
9326
9334
|
/**
|
|
9327
|
-
*
|
|
9328
|
-
*
|
|
9335
|
+
* The LINKED devices whose RISING EDGE opens a window. Absent = the source
|
|
9336
|
+
* is not listened to; an empty array is rejected for the same reason as
|
|
9329
9337
|
* `objectClasses`.
|
|
9330
9338
|
*
|
|
9331
|
-
*
|
|
9332
|
-
*
|
|
9333
|
-
*
|
|
9334
|
-
*
|
|
9335
|
-
* device (D12) —
|
|
9339
|
+
* These are SOURCE device ids, not cameras: the band names them, so the
|
|
9340
|
+
* hot path (`DeviceStateChanged`, at bus rate across the whole fleet)
|
|
9341
|
+
* does no RPC. The OFFER from which the operator picks them is another question, and
|
|
9342
|
+
* is resolved with `deviceManager.getLinkedDevices` + `getBindingsBatch` per
|
|
9343
|
+
* device (D12) — never a global list of caps.
|
|
9336
9344
|
*
|
|
9337
|
-
*
|
|
9338
|
-
* `SOURCE_CAP_ACTIVE_FIELD` (`catalogs/sensor-active-state.ts`)
|
|
9339
|
-
*
|
|
9340
|
-
*
|
|
9341
|
-
*
|
|
9345
|
+
* What "high" means depends on the device TYPE and is not decided here:
|
|
9346
|
+
* `SOURCE_CAP_ACTIVE_FIELD` (`catalogs/sensor-active-state.ts`) is THE table,
|
|
9347
|
+
* the same one as the composite doorbell (D671). And it is the EDGE, not
|
|
9348
|
+
* the level: a contact found already open at runner restart does not
|
|
9349
|
+
* record.
|
|
9342
9350
|
*/
|
|
9343
9351
|
sensorDeviceIds: array(number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional()
|
|
9344
9352
|
});
|
|
@@ -10415,7 +10423,7 @@ var DecoderSessionConfigSchema = object({
|
|
|
10415
10423
|
* - **VALUE** — at which level, for which scope, until when. That stays ONE
|
|
10416
10424
|
* thing: the logging settings document on the `system` cap. Two authorities
|
|
10417
10425
|
* over the values is the exact defect
|
|
10418
|
-
* `docs/design/plans/2026-08-26-
|
|
10426
|
+
* `docs/design/plans/2026-08-26-per-component-logging.md` was written to
|
|
10419
10427
|
* remove; re-introducing it from the cure side would be grotesque.
|
|
10420
10428
|
*
|
|
10421
10429
|
* Nothing in this file reads a clock, an env var or a store. The registry is
|
|
@@ -12126,7 +12134,7 @@ var BrokerStatusEnum = _enum([
|
|
|
12126
12134
|
"unreachable",
|
|
12127
12135
|
"error"
|
|
12128
12136
|
]);
|
|
12129
|
-
var BrokerInfoSchema
|
|
12137
|
+
var BrokerInfoSchema = object({
|
|
12130
12138
|
/** Stable broker id. Persisted; survives addon restarts. */
|
|
12131
12139
|
id: string(),
|
|
12132
12140
|
/** Addon id of the provider that OWNS this broker.
|
|
@@ -12259,7 +12267,7 @@ var GetStateInputSchema = object({
|
|
|
12259
12267
|
* HA: entity_id (returns the cached entity state). */
|
|
12260
12268
|
key: string()
|
|
12261
12269
|
});
|
|
12262
|
-
method(ListInputSchema, array(BrokerInfoSchema
|
|
12270
|
+
method(ListInputSchema, array(BrokerInfoSchema)), method(GetInputSchema, BrokerInfoSchema.nullable()), method(_void(), array(BrokerProviderInfoSchema), { auth: "admin" }), method(AddInputSchema, AddResultSchema, {
|
|
12263
12271
|
kind: "mutation",
|
|
12264
12272
|
auth: "admin"
|
|
12265
12273
|
}), method(RemoveInputSchema, _void(), {
|
|
@@ -13970,7 +13978,7 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
|
|
|
13970
13978
|
*
|
|
13971
13979
|
* ⚠ An earlier version of this comment blamed Zod stripping, and that
|
|
13972
13980
|
* was wrong — corrected 2026-08-26 after the hop map
|
|
13973
|
-
* (`docs/design/2026-08-26-
|
|
13981
|
+
* (`docs/design/2026-08-26-topic-hop-map.md`) traced the path.
|
|
13974
13982
|
* There is **no Zod parse at all** between the door and the engine: the
|
|
13975
13983
|
* dispatcher forwards the payload verbatim and UDS carries it whole. A
|
|
13976
13984
|
* field declared here reaches `SqliteSettingsBackend` either way.
|
|
@@ -14833,7 +14841,17 @@ var SiteZoneSchema = object({
|
|
|
14833
14841
|
var ProviderStatusSchema = object({
|
|
14834
14842
|
connected: boolean(),
|
|
14835
14843
|
deviceCount: number(),
|
|
14836
|
-
error: string().optional()
|
|
14844
|
+
error: string().optional(),
|
|
14845
|
+
/**
|
|
14846
|
+
* `'orchestrator'`: this provider writes NO camera's `motion` runtime slice
|
|
14847
|
+
* — the orchestrator is its only writer (D696). Set by `BaseDeviceProvider`,
|
|
14848
|
+
* which every provider bundles, so only a provider BUILT from D696-amended
|
|
14849
|
+
* code says it. ABSENT means an older provider that may still write it (raw
|
|
14850
|
+
* VMD writes, a boot seed), and the orchestrator's provider gate keeps that
|
|
14851
|
+
* provider's cameras unwritten (`camera-sensors/motion-slice-provider-gate.ts`)
|
|
14852
|
+
* — the provider twin of the runner's `getLocalLoad().motionSliceWriter`.
|
|
14853
|
+
*/
|
|
14854
|
+
motionSliceWriter: literal("orchestrator").optional()
|
|
14837
14855
|
});
|
|
14838
14856
|
object({
|
|
14839
14857
|
externalId: string(),
|
|
@@ -15631,109 +15649,10 @@ method(object({
|
|
|
15631
15649
|
deviceIds: array(number()).readonly(),
|
|
15632
15650
|
caps: array(string()).readonly().optional()
|
|
15633
15651
|
}), record(string(), record(string(), unknown().nullable())));
|
|
15634
|
-
|
|
15635
|
-
|
|
15636
|
-
* name (same pattern as `snapshot`):
|
|
15637
|
-
*
|
|
15638
|
-
* - **Native** providers: registered per-device by device-driver
|
|
15639
|
-
* addons via `ctx.registerNativeCap` — either on a
|
|
15640
|
-
* `DeviceType.Button` accessory with `role: DeviceRole.Doorbell`,
|
|
15641
|
-
* or directly on the camera (Reolink registers at camera level).
|
|
15642
|
-
* Emits an `onPressed` event every time the firmware pushes a
|
|
15643
|
-
* ring; status tracks the last press and a pressCount since start
|
|
15644
|
-
* (diagnostic).
|
|
15645
|
-
*
|
|
15646
|
-
* - **Wrapper** provider: the `virtual-doorbell` system builtin
|
|
15647
|
-
* (`@camstack/system/builtins/doorbell`). Turns ANY binary-ish
|
|
15648
|
-
* device (contact / switch / event-emitter …) into a doorbell for
|
|
15649
|
-
* a camera. `defaultActive: false` — the operator explicitly binds
|
|
15650
|
-
* it per camera in the device-bindings UI, then picks the source
|
|
15651
|
-
* device + trigger in the per-device settings.
|
|
15652
|
-
*
|
|
15653
|
-
* The DeviceEventPropagator re-emits `onPressed` on the camera parent
|
|
15654
|
-
* — subscribers listening at the camera level receive ring events
|
|
15655
|
-
* with `via[]` populated. No code on the parent needed.
|
|
15656
|
-
*/
|
|
15657
|
-
var DoorbellStatusSchema = object({
|
|
15658
|
-
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
15659
|
-
lastPressedAt: number().nullable(),
|
|
15660
|
-
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
15661
|
-
pressCountSinceStart: number()
|
|
15662
|
-
});
|
|
15663
|
-
var DoorbellPressEventSchema = object({
|
|
15664
|
-
deviceId: number(),
|
|
15665
|
-
timestamp: number()
|
|
15666
|
-
});
|
|
15667
|
-
/**
|
|
15668
|
-
* The `doorbell-source` extension slot's editable value (D648): the camera's
|
|
15669
|
-
* virtual-doorbell trigger devices, exactly what the wrapper's
|
|
15670
|
-
* `doorbellSources` persists (as `{ deviceId }` records).
|
|
15671
|
-
*/
|
|
15672
|
-
var DoorbellSourceSlotValueSchema = object({ deviceIds: array(number().int().positive()) });
|
|
15673
|
-
/**
|
|
15674
|
-
* The `doorbell-source` slot — which devices ring this camera's VIRTUAL
|
|
15675
|
-
* doorbell, owned by the `virtual-doorbell` wrapper over its
|
|
15676
|
-
* `doorbellSources` store (D648). A source rings when one of its
|
|
15677
|
-
* `SOURCE_CAPS` rises. Whether the wrapper is bound to the camera at all is a
|
|
15678
|
-
* different authority (`deviceManager.setWrapperActive`, D62) — the slot
|
|
15679
|
-
* reports it, it never writes it.
|
|
15680
|
-
*/
|
|
15681
|
-
var DOORBELL_SOURCE_SLOT = {
|
|
15682
|
-
id: "doorbell-source",
|
|
15683
|
-
label: "Doorbell trigger devices",
|
|
15684
|
-
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.",
|
|
15685
|
-
shape: "association",
|
|
15686
|
-
hostDeviceTypes: [DeviceType.Camera],
|
|
15687
|
-
sourceCaps: SOURCE_CAPS,
|
|
15688
|
-
cardinality: "many",
|
|
15689
|
-
value: DoorbellSourceSlotValueSchema
|
|
15690
|
-
};
|
|
15691
|
-
var doorbellCapability = {
|
|
15692
|
-
name: "doorbell",
|
|
15693
|
-
scope: "device",
|
|
15694
|
-
deviceNative: true,
|
|
15695
|
-
mode: "singleton",
|
|
15696
|
-
kind: "wrapper",
|
|
15697
|
-
defaultActive: false,
|
|
15698
|
-
deviceTypes: [DeviceType.Button, DeviceType.Camera],
|
|
15699
|
-
extensionSlots: [DOORBELL_SOURCE_SLOT],
|
|
15700
|
-
methods: {},
|
|
15701
|
-
events: {
|
|
15702
|
-
/**
|
|
15703
|
-
* Fires once per physical press. Reolink delivers via Baichuan
|
|
15704
|
-
* push (`ReolinkSimpleEvent.type === 'doorbell'`). There is no
|
|
15705
|
-
* release/duration — it's a pulse.
|
|
15706
|
-
*/
|
|
15707
|
-
onPressed: {
|
|
15708
|
-
data: DoorbellPressEventSchema,
|
|
15709
|
-
fromState: {
|
|
15710
|
-
field: "lastPressedAt",
|
|
15711
|
-
on: "advance"
|
|
15712
|
-
}
|
|
15713
|
-
} },
|
|
15714
|
-
status: {
|
|
15715
|
-
schema: DoorbellStatusSchema,
|
|
15716
|
-
kind: "push"
|
|
15717
|
-
},
|
|
15718
|
-
/**
|
|
15719
|
-
* Runtime-state slice — last press timestamp + lifetime press count.
|
|
15720
|
-
* Mirrored by the kernel and readable via
|
|
15721
|
-
* `device.state.doorbell.value`. UIs can show "last ring 5m ago"
|
|
15722
|
-
* without subscribing.
|
|
15723
|
-
*/
|
|
15724
|
-
runtimeState: DoorbellStatusSchema,
|
|
15725
|
-
/**
|
|
15726
|
-
* 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.
|
|
15727
|
-
*
|
|
15728
|
-
* See `RuntimeStateDurability`. Enforced by
|
|
15729
|
-
* `scripts/check-runtime-state-durability.ts`.
|
|
15730
|
-
*/
|
|
15731
|
-
durability: "restored"
|
|
15732
|
-
};
|
|
15733
|
-
var ExtensionSlotIdSchema = _enum(["doorbell-source", "linked-devices"]);
|
|
15734
|
-
DeviceType.Camera, DeviceType.Camera;
|
|
15652
|
+
var ExtensionSlotIdSchema = _enum(["linked-devices"]);
|
|
15653
|
+
DeviceType.Camera;
|
|
15735
15654
|
/** A slot's editable value, discriminated on `slot`. */
|
|
15736
|
-
var ExtensionSlotValueSchema = discriminatedUnion("slot", [
|
|
15655
|
+
var ExtensionSlotValueSchema = discriminatedUnion("slot", [LinkedDevicesSlotValueSchema.extend({ slot: literal("linked-devices") })]);
|
|
15737
15656
|
DeviceType.Camera;
|
|
15738
15657
|
var ExtensionSourceAvailabilitySchema = discriminatedUnion("state", [object({ state: literal("ok") }), object({
|
|
15739
15658
|
state: literal("unreachable"),
|
|
@@ -15770,10 +15689,11 @@ var ExtensionSlotSourceSchema = object({
|
|
|
15770
15689
|
});
|
|
15771
15690
|
/**
|
|
15772
15691
|
* A DIFFERENT authority that gates whether the slot's sources do anything —
|
|
15773
|
-
* reported read-only, named, never written through this contract (D62).
|
|
15774
|
-
*
|
|
15775
|
-
*
|
|
15776
|
-
* `unknown` means the gate could
|
|
15692
|
+
* reported read-only, named, never written through this contract (D62) — e.g.
|
|
15693
|
+
* a slot whose sources act only while a wrapper is bound to the host, a
|
|
15694
|
+
* binding that belongs to `deviceManager.setWrapperActive`. No slot reports
|
|
15695
|
+
* one today (`linked-devices` answers `null`). `unknown` means the gate could
|
|
15696
|
+
* not be read; it is not "inactive" (D315).
|
|
15777
15697
|
*/
|
|
15778
15698
|
var ExtensionSlotActivationSchema = object({
|
|
15779
15699
|
state: _enum([
|
|
@@ -15789,7 +15709,7 @@ var ExtensionSlotRowSchema = discriminatedUnion("state", [object({
|
|
|
15789
15709
|
/** `<source>:<slotId>` — the routing key for `listCandidates` / `setSlot`. */
|
|
15790
15710
|
slotRef: string(),
|
|
15791
15711
|
slot: ExtensionSlotIdSchema,
|
|
15792
|
-
/** Names the store written (D62), e.g. `
|
|
15712
|
+
/** Names the store written (D62), e.g. `device-manager:_linkedDeviceIds`. */
|
|
15793
15713
|
authority: string(),
|
|
15794
15714
|
activation: ExtensionSlotActivationSchema.nullable(),
|
|
15795
15715
|
value: ExtensionSlotValueSchema,
|
|
@@ -16067,7 +15987,7 @@ method(object({
|
|
|
16067
15987
|
* per-device window, `KeyFrameCaptureLog`, `bumpCropMetric`. Every one of them
|
|
16068
15988
|
* ends in a log line, and a log line is the thing the operator asked to stop
|
|
16069
15989
|
* needing: *"possiamo armare questi errori intanto? Così al prossimo giro
|
|
16070
|
-
* ricontrolliamo tutti questi punti"
|
|
15990
|
+
* 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
|
|
16071
15991
|
* hand-correlating timestamps, which is how a 22% thumbnail gap and a 3-hour
|
|
16072
15992
|
* media blackout were both diagnosed. The counters stay; this is where they can
|
|
16073
15993
|
* be READ.
|
|
@@ -17443,7 +17363,7 @@ var BrokerStatusSchema$1 = _enum([
|
|
|
17443
17363
|
"unreachable",
|
|
17444
17364
|
"tls-error"
|
|
17445
17365
|
]);
|
|
17446
|
-
var BrokerInfoSchema = object({
|
|
17366
|
+
var BrokerInfoSchema$1 = object({
|
|
17447
17367
|
id: string(),
|
|
17448
17368
|
name: string(),
|
|
17449
17369
|
url: string(),
|
|
@@ -17506,7 +17426,7 @@ var StatusSchema = object({
|
|
|
17506
17426
|
brokerCount: number(),
|
|
17507
17427
|
embeddedRunning: boolean()
|
|
17508
17428
|
});
|
|
17509
|
-
method(_void(), array(BrokerInfoSchema)), method(IdInputSchema, BrokerConnectionDetailsSchema, { auth: "admin" }), method(AddBrokerInputSchema, AddBrokerResultSchema, {
|
|
17429
|
+
method(_void(), array(BrokerInfoSchema$1)), method(IdInputSchema, BrokerConnectionDetailsSchema, { auth: "admin" }), method(AddBrokerInputSchema, AddBrokerResultSchema, {
|
|
17510
17430
|
kind: "mutation",
|
|
17511
17431
|
auth: "admin"
|
|
17512
17432
|
}), method(IdInputSchema, _void(), {
|
|
@@ -19720,78 +19640,16 @@ var NcRuleInputSchema = object({
|
|
|
19720
19640
|
*/
|
|
19721
19641
|
confirm: NcConfirmSchema.optional(),
|
|
19722
19642
|
/**
|
|
19723
|
-
*
|
|
19724
|
-
*
|
|
19725
|
-
*
|
|
19726
|
-
*
|
|
19727
|
-
*
|
|
19728
|
-
*
|
|
19729
|
-
*
|
|
19730
|
-
*
|
|
19731
|
-
*
|
|
19732
|
-
* Only two honest answers exist, and this flag picks between them. It has
|
|
19733
|
-
* effect ONLY on a rule that declares a recognition scope
|
|
19734
|
-
* ({@link NcConditions.identities} or {@link NcConditions.plates}) — on any
|
|
19735
|
-
* other rule there is nothing to wait for and the flag is inert.
|
|
19736
|
-
*
|
|
19737
|
-
* | value | what happens |
|
|
19738
|
-
* | --- | --- |
|
|
19739
|
-
* | `true` | the rule stops firing on the object event and fires at TRACK CLOSE instead, once, with the name — later, and complete |
|
|
19740
|
-
* | 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) |
|
|
19741
|
-
*
|
|
19742
|
-
* `.optional()` and deliberately NOT `.default()`: a Zod default does not run
|
|
19743
|
-
* on the addon cap path, and absent has to keep meaning exactly what every
|
|
19744
|
-
* rule authored before this field meant.
|
|
19745
|
-
*
|
|
19746
|
-
* The cost of `true` is stated here because the editor states it too: a rule
|
|
19747
|
-
* that waits also inherits track-close SEMANTICS — its `zones` condition
|
|
19748
|
-
* tests every zone the track visited and a `crossing` condition can no longer
|
|
19749
|
-
* be satisfied, because a closed track carries no crossing.
|
|
19643
|
+
* IMMEDIATE GROUPED (D692): the first matching subject opens a window of this many
|
|
19644
|
+
* seconds; the rule sends ONE message when the window closes — early, once every
|
|
19645
|
+
* subject in it is final, never before {@link NC_GROUPING_MIN_SEC} — naming everybody
|
|
19646
|
+
* the rule matched, with one mosaic tile per subject.
|
|
19647
|
+
* Absent = plain immediate (one message per track, at the first match).
|
|
19648
|
+
* Only an `immediate` DETECTION rule may carry it (`ruleGroupingApplies`, enforced on
|
|
19649
|
+
* save by the hub's grouping guard). `.optional()`, never `.default()`: the addon cap
|
|
19650
|
+
* path does not run Zod defaults.
|
|
19750
19651
|
*/
|
|
19751
|
-
|
|
19752
|
-
/**
|
|
19753
|
-
* GROUP a burst of subjects into ONE notification that grows.
|
|
19754
|
-
*
|
|
19755
|
-
* Seconds of quiet after the last matching subject before the burst is
|
|
19756
|
-
* considered over. While it is open, the first subject enqueues immediately —
|
|
19757
|
-
* **exactly as today, with no added latency** — and every real growth (a new
|
|
19758
|
-
* subject, or a name confirmed on one already in it) REPLACES that
|
|
19759
|
-
* notification with an updated one naming everybody. The push carries the
|
|
19760
|
-
* group's own coalescing tag, so the phone replaces rather than stacks.
|
|
19761
|
-
*
|
|
19762
|
-
* `0` / absent = off, and off is today's behaviour byte for byte.
|
|
19763
|
-
*
|
|
19764
|
-
* ### Why an idle cutoff and not a window
|
|
19765
|
-
*
|
|
19766
|
-
* The measured seven-person arrival on device 590 spans 110 s with every
|
|
19767
|
-
* internal gap under 30 s. A 12 s fixed window cuts it into three groups; an
|
|
19768
|
-
* idle cutoff holds it as one and ends it when the arrival actually ends.
|
|
19769
|
-
* 30 s is a widely shipped value for the same decision.
|
|
19770
|
-
*
|
|
19771
|
-
* ### What it replaces
|
|
19772
|
-
*
|
|
19773
|
-
* The blind cooldown, which collapses a burst by DISCARDING it. Measured on
|
|
19774
|
-
* device 615 / *Persona su Uscio* over six days: 116 qualifying tracks → 74
|
|
19775
|
-
* notifications, **44 (37.9%) suppressed outright**, 23 of them overlapping a
|
|
19776
|
-
* track that did fire and 7 carrying a confirmed identity nobody heard about.
|
|
19777
|
-
* A group collapses the same volume by MERGING, so the cooldown becomes a
|
|
19778
|
-
* budget over GROUPS — which is what it always meant — and a growth is never
|
|
19779
|
-
* throttled by the window its own first member spent.
|
|
19780
|
-
*
|
|
19781
|
-
* ### Interaction with {@link waitForEnhancement}
|
|
19782
|
-
*
|
|
19783
|
-
* They compose, and the order matters. `waitForEnhancement` defers the rule to
|
|
19784
|
-
* TRACK CLOSE, so with both set the group is opened by the first member to
|
|
19785
|
-
* CLOSE — already carrying its name — and grows as later members close. That
|
|
19786
|
-
* is later, and complete. With grouping alone the group opens on the first
|
|
19787
|
-
* object event and picks up names as they are confirmed, through the growth
|
|
19788
|
-
* path. Neither combination fires twice for one subject.
|
|
19789
|
-
*
|
|
19790
|
-
* `.optional()` and deliberately NOT `.default()`: a Zod default does not run
|
|
19791
|
-
* on the addon cap path, so absent must keep meaning what it meant before this
|
|
19792
|
-
* field existed.
|
|
19793
|
-
*/
|
|
19794
|
-
groupIdleSec: number().int().min(0).max(600).optional()
|
|
19652
|
+
groupingSec: number().int().min(5).max(60).optional()
|
|
19795
19653
|
});
|
|
19796
19654
|
/**
|
|
19797
19655
|
* Partial patch for `updateRule` — any subset of the input fields, plus the
|
|
@@ -19839,9 +19697,10 @@ var NcRuleClearableKeySchema = _enum([
|
|
|
19839
19697
|
"targetUsers",
|
|
19840
19698
|
"snoozeOptions",
|
|
19841
19699
|
"snoozeAllowGlobal",
|
|
19842
|
-
"waitForEnhancement",
|
|
19843
19700
|
"actions",
|
|
19844
19701
|
"confirm",
|
|
19702
|
+
"groupingSec",
|
|
19703
|
+
"waitForEnhancement",
|
|
19845
19704
|
"groupIdleSec"
|
|
19846
19705
|
]);
|
|
19847
19706
|
var NcRuleUpdateInputSchema = object({
|
|
@@ -19863,9 +19722,25 @@ var NcRuleSchema = NcRuleInputSchema.extend({
|
|
|
19863
19722
|
*/
|
|
19864
19723
|
disabledTargetIds: array(string()).default([])
|
|
19865
19724
|
});
|
|
19725
|
+
/**
|
|
19726
|
+
* The state-summary SECTIONS (D647 / D698): the D637 kind groups that report a
|
|
19727
|
+
* still-true state. `backups-exports` and `alarm` are not sections — a completed
|
|
19728
|
+
* job is not an open state, and the alarm stays instant.
|
|
19729
|
+
*/
|
|
19730
|
+
var NcStateSummarySectionIdSchema = _enum([
|
|
19731
|
+
"device-state",
|
|
19732
|
+
"streams",
|
|
19733
|
+
"battery",
|
|
19734
|
+
"consumables",
|
|
19735
|
+
"tanks",
|
|
19736
|
+
"detection-blind",
|
|
19737
|
+
"nodes",
|
|
19738
|
+
"addons",
|
|
19739
|
+
"updates"
|
|
19740
|
+
]);
|
|
19866
19741
|
/** One section of a previewed state summary. `unavailable` = its state could not be read. */
|
|
19867
19742
|
var NcStateSummaryPreviewSectionSchema = object({
|
|
19868
|
-
id:
|
|
19743
|
+
id: NcStateSummarySectionIdSchema,
|
|
19869
19744
|
status: _enum(["read", "unavailable"]),
|
|
19870
19745
|
items: number().int().nonnegative(),
|
|
19871
19746
|
reason: string().optional()
|
|
@@ -19875,7 +19750,7 @@ var NcStateSummaryPreviewSectionSchema = object({
|
|
|
19875
19750
|
* a `rule` split (no `section`), one section's on a `section` split.
|
|
19876
19751
|
*/
|
|
19877
19752
|
var NcStateSummaryPreviewRowSchema = object({
|
|
19878
|
-
section:
|
|
19753
|
+
section: NcStateSummarySectionIdSchema.optional(),
|
|
19879
19754
|
/** The section's name on a per-section row; every reported section's, joined, on a combined one. */
|
|
19880
19755
|
title: string(),
|
|
19881
19756
|
text: string(),
|
|
@@ -20312,6 +20187,29 @@ object({
|
|
|
20312
20187
|
firstAt: number(),
|
|
20313
20188
|
lastAt: number()
|
|
20314
20189
|
});
|
|
20190
|
+
var NC_ALARM_TRIGGERED_MAX_SEC = 3600;
|
|
20191
|
+
var NcAlarmDelaySecSchema = number().int().min(0).max(600);
|
|
20192
|
+
var NcAlarmTriggeredSecSchema = number().int().min(0).max(NC_ALARM_TRIGGERED_MAX_SEC);
|
|
20193
|
+
var uniqueModes = (entries) => new Set(entries.map((e) => e.mode)).size === entries.length;
|
|
20194
|
+
var NcAlarmModeDelaysListSchema = array(object({
|
|
20195
|
+
mode: AlarmArmModeSchema,
|
|
20196
|
+
exitDelaySec: NcAlarmDelaySecSchema.optional(),
|
|
20197
|
+
entryDelaySec: NcAlarmDelaySecSchema.optional(),
|
|
20198
|
+
triggeredDurationSec: NcAlarmTriggeredSecSchema.optional()
|
|
20199
|
+
})).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
|
|
20200
|
+
var NcAlarmModeDelaysEditListSchema = array(object({
|
|
20201
|
+
mode: AlarmArmModeSchema,
|
|
20202
|
+
exitDelaySec: NcAlarmDelaySecSchema.nullable().optional(),
|
|
20203
|
+
entryDelaySec: NcAlarmDelaySecSchema.nullable().optional(),
|
|
20204
|
+
triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional()
|
|
20205
|
+
})).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
|
|
20206
|
+
/** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
|
|
20207
|
+
var NcAlarmNonBlockingEditSchema = object({
|
|
20208
|
+
mode: AlarmArmModeSchema,
|
|
20209
|
+
deviceId: number().int().positive(),
|
|
20210
|
+
/** true = on the list (may be open, does not block); false = off the list (blocks). */
|
|
20211
|
+
nonBlocking: boolean()
|
|
20212
|
+
});
|
|
20315
20213
|
/**
|
|
20316
20214
|
* The per-mode lists, at most one per mode. Two lists for one mode have no
|
|
20317
20215
|
* meaning a reader could agree on (union? the last one?), so they are refused
|
|
@@ -20320,10 +20218,10 @@ object({
|
|
|
20320
20218
|
var NcAlarmNonBlockingListSchema = array(object({
|
|
20321
20219
|
mode: AlarmArmModeSchema,
|
|
20322
20220
|
deviceIds: array(number().int()).max(200)
|
|
20323
|
-
})).max(8).refine(
|
|
20221
|
+
})).max(8).refine(uniqueModes, { message: "nonBlocking: at most one list per arm mode" });
|
|
20324
20222
|
/**
|
|
20325
|
-
* The three durations
|
|
20326
|
-
* transitions, and which openings each mode tolerates.
|
|
20223
|
+
* The three durations — global, and per mode since D697 — the panel's state
|
|
20224
|
+
* machine runs on, who hears about its transitions, and which openings each mode tolerates.
|
|
20327
20225
|
*
|
|
20328
20226
|
* They live on the NOTIFICATION-RULES cap, not on `alarm-panel`, on purpose:
|
|
20329
20227
|
* `alarm-panel` is `deviceNative` and its other provider mirrors somebody
|
|
@@ -20333,15 +20231,15 @@ var NcAlarmNonBlockingListSchema = array(object({
|
|
|
20333
20231
|
*/
|
|
20334
20232
|
var NcAlarmSettingsSchema = object({
|
|
20335
20233
|
/** Grace period between arming and the mode taking effect. 0 = immediate. */
|
|
20336
|
-
exitDelaySec:
|
|
20234
|
+
exitDelaySec: NcAlarmDelaySecSchema,
|
|
20337
20235
|
/** Grace period between a trigger and the alarm firing. 0 = immediate. */
|
|
20338
|
-
entryDelaySec:
|
|
20236
|
+
entryDelaySec: NcAlarmDelaySecSchema,
|
|
20339
20237
|
/**
|
|
20340
20238
|
* How long `triggered` lasts before the panel re-arms itself.
|
|
20341
20239
|
* **0 = until an operator disarms it** — the behaviour before this field
|
|
20342
20240
|
* existed, and therefore what an untouched install keeps doing.
|
|
20343
20241
|
*/
|
|
20344
|
-
triggeredDurationSec:
|
|
20242
|
+
triggeredDurationSec: NcAlarmTriggeredSecSchema,
|
|
20345
20243
|
/**
|
|
20346
20244
|
* Deprecated by D630 — every transition is announced. Parsed, never read;
|
|
20347
20245
|
* remove after one release. Optional so an older admin's patch (which still
|
|
@@ -20364,17 +20262,30 @@ var NcAlarmSettingsSchema = object({
|
|
|
20364
20262
|
* per mode is meaningful. Defaulted to `[]` so a blob stored before D630
|
|
20365
20263
|
* parses as "every opening blocks" — the behaviour it was written under.
|
|
20366
20264
|
*/
|
|
20367
|
-
nonBlocking: NcAlarmNonBlockingListSchema.default([])
|
|
20265
|
+
nonBlocking: NcAlarmNonBlockingListSchema.default([]),
|
|
20266
|
+
/**
|
|
20267
|
+
* Per arm mode, the delays that mode OVERRIDES (D697). A mode with no entry, or an entry
|
|
20268
|
+
* without a field, uses the global value above — so `[]`, the default, is exactly the
|
|
20269
|
+
* behaviour of a blob stored before this field existed. Read through `resolveModeDelays`.
|
|
20270
|
+
*/
|
|
20271
|
+
modeDelays: NcAlarmModeDelaysListSchema.default([])
|
|
20368
20272
|
});
|
|
20369
20273
|
/**
|
|
20370
20274
|
* Every field optional — a tab edits one control at a time.
|
|
20371
20275
|
*
|
|
20372
|
-
* `nonBlocking`
|
|
20373
|
-
* remove an inner `.default()`, so a patch that never
|
|
20374
|
-
* parse to `
|
|
20375
|
-
* (the same trap {@link NcRulePatchSchema} documents).
|
|
20276
|
+
* `nonBlocking` and `modeDelays` are re-declared WITHOUT their defaults:
|
|
20277
|
+
* `.partial()` does not remove an inner `.default()`, so a patch that never
|
|
20278
|
+
* named the field would parse to `[]` and wipe every mode's list on an
|
|
20279
|
+
* unrelated edit (the same trap {@link NcRulePatchSchema} documents). Here
|
|
20280
|
+
* `modeDelays` means EDITS, not the stored overrides.
|
|
20376
20281
|
*/
|
|
20377
|
-
var NcAlarmSettingsPatchSchema = NcAlarmSettingsSchema.extend({
|
|
20282
|
+
var NcAlarmSettingsPatchSchema = NcAlarmSettingsSchema.extend({
|
|
20283
|
+
nonBlocking: NcAlarmNonBlockingListSchema,
|
|
20284
|
+
/** Per-mode, per-field edits — NOT the whole list (see NcAlarmModeDelaysEditSchema). */
|
|
20285
|
+
modeDelays: NcAlarmModeDelaysEditListSchema,
|
|
20286
|
+
/** ONE membership change; the panel applies it to the list it holds at its turn. */
|
|
20287
|
+
nonBlockingEdit: NcAlarmNonBlockingEditSchema
|
|
20288
|
+
}).partial().refine((p) => p.nonBlocking === void 0 || p.nonBlockingEdit === void 0, { message: "nonBlocking and nonBlockingEdit are exclusive — send the whole lists or one edit" });
|
|
20378
20289
|
/**
|
|
20379
20290
|
* What one arm mode actually arms, DERIVED from the enabled rules gated on it.
|
|
20380
20291
|
* Never authored, never stored — see `alarm-mode-coverage.ts` for why a stored
|
|
@@ -20474,6 +20385,28 @@ var NcAlarmConfigSchema = object({
|
|
|
20474
20385
|
*/
|
|
20475
20386
|
live: NcAlarmLiveSchema.optional()
|
|
20476
20387
|
});
|
|
20388
|
+
var NcAlarmSensorReadingSchema = _enum([
|
|
20389
|
+
"open",
|
|
20390
|
+
"closed",
|
|
20391
|
+
"unknown",
|
|
20392
|
+
"not-opening"
|
|
20393
|
+
]);
|
|
20394
|
+
/** One device's state as the alarm reads it — the classifier the arm check uses. */
|
|
20395
|
+
var NcAlarmSensorStateSchema = object({
|
|
20396
|
+
deviceId: number().int().positive(),
|
|
20397
|
+
reading: NcAlarmSensorReadingSchema,
|
|
20398
|
+
/** The word as read (`open`, `closed`, `unlocked`, `stopped`, …); null when unknown / not an opening. */
|
|
20399
|
+
state: string().nullable(),
|
|
20400
|
+
/** Why `unknown`: the read failed, or the slice holds no word its cap defines (a placeholder included). */
|
|
20401
|
+
unknownWhy: _enum(["read-failed", "unknown-word"]).nullable(),
|
|
20402
|
+
/** The device manager's liveness as the centre mirrors it; null = not known. */
|
|
20403
|
+
online: boolean().nullable()
|
|
20404
|
+
});
|
|
20405
|
+
var NcAlarmSensorsInputSchema = object({ deviceIds: array(number().int().positive()).max(500) });
|
|
20406
|
+
var NcAlarmSensorsSchema = object({
|
|
20407
|
+
sensors: array(NcAlarmSensorStateSchema),
|
|
20408
|
+
readAt: number().int().nonnegative()
|
|
20409
|
+
});
|
|
20477
20410
|
/**
|
|
20478
20411
|
* ONE rule's demand on ONE camera's clip ring.
|
|
20479
20412
|
*
|
|
@@ -20564,7 +20497,7 @@ method(object({}), object({ rules: array(NcRuleSchema) }), { auth: "admin" }), m
|
|
|
20564
20497
|
}), method(object({}), NcAlarmConfigSchema, { auth: "admin" }), method(object({ patch: NcAlarmSettingsPatchSchema }), NcAlarmConfigSchema, {
|
|
20565
20498
|
kind: "mutation",
|
|
20566
20499
|
auth: "admin"
|
|
20567
|
-
});
|
|
20500
|
+
}), method(NcAlarmSensorsInputSchema, NcAlarmSensorsSchema, { auth: "admin" });
|
|
20568
20501
|
/**
|
|
20569
20502
|
* Zod schemas for persisted record types.
|
|
20570
20503
|
*
|
|
@@ -20911,12 +20844,26 @@ var CameraSensorRefSchema = object({
|
|
|
20911
20844
|
function cameraSensorRefKey(ref) {
|
|
20912
20845
|
return `${ref.addonId}/${ref.stableId}`;
|
|
20913
20846
|
}
|
|
20914
|
-
/**
|
|
20915
|
-
|
|
20916
|
-
|
|
20917
|
-
|
|
20918
|
-
|
|
20919
|
-
|
|
20847
|
+
/**
|
|
20848
|
+
* A sensor's mode (D673). `in-addition`: its motion is the camera's motion too.
|
|
20849
|
+
* `replace`: its motion is the camera's, and while one is READY the camera's
|
|
20850
|
+
* own motion no longer counts on its own. `confirm`: while one is READY the
|
|
20851
|
+
* camera's own motion counts only while a confirm sensor is active — with or
|
|
20852
|
+
* without a replace sensor (spec C2, the controller's ruling on Q1).
|
|
20853
|
+
*/
|
|
20854
|
+
var CameraSensorModeSchema = _enum([
|
|
20855
|
+
"in-addition",
|
|
20856
|
+
"confirm",
|
|
20857
|
+
"replace"
|
|
20858
|
+
]);
|
|
20859
|
+
/** A stored sensor with no mode — every CS-1 row — is in addition. */
|
|
20860
|
+
var DEFAULT_CAMERA_SENSOR_MODE = "in-addition";
|
|
20861
|
+
/**
|
|
20862
|
+
* A camera's attached sensors. A CS-1 row carried an envelope
|
|
20863
|
+
* `mode: 'in-addition'`: `z.object` drops it on parse, and the PARSED value is
|
|
20864
|
+
* what the write stores (D672 rule 3), so it is never written again.
|
|
20865
|
+
*/
|
|
20866
|
+
var CameraSensorsConfigSchema = object({ sensors: array(CameraSensorRefSchema.extend({ mode: CameraSensorModeSchema.default(DEFAULT_CAMERA_SENSOR_MODE) })).min(1).max(8) }).superRefine((value, ctx) => {
|
|
20920
20867
|
const seen = /* @__PURE__ */ new Set();
|
|
20921
20868
|
value.sensors.forEach((ref, index) => {
|
|
20922
20869
|
const key = cameraSensorRefKey(ref);
|
|
@@ -20928,39 +20875,41 @@ var CameraSensorsConfigSchema = object({
|
|
|
20928
20875
|
seen.add(key);
|
|
20929
20876
|
});
|
|
20930
20877
|
});
|
|
20931
|
-
|
|
20878
|
+
/** Every attachment names its mode; an older orchestrator that does not is in addition. */
|
|
20879
|
+
var AttachmentFields = {
|
|
20932
20880
|
addonId: string(),
|
|
20933
|
-
stableId: string()
|
|
20881
|
+
stableId: string(),
|
|
20882
|
+
mode: CameraSensorModeSchema.default(DEFAULT_CAMERA_SENSOR_MODE)
|
|
20934
20883
|
};
|
|
20935
20884
|
var CameraSensorAttachmentSchema = discriminatedUnion("state", [
|
|
20936
20885
|
object({
|
|
20937
|
-
...
|
|
20886
|
+
...AttachmentFields,
|
|
20938
20887
|
state: literal("ready"),
|
|
20939
20888
|
deviceId: number(),
|
|
20940
20889
|
name: string(),
|
|
20941
20890
|
caps: array(string()).readonly()
|
|
20942
20891
|
}),
|
|
20943
20892
|
object({
|
|
20944
|
-
...
|
|
20893
|
+
...AttachmentFields,
|
|
20945
20894
|
state: literal("offline"),
|
|
20946
20895
|
deviceId: number(),
|
|
20947
20896
|
name: string(),
|
|
20948
20897
|
reason: _enum(["offline", "disabled"])
|
|
20949
20898
|
}),
|
|
20950
20899
|
object({
|
|
20951
|
-
...
|
|
20900
|
+
...AttachmentFields,
|
|
20952
20901
|
state: literal("missing"),
|
|
20953
20902
|
reason: string()
|
|
20954
20903
|
}),
|
|
20955
20904
|
object({
|
|
20956
|
-
...
|
|
20905
|
+
...AttachmentFields,
|
|
20957
20906
|
state: literal("unsupported"),
|
|
20958
20907
|
deviceId: number(),
|
|
20959
20908
|
name: string(),
|
|
20960
20909
|
reason: string()
|
|
20961
20910
|
}),
|
|
20962
20911
|
object({
|
|
20963
|
-
...
|
|
20912
|
+
...AttachmentFields,
|
|
20964
20913
|
state: literal("unreadable"),
|
|
20965
20914
|
reason: string()
|
|
20966
20915
|
})
|
|
@@ -20973,17 +20922,49 @@ var CameraSensorAttachmentSchema = discriminatedUnion("state", [
|
|
|
20973
20922
|
* say.
|
|
20974
20923
|
*/
|
|
20975
20924
|
var CameraSensorsNotForwardedSchema = _enum(["onboard-not-listed", "no-active-detection"]);
|
|
20925
|
+
/** Whether the camera's OWN motion counts on its own (D673 C2), from its READY sensors (C3). */
|
|
20926
|
+
var CameraOwnMotionSchema = _enum([
|
|
20927
|
+
"always",
|
|
20928
|
+
"when-confirmed",
|
|
20929
|
+
"never"
|
|
20930
|
+
]);
|
|
20931
|
+
/** Confirm / Replace cannot suppress this camera's motion: its provider still emits it directly (D673 C13). */
|
|
20932
|
+
var CameraSensorsNotEnforcedSchema = _enum(["provider-not-split"]);
|
|
20933
|
+
/**
|
|
20934
|
+
* The camera's OWN onboard motion (D696): the raw input the bridge combines,
|
|
20935
|
+
* never the effective value. The camera's `motion` slice is the effective one,
|
|
20936
|
+
* so a view of the camera's own row reads this.
|
|
20937
|
+
* - `atMs`: when the bridge received the camera's last own edge.
|
|
20938
|
+
* - `detected`: evaluated WHEN THE STATUS IS ASKED — the last edge said `true`
|
|
20939
|
+
* AND it is younger than the window the bridge counts the camera's own motion
|
|
20940
|
+
* for (`motionCooldownMs`, floored at two sustain ticks). A camera that never
|
|
20941
|
+
* sends a clear (heartbeats only) therefore reads `false` once no push came
|
|
20942
|
+
* within the window; a status read is a snapshot, so a live view re-asks.
|
|
20943
|
+
* Absent = this orchestrator has not received the camera's own motion since it
|
|
20944
|
+
* started (unknown, never "quiet"), or an orchestrator older than D696.
|
|
20945
|
+
*/
|
|
20946
|
+
var CameraRawLevelSchema = object({
|
|
20947
|
+
detected: boolean(),
|
|
20948
|
+
atMs: number()
|
|
20949
|
+
});
|
|
20976
20950
|
var CameraSensorsStatusSchema = discriminatedUnion("state", [
|
|
20977
|
-
object({
|
|
20951
|
+
object({
|
|
20952
|
+
state: literal("not-configured"),
|
|
20953
|
+
cameraLevel: CameraRawLevelSchema.optional()
|
|
20954
|
+
}),
|
|
20978
20955
|
object({
|
|
20979
20956
|
state: literal("unreadable"),
|
|
20980
|
-
reason: string()
|
|
20957
|
+
reason: string(),
|
|
20958
|
+
cameraLevel: CameraRawLevelSchema.optional()
|
|
20981
20959
|
}),
|
|
20982
20960
|
object({
|
|
20983
20961
|
state: literal("configured"),
|
|
20984
|
-
|
|
20962
|
+
cameraLevel: CameraRawLevelSchema.optional(),
|
|
20985
20963
|
sensors: array(CameraSensorAttachmentSchema).readonly(),
|
|
20986
|
-
|
|
20964
|
+
/** Absent = an orchestrator older than CS-2: it does not say (D315). */
|
|
20965
|
+
cameraMotion: CameraOwnMotionSchema.optional(),
|
|
20966
|
+
notForwarded: CameraSensorsNotForwardedSchema.optional(),
|
|
20967
|
+
notEnforced: CameraSensorsNotEnforcedSchema.optional()
|
|
20987
20968
|
})
|
|
20988
20969
|
]);
|
|
20989
20970
|
Object.freeze({
|
|
@@ -21668,14 +21649,14 @@ var TrackSchema = object({
|
|
|
21668
21649
|
* `derive-returned-null tile=standin`,
|
|
21669
21650
|
* `native-tile tile=native no-key-frame-at-close`, …) written at close and
|
|
21670
21651
|
* CLEARED by the late-keyFrame upgrade when a native tile lands after all.
|
|
21671
|
-
* The operator-facing answer to "perché manca l'immagine?" on a track whose
|
|
21652
|
+
* The operator-facing answer to "perché manca l'immagine?" [why is the image missing?] on a track whose
|
|
21672
21653
|
* tile is a face/plate stand-in, a raster crop, or an icon.
|
|
21673
21654
|
*
|
|
21674
21655
|
* **`no-key-frame-at-close` (D400).** The line used to be written ONLY when
|
|
21675
21656
|
* the TILE ranked below native, so a track whose thumbnail landed natively
|
|
21676
21657
|
* while its key frame missed carried no reason at all — three of the four
|
|
21677
21658
|
* `MISSING_KEYFRAME` tracks in the 2026-09-07 operator audit were exactly
|
|
21678
|
-
* that shape, and their "niente ultimo" had no cause anywhere on the row.
|
|
21659
|
+
* that shape, and their "niente ultimo" [no last frame] had no cause anywhere on the row.
|
|
21679
21660
|
* The key frame is the head of a cascade (`keyFrame ⇒ keyFrameSmall ⇒ the
|
|
21680
21661
|
* lastFrame copy source`), so its absence is now on this line whatever the
|
|
21681
21662
|
* tile ended up being.
|
|
@@ -21762,7 +21743,7 @@ var MotionEventSchema = object({
|
|
|
21762
21743
|
/**
|
|
21763
21744
|
* Ms offsets from `timestamp` (the episode's own first rising edge, so the
|
|
21764
21745
|
* first entry is always `0`) of every genuine off→on transition the
|
|
21765
|
-
* episode saw — "ogni evento on si deve salvare" (D475). NOT one entry per
|
|
21746
|
+
* episode saw — "ogni evento on si deve salvare" [every ON event must be saved] (D475). NOT one entry per
|
|
21766
21747
|
* push: a firmware source that keepalives at ~1 Hz for the whole burst
|
|
21767
21748
|
* (Reolink, Hikvision) produces exactly one edge; a source that reports an
|
|
21768
21749
|
* explicit `false` mid-episode and then resumes before the quiet window
|
|
@@ -22286,6 +22267,7 @@ var KeyEventSchema = object({
|
|
|
22286
22267
|
bestEventId: string(),
|
|
22287
22268
|
/** Track lifetime in ms (lastSeen - firstSeen). */
|
|
22288
22269
|
windowMs: number().optional(),
|
|
22270
|
+
audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
|
|
22289
22271
|
...TrackFlagFields,
|
|
22290
22272
|
...TrackRetrainFields
|
|
22291
22273
|
});
|
|
@@ -24214,8 +24196,10 @@ var RunnerCameraConfigSchema = object({
|
|
|
24214
24196
|
* - `analyzer`: ML/frame-diff motion detection (motion-wasm or other
|
|
24215
24197
|
* analyzer providers) running on decoded frames in this runner.
|
|
24216
24198
|
* - `onboard`: camera-native motion pushes (Reolink Baichuan, ONVIF
|
|
24217
|
-
* analytics). The provider emits ProviderMotion
|
|
24218
|
-
*
|
|
24199
|
+
* analytics). The provider emits its raw push as `ProviderMotion`
|
|
24200
|
+
* (D673); the orchestrator's camera-sensors bridge re-emits the camera's
|
|
24201
|
+
* effective motion as `MotionOnMotionChanged`, which is what reaches
|
|
24202
|
+
* `reportMotion`.
|
|
24219
24203
|
*/
|
|
24220
24204
|
motionSources: MotionSourcesSchema.default(["analyzer"]),
|
|
24221
24205
|
/**
|
|
@@ -24392,7 +24376,15 @@ var RunnerLocalLoadSchema = object({
|
|
|
24392
24376
|
hasGpu: boolean(),
|
|
24393
24377
|
inferenceBackend: string().optional(),
|
|
24394
24378
|
cpuCores: number().optional()
|
|
24395
|
-
})
|
|
24379
|
+
}),
|
|
24380
|
+
/**
|
|
24381
|
+
* Who writes a camera's `motion` runtime slice (D696). `'orchestrator'`: this
|
|
24382
|
+
* runner never writes it. ABSENT = a runner older than D696, which still
|
|
24383
|
+
* writes the slice from its phase machine; the orchestrator does not write
|
|
24384
|
+
* while any runner node is absent-or-unanswered, so one slice never has two
|
|
24385
|
+
* writers.
|
|
24386
|
+
*/
|
|
24387
|
+
motionSliceWriter: literal("orchestrator").optional()
|
|
24396
24388
|
});
|
|
24397
24389
|
/**
|
|
24398
24390
|
* Aggregate runtime metrics for the runner's whole local pool. Mirrors the
|
|
@@ -27205,7 +27197,7 @@ var ClipPlaybackSchema = object({
|
|
|
27205
27197
|
* **One authorised yes is one wake.** `next-natural` — take the clip the next
|
|
27206
27198
|
* time the camera is awake for its own reasons — is deliberately not a member:
|
|
27207
27199
|
* it was proposed, it is free on the battery, and the operator declined it on
|
|
27208
|
-
* 2026-09-20 (*"Quando un export viene richiesto si sveglia la camera."
|
|
27200
|
+
* 2026-09-20 (*"Quando un export viene richiesto si sveglia la camera."* [When an export is requested the camera wakes up],
|
|
27209
27201
|
* D558 "Considered and not taken").
|
|
27210
27202
|
*/
|
|
27211
27203
|
var ClipWakeSchema = _enum(["authorised"]);
|
|
@@ -27466,7 +27458,7 @@ DeviceType.Camera, method(object({
|
|
|
27466
27458
|
* It replaced `sources?: string[]`, a VIEW filter over source ids that
|
|
27467
27459
|
* assumed the answer was a fan-out over everything a camera has. The
|
|
27468
27460
|
* operator settled otherwise on 2026-09-20 — *"l'utilizzatore è uno
|
|
27469
|
-
* solo"* — so the list is asked of one provider at a time and there is
|
|
27461
|
+
* solo"* [there is only one user] — so the list is asked of one provider at a time and there is
|
|
27470
27462
|
* nothing to filter out of it.
|
|
27471
27463
|
*/
|
|
27472
27464
|
provider: string().min(1)
|
|
@@ -30061,6 +30053,70 @@ onStatusChanged: { data: object({
|
|
|
30061
30053
|
* whether persisting is worth a SQLite commit. */
|
|
30062
30054
|
volatileStateFields: ["lastChangedAt"]
|
|
30063
30055
|
};
|
|
30056
|
+
var DoorbellStatusSchema = object({
|
|
30057
|
+
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
30058
|
+
lastPressedAt: number().nullable(),
|
|
30059
|
+
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
30060
|
+
pressCountSinceStart: number()
|
|
30061
|
+
});
|
|
30062
|
+
var DoorbellPressEventSchema = object({
|
|
30063
|
+
deviceId: number(),
|
|
30064
|
+
timestamp: number()
|
|
30065
|
+
});
|
|
30066
|
+
/**
|
|
30067
|
+
* Doorbell button cap. Two kinds of provider serve it, and to every consumer
|
|
30068
|
+
* they are the same cap:
|
|
30069
|
+
*
|
|
30070
|
+
* - **Native** providers, registered per device by a driver addon through
|
|
30071
|
+
* `ctx.registerNativeCap` — a `DeviceType.Button` accessory with
|
|
30072
|
+
* `role: DeviceRole.Doorbell`, or the camera itself (Reolink registers at
|
|
30073
|
+
* camera level). They emit `onPressed` on every firmware ring.
|
|
30074
|
+
* - **A composed doorbell** (D670, D671): a camera's customization gives it
|
|
30075
|
+
* the cap, its `lastPressedAt` rising from the sources the operator
|
|
30076
|
+
* assigned in Customize → Doorbell, and the composer emits `onPressed`
|
|
30077
|
+
* from that field's advance (`fromState`).
|
|
30078
|
+
*
|
|
30079
|
+
* The DeviceEventPropagator re-emits `onPressed` on the camera parent.
|
|
30080
|
+
*/
|
|
30081
|
+
var doorbellCapability = {
|
|
30082
|
+
name: "doorbell",
|
|
30083
|
+
scope: "device",
|
|
30084
|
+
deviceNative: true,
|
|
30085
|
+
mode: "singleton",
|
|
30086
|
+
deviceTypes: [DeviceType.Button, DeviceType.Camera],
|
|
30087
|
+
methods: {},
|
|
30088
|
+
events: {
|
|
30089
|
+
/**
|
|
30090
|
+
* Fires once per physical press. Reolink delivers via Baichuan
|
|
30091
|
+
* push (`ReolinkSimpleEvent.type === 'doorbell'`). There is no
|
|
30092
|
+
* release/duration — it's a pulse.
|
|
30093
|
+
*/
|
|
30094
|
+
onPressed: {
|
|
30095
|
+
data: DoorbellPressEventSchema,
|
|
30096
|
+
fromState: {
|
|
30097
|
+
field: "lastPressedAt",
|
|
30098
|
+
on: "advance"
|
|
30099
|
+
}
|
|
30100
|
+
} },
|
|
30101
|
+
status: {
|
|
30102
|
+
schema: DoorbellStatusSchema,
|
|
30103
|
+
kind: "push"
|
|
30104
|
+
},
|
|
30105
|
+
/**
|
|
30106
|
+
* Runtime-state slice — last press timestamp + lifetime press count.
|
|
30107
|
+
* Mirrored by the kernel and readable via
|
|
30108
|
+
* `device.state.doorbell.value`. UIs can show "last ring 5m ago"
|
|
30109
|
+
* without subscribing.
|
|
30110
|
+
*/
|
|
30111
|
+
runtimeState: DoorbellStatusSchema,
|
|
30112
|
+
/**
|
|
30113
|
+
* 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.
|
|
30114
|
+
*
|
|
30115
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
30116
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
30117
|
+
*/
|
|
30118
|
+
durability: "restored"
|
|
30119
|
+
};
|
|
30064
30120
|
/**
|
|
30065
30121
|
* Enum-state sensor — a string value picked from a finite option set.
|
|
30066
30122
|
* Drives HA `sensor` entries with `state_class: enum` (HVAC action
|
|
@@ -32205,9 +32261,9 @@ var MotionStatusSchema = object({
|
|
|
32205
32261
|
/** Ms epoch of the last detected-true observation. Null if never detected. */
|
|
32206
32262
|
lastDetectedAt: number().nullable(),
|
|
32207
32263
|
/**
|
|
32208
|
-
* `MOTION_CLOSE_AFTER_MS` while `detected: true` on a `Camera` device
|
|
32209
|
-
* `null` while false and on every `Sensor`
|
|
32210
|
-
* constant's doc for the one-authority rule.
|
|
32264
|
+
* `MOTION_CLOSE_AFTER_MS` while `detected: true` on a `Camera` device (the
|
|
32265
|
+
* orchestrator writes it, D696), `null` while false and on every `Sensor`
|
|
32266
|
+
* device (D475) — see that constant's doc for the one-authority rule.
|
|
32211
32267
|
*
|
|
32212
32268
|
* ## Reading this field still arms nothing
|
|
32213
32269
|
*
|
|
@@ -32225,34 +32281,31 @@ var MotionStatusSchema = object({
|
|
|
32225
32281
|
* `addon-export-alexa/src/motion-clear-hold.ts` and
|
|
32226
32282
|
* `addon-export-hap`'s `RESET_DEBOUNCE_MS` both do.
|
|
32227
32283
|
*
|
|
32228
|
-
* ## Who writes it
|
|
32229
|
-
*
|
|
32230
|
-
* - **Cameras** — the
|
|
32231
|
-
*
|
|
32232
|
-
* `
|
|
32233
|
-
* `
|
|
32234
|
-
*
|
|
32235
|
-
*
|
|
32236
|
-
* a
|
|
32237
|
-
*
|
|
32238
|
-
*
|
|
32239
|
-
*
|
|
32240
|
-
*
|
|
32241
|
-
*
|
|
32242
|
-
*
|
|
32243
|
-
*
|
|
32244
|
-
*
|
|
32245
|
-
*
|
|
32246
|
-
* `
|
|
32247
|
-
*
|
|
32248
|
-
*
|
|
32249
|
-
*
|
|
32250
|
-
*
|
|
32251
|
-
*
|
|
32252
|
-
*
|
|
32253
|
-
* This predates D475 and is not fixed there: the fix touches every
|
|
32254
|
-
* camera provider. Recorded in D475's Consequences. Do not restore the
|
|
32255
|
-
* "sole writer" wording without also removing the other writers.
|
|
32284
|
+
* ## Who writes it (D696)
|
|
32285
|
+
*
|
|
32286
|
+
* - **Cameras** — the orchestrator, and nothing else. It writes the camera's
|
|
32287
|
+
* EFFECTIVE motion (`addon-pipeline-orchestrator`
|
|
32288
|
+
* `camera-sensors/motion-slice.ts`), alongside the effective
|
|
32289
|
+
* `MotionOnMotionChanged` it emits or receives: the camera-sensors bridge
|
|
32290
|
+
* for a split camera, an unsplit emitter's direct event, the analyzer and
|
|
32291
|
+
* device activity, as the camera's `motionSources` counts them. A source
|
|
32292
|
+
* that never sends a clear falls one window after its last `true`.
|
|
32293
|
+
* `lastDetectedAt` moves only on an effective rise. No camera provider
|
|
32294
|
+
* writes this slice (not even a boot seed), and neither does the runner's
|
|
32295
|
+
* phase machine: its phase is "a session is attached" for every on-motion
|
|
32296
|
+
* session, not motion, and it now has its own `DetectionPhaseTransition`.
|
|
32297
|
+
* A provider's `isDetected` answers from the hub's slice.
|
|
32298
|
+
* - **Sensors** (Home Assistant binary sensors, Homematic, Matter, Alexa
|
|
32299
|
+
* imports) — the provider pushes both edges itself, from the upstream
|
|
32300
|
+
* system's own state change. That is the sensor's own fact.
|
|
32301
|
+
*
|
|
32302
|
+
* `scripts/check-onboard-motion-emitters.ts` refuses any other writer of a
|
|
32303
|
+
* `motion` slice; each sensor writer is a named exemption.
|
|
32304
|
+
*
|
|
32305
|
+
* This replaces the D475 §4 rule ("the phase machine is the sole writer").
|
|
32306
|
+
* That rule was never true: Hikvision and Amcrest wrote the slice raw beside
|
|
32307
|
+
* it, every provider seeded it at boot, and every session left it
|
|
32308
|
+
* `detected: true` after its detach.
|
|
32256
32309
|
*/
|
|
32257
32310
|
autoClearAfterMs: number().nullable()
|
|
32258
32311
|
});
|
|
@@ -32324,11 +32377,12 @@ onMotionChanged: { data: MotionOnMotionChangedDataSchema } },
|
|
|
32324
32377
|
*/
|
|
32325
32378
|
runtimeState: MotionStatusSchema,
|
|
32326
32379
|
/**
|
|
32327
|
-
* Runtime-state durability: **session** —
|
|
32380
|
+
* Runtime-state durability: **session** — the writer of this slice
|
|
32328
32381
|
* writes only on an EDGE, so a restored `detected: true` would stay
|
|
32329
32382
|
* frozen until the next one instead of being corrected. The next edge
|
|
32330
|
-
* re-publishes the real state
|
|
32331
|
-
*
|
|
32383
|
+
* re-publishes the real state, and the orchestrator re-publishes every
|
|
32384
|
+
* camera when it starts writing (D696; on who writes it, see
|
|
32385
|
+
* `autoClearAfterMs` above).
|
|
32332
32386
|
*
|
|
32333
32387
|
* See `RuntimeStateDurability`. Enforced by
|
|
32334
32388
|
* `scripts/check-runtime-state-durability.ts`.
|
|
@@ -34711,8 +34765,7 @@ var ptzAutotrackCapability = {
|
|
|
34711
34765
|
deviceNative: true,
|
|
34712
34766
|
mode: "singleton",
|
|
34713
34767
|
/**
|
|
34714
|
-
* Two kinds of provider behind one name, the same shape `snapshot`
|
|
34715
|
-
* `doorbell` use:
|
|
34768
|
+
* Two kinds of provider behind one name, the same shape `snapshot` uses:
|
|
34716
34769
|
*
|
|
34717
34770
|
* - **Native**: the camera's own firmware autotrack, registered per device by
|
|
34718
34771
|
* the driver when the probe says it exists (Reolink: yes; Hikvision:
|
|
@@ -34720,7 +34773,7 @@ var ptzAutotrackCapability = {
|
|
|
34720
34773
|
* - **Wrapper**: the emulated implementation (`@camstack/system`'s `autotrack` builtin),
|
|
34721
34774
|
* which follows a subject with `ptz.move` pulses driven by the detection
|
|
34722
34775
|
* pipeline. `defaultActive: false` — the operator binds it per camera in
|
|
34723
|
-
* the bindings UI
|
|
34776
|
+
* the bindings UI.
|
|
34724
34777
|
*
|
|
34725
34778
|
* The binding chooses WHICH implementation answers; `setEnabled` stays the
|
|
34726
34779
|
* one switch for the function either way. A camera never has both driving its
|
|
@@ -35395,7 +35448,7 @@ var ReadGopBytesResultSchema = object({
|
|
|
35395
35448
|
/**
|
|
35396
35449
|
* A time WINDOW of one finalized segment, cut by byte range — the multi-GOP
|
|
35397
35450
|
* twin of {@link ReadGopBytesResultSchema}'s single instant. Built for the
|
|
35398
|
-
* replay clip's `recording` source (`docs/design/plans/2026-08-26-replay-
|
|
35451
|
+
* replay clip's `recording` source (`docs/design/plans/2026-08-26-clip-replay-on-pipeline.md`):
|
|
35399
35452
|
* a replay needs several seconds of native pixels, not one frame.
|
|
35400
35453
|
*
|
|
35401
35454
|
* `ok.data` is standalone-demuxable, same as a GOP read. `ok.reachesRequestedEnd`
|
|
@@ -38759,6 +38812,7 @@ var zoneRulesCapability = {
|
|
|
38759
38812
|
*/
|
|
38760
38813
|
durability: "restored"
|
|
38761
38814
|
};
|
|
38815
|
+
SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
|
|
38762
38816
|
/**
|
|
38763
38817
|
* Accessory device helpers — shared across drivers.
|
|
38764
38818
|
*
|
|
@@ -44784,6 +44838,12 @@ Object.freeze({
|
|
|
44784
44838
|
addonId: null,
|
|
44785
44839
|
access: "view"
|
|
44786
44840
|
},
|
|
44841
|
+
"notificationRules.getAlarmSensors": {
|
|
44842
|
+
capName: "notification-rules",
|
|
44843
|
+
capScope: "system",
|
|
44844
|
+
addonId: null,
|
|
44845
|
+
access: "view"
|
|
44846
|
+
},
|
|
44787
44847
|
"notificationRules.getClipRetentionAsks": {
|
|
44788
44848
|
capName: "notification-rules",
|
|
44789
44849
|
capScope: "system",
|
|
@@ -48362,6 +48422,11 @@ Object.freeze({
|
|
|
48362
48422
|
}
|
|
48363
48423
|
});
|
|
48364
48424
|
Object.freeze({
|
|
48425
|
+
"accessories.getStatus": [{
|
|
48426
|
+
name: "deviceId",
|
|
48427
|
+
form: "single",
|
|
48428
|
+
optional: false
|
|
48429
|
+
}],
|
|
48365
48430
|
"accessories.setChildHidden": [{
|
|
48366
48431
|
name: "childDeviceId",
|
|
48367
48432
|
form: "single",
|
|
@@ -48381,6 +48446,11 @@ Object.freeze({
|
|
|
48381
48446
|
form: "single",
|
|
48382
48447
|
optional: false
|
|
48383
48448
|
}],
|
|
48449
|
+
"airQualitySensor.getStatus": [{
|
|
48450
|
+
name: "deviceId",
|
|
48451
|
+
form: "single",
|
|
48452
|
+
optional: false
|
|
48453
|
+
}],
|
|
48384
48454
|
"alarmPanel.arm": [{
|
|
48385
48455
|
name: "deviceId",
|
|
48386
48456
|
form: "single",
|
|
@@ -48391,11 +48461,36 @@ Object.freeze({
|
|
|
48391
48461
|
form: "single",
|
|
48392
48462
|
optional: false
|
|
48393
48463
|
}],
|
|
48464
|
+
"alarmPanel.getStatus": [{
|
|
48465
|
+
name: "deviceId",
|
|
48466
|
+
form: "single",
|
|
48467
|
+
optional: false
|
|
48468
|
+
}],
|
|
48394
48469
|
"alarmPanel.trigger": [{
|
|
48395
48470
|
name: "deviceId",
|
|
48396
48471
|
form: "single",
|
|
48397
48472
|
optional: false
|
|
48398
48473
|
}],
|
|
48474
|
+
"ambientLightSensor.getStatus": [{
|
|
48475
|
+
name: "deviceId",
|
|
48476
|
+
form: "single",
|
|
48477
|
+
optional: false
|
|
48478
|
+
}],
|
|
48479
|
+
"audioAnalysis.applyDeviceSettingsPatch": [{
|
|
48480
|
+
name: "deviceId",
|
|
48481
|
+
form: "single",
|
|
48482
|
+
optional: false
|
|
48483
|
+
}],
|
|
48484
|
+
"audioAnalysis.getDeviceLiveContribution": [{
|
|
48485
|
+
name: "deviceId",
|
|
48486
|
+
form: "single",
|
|
48487
|
+
optional: false
|
|
48488
|
+
}],
|
|
48489
|
+
"audioAnalysis.getDeviceSettingsContribution": [{
|
|
48490
|
+
name: "deviceId",
|
|
48491
|
+
form: "single",
|
|
48492
|
+
optional: false
|
|
48493
|
+
}],
|
|
48399
48494
|
"audioAnalysis.resolveDeviceSettings": [{
|
|
48400
48495
|
name: "deviceId",
|
|
48401
48496
|
form: "single",
|
|
@@ -48436,16 +48531,36 @@ Object.freeze({
|
|
|
48436
48531
|
form: "single",
|
|
48437
48532
|
optional: false
|
|
48438
48533
|
}],
|
|
48534
|
+
"automationControl.getStatus": [{
|
|
48535
|
+
name: "deviceId",
|
|
48536
|
+
form: "single",
|
|
48537
|
+
optional: false
|
|
48538
|
+
}],
|
|
48439
48539
|
"automationControl.trigger": [{
|
|
48440
48540
|
name: "deviceId",
|
|
48441
48541
|
form: "single",
|
|
48442
48542
|
optional: false
|
|
48443
48543
|
}],
|
|
48544
|
+
"battery.getStatus": [{
|
|
48545
|
+
name: "deviceId",
|
|
48546
|
+
form: "single",
|
|
48547
|
+
optional: false
|
|
48548
|
+
}],
|
|
48444
48549
|
"battery.wakeForStream": [{
|
|
48445
48550
|
name: "deviceId",
|
|
48446
48551
|
form: "single",
|
|
48447
48552
|
optional: false
|
|
48448
48553
|
}],
|
|
48554
|
+
"binary.getStatus": [{
|
|
48555
|
+
name: "deviceId",
|
|
48556
|
+
form: "single",
|
|
48557
|
+
optional: false
|
|
48558
|
+
}],
|
|
48559
|
+
"brightness.getStatus": [{
|
|
48560
|
+
name: "deviceId",
|
|
48561
|
+
form: "single",
|
|
48562
|
+
optional: false
|
|
48563
|
+
}],
|
|
48449
48564
|
"brightness.setBrightness": [{
|
|
48450
48565
|
name: "deviceId",
|
|
48451
48566
|
form: "single",
|
|
@@ -48461,6 +48576,26 @@ Object.freeze({
|
|
|
48461
48576
|
form: "single",
|
|
48462
48577
|
optional: false
|
|
48463
48578
|
}],
|
|
48579
|
+
"cameraCredentials.getStatus": [{
|
|
48580
|
+
name: "deviceId",
|
|
48581
|
+
form: "single",
|
|
48582
|
+
optional: false
|
|
48583
|
+
}],
|
|
48584
|
+
"cameraGridLayout.applyDeviceSettingsPatch": [{
|
|
48585
|
+
name: "deviceId",
|
|
48586
|
+
form: "single",
|
|
48587
|
+
optional: false
|
|
48588
|
+
}],
|
|
48589
|
+
"cameraGridLayout.getDeviceLiveContribution": [{
|
|
48590
|
+
name: "deviceId",
|
|
48591
|
+
form: "single",
|
|
48592
|
+
optional: false
|
|
48593
|
+
}],
|
|
48594
|
+
"cameraGridLayout.getDeviceSettingsContribution": [{
|
|
48595
|
+
name: "deviceId",
|
|
48596
|
+
form: "single",
|
|
48597
|
+
optional: false
|
|
48598
|
+
}],
|
|
48464
48599
|
"cameraGridLayout.getLayout": [{
|
|
48465
48600
|
name: "deviceId",
|
|
48466
48601
|
form: "single",
|
|
@@ -48476,6 +48611,21 @@ Object.freeze({
|
|
|
48476
48611
|
form: "single",
|
|
48477
48612
|
optional: false
|
|
48478
48613
|
}],
|
|
48614
|
+
"cameraPipelineConfig.applyDeviceSettingsPatch": [{
|
|
48615
|
+
name: "deviceId",
|
|
48616
|
+
form: "single",
|
|
48617
|
+
optional: false
|
|
48618
|
+
}],
|
|
48619
|
+
"cameraPipelineConfig.getDeviceLiveContribution": [{
|
|
48620
|
+
name: "deviceId",
|
|
48621
|
+
form: "single",
|
|
48622
|
+
optional: false
|
|
48623
|
+
}],
|
|
48624
|
+
"cameraPipelineConfig.getDeviceSettingsContribution": [{
|
|
48625
|
+
name: "deviceId",
|
|
48626
|
+
form: "single",
|
|
48627
|
+
optional: false
|
|
48628
|
+
}],
|
|
48479
48629
|
"cameraStreams.getBrokerStreams": [{
|
|
48480
48630
|
name: "deviceId",
|
|
48481
48631
|
form: "single",
|
|
@@ -48501,6 +48651,16 @@ Object.freeze({
|
|
|
48501
48651
|
form: "single",
|
|
48502
48652
|
optional: false
|
|
48503
48653
|
}],
|
|
48654
|
+
"carbonMonoxide.getStatus": [{
|
|
48655
|
+
name: "deviceId",
|
|
48656
|
+
form: "single",
|
|
48657
|
+
optional: false
|
|
48658
|
+
}],
|
|
48659
|
+
"climateControl.getStatus": [{
|
|
48660
|
+
name: "deviceId",
|
|
48661
|
+
form: "single",
|
|
48662
|
+
optional: false
|
|
48663
|
+
}],
|
|
48504
48664
|
"climateControl.setFanMode": [{
|
|
48505
48665
|
name: "deviceId",
|
|
48506
48666
|
form: "single",
|
|
@@ -48541,16 +48701,41 @@ Object.freeze({
|
|
|
48541
48701
|
form: "single",
|
|
48542
48702
|
optional: false
|
|
48543
48703
|
}],
|
|
48704
|
+
"color.getStatus": [{
|
|
48705
|
+
name: "deviceId",
|
|
48706
|
+
form: "single",
|
|
48707
|
+
optional: false
|
|
48708
|
+
}],
|
|
48544
48709
|
"color.setColor": [{
|
|
48545
48710
|
name: "deviceId",
|
|
48546
48711
|
form: "single",
|
|
48547
48712
|
optional: false
|
|
48548
48713
|
}],
|
|
48714
|
+
"connectivity.getStatus": [{
|
|
48715
|
+
name: "deviceId",
|
|
48716
|
+
form: "single",
|
|
48717
|
+
optional: false
|
|
48718
|
+
}],
|
|
48719
|
+
"consumables.getStatus": [{
|
|
48720
|
+
name: "deviceId",
|
|
48721
|
+
form: "single",
|
|
48722
|
+
optional: false
|
|
48723
|
+
}],
|
|
48549
48724
|
"consumables.reset": [{
|
|
48550
48725
|
name: "deviceId",
|
|
48551
48726
|
form: "single",
|
|
48552
48727
|
optional: false
|
|
48553
48728
|
}],
|
|
48729
|
+
"contact.getStatus": [{
|
|
48730
|
+
name: "deviceId",
|
|
48731
|
+
form: "single",
|
|
48732
|
+
optional: false
|
|
48733
|
+
}],
|
|
48734
|
+
"control.getStatus": [{
|
|
48735
|
+
name: "deviceId",
|
|
48736
|
+
form: "single",
|
|
48737
|
+
optional: false
|
|
48738
|
+
}],
|
|
48554
48739
|
"control.setValue": [{
|
|
48555
48740
|
name: "deviceId",
|
|
48556
48741
|
form: "single",
|
|
@@ -48561,6 +48746,11 @@ Object.freeze({
|
|
|
48561
48746
|
form: "single",
|
|
48562
48747
|
optional: false
|
|
48563
48748
|
}],
|
|
48749
|
+
"cover.getStatus": [{
|
|
48750
|
+
name: "deviceId",
|
|
48751
|
+
form: "single",
|
|
48752
|
+
optional: false
|
|
48753
|
+
}],
|
|
48564
48754
|
"cover.open": [{
|
|
48565
48755
|
name: "deviceId",
|
|
48566
48756
|
form: "single",
|
|
@@ -48586,6 +48776,11 @@ Object.freeze({
|
|
|
48586
48776
|
form: "single",
|
|
48587
48777
|
optional: false
|
|
48588
48778
|
}],
|
|
48779
|
+
"dayNight.getStatus": [{
|
|
48780
|
+
name: "deviceId",
|
|
48781
|
+
form: "single",
|
|
48782
|
+
optional: false
|
|
48783
|
+
}],
|
|
48589
48784
|
"dayNight.setSettings": [{
|
|
48590
48785
|
name: "deviceId",
|
|
48591
48786
|
form: "single",
|
|
@@ -48596,11 +48791,31 @@ Object.freeze({
|
|
|
48596
48791
|
form: "single",
|
|
48597
48792
|
optional: true
|
|
48598
48793
|
}],
|
|
48794
|
+
"detectionPipeline.applyDeviceSettingsPatch": [{
|
|
48795
|
+
name: "deviceId",
|
|
48796
|
+
form: "single",
|
|
48797
|
+
optional: false
|
|
48798
|
+
}],
|
|
48799
|
+
"detectionPipeline.getDeviceLiveContribution": [{
|
|
48800
|
+
name: "deviceId",
|
|
48801
|
+
form: "single",
|
|
48802
|
+
optional: false
|
|
48803
|
+
}],
|
|
48804
|
+
"detectionPipeline.getDeviceSettingsContribution": [{
|
|
48805
|
+
name: "deviceId",
|
|
48806
|
+
form: "single",
|
|
48807
|
+
optional: false
|
|
48808
|
+
}],
|
|
48599
48809
|
"deviceAdminLink.getAdminLink": [{
|
|
48600
48810
|
name: "deviceId",
|
|
48601
48811
|
form: "single",
|
|
48602
48812
|
optional: false
|
|
48603
48813
|
}],
|
|
48814
|
+
"deviceAdoption.getStatus": [{
|
|
48815
|
+
name: "deviceId",
|
|
48816
|
+
form: "single",
|
|
48817
|
+
optional: false
|
|
48818
|
+
}],
|
|
48604
48819
|
"deviceAdoption.release": [{
|
|
48605
48820
|
name: "camDeviceId",
|
|
48606
48821
|
form: "single",
|
|
@@ -48616,6 +48831,11 @@ Object.freeze({
|
|
|
48616
48831
|
form: "single",
|
|
48617
48832
|
optional: false
|
|
48618
48833
|
}],
|
|
48834
|
+
"deviceDiscovery.getStatus": [{
|
|
48835
|
+
name: "deviceId",
|
|
48836
|
+
form: "single",
|
|
48837
|
+
optional: false
|
|
48838
|
+
}],
|
|
48619
48839
|
"deviceDiscovery.listDiscovered": [{
|
|
48620
48840
|
name: "deviceId",
|
|
48621
48841
|
form: "single",
|
|
@@ -48635,6 +48855,21 @@ Object.freeze({
|
|
|
48635
48855
|
form: "single",
|
|
48636
48856
|
optional: false
|
|
48637
48857
|
}],
|
|
48858
|
+
"deviceExport.applyDeviceSettingsPatch": [{
|
|
48859
|
+
name: "deviceId",
|
|
48860
|
+
form: "single",
|
|
48861
|
+
optional: false
|
|
48862
|
+
}],
|
|
48863
|
+
"deviceExport.getDeviceLiveContribution": [{
|
|
48864
|
+
name: "deviceId",
|
|
48865
|
+
form: "single",
|
|
48866
|
+
optional: false
|
|
48867
|
+
}],
|
|
48868
|
+
"deviceExport.getDeviceSettingsContribution": [{
|
|
48869
|
+
name: "deviceId",
|
|
48870
|
+
form: "single",
|
|
48871
|
+
optional: false
|
|
48872
|
+
}],
|
|
48638
48873
|
"deviceExtension.listCandidates": [{
|
|
48639
48874
|
name: "deviceId",
|
|
48640
48875
|
form: "single",
|
|
@@ -48983,6 +49218,26 @@ Object.freeze({
|
|
|
48983
49218
|
form: "single",
|
|
48984
49219
|
optional: false
|
|
48985
49220
|
}],
|
|
49221
|
+
"deviceStatus.getStatus": [{
|
|
49222
|
+
name: "deviceId",
|
|
49223
|
+
form: "single",
|
|
49224
|
+
optional: false
|
|
49225
|
+
}],
|
|
49226
|
+
"doorbell.getStatus": [{
|
|
49227
|
+
name: "deviceId",
|
|
49228
|
+
form: "single",
|
|
49229
|
+
optional: false
|
|
49230
|
+
}],
|
|
49231
|
+
"enumSensor.getStatus": [{
|
|
49232
|
+
name: "deviceId",
|
|
49233
|
+
form: "single",
|
|
49234
|
+
optional: false
|
|
49235
|
+
}],
|
|
49236
|
+
"eventEmitter.getStatus": [{
|
|
49237
|
+
name: "deviceId",
|
|
49238
|
+
form: "single",
|
|
49239
|
+
optional: false
|
|
49240
|
+
}],
|
|
48986
49241
|
"faceGallery.getFaceByTrack": [{
|
|
48987
49242
|
name: "deviceId",
|
|
48988
49243
|
form: "single",
|
|
@@ -48997,6 +49252,11 @@ Object.freeze({
|
|
|
48997
49252
|
form: "array",
|
|
48998
49253
|
optional: true
|
|
48999
49254
|
}],
|
|
49255
|
+
"fanControl.getStatus": [{
|
|
49256
|
+
name: "deviceId",
|
|
49257
|
+
form: "single",
|
|
49258
|
+
optional: false
|
|
49259
|
+
}],
|
|
49000
49260
|
"fanControl.setDirection": [{
|
|
49001
49261
|
name: "deviceId",
|
|
49002
49262
|
form: "single",
|
|
@@ -49017,6 +49277,26 @@ Object.freeze({
|
|
|
49017
49277
|
form: "single",
|
|
49018
49278
|
optional: false
|
|
49019
49279
|
}],
|
|
49280
|
+
"featureProbe.getStatus": [{
|
|
49281
|
+
name: "deviceId",
|
|
49282
|
+
form: "single",
|
|
49283
|
+
optional: false
|
|
49284
|
+
}],
|
|
49285
|
+
"flood.getStatus": [{
|
|
49286
|
+
name: "deviceId",
|
|
49287
|
+
form: "single",
|
|
49288
|
+
optional: false
|
|
49289
|
+
}],
|
|
49290
|
+
"gas.getStatus": [{
|
|
49291
|
+
name: "deviceId",
|
|
49292
|
+
form: "single",
|
|
49293
|
+
optional: false
|
|
49294
|
+
}],
|
|
49295
|
+
"humidifier.getStatus": [{
|
|
49296
|
+
name: "deviceId",
|
|
49297
|
+
form: "single",
|
|
49298
|
+
optional: false
|
|
49299
|
+
}],
|
|
49020
49300
|
"humidifier.setMode": [{
|
|
49021
49301
|
name: "deviceId",
|
|
49022
49302
|
form: "single",
|
|
@@ -49032,11 +49312,26 @@ Object.freeze({
|
|
|
49032
49312
|
form: "single",
|
|
49033
49313
|
optional: false
|
|
49034
49314
|
}],
|
|
49315
|
+
"humiditySensor.getStatus": [{
|
|
49316
|
+
name: "deviceId",
|
|
49317
|
+
form: "single",
|
|
49318
|
+
optional: false
|
|
49319
|
+
}],
|
|
49320
|
+
"image.getStatus": [{
|
|
49321
|
+
name: "deviceId",
|
|
49322
|
+
form: "single",
|
|
49323
|
+
optional: false
|
|
49324
|
+
}],
|
|
49035
49325
|
"imageSettings.getOptions": [{
|
|
49036
49326
|
name: "deviceId",
|
|
49037
49327
|
form: "single",
|
|
49038
49328
|
optional: false
|
|
49039
49329
|
}],
|
|
49330
|
+
"imageSettings.getStatus": [{
|
|
49331
|
+
name: "deviceId",
|
|
49332
|
+
form: "single",
|
|
49333
|
+
optional: false
|
|
49334
|
+
}],
|
|
49040
49335
|
"imageSettings.setSettings": [{
|
|
49041
49336
|
name: "deviceId",
|
|
49042
49337
|
form: "single",
|
|
@@ -49047,6 +49342,11 @@ Object.freeze({
|
|
|
49047
49342
|
form: "single",
|
|
49048
49343
|
optional: false
|
|
49049
49344
|
}],
|
|
49345
|
+
"intercom.getStatus": [{
|
|
49346
|
+
name: "deviceId",
|
|
49347
|
+
form: "single",
|
|
49348
|
+
optional: false
|
|
49349
|
+
}],
|
|
49050
49350
|
"intercom.handleAnswer": [{
|
|
49051
49351
|
name: "deviceId",
|
|
49052
49352
|
form: "single",
|
|
@@ -49077,6 +49377,11 @@ Object.freeze({
|
|
|
49077
49377
|
form: "single",
|
|
49078
49378
|
optional: false
|
|
49079
49379
|
}],
|
|
49380
|
+
"lawnMowerControl.getStatus": [{
|
|
49381
|
+
name: "deviceId",
|
|
49382
|
+
form: "single",
|
|
49383
|
+
optional: false
|
|
49384
|
+
}],
|
|
49080
49385
|
"lawnMowerControl.pause": [{
|
|
49081
49386
|
name: "deviceId",
|
|
49082
49387
|
form: "single",
|
|
@@ -49087,6 +49392,11 @@ Object.freeze({
|
|
|
49087
49392
|
form: "single",
|
|
49088
49393
|
optional: false
|
|
49089
49394
|
}],
|
|
49395
|
+
"lockControl.getStatus": [{
|
|
49396
|
+
name: "deviceId",
|
|
49397
|
+
form: "single",
|
|
49398
|
+
optional: false
|
|
49399
|
+
}],
|
|
49090
49400
|
"lockControl.lock": [{
|
|
49091
49401
|
name: "deviceId",
|
|
49092
49402
|
form: "single",
|
|
@@ -49102,6 +49412,11 @@ Object.freeze({
|
|
|
49102
49412
|
form: "single",
|
|
49103
49413
|
optional: false
|
|
49104
49414
|
}],
|
|
49415
|
+
"mediaPlayer.getStatus": [{
|
|
49416
|
+
name: "deviceId",
|
|
49417
|
+
form: "single",
|
|
49418
|
+
optional: false
|
|
49419
|
+
}],
|
|
49105
49420
|
"mediaPlayer.next": [{
|
|
49106
49421
|
name: "deviceId",
|
|
49107
49422
|
form: "single",
|
|
@@ -49162,6 +49477,11 @@ Object.freeze({
|
|
|
49162
49477
|
form: "single",
|
|
49163
49478
|
optional: false
|
|
49164
49479
|
}],
|
|
49480
|
+
"motion.getStatus": [{
|
|
49481
|
+
name: "deviceId",
|
|
49482
|
+
form: "single",
|
|
49483
|
+
optional: false
|
|
49484
|
+
}],
|
|
49165
49485
|
"motion.isDetected": [{
|
|
49166
49486
|
name: "deviceId",
|
|
49167
49487
|
form: "single",
|
|
@@ -49172,11 +49492,31 @@ Object.freeze({
|
|
|
49172
49492
|
form: "single",
|
|
49173
49493
|
optional: false
|
|
49174
49494
|
}],
|
|
49495
|
+
"motionDetection.applyDeviceSettingsPatch": [{
|
|
49496
|
+
name: "deviceId",
|
|
49497
|
+
form: "single",
|
|
49498
|
+
optional: false
|
|
49499
|
+
}],
|
|
49500
|
+
"motionDetection.getDeviceLiveContribution": [{
|
|
49501
|
+
name: "deviceId",
|
|
49502
|
+
form: "single",
|
|
49503
|
+
optional: false
|
|
49504
|
+
}],
|
|
49505
|
+
"motionDetection.getDeviceSettingsContribution": [{
|
|
49506
|
+
name: "deviceId",
|
|
49507
|
+
form: "single",
|
|
49508
|
+
optional: false
|
|
49509
|
+
}],
|
|
49175
49510
|
"motionDetection.removeCamera": [{
|
|
49176
49511
|
name: "deviceId",
|
|
49177
49512
|
form: "single",
|
|
49178
49513
|
optional: false
|
|
49179
49514
|
}],
|
|
49515
|
+
"motionTrigger.getStatus": [{
|
|
49516
|
+
name: "deviceId",
|
|
49517
|
+
form: "single",
|
|
49518
|
+
optional: false
|
|
49519
|
+
}],
|
|
49180
49520
|
"motionTrigger.setMotionTrigger": [{
|
|
49181
49521
|
name: "deviceId",
|
|
49182
49522
|
form: "single",
|
|
@@ -49187,6 +49527,11 @@ Object.freeze({
|
|
|
49187
49527
|
form: "single",
|
|
49188
49528
|
optional: false
|
|
49189
49529
|
}],
|
|
49530
|
+
"motionZones.getStatus": [{
|
|
49531
|
+
name: "deviceId",
|
|
49532
|
+
form: "single",
|
|
49533
|
+
optional: false
|
|
49534
|
+
}],
|
|
49190
49535
|
"motionZones.setZone": [{
|
|
49191
49536
|
name: "deviceId",
|
|
49192
49537
|
form: "single",
|
|
@@ -49197,6 +49542,11 @@ Object.freeze({
|
|
|
49197
49542
|
form: "single",
|
|
49198
49543
|
optional: false
|
|
49199
49544
|
}],
|
|
49545
|
+
"nativeObjectDetection.getStatus": [{
|
|
49546
|
+
name: "deviceId",
|
|
49547
|
+
form: "single",
|
|
49548
|
+
optional: false
|
|
49549
|
+
}],
|
|
49200
49550
|
"nativeObjectDetection.setEnabled": [{
|
|
49201
49551
|
name: "deviceId",
|
|
49202
49552
|
form: "single",
|
|
@@ -49212,6 +49562,11 @@ Object.freeze({
|
|
|
49212
49562
|
form: "single",
|
|
49213
49563
|
optional: false
|
|
49214
49564
|
}],
|
|
49565
|
+
"navigation.getStatus": [{
|
|
49566
|
+
name: "deviceId",
|
|
49567
|
+
form: "single",
|
|
49568
|
+
optional: false
|
|
49569
|
+
}],
|
|
49215
49570
|
"navigation.goToPoint": [{
|
|
49216
49571
|
name: "deviceId",
|
|
49217
49572
|
form: "single",
|
|
@@ -49257,6 +49612,11 @@ Object.freeze({
|
|
|
49257
49612
|
form: "single",
|
|
49258
49613
|
optional: false
|
|
49259
49614
|
}],
|
|
49615
|
+
"networkLink.getStatus": [{
|
|
49616
|
+
name: "deviceId",
|
|
49617
|
+
form: "single",
|
|
49618
|
+
optional: false
|
|
49619
|
+
}],
|
|
49260
49620
|
"networkQuality.getDeviceStats": [{
|
|
49261
49621
|
name: "deviceId",
|
|
49262
49622
|
form: "single",
|
|
@@ -49267,6 +49627,11 @@ Object.freeze({
|
|
|
49267
49627
|
form: "single",
|
|
49268
49628
|
optional: false
|
|
49269
49629
|
}],
|
|
49630
|
+
"notificationRules.getAlarmSensors": [{
|
|
49631
|
+
name: "deviceIds",
|
|
49632
|
+
form: "array",
|
|
49633
|
+
optional: false
|
|
49634
|
+
}],
|
|
49270
49635
|
"notificationRules.setDeviceMuted": [{
|
|
49271
49636
|
name: "deviceId",
|
|
49272
49637
|
form: "single",
|
|
@@ -49277,11 +49642,26 @@ Object.freeze({
|
|
|
49277
49642
|
form: "single",
|
|
49278
49643
|
optional: false
|
|
49279
49644
|
}],
|
|
49645
|
+
"notifier.getStatus": [{
|
|
49646
|
+
name: "deviceId",
|
|
49647
|
+
form: "single",
|
|
49648
|
+
optional: false
|
|
49649
|
+
}],
|
|
49280
49650
|
"notifier.send": [{
|
|
49281
49651
|
name: "deviceId",
|
|
49282
49652
|
form: "single",
|
|
49283
49653
|
optional: false
|
|
49284
49654
|
}],
|
|
49655
|
+
"numericSensor.getStatus": [{
|
|
49656
|
+
name: "deviceId",
|
|
49657
|
+
form: "single",
|
|
49658
|
+
optional: false
|
|
49659
|
+
}],
|
|
49660
|
+
"osd.getStatus": [{
|
|
49661
|
+
name: "deviceId",
|
|
49662
|
+
form: "single",
|
|
49663
|
+
optional: false
|
|
49664
|
+
}],
|
|
49285
49665
|
"osd.setOverlay": [{
|
|
49286
49666
|
name: "deviceId",
|
|
49287
49667
|
form: "single",
|
|
@@ -49341,6 +49721,11 @@ Object.freeze({
|
|
|
49341
49721
|
form: "single",
|
|
49342
49722
|
optional: false
|
|
49343
49723
|
}],
|
|
49724
|
+
"petFeeder.getStatus": [{
|
|
49725
|
+
name: "deviceId",
|
|
49726
|
+
form: "single",
|
|
49727
|
+
optional: false
|
|
49728
|
+
}],
|
|
49344
49729
|
"petFeeder.markFoodReplenished": [{
|
|
49345
49730
|
name: "deviceId",
|
|
49346
49731
|
form: "single",
|
|
@@ -49376,6 +49761,11 @@ Object.freeze({
|
|
|
49376
49761
|
form: "single",
|
|
49377
49762
|
optional: false
|
|
49378
49763
|
}],
|
|
49764
|
+
"pipelineAnalytics.applyDeviceSettingsPatch": [{
|
|
49765
|
+
name: "deviceId",
|
|
49766
|
+
form: "single",
|
|
49767
|
+
optional: false
|
|
49768
|
+
}],
|
|
49379
49769
|
"pipelineAnalytics.clearTrackRelation": [{
|
|
49380
49770
|
name: "deviceId",
|
|
49381
49771
|
form: "single",
|
|
@@ -49416,6 +49806,16 @@ Object.freeze({
|
|
|
49416
49806
|
form: "single",
|
|
49417
49807
|
optional: false
|
|
49418
49808
|
}],
|
|
49809
|
+
"pipelineAnalytics.getDeviceLiveContribution": [{
|
|
49810
|
+
name: "deviceId",
|
|
49811
|
+
form: "single",
|
|
49812
|
+
optional: false
|
|
49813
|
+
}],
|
|
49814
|
+
"pipelineAnalytics.getDeviceSettingsContribution": [{
|
|
49815
|
+
name: "deviceId",
|
|
49816
|
+
form: "single",
|
|
49817
|
+
optional: false
|
|
49818
|
+
}],
|
|
49419
49819
|
"pipelineAnalytics.getEventDensity": [{
|
|
49420
49820
|
name: "deviceId",
|
|
49421
49821
|
form: "single",
|
|
@@ -49631,6 +50031,11 @@ Object.freeze({
|
|
|
49631
50031
|
form: "single",
|
|
49632
50032
|
optional: true
|
|
49633
50033
|
}],
|
|
50034
|
+
"pipelineOrchestrator.applyDeviceSettingsPatch": [{
|
|
50035
|
+
name: "deviceId",
|
|
50036
|
+
form: "single",
|
|
50037
|
+
optional: false
|
|
50038
|
+
}],
|
|
49634
50039
|
"pipelineOrchestrator.assignAudio": [{
|
|
49635
50040
|
name: "deviceId",
|
|
49636
50041
|
form: "single",
|
|
@@ -49676,6 +50081,16 @@ Object.freeze({
|
|
|
49676
50081
|
form: "single",
|
|
49677
50082
|
optional: false
|
|
49678
50083
|
}],
|
|
50084
|
+
"pipelineOrchestrator.getDeviceLiveContribution": [{
|
|
50085
|
+
name: "deviceId",
|
|
50086
|
+
form: "single",
|
|
50087
|
+
optional: false
|
|
50088
|
+
}],
|
|
50089
|
+
"pipelineOrchestrator.getDeviceSettingsContribution": [{
|
|
50090
|
+
name: "deviceId",
|
|
50091
|
+
form: "single",
|
|
50092
|
+
optional: false
|
|
50093
|
+
}],
|
|
49679
50094
|
"pipelineOrchestrator.getPipelineAssignment": [{
|
|
49680
50095
|
name: "deviceId",
|
|
49681
50096
|
form: "single",
|
|
@@ -49796,11 +50211,31 @@ Object.freeze({
|
|
|
49796
50211
|
form: "single",
|
|
49797
50212
|
optional: true
|
|
49798
50213
|
}],
|
|
50214
|
+
"powerMeter.getStatus": [{
|
|
50215
|
+
name: "deviceId",
|
|
50216
|
+
form: "single",
|
|
50217
|
+
optional: false
|
|
50218
|
+
}],
|
|
50219
|
+
"presence.getStatus": [{
|
|
50220
|
+
name: "deviceId",
|
|
50221
|
+
form: "single",
|
|
50222
|
+
optional: false
|
|
50223
|
+
}],
|
|
50224
|
+
"pressureSensor.getStatus": [{
|
|
50225
|
+
name: "deviceId",
|
|
50226
|
+
form: "single",
|
|
50227
|
+
optional: false
|
|
50228
|
+
}],
|
|
49799
50229
|
"privacyMask.getOptions": [{
|
|
49800
50230
|
name: "deviceId",
|
|
49801
50231
|
form: "single",
|
|
49802
50232
|
optional: false
|
|
49803
50233
|
}],
|
|
50234
|
+
"privacyMask.getStatus": [{
|
|
50235
|
+
name: "deviceId",
|
|
50236
|
+
form: "single",
|
|
50237
|
+
optional: false
|
|
50238
|
+
}],
|
|
49804
50239
|
"privacyMask.setAudioEnabled": [{
|
|
49805
50240
|
name: "deviceId",
|
|
49806
50241
|
form: "single",
|
|
@@ -49851,6 +50286,11 @@ Object.freeze({
|
|
|
49851
50286
|
form: "single",
|
|
49852
50287
|
optional: false
|
|
49853
50288
|
}],
|
|
50289
|
+
"ptz.getStatus": [{
|
|
50290
|
+
name: "deviceId",
|
|
50291
|
+
form: "single",
|
|
50292
|
+
optional: false
|
|
50293
|
+
}],
|
|
49854
50294
|
"ptz.goHome": [{
|
|
49855
50295
|
name: "deviceId",
|
|
49856
50296
|
form: "single",
|
|
@@ -49941,6 +50381,11 @@ Object.freeze({
|
|
|
49941
50381
|
form: "single",
|
|
49942
50382
|
optional: false
|
|
49943
50383
|
}],
|
|
50384
|
+
"recordingArchive.applyDeviceSettingsPatch": [{
|
|
50385
|
+
name: "deviceId",
|
|
50386
|
+
form: "single",
|
|
50387
|
+
optional: false
|
|
50388
|
+
}],
|
|
49944
50389
|
"recordingArchive.deleteFootprint": [{
|
|
49945
50390
|
name: "deviceId",
|
|
49946
50391
|
form: "single",
|
|
@@ -49961,6 +50406,21 @@ Object.freeze({
|
|
|
49961
50406
|
form: "single",
|
|
49962
50407
|
optional: false
|
|
49963
50408
|
}],
|
|
50409
|
+
"recordingArchive.getDeviceLiveContribution": [{
|
|
50410
|
+
name: "deviceId",
|
|
50411
|
+
form: "single",
|
|
50412
|
+
optional: false
|
|
50413
|
+
}],
|
|
50414
|
+
"recordingArchive.getDeviceSettingsContribution": [{
|
|
50415
|
+
name: "deviceId",
|
|
50416
|
+
form: "single",
|
|
50417
|
+
optional: false
|
|
50418
|
+
}],
|
|
50419
|
+
"recordingArchive.getStatus": [{
|
|
50420
|
+
name: "deviceId",
|
|
50421
|
+
form: "single",
|
|
50422
|
+
optional: false
|
|
50423
|
+
}],
|
|
49964
50424
|
"recordingArchive.listOpsLog": [{
|
|
49965
50425
|
name: "deviceId",
|
|
49966
50426
|
form: "single",
|
|
@@ -50046,6 +50506,11 @@ Object.freeze({
|
|
|
50046
50506
|
form: "single",
|
|
50047
50507
|
optional: false
|
|
50048
50508
|
}],
|
|
50509
|
+
"recordingOnboard.getStatus": [{
|
|
50510
|
+
name: "deviceId",
|
|
50511
|
+
form: "single",
|
|
50512
|
+
optional: false
|
|
50513
|
+
}],
|
|
50049
50514
|
"recordingOnboard.setSettings": [{
|
|
50050
50515
|
name: "deviceId",
|
|
50051
50516
|
form: "single",
|
|
@@ -50076,6 +50541,11 @@ Object.freeze({
|
|
|
50076
50541
|
form: "single",
|
|
50077
50542
|
optional: false
|
|
50078
50543
|
}],
|
|
50544
|
+
"sceneMonitor.getStatus": [{
|
|
50545
|
+
name: "deviceId",
|
|
50546
|
+
form: "single",
|
|
50547
|
+
optional: false
|
|
50548
|
+
}],
|
|
50079
50549
|
"sceneMonitor.listScenes": [{
|
|
50080
50550
|
name: "deviceId",
|
|
50081
50551
|
form: "single",
|
|
@@ -50101,6 +50571,11 @@ Object.freeze({
|
|
|
50101
50571
|
form: "single",
|
|
50102
50572
|
optional: false
|
|
50103
50573
|
}],
|
|
50574
|
+
"scriptRunner.getStatus": [{
|
|
50575
|
+
name: "deviceId",
|
|
50576
|
+
form: "single",
|
|
50577
|
+
optional: false
|
|
50578
|
+
}],
|
|
50104
50579
|
"scriptRunner.run": [{
|
|
50105
50580
|
name: "deviceId",
|
|
50106
50581
|
form: "single",
|
|
@@ -50111,11 +50586,31 @@ Object.freeze({
|
|
|
50111
50586
|
form: "single",
|
|
50112
50587
|
optional: false
|
|
50113
50588
|
}],
|
|
50589
|
+
"smoke.getStatus": [{
|
|
50590
|
+
name: "deviceId",
|
|
50591
|
+
form: "single",
|
|
50592
|
+
optional: false
|
|
50593
|
+
}],
|
|
50594
|
+
"snapshot.applyDeviceSettingsPatch": [{
|
|
50595
|
+
name: "deviceId",
|
|
50596
|
+
form: "single",
|
|
50597
|
+
optional: false
|
|
50598
|
+
}],
|
|
50114
50599
|
"snapshot.getDebugState": [{
|
|
50115
50600
|
name: "deviceId",
|
|
50116
50601
|
form: "single",
|
|
50117
50602
|
optional: false
|
|
50118
50603
|
}],
|
|
50604
|
+
"snapshot.getDeviceLiveContribution": [{
|
|
50605
|
+
name: "deviceId",
|
|
50606
|
+
form: "single",
|
|
50607
|
+
optional: false
|
|
50608
|
+
}],
|
|
50609
|
+
"snapshot.getDeviceSettingsContribution": [{
|
|
50610
|
+
name: "deviceId",
|
|
50611
|
+
form: "single",
|
|
50612
|
+
optional: false
|
|
50613
|
+
}],
|
|
50119
50614
|
"snapshot.getSnapshot": [{
|
|
50120
50615
|
name: "deviceId",
|
|
50121
50616
|
form: "single",
|
|
@@ -50132,6 +50627,11 @@ Object.freeze({
|
|
|
50132
50627
|
form: "array",
|
|
50133
50628
|
optional: false
|
|
50134
50629
|
}],
|
|
50630
|
+
"snapshot.getStatus": [{
|
|
50631
|
+
name: "deviceId",
|
|
50632
|
+
form: "single",
|
|
50633
|
+
optional: false
|
|
50634
|
+
}],
|
|
50135
50635
|
"snapshot.invalidateCache": [{
|
|
50136
50636
|
name: "deviceId",
|
|
50137
50637
|
form: "single",
|
|
@@ -50142,6 +50642,11 @@ Object.freeze({
|
|
|
50142
50642
|
form: "single",
|
|
50143
50643
|
optional: false
|
|
50144
50644
|
}],
|
|
50645
|
+
"streamBroker.applyDeviceSettingsPatch": [{
|
|
50646
|
+
name: "deviceId",
|
|
50647
|
+
form: "single",
|
|
50648
|
+
optional: false
|
|
50649
|
+
}],
|
|
50145
50650
|
"streamBroker.assignProfile": [{
|
|
50146
50651
|
name: "deviceId",
|
|
50147
50652
|
form: "single",
|
|
@@ -50157,6 +50662,16 @@ Object.freeze({
|
|
|
50157
50662
|
form: "single",
|
|
50158
50663
|
optional: false
|
|
50159
50664
|
}],
|
|
50665
|
+
"streamBroker.getDeviceLiveContribution": [{
|
|
50666
|
+
name: "deviceId",
|
|
50667
|
+
form: "single",
|
|
50668
|
+
optional: false
|
|
50669
|
+
}],
|
|
50670
|
+
"streamBroker.getDeviceSettingsContribution": [{
|
|
50671
|
+
name: "deviceId",
|
|
50672
|
+
form: "single",
|
|
50673
|
+
optional: false
|
|
50674
|
+
}],
|
|
50160
50675
|
"streamBroker.getStreamWithCodec": [{
|
|
50161
50676
|
name: "deviceId",
|
|
50162
50677
|
form: "single",
|
|
@@ -50217,16 +50732,46 @@ Object.freeze({
|
|
|
50217
50732
|
form: "single",
|
|
50218
50733
|
optional: false
|
|
50219
50734
|
}],
|
|
50735
|
+
"streamParams.getStatus": [{
|
|
50736
|
+
name: "deviceId",
|
|
50737
|
+
form: "single",
|
|
50738
|
+
optional: false
|
|
50739
|
+
}],
|
|
50220
50740
|
"streamParams.setProfile": [{
|
|
50221
50741
|
name: "deviceId",
|
|
50222
50742
|
form: "single",
|
|
50223
50743
|
optional: false
|
|
50224
50744
|
}],
|
|
50745
|
+
"switch.getStatus": [{
|
|
50746
|
+
name: "deviceId",
|
|
50747
|
+
form: "single",
|
|
50748
|
+
optional: false
|
|
50749
|
+
}],
|
|
50225
50750
|
"switch.setState": [{
|
|
50226
50751
|
name: "deviceId",
|
|
50227
50752
|
form: "single",
|
|
50228
50753
|
optional: false
|
|
50229
50754
|
}],
|
|
50755
|
+
"tamper.getStatus": [{
|
|
50756
|
+
name: "deviceId",
|
|
50757
|
+
form: "single",
|
|
50758
|
+
optional: false
|
|
50759
|
+
}],
|
|
50760
|
+
"temperatureSensor.getStatus": [{
|
|
50761
|
+
name: "deviceId",
|
|
50762
|
+
form: "single",
|
|
50763
|
+
optional: false
|
|
50764
|
+
}],
|
|
50765
|
+
"update.getStatus": [{
|
|
50766
|
+
name: "deviceId",
|
|
50767
|
+
form: "single",
|
|
50768
|
+
optional: false
|
|
50769
|
+
}],
|
|
50770
|
+
"vacuumControl.getStatus": [{
|
|
50771
|
+
name: "deviceId",
|
|
50772
|
+
form: "single",
|
|
50773
|
+
optional: false
|
|
50774
|
+
}],
|
|
50230
50775
|
"vacuumControl.locate": [{
|
|
50231
50776
|
name: "deviceId",
|
|
50232
50777
|
form: "single",
|
|
@@ -50262,6 +50807,11 @@ Object.freeze({
|
|
|
50262
50807
|
form: "single",
|
|
50263
50808
|
optional: false
|
|
50264
50809
|
}],
|
|
50810
|
+
"valve.getStatus": [{
|
|
50811
|
+
name: "deviceId",
|
|
50812
|
+
form: "single",
|
|
50813
|
+
optional: false
|
|
50814
|
+
}],
|
|
50265
50815
|
"valve.open": [{
|
|
50266
50816
|
name: "deviceId",
|
|
50267
50817
|
form: "single",
|
|
@@ -50277,6 +50827,11 @@ Object.freeze({
|
|
|
50277
50827
|
form: "single",
|
|
50278
50828
|
optional: false
|
|
50279
50829
|
}],
|
|
50830
|
+
"vibration.getStatus": [{
|
|
50831
|
+
name: "deviceId",
|
|
50832
|
+
form: "single",
|
|
50833
|
+
optional: false
|
|
50834
|
+
}],
|
|
50280
50835
|
"videoclips.dialClipStream": [{
|
|
50281
50836
|
name: "deviceId",
|
|
50282
50837
|
form: "single",
|
|
@@ -50312,6 +50867,11 @@ Object.freeze({
|
|
|
50312
50867
|
form: "single",
|
|
50313
50868
|
optional: false
|
|
50314
50869
|
}],
|
|
50870
|
+
"waterHeater.getStatus": [{
|
|
50871
|
+
name: "deviceId",
|
|
50872
|
+
form: "single",
|
|
50873
|
+
optional: false
|
|
50874
|
+
}],
|
|
50315
50875
|
"waterHeater.setAway": [{
|
|
50316
50876
|
name: "deviceId",
|
|
50317
50877
|
form: "single",
|
|
@@ -50327,6 +50887,11 @@ Object.freeze({
|
|
|
50327
50887
|
form: "single",
|
|
50328
50888
|
optional: false
|
|
50329
50889
|
}],
|
|
50890
|
+
"weather.getStatus": [{
|
|
50891
|
+
name: "deviceId",
|
|
50892
|
+
form: "single",
|
|
50893
|
+
optional: false
|
|
50894
|
+
}],
|
|
50330
50895
|
"webrtcSession.addIceCandidate": [{
|
|
50331
50896
|
name: "deviceId",
|
|
50332
50897
|
form: "single",
|
|
@@ -51064,7 +51629,7 @@ var PreviewTextField = string().max(200);
|
|
|
51064
51629
|
* Whether the notification's preview is a STILL or a short animation.
|
|
51065
51630
|
*
|
|
51066
51631
|
* The operator's ask, verbatim: *"inviato come gif o video (come per le altre
|
|
51067
|
-
* rule)"* — the other rules already offer an animated preview, and a ten-hour
|
|
51632
|
+
* rule)"* [sent as a gif or video (as for the other rules)] — the other rules already offer an animated preview, and a ten-hour
|
|
51068
51633
|
* night reads better as three seconds of motion than as one frame of it. Both
|
|
51069
51634
|
* modes get the SAME treatment (blurred frame, large centred title); `'gif'`
|
|
51070
51635
|
* simply applies it to a dozen frames sampled across the render and assembles
|
|
@@ -51202,6 +51767,7 @@ TimelapseRuleInputSchema.extend({
|
|
|
51202
51767
|
createdAt: number(),
|
|
51203
51768
|
updatedAt: number()
|
|
51204
51769
|
});
|
|
51770
|
+
MotionOnMotionChangedDataSchema.omit({ triggeredBy: true });
|
|
51205
51771
|
object({
|
|
51206
51772
|
/**
|
|
51207
51773
|
* Fraction of the box's own size added on EACH side before cutting.
|