@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.mjs
CHANGED
|
@@ -8,7 +8,7 @@ import { createServer } from "node:http";
|
|
|
8
8
|
//#region \0rolldown/runtime.js
|
|
9
9
|
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
|
|
10
10
|
//#endregion
|
|
11
|
-
//#region ../types/dist/event-category-
|
|
11
|
+
//#region ../types/dist/event-category-BGmz_oxW.mjs
|
|
12
12
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
13
13
|
EventCategory["SystemBoot"] = "system.boot";
|
|
14
14
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -541,6 +541,15 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
541
541
|
*/
|
|
542
542
|
EventCategory["PipelineAudioInferenceResult"] = "pipeline.audio-inference-result";
|
|
543
543
|
EventCategory["DetectionPhaseTransition"] = "detection.phase-transition";
|
|
544
|
+
/**
|
|
545
|
+
* A camera provider's RAW onboard motion push (D673): the `MotionOnMotionChanged`
|
|
546
|
+
* data shape without `triggeredBy`, built by `providerMotionEvent`. Its one
|
|
547
|
+
* consumer is the orchestrator's camera-sensors bridge, which re-emits the
|
|
548
|
+
* camera's EFFECTIVE onboard motion as `MotionOnMotionChanged` (a pass-through
|
|
549
|
+
* for a camera with no attached sensor). Providers must not emit
|
|
550
|
+
* `MotionOnMotionChanged` themselves; `scripts/check-onboard-motion-emitters.ts`
|
|
551
|
+
* keeps it so (camera-grid is a named, deferred exception).
|
|
552
|
+
*/
|
|
544
553
|
EventCategory["ProviderMotion"] = "provider.motion";
|
|
545
554
|
EventCategory["ProviderDetection"] = "provider.detection";
|
|
546
555
|
EventCategory["EnrichmentEmbeddingStored"] = "enrichment.embedding.stored";
|
|
@@ -5379,7 +5388,7 @@ var ZodIssueCode = {
|
|
|
5379
5388
|
var ZodFirstPartyTypeKind;
|
|
5380
5389
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5381
5390
|
//#endregion
|
|
5382
|
-
//#region ../types/dist/sleep-
|
|
5391
|
+
//#region ../types/dist/sleep-CDCONfkt.mjs
|
|
5383
5392
|
/**
|
|
5384
5393
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5385
5394
|
* window to float samples (D455).
|
|
@@ -7481,7 +7490,7 @@ function errMsg(err) {
|
|
|
7481
7490
|
return String(err);
|
|
7482
7491
|
}
|
|
7483
7492
|
//#endregion
|
|
7484
|
-
//#region ../types/dist/composition-
|
|
7493
|
+
//#region ../types/dist/composition-Bzr7GwgP.mjs
|
|
7485
7494
|
/**
|
|
7486
7495
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
7487
7496
|
*
|
|
@@ -7535,21 +7544,20 @@ function portable(target) {
|
|
|
7535
7544
|
}
|
|
7536
7545
|
portable("linux64"), portable("linuxarm64"), portable("macarm64"), portable("mac64");
|
|
7537
7546
|
/**
|
|
7538
|
-
*
|
|
7539
|
-
*
|
|
7547
|
+
* THE table "which boolean of this device type counts as HIGH", and the
|
|
7548
|
+
* pure evaluator of its EDGE.
|
|
7540
7549
|
*
|
|
7541
|
-
*
|
|
7542
|
-
*
|
|
7543
|
-
*
|
|
7544
|
-
*
|
|
7545
|
-
*
|
|
7546
|
-
*
|
|
7547
|
-
* SPOSTA qui e il doorbell la ri-esporta.
|
|
7550
|
+
* ONE table for everyone who asks "is this device HIGH?": the
|
|
7551
|
+
* recorder's `RecordingTriggers.sensorDeviceIds` trigger, the post-analysis
|
|
7552
|
+
* sensor markers, the orchestrator's camera-sensors bridge and
|
|
7553
|
+
* the sources of a composite doorbell (`doorbellFeatureSources`, D671).
|
|
7554
|
+
* A second copy would diverge at the first cap added, and the symptom — "the
|
|
7555
|
+
* sensor rings the doorbell but does not record" — is exactly D62.
|
|
7548
7556
|
*
|
|
7549
|
-
* ⚠
|
|
7550
|
-
*
|
|
7551
|
-
*
|
|
7552
|
-
*
|
|
7557
|
+
* ⚠ NOT `DEVICE_STATE_READERS` (`catalogs/device-state-vocabulary.ts`), and the
|
|
7558
|
+
* two must not be unified: that one answers "what is the state WORD for a
|
|
7559
|
+
* rule" (and includes `presence`, `cover`, `alarm-panel`), this one "which
|
|
7560
|
+
* boolean's EDGE counts". Deliberately different vocabularies.
|
|
7553
7561
|
*/
|
|
7554
7562
|
/**
|
|
7555
7563
|
* Known binary / switch source caps → the boolean slice field whose
|
|
@@ -9190,22 +9198,22 @@ var CLASS_MAP_MACRO_TARGETS = [
|
|
|
9190
9198
|
"package"
|
|
9191
9199
|
];
|
|
9192
9200
|
/**
|
|
9193
|
-
*
|
|
9194
|
-
*
|
|
9201
|
+
* The FIRST-LEVEL macro classes: those an object detector emits and that
|
|
9202
|
+
* an operator can select.
|
|
9195
9203
|
*
|
|
9196
|
-
*
|
|
9204
|
+
* They are the three offered by the `object-detection` step
|
|
9197
9205
|
* (`addon-pipeline/src/detection-pipeline/registry/step-definitions.ts`,
|
|
9198
|
-
* `enabledMacroClasses`). `package`
|
|
9199
|
-
* `MACRO_LABELS` —
|
|
9200
|
-
* `package-detection`,
|
|
9201
|
-
*
|
|
9206
|
+
* `enabledMacroClasses`). `package` is in {@link CLASS_MAP_MACRO_TARGETS} and in
|
|
9207
|
+
* `MACRO_LABELS` — it is a true macro — but NOT here: it belongs to the step
|
|
9208
|
+
* `package-detection`, whose enablement is driven by zones, and offering the
|
|
9209
|
+
* same word twice has already made an operator turn on the COCO proxy
|
|
9202
9210
|
* (suitcase/backpack/handbag) lasciando spento il detector dedicato.
|
|
9203
9211
|
*
|
|
9204
|
-
*
|
|
9205
|
-
*
|
|
9206
|
-
* (`types/detection.ts`);
|
|
9207
|
-
* (`RecordingTriggers.objectClasses`)
|
|
9208
|
-
*
|
|
9212
|
+
* ONE list. Before today the same three were hand-written in the step's offer
|
|
9213
|
+
* and a second time as the union `FirstLevelMacro`
|
|
9214
|
+
* (`types/detection.ts`); a third copy for the recording trigger
|
|
9215
|
+
* (`RecordingTriggers.objectClasses`) would have made the later divergence
|
|
9216
|
+
* invisible.
|
|
9209
9217
|
*/
|
|
9210
9218
|
var FIRST_LEVEL_MACRO_CLASSES = [
|
|
9211
9219
|
"person",
|
|
@@ -9270,17 +9278,17 @@ var RecordingStorageModeSchema = _enum([
|
|
|
9270
9278
|
"on-device-decision"
|
|
9271
9279
|
]);
|
|
9272
9280
|
/**
|
|
9273
|
-
*
|
|
9274
|
-
*
|
|
9281
|
+
* The macro classes that can open a recording window — the same
|
|
9282
|
+
* three offered by the `object-detection` step, from ONE list
|
|
9275
9283
|
* ({@link FIRST_LEVEL_MACRO_CLASSES}).
|
|
9276
9284
|
*/
|
|
9277
9285
|
var RecordingObjectTriggerClassSchema = _enum(FIRST_LEVEL_MACRO_CLASSES);
|
|
9278
9286
|
/**
|
|
9279
|
-
* True
|
|
9287
|
+
* True when `values` does not repeat an element.
|
|
9280
9288
|
*
|
|
9281
|
-
*
|
|
9282
|
-
*
|
|
9283
|
-
*
|
|
9289
|
+
* A duplicate is not harmless: every entry of `objectClasses` / `sensorDeviceIds`
|
|
9290
|
+
* becomes a SOURCE in `bandTriggerSources`, and the same source twice
|
|
9291
|
+
* would count its windows twice in `segmentMissedByMs`.
|
|
9284
9292
|
*/
|
|
9285
9293
|
var noDuplicates = (values) => new Set(values).size === values.length;
|
|
9286
9294
|
/** Which detectors trigger an `events`-mode band. */
|
|
@@ -9288,34 +9296,34 @@ var RecordingTriggersSchema = object({
|
|
|
9288
9296
|
motion: boolean().optional(),
|
|
9289
9297
|
audioThresholdDbfs: number().optional(),
|
|
9290
9298
|
/**
|
|
9291
|
-
*
|
|
9292
|
-
*
|
|
9293
|
-
*
|
|
9294
|
-
*
|
|
9299
|
+
* The macro classes whose detection opens a window. ABSENT = the source
|
|
9300
|
+
* is not listened to; an EMPTY array is rejected, because "events band, object
|
|
9301
|
+
* trigger on, no class" is the same shape "enabled and records
|
|
9302
|
+
* nothing, forever" that `eventsBandCanEverDemand` is written against.
|
|
9295
9303
|
*
|
|
9296
|
-
*
|
|
9297
|
-
*
|
|
9298
|
-
* `minConfidence<Macro>`
|
|
9299
|
-
* (`source: 'onboard'`)
|
|
9300
|
-
*
|
|
9304
|
+
* The signal read is ALREADY FILTERED: only `source: 'pipeline'` detections, i.e.
|
|
9305
|
+
* those that went through `enabledMacroClasses`, the
|
|
9306
|
+
* `minConfidence<Macro>` and the full-frame guard. The camera's onboard AI
|
|
9307
|
+
* (`source: 'onboard'`) goes through none of those gates and does NOT open
|
|
9308
|
+
* windows — see `recorder/object-trigger.ts`.
|
|
9301
9309
|
*/
|
|
9302
9310
|
objectClasses: array(RecordingObjectTriggerClassSchema).min(1).refine(noDuplicates, { message: "objectClasses must not repeat a class" }).optional(),
|
|
9303
9311
|
/**
|
|
9304
|
-
*
|
|
9305
|
-
*
|
|
9312
|
+
* The LINKED devices whose RISING EDGE opens a window. Absent = the source
|
|
9313
|
+
* is not listened to; an empty array is rejected for the same reason as
|
|
9306
9314
|
* `objectClasses`.
|
|
9307
9315
|
*
|
|
9308
|
-
*
|
|
9309
|
-
*
|
|
9310
|
-
*
|
|
9311
|
-
*
|
|
9312
|
-
* device (D12) —
|
|
9316
|
+
* These are SOURCE device ids, not cameras: the band names them, so the
|
|
9317
|
+
* hot path (`DeviceStateChanged`, at bus rate across the whole fleet)
|
|
9318
|
+
* does no RPC. The OFFER from which the operator picks them is another question, and
|
|
9319
|
+
* is resolved with `deviceManager.getLinkedDevices` + `getBindingsBatch` per
|
|
9320
|
+
* device (D12) — never a global list of caps.
|
|
9313
9321
|
*
|
|
9314
|
-
*
|
|
9315
|
-
* `SOURCE_CAP_ACTIVE_FIELD` (`catalogs/sensor-active-state.ts`)
|
|
9316
|
-
*
|
|
9317
|
-
*
|
|
9318
|
-
*
|
|
9322
|
+
* What "high" means depends on the device TYPE and is not decided here:
|
|
9323
|
+
* `SOURCE_CAP_ACTIVE_FIELD` (`catalogs/sensor-active-state.ts`) is THE table,
|
|
9324
|
+
* the same one as the composite doorbell (D671). And it is the EDGE, not
|
|
9325
|
+
* the level: a contact found already open at runner restart does not
|
|
9326
|
+
* record.
|
|
9319
9327
|
*/
|
|
9320
9328
|
sensorDeviceIds: array(number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional()
|
|
9321
9329
|
});
|
|
@@ -10392,7 +10400,7 @@ var DecoderSessionConfigSchema = object({
|
|
|
10392
10400
|
* - **VALUE** — at which level, for which scope, until when. That stays ONE
|
|
10393
10401
|
* thing: the logging settings document on the `system` cap. Two authorities
|
|
10394
10402
|
* over the values is the exact defect
|
|
10395
|
-
* `docs/design/plans/2026-08-26-
|
|
10403
|
+
* `docs/design/plans/2026-08-26-per-component-logging.md` was written to
|
|
10396
10404
|
* remove; re-introducing it from the cure side would be grotesque.
|
|
10397
10405
|
*
|
|
10398
10406
|
* Nothing in this file reads a clock, an env var or a store. The registry is
|
|
@@ -12103,7 +12111,7 @@ var BrokerStatusEnum = _enum([
|
|
|
12103
12111
|
"unreachable",
|
|
12104
12112
|
"error"
|
|
12105
12113
|
]);
|
|
12106
|
-
var BrokerInfoSchema
|
|
12114
|
+
var BrokerInfoSchema = object({
|
|
12107
12115
|
/** Stable broker id. Persisted; survives addon restarts. */
|
|
12108
12116
|
id: string(),
|
|
12109
12117
|
/** Addon id of the provider that OWNS this broker.
|
|
@@ -12236,7 +12244,7 @@ var GetStateInputSchema = object({
|
|
|
12236
12244
|
* HA: entity_id (returns the cached entity state). */
|
|
12237
12245
|
key: string()
|
|
12238
12246
|
});
|
|
12239
|
-
method(ListInputSchema, array(BrokerInfoSchema
|
|
12247
|
+
method(ListInputSchema, array(BrokerInfoSchema)), method(GetInputSchema, BrokerInfoSchema.nullable()), method(_void(), array(BrokerProviderInfoSchema), { auth: "admin" }), method(AddInputSchema, AddResultSchema, {
|
|
12240
12248
|
kind: "mutation",
|
|
12241
12249
|
auth: "admin"
|
|
12242
12250
|
}), method(RemoveInputSchema, _void(), {
|
|
@@ -13947,7 +13955,7 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
|
|
|
13947
13955
|
*
|
|
13948
13956
|
* ⚠ An earlier version of this comment blamed Zod stripping, and that
|
|
13949
13957
|
* was wrong — corrected 2026-08-26 after the hop map
|
|
13950
|
-
* (`docs/design/2026-08-26-
|
|
13958
|
+
* (`docs/design/2026-08-26-topic-hop-map.md`) traced the path.
|
|
13951
13959
|
* There is **no Zod parse at all** between the door and the engine: the
|
|
13952
13960
|
* dispatcher forwards the payload verbatim and UDS carries it whole. A
|
|
13953
13961
|
* field declared here reaches `SqliteSettingsBackend` either way.
|
|
@@ -14810,7 +14818,17 @@ var SiteZoneSchema = object({
|
|
|
14810
14818
|
var ProviderStatusSchema = object({
|
|
14811
14819
|
connected: boolean(),
|
|
14812
14820
|
deviceCount: number(),
|
|
14813
|
-
error: string().optional()
|
|
14821
|
+
error: string().optional(),
|
|
14822
|
+
/**
|
|
14823
|
+
* `'orchestrator'`: this provider writes NO camera's `motion` runtime slice
|
|
14824
|
+
* — the orchestrator is its only writer (D696). Set by `BaseDeviceProvider`,
|
|
14825
|
+
* which every provider bundles, so only a provider BUILT from D696-amended
|
|
14826
|
+
* code says it. ABSENT means an older provider that may still write it (raw
|
|
14827
|
+
* VMD writes, a boot seed), and the orchestrator's provider gate keeps that
|
|
14828
|
+
* provider's cameras unwritten (`camera-sensors/motion-slice-provider-gate.ts`)
|
|
14829
|
+
* — the provider twin of the runner's `getLocalLoad().motionSliceWriter`.
|
|
14830
|
+
*/
|
|
14831
|
+
motionSliceWriter: literal("orchestrator").optional()
|
|
14814
14832
|
});
|
|
14815
14833
|
object({
|
|
14816
14834
|
externalId: string(),
|
|
@@ -15608,109 +15626,10 @@ method(object({
|
|
|
15608
15626
|
deviceIds: array(number()).readonly(),
|
|
15609
15627
|
caps: array(string()).readonly().optional()
|
|
15610
15628
|
}), record(string(), record(string(), unknown().nullable())));
|
|
15611
|
-
|
|
15612
|
-
|
|
15613
|
-
* name (same pattern as `snapshot`):
|
|
15614
|
-
*
|
|
15615
|
-
* - **Native** providers: registered per-device by device-driver
|
|
15616
|
-
* addons via `ctx.registerNativeCap` — either on a
|
|
15617
|
-
* `DeviceType.Button` accessory with `role: DeviceRole.Doorbell`,
|
|
15618
|
-
* or directly on the camera (Reolink registers at camera level).
|
|
15619
|
-
* Emits an `onPressed` event every time the firmware pushes a
|
|
15620
|
-
* ring; status tracks the last press and a pressCount since start
|
|
15621
|
-
* (diagnostic).
|
|
15622
|
-
*
|
|
15623
|
-
* - **Wrapper** provider: the `virtual-doorbell` system builtin
|
|
15624
|
-
* (`@camstack/system/builtins/doorbell`). Turns ANY binary-ish
|
|
15625
|
-
* device (contact / switch / event-emitter …) into a doorbell for
|
|
15626
|
-
* a camera. `defaultActive: false` — the operator explicitly binds
|
|
15627
|
-
* it per camera in the device-bindings UI, then picks the source
|
|
15628
|
-
* device + trigger in the per-device settings.
|
|
15629
|
-
*
|
|
15630
|
-
* The DeviceEventPropagator re-emits `onPressed` on the camera parent
|
|
15631
|
-
* — subscribers listening at the camera level receive ring events
|
|
15632
|
-
* with `via[]` populated. No code on the parent needed.
|
|
15633
|
-
*/
|
|
15634
|
-
var DoorbellStatusSchema = object({
|
|
15635
|
-
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
15636
|
-
lastPressedAt: number().nullable(),
|
|
15637
|
-
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
15638
|
-
pressCountSinceStart: number()
|
|
15639
|
-
});
|
|
15640
|
-
var DoorbellPressEventSchema = object({
|
|
15641
|
-
deviceId: number(),
|
|
15642
|
-
timestamp: number()
|
|
15643
|
-
});
|
|
15644
|
-
/**
|
|
15645
|
-
* The `doorbell-source` extension slot's editable value (D648): the camera's
|
|
15646
|
-
* virtual-doorbell trigger devices, exactly what the wrapper's
|
|
15647
|
-
* `doorbellSources` persists (as `{ deviceId }` records).
|
|
15648
|
-
*/
|
|
15649
|
-
var DoorbellSourceSlotValueSchema = object({ deviceIds: array(number().int().positive()) });
|
|
15650
|
-
/**
|
|
15651
|
-
* The `doorbell-source` slot — which devices ring this camera's VIRTUAL
|
|
15652
|
-
* doorbell, owned by the `virtual-doorbell` wrapper over its
|
|
15653
|
-
* `doorbellSources` store (D648). A source rings when one of its
|
|
15654
|
-
* `SOURCE_CAPS` rises. Whether the wrapper is bound to the camera at all is a
|
|
15655
|
-
* different authority (`deviceManager.setWrapperActive`, D62) — the slot
|
|
15656
|
-
* reports it, it never writes it.
|
|
15657
|
-
*/
|
|
15658
|
-
var DOORBELL_SOURCE_SLOT = {
|
|
15659
|
-
id: "doorbell-source",
|
|
15660
|
-
label: "Doorbell trigger devices",
|
|
15661
|
-
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.",
|
|
15662
|
-
shape: "association",
|
|
15663
|
-
hostDeviceTypes: [DeviceType.Camera],
|
|
15664
|
-
sourceCaps: SOURCE_CAPS,
|
|
15665
|
-
cardinality: "many",
|
|
15666
|
-
value: DoorbellSourceSlotValueSchema
|
|
15667
|
-
};
|
|
15668
|
-
var doorbellCapability = {
|
|
15669
|
-
name: "doorbell",
|
|
15670
|
-
scope: "device",
|
|
15671
|
-
deviceNative: true,
|
|
15672
|
-
mode: "singleton",
|
|
15673
|
-
kind: "wrapper",
|
|
15674
|
-
defaultActive: false,
|
|
15675
|
-
deviceTypes: [DeviceType.Button, DeviceType.Camera],
|
|
15676
|
-
extensionSlots: [DOORBELL_SOURCE_SLOT],
|
|
15677
|
-
methods: {},
|
|
15678
|
-
events: {
|
|
15679
|
-
/**
|
|
15680
|
-
* Fires once per physical press. Reolink delivers via Baichuan
|
|
15681
|
-
* push (`ReolinkSimpleEvent.type === 'doorbell'`). There is no
|
|
15682
|
-
* release/duration — it's a pulse.
|
|
15683
|
-
*/
|
|
15684
|
-
onPressed: {
|
|
15685
|
-
data: DoorbellPressEventSchema,
|
|
15686
|
-
fromState: {
|
|
15687
|
-
field: "lastPressedAt",
|
|
15688
|
-
on: "advance"
|
|
15689
|
-
}
|
|
15690
|
-
} },
|
|
15691
|
-
status: {
|
|
15692
|
-
schema: DoorbellStatusSchema,
|
|
15693
|
-
kind: "push"
|
|
15694
|
-
},
|
|
15695
|
-
/**
|
|
15696
|
-
* Runtime-state slice — last press timestamp + lifetime press count.
|
|
15697
|
-
* Mirrored by the kernel and readable via
|
|
15698
|
-
* `device.state.doorbell.value`. UIs can show "last ring 5m ago"
|
|
15699
|
-
* without subscribing.
|
|
15700
|
-
*/
|
|
15701
|
-
runtimeState: DoorbellStatusSchema,
|
|
15702
|
-
/**
|
|
15703
|
-
* 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.
|
|
15704
|
-
*
|
|
15705
|
-
* See `RuntimeStateDurability`. Enforced by
|
|
15706
|
-
* `scripts/check-runtime-state-durability.ts`.
|
|
15707
|
-
*/
|
|
15708
|
-
durability: "restored"
|
|
15709
|
-
};
|
|
15710
|
-
var ExtensionSlotIdSchema = _enum(["doorbell-source", "linked-devices"]);
|
|
15711
|
-
DeviceType.Camera, DeviceType.Camera;
|
|
15629
|
+
var ExtensionSlotIdSchema = _enum(["linked-devices"]);
|
|
15630
|
+
DeviceType.Camera;
|
|
15712
15631
|
/** A slot's editable value, discriminated on `slot`. */
|
|
15713
|
-
var ExtensionSlotValueSchema = discriminatedUnion("slot", [
|
|
15632
|
+
var ExtensionSlotValueSchema = discriminatedUnion("slot", [LinkedDevicesSlotValueSchema.extend({ slot: literal("linked-devices") })]);
|
|
15714
15633
|
DeviceType.Camera;
|
|
15715
15634
|
var ExtensionSourceAvailabilitySchema = discriminatedUnion("state", [object({ state: literal("ok") }), object({
|
|
15716
15635
|
state: literal("unreachable"),
|
|
@@ -15747,10 +15666,11 @@ var ExtensionSlotSourceSchema = object({
|
|
|
15747
15666
|
});
|
|
15748
15667
|
/**
|
|
15749
15668
|
* A DIFFERENT authority that gates whether the slot's sources do anything —
|
|
15750
|
-
* reported read-only, named, never written through this contract (D62).
|
|
15751
|
-
*
|
|
15752
|
-
*
|
|
15753
|
-
* `unknown` means the gate could
|
|
15669
|
+
* reported read-only, named, never written through this contract (D62) — e.g.
|
|
15670
|
+
* a slot whose sources act only while a wrapper is bound to the host, a
|
|
15671
|
+
* binding that belongs to `deviceManager.setWrapperActive`. No slot reports
|
|
15672
|
+
* one today (`linked-devices` answers `null`). `unknown` means the gate could
|
|
15673
|
+
* not be read; it is not "inactive" (D315).
|
|
15754
15674
|
*/
|
|
15755
15675
|
var ExtensionSlotActivationSchema = object({
|
|
15756
15676
|
state: _enum([
|
|
@@ -15766,7 +15686,7 @@ var ExtensionSlotRowSchema = discriminatedUnion("state", [object({
|
|
|
15766
15686
|
/** `<source>:<slotId>` — the routing key for `listCandidates` / `setSlot`. */
|
|
15767
15687
|
slotRef: string(),
|
|
15768
15688
|
slot: ExtensionSlotIdSchema,
|
|
15769
|
-
/** Names the store written (D62), e.g. `
|
|
15689
|
+
/** Names the store written (D62), e.g. `device-manager:_linkedDeviceIds`. */
|
|
15770
15690
|
authority: string(),
|
|
15771
15691
|
activation: ExtensionSlotActivationSchema.nullable(),
|
|
15772
15692
|
value: ExtensionSlotValueSchema,
|
|
@@ -16044,7 +15964,7 @@ method(object({
|
|
|
16044
15964
|
* per-device window, `KeyFrameCaptureLog`, `bumpCropMetric`. Every one of them
|
|
16045
15965
|
* ends in a log line, and a log line is the thing the operator asked to stop
|
|
16046
15966
|
* needing: *"possiamo armare questi errori intanto? Così al prossimo giro
|
|
16047
|
-
* ricontrolliamo tutti questi punti"
|
|
15967
|
+
* 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
|
|
16048
15968
|
* hand-correlating timestamps, which is how a 22% thumbnail gap and a 3-hour
|
|
16049
15969
|
* media blackout were both diagnosed. The counters stay; this is where they can
|
|
16050
15970
|
* be READ.
|
|
@@ -17420,7 +17340,7 @@ var BrokerStatusSchema$1 = _enum([
|
|
|
17420
17340
|
"unreachable",
|
|
17421
17341
|
"tls-error"
|
|
17422
17342
|
]);
|
|
17423
|
-
var BrokerInfoSchema = object({
|
|
17343
|
+
var BrokerInfoSchema$1 = object({
|
|
17424
17344
|
id: string(),
|
|
17425
17345
|
name: string(),
|
|
17426
17346
|
url: string(),
|
|
@@ -17483,7 +17403,7 @@ var StatusSchema = object({
|
|
|
17483
17403
|
brokerCount: number(),
|
|
17484
17404
|
embeddedRunning: boolean()
|
|
17485
17405
|
});
|
|
17486
|
-
method(_void(), array(BrokerInfoSchema)), method(IdInputSchema, BrokerConnectionDetailsSchema, { auth: "admin" }), method(AddBrokerInputSchema, AddBrokerResultSchema, {
|
|
17406
|
+
method(_void(), array(BrokerInfoSchema$1)), method(IdInputSchema, BrokerConnectionDetailsSchema, { auth: "admin" }), method(AddBrokerInputSchema, AddBrokerResultSchema, {
|
|
17487
17407
|
kind: "mutation",
|
|
17488
17408
|
auth: "admin"
|
|
17489
17409
|
}), method(IdInputSchema, _void(), {
|
|
@@ -19697,78 +19617,16 @@ var NcRuleInputSchema = object({
|
|
|
19697
19617
|
*/
|
|
19698
19618
|
confirm: NcConfirmSchema.optional(),
|
|
19699
19619
|
/**
|
|
19700
|
-
*
|
|
19701
|
-
*
|
|
19702
|
-
*
|
|
19703
|
-
*
|
|
19704
|
-
*
|
|
19705
|
-
*
|
|
19706
|
-
*
|
|
19707
|
-
*
|
|
19708
|
-
*
|
|
19709
|
-
* Only two honest answers exist, and this flag picks between them. It has
|
|
19710
|
-
* effect ONLY on a rule that declares a recognition scope
|
|
19711
|
-
* ({@link NcConditions.identities} or {@link NcConditions.plates}) — on any
|
|
19712
|
-
* other rule there is nothing to wait for and the flag is inert.
|
|
19713
|
-
*
|
|
19714
|
-
* | value | what happens |
|
|
19715
|
-
* | --- | --- |
|
|
19716
|
-
* | `true` | the rule stops firing on the object event and fires at TRACK CLOSE instead, once, with the name — later, and complete |
|
|
19717
|
-
* | 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) |
|
|
19718
|
-
*
|
|
19719
|
-
* `.optional()` and deliberately NOT `.default()`: a Zod default does not run
|
|
19720
|
-
* on the addon cap path, and absent has to keep meaning exactly what every
|
|
19721
|
-
* rule authored before this field meant.
|
|
19722
|
-
*
|
|
19723
|
-
* The cost of `true` is stated here because the editor states it too: a rule
|
|
19724
|
-
* that waits also inherits track-close SEMANTICS — its `zones` condition
|
|
19725
|
-
* tests every zone the track visited and a `crossing` condition can no longer
|
|
19726
|
-
* be satisfied, because a closed track carries no crossing.
|
|
19620
|
+
* IMMEDIATE GROUPED (D692): the first matching subject opens a window of this many
|
|
19621
|
+
* seconds; the rule sends ONE message when the window closes — early, once every
|
|
19622
|
+
* subject in it is final, never before {@link NC_GROUPING_MIN_SEC} — naming everybody
|
|
19623
|
+
* the rule matched, with one mosaic tile per subject.
|
|
19624
|
+
* Absent = plain immediate (one message per track, at the first match).
|
|
19625
|
+
* Only an `immediate` DETECTION rule may carry it (`ruleGroupingApplies`, enforced on
|
|
19626
|
+
* save by the hub's grouping guard). `.optional()`, never `.default()`: the addon cap
|
|
19627
|
+
* path does not run Zod defaults.
|
|
19727
19628
|
*/
|
|
19728
|
-
|
|
19729
|
-
/**
|
|
19730
|
-
* GROUP a burst of subjects into ONE notification that grows.
|
|
19731
|
-
*
|
|
19732
|
-
* Seconds of quiet after the last matching subject before the burst is
|
|
19733
|
-
* considered over. While it is open, the first subject enqueues immediately —
|
|
19734
|
-
* **exactly as today, with no added latency** — and every real growth (a new
|
|
19735
|
-
* subject, or a name confirmed on one already in it) REPLACES that
|
|
19736
|
-
* notification with an updated one naming everybody. The push carries the
|
|
19737
|
-
* group's own coalescing tag, so the phone replaces rather than stacks.
|
|
19738
|
-
*
|
|
19739
|
-
* `0` / absent = off, and off is today's behaviour byte for byte.
|
|
19740
|
-
*
|
|
19741
|
-
* ### Why an idle cutoff and not a window
|
|
19742
|
-
*
|
|
19743
|
-
* The measured seven-person arrival on device 590 spans 110 s with every
|
|
19744
|
-
* internal gap under 30 s. A 12 s fixed window cuts it into three groups; an
|
|
19745
|
-
* idle cutoff holds it as one and ends it when the arrival actually ends.
|
|
19746
|
-
* 30 s is a widely shipped value for the same decision.
|
|
19747
|
-
*
|
|
19748
|
-
* ### What it replaces
|
|
19749
|
-
*
|
|
19750
|
-
* The blind cooldown, which collapses a burst by DISCARDING it. Measured on
|
|
19751
|
-
* device 615 / *Persona su Uscio* over six days: 116 qualifying tracks → 74
|
|
19752
|
-
* notifications, **44 (37.9%) suppressed outright**, 23 of them overlapping a
|
|
19753
|
-
* track that did fire and 7 carrying a confirmed identity nobody heard about.
|
|
19754
|
-
* A group collapses the same volume by MERGING, so the cooldown becomes a
|
|
19755
|
-
* budget over GROUPS — which is what it always meant — and a growth is never
|
|
19756
|
-
* throttled by the window its own first member spent.
|
|
19757
|
-
*
|
|
19758
|
-
* ### Interaction with {@link waitForEnhancement}
|
|
19759
|
-
*
|
|
19760
|
-
* They compose, and the order matters. `waitForEnhancement` defers the rule to
|
|
19761
|
-
* TRACK CLOSE, so with both set the group is opened by the first member to
|
|
19762
|
-
* CLOSE — already carrying its name — and grows as later members close. That
|
|
19763
|
-
* is later, and complete. With grouping alone the group opens on the first
|
|
19764
|
-
* object event and picks up names as they are confirmed, through the growth
|
|
19765
|
-
* path. Neither combination fires twice for one subject.
|
|
19766
|
-
*
|
|
19767
|
-
* `.optional()` and deliberately NOT `.default()`: a Zod default does not run
|
|
19768
|
-
* on the addon cap path, so absent must keep meaning what it meant before this
|
|
19769
|
-
* field existed.
|
|
19770
|
-
*/
|
|
19771
|
-
groupIdleSec: number().int().min(0).max(600).optional()
|
|
19629
|
+
groupingSec: number().int().min(5).max(60).optional()
|
|
19772
19630
|
});
|
|
19773
19631
|
/**
|
|
19774
19632
|
* Partial patch for `updateRule` — any subset of the input fields, plus the
|
|
@@ -19816,9 +19674,10 @@ var NcRuleClearableKeySchema = _enum([
|
|
|
19816
19674
|
"targetUsers",
|
|
19817
19675
|
"snoozeOptions",
|
|
19818
19676
|
"snoozeAllowGlobal",
|
|
19819
|
-
"waitForEnhancement",
|
|
19820
19677
|
"actions",
|
|
19821
19678
|
"confirm",
|
|
19679
|
+
"groupingSec",
|
|
19680
|
+
"waitForEnhancement",
|
|
19822
19681
|
"groupIdleSec"
|
|
19823
19682
|
]);
|
|
19824
19683
|
var NcRuleUpdateInputSchema = object({
|
|
@@ -19840,9 +19699,25 @@ var NcRuleSchema = NcRuleInputSchema.extend({
|
|
|
19840
19699
|
*/
|
|
19841
19700
|
disabledTargetIds: array(string()).default([])
|
|
19842
19701
|
});
|
|
19702
|
+
/**
|
|
19703
|
+
* The state-summary SECTIONS (D647 / D698): the D637 kind groups that report a
|
|
19704
|
+
* still-true state. `backups-exports` and `alarm` are not sections — a completed
|
|
19705
|
+
* job is not an open state, and the alarm stays instant.
|
|
19706
|
+
*/
|
|
19707
|
+
var NcStateSummarySectionIdSchema = _enum([
|
|
19708
|
+
"device-state",
|
|
19709
|
+
"streams",
|
|
19710
|
+
"battery",
|
|
19711
|
+
"consumables",
|
|
19712
|
+
"tanks",
|
|
19713
|
+
"detection-blind",
|
|
19714
|
+
"nodes",
|
|
19715
|
+
"addons",
|
|
19716
|
+
"updates"
|
|
19717
|
+
]);
|
|
19843
19718
|
/** One section of a previewed state summary. `unavailable` = its state could not be read. */
|
|
19844
19719
|
var NcStateSummaryPreviewSectionSchema = object({
|
|
19845
|
-
id:
|
|
19720
|
+
id: NcStateSummarySectionIdSchema,
|
|
19846
19721
|
status: _enum(["read", "unavailable"]),
|
|
19847
19722
|
items: number().int().nonnegative(),
|
|
19848
19723
|
reason: string().optional()
|
|
@@ -19852,7 +19727,7 @@ var NcStateSummaryPreviewSectionSchema = object({
|
|
|
19852
19727
|
* a `rule` split (no `section`), one section's on a `section` split.
|
|
19853
19728
|
*/
|
|
19854
19729
|
var NcStateSummaryPreviewRowSchema = object({
|
|
19855
|
-
section:
|
|
19730
|
+
section: NcStateSummarySectionIdSchema.optional(),
|
|
19856
19731
|
/** The section's name on a per-section row; every reported section's, joined, on a combined one. */
|
|
19857
19732
|
title: string(),
|
|
19858
19733
|
text: string(),
|
|
@@ -20289,6 +20164,29 @@ object({
|
|
|
20289
20164
|
firstAt: number(),
|
|
20290
20165
|
lastAt: number()
|
|
20291
20166
|
});
|
|
20167
|
+
var NC_ALARM_TRIGGERED_MAX_SEC = 3600;
|
|
20168
|
+
var NcAlarmDelaySecSchema = number().int().min(0).max(600);
|
|
20169
|
+
var NcAlarmTriggeredSecSchema = number().int().min(0).max(NC_ALARM_TRIGGERED_MAX_SEC);
|
|
20170
|
+
var uniqueModes = (entries) => new Set(entries.map((e) => e.mode)).size === entries.length;
|
|
20171
|
+
var NcAlarmModeDelaysListSchema = array(object({
|
|
20172
|
+
mode: AlarmArmModeSchema,
|
|
20173
|
+
exitDelaySec: NcAlarmDelaySecSchema.optional(),
|
|
20174
|
+
entryDelaySec: NcAlarmDelaySecSchema.optional(),
|
|
20175
|
+
triggeredDurationSec: NcAlarmTriggeredSecSchema.optional()
|
|
20176
|
+
})).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
|
|
20177
|
+
var NcAlarmModeDelaysEditListSchema = array(object({
|
|
20178
|
+
mode: AlarmArmModeSchema,
|
|
20179
|
+
exitDelaySec: NcAlarmDelaySecSchema.nullable().optional(),
|
|
20180
|
+
entryDelaySec: NcAlarmDelaySecSchema.nullable().optional(),
|
|
20181
|
+
triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional()
|
|
20182
|
+
})).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
|
|
20183
|
+
/** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
|
|
20184
|
+
var NcAlarmNonBlockingEditSchema = object({
|
|
20185
|
+
mode: AlarmArmModeSchema,
|
|
20186
|
+
deviceId: number().int().positive(),
|
|
20187
|
+
/** true = on the list (may be open, does not block); false = off the list (blocks). */
|
|
20188
|
+
nonBlocking: boolean()
|
|
20189
|
+
});
|
|
20292
20190
|
/**
|
|
20293
20191
|
* The per-mode lists, at most one per mode. Two lists for one mode have no
|
|
20294
20192
|
* meaning a reader could agree on (union? the last one?), so they are refused
|
|
@@ -20297,10 +20195,10 @@ object({
|
|
|
20297
20195
|
var NcAlarmNonBlockingListSchema = array(object({
|
|
20298
20196
|
mode: AlarmArmModeSchema,
|
|
20299
20197
|
deviceIds: array(number().int()).max(200)
|
|
20300
|
-
})).max(8).refine(
|
|
20198
|
+
})).max(8).refine(uniqueModes, { message: "nonBlocking: at most one list per arm mode" });
|
|
20301
20199
|
/**
|
|
20302
|
-
* The three durations
|
|
20303
|
-
* transitions, and which openings each mode tolerates.
|
|
20200
|
+
* The three durations — global, and per mode since D697 — the panel's state
|
|
20201
|
+
* machine runs on, who hears about its transitions, and which openings each mode tolerates.
|
|
20304
20202
|
*
|
|
20305
20203
|
* They live on the NOTIFICATION-RULES cap, not on `alarm-panel`, on purpose:
|
|
20306
20204
|
* `alarm-panel` is `deviceNative` and its other provider mirrors somebody
|
|
@@ -20310,15 +20208,15 @@ var NcAlarmNonBlockingListSchema = array(object({
|
|
|
20310
20208
|
*/
|
|
20311
20209
|
var NcAlarmSettingsSchema = object({
|
|
20312
20210
|
/** Grace period between arming and the mode taking effect. 0 = immediate. */
|
|
20313
|
-
exitDelaySec:
|
|
20211
|
+
exitDelaySec: NcAlarmDelaySecSchema,
|
|
20314
20212
|
/** Grace period between a trigger and the alarm firing. 0 = immediate. */
|
|
20315
|
-
entryDelaySec:
|
|
20213
|
+
entryDelaySec: NcAlarmDelaySecSchema,
|
|
20316
20214
|
/**
|
|
20317
20215
|
* How long `triggered` lasts before the panel re-arms itself.
|
|
20318
20216
|
* **0 = until an operator disarms it** — the behaviour before this field
|
|
20319
20217
|
* existed, and therefore what an untouched install keeps doing.
|
|
20320
20218
|
*/
|
|
20321
|
-
triggeredDurationSec:
|
|
20219
|
+
triggeredDurationSec: NcAlarmTriggeredSecSchema,
|
|
20322
20220
|
/**
|
|
20323
20221
|
* Deprecated by D630 — every transition is announced. Parsed, never read;
|
|
20324
20222
|
* remove after one release. Optional so an older admin's patch (which still
|
|
@@ -20341,17 +20239,30 @@ var NcAlarmSettingsSchema = object({
|
|
|
20341
20239
|
* per mode is meaningful. Defaulted to `[]` so a blob stored before D630
|
|
20342
20240
|
* parses as "every opening blocks" — the behaviour it was written under.
|
|
20343
20241
|
*/
|
|
20344
|
-
nonBlocking: NcAlarmNonBlockingListSchema.default([])
|
|
20242
|
+
nonBlocking: NcAlarmNonBlockingListSchema.default([]),
|
|
20243
|
+
/**
|
|
20244
|
+
* Per arm mode, the delays that mode OVERRIDES (D697). A mode with no entry, or an entry
|
|
20245
|
+
* without a field, uses the global value above — so `[]`, the default, is exactly the
|
|
20246
|
+
* behaviour of a blob stored before this field existed. Read through `resolveModeDelays`.
|
|
20247
|
+
*/
|
|
20248
|
+
modeDelays: NcAlarmModeDelaysListSchema.default([])
|
|
20345
20249
|
});
|
|
20346
20250
|
/**
|
|
20347
20251
|
* Every field optional — a tab edits one control at a time.
|
|
20348
20252
|
*
|
|
20349
|
-
* `nonBlocking`
|
|
20350
|
-
* remove an inner `.default()`, so a patch that never
|
|
20351
|
-
* parse to `
|
|
20352
|
-
* (the same trap {@link NcRulePatchSchema} documents).
|
|
20253
|
+
* `nonBlocking` and `modeDelays` are re-declared WITHOUT their defaults:
|
|
20254
|
+
* `.partial()` does not remove an inner `.default()`, so a patch that never
|
|
20255
|
+
* named the field would parse to `[]` and wipe every mode's list on an
|
|
20256
|
+
* unrelated edit (the same trap {@link NcRulePatchSchema} documents). Here
|
|
20257
|
+
* `modeDelays` means EDITS, not the stored overrides.
|
|
20353
20258
|
*/
|
|
20354
|
-
var NcAlarmSettingsPatchSchema = NcAlarmSettingsSchema.extend({
|
|
20259
|
+
var NcAlarmSettingsPatchSchema = NcAlarmSettingsSchema.extend({
|
|
20260
|
+
nonBlocking: NcAlarmNonBlockingListSchema,
|
|
20261
|
+
/** Per-mode, per-field edits — NOT the whole list (see NcAlarmModeDelaysEditSchema). */
|
|
20262
|
+
modeDelays: NcAlarmModeDelaysEditListSchema,
|
|
20263
|
+
/** ONE membership change; the panel applies it to the list it holds at its turn. */
|
|
20264
|
+
nonBlockingEdit: NcAlarmNonBlockingEditSchema
|
|
20265
|
+
}).partial().refine((p) => p.nonBlocking === void 0 || p.nonBlockingEdit === void 0, { message: "nonBlocking and nonBlockingEdit are exclusive — send the whole lists or one edit" });
|
|
20355
20266
|
/**
|
|
20356
20267
|
* What one arm mode actually arms, DERIVED from the enabled rules gated on it.
|
|
20357
20268
|
* Never authored, never stored — see `alarm-mode-coverage.ts` for why a stored
|
|
@@ -20451,6 +20362,28 @@ var NcAlarmConfigSchema = object({
|
|
|
20451
20362
|
*/
|
|
20452
20363
|
live: NcAlarmLiveSchema.optional()
|
|
20453
20364
|
});
|
|
20365
|
+
var NcAlarmSensorReadingSchema = _enum([
|
|
20366
|
+
"open",
|
|
20367
|
+
"closed",
|
|
20368
|
+
"unknown",
|
|
20369
|
+
"not-opening"
|
|
20370
|
+
]);
|
|
20371
|
+
/** One device's state as the alarm reads it — the classifier the arm check uses. */
|
|
20372
|
+
var NcAlarmSensorStateSchema = object({
|
|
20373
|
+
deviceId: number().int().positive(),
|
|
20374
|
+
reading: NcAlarmSensorReadingSchema,
|
|
20375
|
+
/** The word as read (`open`, `closed`, `unlocked`, `stopped`, …); null when unknown / not an opening. */
|
|
20376
|
+
state: string().nullable(),
|
|
20377
|
+
/** Why `unknown`: the read failed, or the slice holds no word its cap defines (a placeholder included). */
|
|
20378
|
+
unknownWhy: _enum(["read-failed", "unknown-word"]).nullable(),
|
|
20379
|
+
/** The device manager's liveness as the centre mirrors it; null = not known. */
|
|
20380
|
+
online: boolean().nullable()
|
|
20381
|
+
});
|
|
20382
|
+
var NcAlarmSensorsInputSchema = object({ deviceIds: array(number().int().positive()).max(500) });
|
|
20383
|
+
var NcAlarmSensorsSchema = object({
|
|
20384
|
+
sensors: array(NcAlarmSensorStateSchema),
|
|
20385
|
+
readAt: number().int().nonnegative()
|
|
20386
|
+
});
|
|
20454
20387
|
/**
|
|
20455
20388
|
* ONE rule's demand on ONE camera's clip ring.
|
|
20456
20389
|
*
|
|
@@ -20541,7 +20474,7 @@ method(object({}), object({ rules: array(NcRuleSchema) }), { auth: "admin" }), m
|
|
|
20541
20474
|
}), method(object({}), NcAlarmConfigSchema, { auth: "admin" }), method(object({ patch: NcAlarmSettingsPatchSchema }), NcAlarmConfigSchema, {
|
|
20542
20475
|
kind: "mutation",
|
|
20543
20476
|
auth: "admin"
|
|
20544
|
-
});
|
|
20477
|
+
}), method(NcAlarmSensorsInputSchema, NcAlarmSensorsSchema, { auth: "admin" });
|
|
20545
20478
|
/**
|
|
20546
20479
|
* Zod schemas for persisted record types.
|
|
20547
20480
|
*
|
|
@@ -20888,12 +20821,26 @@ var CameraSensorRefSchema = object({
|
|
|
20888
20821
|
function cameraSensorRefKey(ref) {
|
|
20889
20822
|
return `${ref.addonId}/${ref.stableId}`;
|
|
20890
20823
|
}
|
|
20891
|
-
/**
|
|
20892
|
-
|
|
20893
|
-
|
|
20894
|
-
|
|
20895
|
-
|
|
20896
|
-
|
|
20824
|
+
/**
|
|
20825
|
+
* A sensor's mode (D673). `in-addition`: its motion is the camera's motion too.
|
|
20826
|
+
* `replace`: its motion is the camera's, and while one is READY the camera's
|
|
20827
|
+
* own motion no longer counts on its own. `confirm`: while one is READY the
|
|
20828
|
+
* camera's own motion counts only while a confirm sensor is active — with or
|
|
20829
|
+
* without a replace sensor (spec C2, the controller's ruling on Q1).
|
|
20830
|
+
*/
|
|
20831
|
+
var CameraSensorModeSchema = _enum([
|
|
20832
|
+
"in-addition",
|
|
20833
|
+
"confirm",
|
|
20834
|
+
"replace"
|
|
20835
|
+
]);
|
|
20836
|
+
/** A stored sensor with no mode — every CS-1 row — is in addition. */
|
|
20837
|
+
var DEFAULT_CAMERA_SENSOR_MODE = "in-addition";
|
|
20838
|
+
/**
|
|
20839
|
+
* A camera's attached sensors. A CS-1 row carried an envelope
|
|
20840
|
+
* `mode: 'in-addition'`: `z.object` drops it on parse, and the PARSED value is
|
|
20841
|
+
* what the write stores (D672 rule 3), so it is never written again.
|
|
20842
|
+
*/
|
|
20843
|
+
var CameraSensorsConfigSchema = object({ sensors: array(CameraSensorRefSchema.extend({ mode: CameraSensorModeSchema.default(DEFAULT_CAMERA_SENSOR_MODE) })).min(1).max(8) }).superRefine((value, ctx) => {
|
|
20897
20844
|
const seen = /* @__PURE__ */ new Set();
|
|
20898
20845
|
value.sensors.forEach((ref, index) => {
|
|
20899
20846
|
const key = cameraSensorRefKey(ref);
|
|
@@ -20905,39 +20852,41 @@ var CameraSensorsConfigSchema = object({
|
|
|
20905
20852
|
seen.add(key);
|
|
20906
20853
|
});
|
|
20907
20854
|
});
|
|
20908
|
-
|
|
20855
|
+
/** Every attachment names its mode; an older orchestrator that does not is in addition. */
|
|
20856
|
+
var AttachmentFields = {
|
|
20909
20857
|
addonId: string(),
|
|
20910
|
-
stableId: string()
|
|
20858
|
+
stableId: string(),
|
|
20859
|
+
mode: CameraSensorModeSchema.default(DEFAULT_CAMERA_SENSOR_MODE)
|
|
20911
20860
|
};
|
|
20912
20861
|
var CameraSensorAttachmentSchema = discriminatedUnion("state", [
|
|
20913
20862
|
object({
|
|
20914
|
-
...
|
|
20863
|
+
...AttachmentFields,
|
|
20915
20864
|
state: literal("ready"),
|
|
20916
20865
|
deviceId: number(),
|
|
20917
20866
|
name: string(),
|
|
20918
20867
|
caps: array(string()).readonly()
|
|
20919
20868
|
}),
|
|
20920
20869
|
object({
|
|
20921
|
-
...
|
|
20870
|
+
...AttachmentFields,
|
|
20922
20871
|
state: literal("offline"),
|
|
20923
20872
|
deviceId: number(),
|
|
20924
20873
|
name: string(),
|
|
20925
20874
|
reason: _enum(["offline", "disabled"])
|
|
20926
20875
|
}),
|
|
20927
20876
|
object({
|
|
20928
|
-
...
|
|
20877
|
+
...AttachmentFields,
|
|
20929
20878
|
state: literal("missing"),
|
|
20930
20879
|
reason: string()
|
|
20931
20880
|
}),
|
|
20932
20881
|
object({
|
|
20933
|
-
...
|
|
20882
|
+
...AttachmentFields,
|
|
20934
20883
|
state: literal("unsupported"),
|
|
20935
20884
|
deviceId: number(),
|
|
20936
20885
|
name: string(),
|
|
20937
20886
|
reason: string()
|
|
20938
20887
|
}),
|
|
20939
20888
|
object({
|
|
20940
|
-
...
|
|
20889
|
+
...AttachmentFields,
|
|
20941
20890
|
state: literal("unreadable"),
|
|
20942
20891
|
reason: string()
|
|
20943
20892
|
})
|
|
@@ -20950,17 +20899,49 @@ var CameraSensorAttachmentSchema = discriminatedUnion("state", [
|
|
|
20950
20899
|
* say.
|
|
20951
20900
|
*/
|
|
20952
20901
|
var CameraSensorsNotForwardedSchema = _enum(["onboard-not-listed", "no-active-detection"]);
|
|
20902
|
+
/** Whether the camera's OWN motion counts on its own (D673 C2), from its READY sensors (C3). */
|
|
20903
|
+
var CameraOwnMotionSchema = _enum([
|
|
20904
|
+
"always",
|
|
20905
|
+
"when-confirmed",
|
|
20906
|
+
"never"
|
|
20907
|
+
]);
|
|
20908
|
+
/** Confirm / Replace cannot suppress this camera's motion: its provider still emits it directly (D673 C13). */
|
|
20909
|
+
var CameraSensorsNotEnforcedSchema = _enum(["provider-not-split"]);
|
|
20910
|
+
/**
|
|
20911
|
+
* The camera's OWN onboard motion (D696): the raw input the bridge combines,
|
|
20912
|
+
* never the effective value. The camera's `motion` slice is the effective one,
|
|
20913
|
+
* so a view of the camera's own row reads this.
|
|
20914
|
+
* - `atMs`: when the bridge received the camera's last own edge.
|
|
20915
|
+
* - `detected`: evaluated WHEN THE STATUS IS ASKED — the last edge said `true`
|
|
20916
|
+
* AND it is younger than the window the bridge counts the camera's own motion
|
|
20917
|
+
* for (`motionCooldownMs`, floored at two sustain ticks). A camera that never
|
|
20918
|
+
* sends a clear (heartbeats only) therefore reads `false` once no push came
|
|
20919
|
+
* within the window; a status read is a snapshot, so a live view re-asks.
|
|
20920
|
+
* Absent = this orchestrator has not received the camera's own motion since it
|
|
20921
|
+
* started (unknown, never "quiet"), or an orchestrator older than D696.
|
|
20922
|
+
*/
|
|
20923
|
+
var CameraRawLevelSchema = object({
|
|
20924
|
+
detected: boolean(),
|
|
20925
|
+
atMs: number()
|
|
20926
|
+
});
|
|
20953
20927
|
var CameraSensorsStatusSchema = discriminatedUnion("state", [
|
|
20954
|
-
object({
|
|
20928
|
+
object({
|
|
20929
|
+
state: literal("not-configured"),
|
|
20930
|
+
cameraLevel: CameraRawLevelSchema.optional()
|
|
20931
|
+
}),
|
|
20955
20932
|
object({
|
|
20956
20933
|
state: literal("unreadable"),
|
|
20957
|
-
reason: string()
|
|
20934
|
+
reason: string(),
|
|
20935
|
+
cameraLevel: CameraRawLevelSchema.optional()
|
|
20958
20936
|
}),
|
|
20959
20937
|
object({
|
|
20960
20938
|
state: literal("configured"),
|
|
20961
|
-
|
|
20939
|
+
cameraLevel: CameraRawLevelSchema.optional(),
|
|
20962
20940
|
sensors: array(CameraSensorAttachmentSchema).readonly(),
|
|
20963
|
-
|
|
20941
|
+
/** Absent = an orchestrator older than CS-2: it does not say (D315). */
|
|
20942
|
+
cameraMotion: CameraOwnMotionSchema.optional(),
|
|
20943
|
+
notForwarded: CameraSensorsNotForwardedSchema.optional(),
|
|
20944
|
+
notEnforced: CameraSensorsNotEnforcedSchema.optional()
|
|
20964
20945
|
})
|
|
20965
20946
|
]);
|
|
20966
20947
|
Object.freeze({
|
|
@@ -21645,14 +21626,14 @@ var TrackSchema = object({
|
|
|
21645
21626
|
* `derive-returned-null tile=standin`,
|
|
21646
21627
|
* `native-tile tile=native no-key-frame-at-close`, …) written at close and
|
|
21647
21628
|
* CLEARED by the late-keyFrame upgrade when a native tile lands after all.
|
|
21648
|
-
* The operator-facing answer to "perché manca l'immagine?" on a track whose
|
|
21629
|
+
* The operator-facing answer to "perché manca l'immagine?" [why is the image missing?] on a track whose
|
|
21649
21630
|
* tile is a face/plate stand-in, a raster crop, or an icon.
|
|
21650
21631
|
*
|
|
21651
21632
|
* **`no-key-frame-at-close` (D400).** The line used to be written ONLY when
|
|
21652
21633
|
* the TILE ranked below native, so a track whose thumbnail landed natively
|
|
21653
21634
|
* while its key frame missed carried no reason at all — three of the four
|
|
21654
21635
|
* `MISSING_KEYFRAME` tracks in the 2026-09-07 operator audit were exactly
|
|
21655
|
-
* that shape, and their "niente ultimo" had no cause anywhere on the row.
|
|
21636
|
+
* that shape, and their "niente ultimo" [no last frame] had no cause anywhere on the row.
|
|
21656
21637
|
* The key frame is the head of a cascade (`keyFrame ⇒ keyFrameSmall ⇒ the
|
|
21657
21638
|
* lastFrame copy source`), so its absence is now on this line whatever the
|
|
21658
21639
|
* tile ended up being.
|
|
@@ -21739,7 +21720,7 @@ var MotionEventSchema = object({
|
|
|
21739
21720
|
/**
|
|
21740
21721
|
* Ms offsets from `timestamp` (the episode's own first rising edge, so the
|
|
21741
21722
|
* first entry is always `0`) of every genuine off→on transition the
|
|
21742
|
-
* episode saw — "ogni evento on si deve salvare" (D475). NOT one entry per
|
|
21723
|
+
* episode saw — "ogni evento on si deve salvare" [every ON event must be saved] (D475). NOT one entry per
|
|
21743
21724
|
* push: a firmware source that keepalives at ~1 Hz for the whole burst
|
|
21744
21725
|
* (Reolink, Hikvision) produces exactly one edge; a source that reports an
|
|
21745
21726
|
* explicit `false` mid-episode and then resumes before the quiet window
|
|
@@ -22263,6 +22244,7 @@ var KeyEventSchema = object({
|
|
|
22263
22244
|
bestEventId: string(),
|
|
22264
22245
|
/** Track lifetime in ms (lastSeen - firstSeen). */
|
|
22265
22246
|
windowMs: number().optional(),
|
|
22247
|
+
audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
|
|
22266
22248
|
...TrackFlagFields,
|
|
22267
22249
|
...TrackRetrainFields
|
|
22268
22250
|
});
|
|
@@ -24191,8 +24173,10 @@ var RunnerCameraConfigSchema = object({
|
|
|
24191
24173
|
* - `analyzer`: ML/frame-diff motion detection (motion-wasm or other
|
|
24192
24174
|
* analyzer providers) running on decoded frames in this runner.
|
|
24193
24175
|
* - `onboard`: camera-native motion pushes (Reolink Baichuan, ONVIF
|
|
24194
|
-
* analytics). The provider emits ProviderMotion
|
|
24195
|
-
*
|
|
24176
|
+
* analytics). The provider emits its raw push as `ProviderMotion`
|
|
24177
|
+
* (D673); the orchestrator's camera-sensors bridge re-emits the camera's
|
|
24178
|
+
* effective motion as `MotionOnMotionChanged`, which is what reaches
|
|
24179
|
+
* `reportMotion`.
|
|
24196
24180
|
*/
|
|
24197
24181
|
motionSources: MotionSourcesSchema.default(["analyzer"]),
|
|
24198
24182
|
/**
|
|
@@ -24369,7 +24353,15 @@ var RunnerLocalLoadSchema = object({
|
|
|
24369
24353
|
hasGpu: boolean(),
|
|
24370
24354
|
inferenceBackend: string().optional(),
|
|
24371
24355
|
cpuCores: number().optional()
|
|
24372
|
-
})
|
|
24356
|
+
}),
|
|
24357
|
+
/**
|
|
24358
|
+
* Who writes a camera's `motion` runtime slice (D696). `'orchestrator'`: this
|
|
24359
|
+
* runner never writes it. ABSENT = a runner older than D696, which still
|
|
24360
|
+
* writes the slice from its phase machine; the orchestrator does not write
|
|
24361
|
+
* while any runner node is absent-or-unanswered, so one slice never has two
|
|
24362
|
+
* writers.
|
|
24363
|
+
*/
|
|
24364
|
+
motionSliceWriter: literal("orchestrator").optional()
|
|
24373
24365
|
});
|
|
24374
24366
|
/**
|
|
24375
24367
|
* Aggregate runtime metrics for the runner's whole local pool. Mirrors the
|
|
@@ -27182,7 +27174,7 @@ var ClipPlaybackSchema = object({
|
|
|
27182
27174
|
* **One authorised yes is one wake.** `next-natural` — take the clip the next
|
|
27183
27175
|
* time the camera is awake for its own reasons — is deliberately not a member:
|
|
27184
27176
|
* it was proposed, it is free on the battery, and the operator declined it on
|
|
27185
|
-
* 2026-09-20 (*"Quando un export viene richiesto si sveglia la camera."
|
|
27177
|
+
* 2026-09-20 (*"Quando un export viene richiesto si sveglia la camera."* [When an export is requested the camera wakes up],
|
|
27186
27178
|
* D558 "Considered and not taken").
|
|
27187
27179
|
*/
|
|
27188
27180
|
var ClipWakeSchema = _enum(["authorised"]);
|
|
@@ -27443,7 +27435,7 @@ DeviceType.Camera, method(object({
|
|
|
27443
27435
|
* It replaced `sources?: string[]`, a VIEW filter over source ids that
|
|
27444
27436
|
* assumed the answer was a fan-out over everything a camera has. The
|
|
27445
27437
|
* operator settled otherwise on 2026-09-20 — *"l'utilizzatore è uno
|
|
27446
|
-
* solo"* — so the list is asked of one provider at a time and there is
|
|
27438
|
+
* solo"* [there is only one user] — so the list is asked of one provider at a time and there is
|
|
27447
27439
|
* nothing to filter out of it.
|
|
27448
27440
|
*/
|
|
27449
27441
|
provider: string().min(1)
|
|
@@ -30038,6 +30030,70 @@ onStatusChanged: { data: object({
|
|
|
30038
30030
|
* whether persisting is worth a SQLite commit. */
|
|
30039
30031
|
volatileStateFields: ["lastChangedAt"]
|
|
30040
30032
|
};
|
|
30033
|
+
var DoorbellStatusSchema = object({
|
|
30034
|
+
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
30035
|
+
lastPressedAt: number().nullable(),
|
|
30036
|
+
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
30037
|
+
pressCountSinceStart: number()
|
|
30038
|
+
});
|
|
30039
|
+
var DoorbellPressEventSchema = object({
|
|
30040
|
+
deviceId: number(),
|
|
30041
|
+
timestamp: number()
|
|
30042
|
+
});
|
|
30043
|
+
/**
|
|
30044
|
+
* Doorbell button cap. Two kinds of provider serve it, and to every consumer
|
|
30045
|
+
* they are the same cap:
|
|
30046
|
+
*
|
|
30047
|
+
* - **Native** providers, registered per device by a driver addon through
|
|
30048
|
+
* `ctx.registerNativeCap` — a `DeviceType.Button` accessory with
|
|
30049
|
+
* `role: DeviceRole.Doorbell`, or the camera itself (Reolink registers at
|
|
30050
|
+
* camera level). They emit `onPressed` on every firmware ring.
|
|
30051
|
+
* - **A composed doorbell** (D670, D671): a camera's customization gives it
|
|
30052
|
+
* the cap, its `lastPressedAt` rising from the sources the operator
|
|
30053
|
+
* assigned in Customize → Doorbell, and the composer emits `onPressed`
|
|
30054
|
+
* from that field's advance (`fromState`).
|
|
30055
|
+
*
|
|
30056
|
+
* The DeviceEventPropagator re-emits `onPressed` on the camera parent.
|
|
30057
|
+
*/
|
|
30058
|
+
var doorbellCapability = {
|
|
30059
|
+
name: "doorbell",
|
|
30060
|
+
scope: "device",
|
|
30061
|
+
deviceNative: true,
|
|
30062
|
+
mode: "singleton",
|
|
30063
|
+
deviceTypes: [DeviceType.Button, DeviceType.Camera],
|
|
30064
|
+
methods: {},
|
|
30065
|
+
events: {
|
|
30066
|
+
/**
|
|
30067
|
+
* Fires once per physical press. Reolink delivers via Baichuan
|
|
30068
|
+
* push (`ReolinkSimpleEvent.type === 'doorbell'`). There is no
|
|
30069
|
+
* release/duration — it's a pulse.
|
|
30070
|
+
*/
|
|
30071
|
+
onPressed: {
|
|
30072
|
+
data: DoorbellPressEventSchema,
|
|
30073
|
+
fromState: {
|
|
30074
|
+
field: "lastPressedAt",
|
|
30075
|
+
on: "advance"
|
|
30076
|
+
}
|
|
30077
|
+
} },
|
|
30078
|
+
status: {
|
|
30079
|
+
schema: DoorbellStatusSchema,
|
|
30080
|
+
kind: "push"
|
|
30081
|
+
},
|
|
30082
|
+
/**
|
|
30083
|
+
* Runtime-state slice — last press timestamp + lifetime press count.
|
|
30084
|
+
* Mirrored by the kernel and readable via
|
|
30085
|
+
* `device.state.doorbell.value`. UIs can show "last ring 5m ago"
|
|
30086
|
+
* without subscribing.
|
|
30087
|
+
*/
|
|
30088
|
+
runtimeState: DoorbellStatusSchema,
|
|
30089
|
+
/**
|
|
30090
|
+
* 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.
|
|
30091
|
+
*
|
|
30092
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
30093
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
30094
|
+
*/
|
|
30095
|
+
durability: "restored"
|
|
30096
|
+
};
|
|
30041
30097
|
/**
|
|
30042
30098
|
* Enum-state sensor — a string value picked from a finite option set.
|
|
30043
30099
|
* Drives HA `sensor` entries with `state_class: enum` (HVAC action
|
|
@@ -32182,9 +32238,9 @@ var MotionStatusSchema = object({
|
|
|
32182
32238
|
/** Ms epoch of the last detected-true observation. Null if never detected. */
|
|
32183
32239
|
lastDetectedAt: number().nullable(),
|
|
32184
32240
|
/**
|
|
32185
|
-
* `MOTION_CLOSE_AFTER_MS` while `detected: true` on a `Camera` device
|
|
32186
|
-
* `null` while false and on every `Sensor`
|
|
32187
|
-
* constant's doc for the one-authority rule.
|
|
32241
|
+
* `MOTION_CLOSE_AFTER_MS` while `detected: true` on a `Camera` device (the
|
|
32242
|
+
* orchestrator writes it, D696), `null` while false and on every `Sensor`
|
|
32243
|
+
* device (D475) — see that constant's doc for the one-authority rule.
|
|
32188
32244
|
*
|
|
32189
32245
|
* ## Reading this field still arms nothing
|
|
32190
32246
|
*
|
|
@@ -32202,34 +32258,31 @@ var MotionStatusSchema = object({
|
|
|
32202
32258
|
* `addon-export-alexa/src/motion-clear-hold.ts` and
|
|
32203
32259
|
* `addon-export-hap`'s `RESET_DEBOUNCE_MS` both do.
|
|
32204
32260
|
*
|
|
32205
|
-
* ## Who writes it
|
|
32206
|
-
*
|
|
32207
|
-
* - **Cameras** — the
|
|
32208
|
-
*
|
|
32209
|
-
* `
|
|
32210
|
-
* `
|
|
32211
|
-
*
|
|
32212
|
-
*
|
|
32213
|
-
* a
|
|
32214
|
-
*
|
|
32215
|
-
*
|
|
32216
|
-
*
|
|
32217
|
-
*
|
|
32218
|
-
*
|
|
32219
|
-
*
|
|
32220
|
-
*
|
|
32221
|
-
*
|
|
32222
|
-
*
|
|
32223
|
-
* `
|
|
32224
|
-
*
|
|
32225
|
-
*
|
|
32226
|
-
*
|
|
32227
|
-
*
|
|
32228
|
-
*
|
|
32229
|
-
*
|
|
32230
|
-
* This predates D475 and is not fixed there: the fix touches every
|
|
32231
|
-
* camera provider. Recorded in D475's Consequences. Do not restore the
|
|
32232
|
-
* "sole writer" wording without also removing the other writers.
|
|
32261
|
+
* ## Who writes it (D696)
|
|
32262
|
+
*
|
|
32263
|
+
* - **Cameras** — the orchestrator, and nothing else. It writes the camera's
|
|
32264
|
+
* EFFECTIVE motion (`addon-pipeline-orchestrator`
|
|
32265
|
+
* `camera-sensors/motion-slice.ts`), alongside the effective
|
|
32266
|
+
* `MotionOnMotionChanged` it emits or receives: the camera-sensors bridge
|
|
32267
|
+
* for a split camera, an unsplit emitter's direct event, the analyzer and
|
|
32268
|
+
* device activity, as the camera's `motionSources` counts them. A source
|
|
32269
|
+
* that never sends a clear falls one window after its last `true`.
|
|
32270
|
+
* `lastDetectedAt` moves only on an effective rise. No camera provider
|
|
32271
|
+
* writes this slice (not even a boot seed), and neither does the runner's
|
|
32272
|
+
* phase machine: its phase is "a session is attached" for every on-motion
|
|
32273
|
+
* session, not motion, and it now has its own `DetectionPhaseTransition`.
|
|
32274
|
+
* A provider's `isDetected` answers from the hub's slice.
|
|
32275
|
+
* - **Sensors** (Home Assistant binary sensors, Homematic, Matter, Alexa
|
|
32276
|
+
* imports) — the provider pushes both edges itself, from the upstream
|
|
32277
|
+
* system's own state change. That is the sensor's own fact.
|
|
32278
|
+
*
|
|
32279
|
+
* `scripts/check-onboard-motion-emitters.ts` refuses any other writer of a
|
|
32280
|
+
* `motion` slice; each sensor writer is a named exemption.
|
|
32281
|
+
*
|
|
32282
|
+
* This replaces the D475 §4 rule ("the phase machine is the sole writer").
|
|
32283
|
+
* That rule was never true: Hikvision and Amcrest wrote the slice raw beside
|
|
32284
|
+
* it, every provider seeded it at boot, and every session left it
|
|
32285
|
+
* `detected: true` after its detach.
|
|
32233
32286
|
*/
|
|
32234
32287
|
autoClearAfterMs: number().nullable()
|
|
32235
32288
|
});
|
|
@@ -32301,11 +32354,12 @@ onMotionChanged: { data: MotionOnMotionChangedDataSchema } },
|
|
|
32301
32354
|
*/
|
|
32302
32355
|
runtimeState: MotionStatusSchema,
|
|
32303
32356
|
/**
|
|
32304
|
-
* Runtime-state durability: **session** —
|
|
32357
|
+
* Runtime-state durability: **session** — the writer of this slice
|
|
32305
32358
|
* writes only on an EDGE, so a restored `detected: true` would stay
|
|
32306
32359
|
* frozen until the next one instead of being corrected. The next edge
|
|
32307
|
-
* re-publishes the real state
|
|
32308
|
-
*
|
|
32360
|
+
* re-publishes the real state, and the orchestrator re-publishes every
|
|
32361
|
+
* camera when it starts writing (D696; on who writes it, see
|
|
32362
|
+
* `autoClearAfterMs` above).
|
|
32309
32363
|
*
|
|
32310
32364
|
* See `RuntimeStateDurability`. Enforced by
|
|
32311
32365
|
* `scripts/check-runtime-state-durability.ts`.
|
|
@@ -34688,8 +34742,7 @@ var ptzAutotrackCapability = {
|
|
|
34688
34742
|
deviceNative: true,
|
|
34689
34743
|
mode: "singleton",
|
|
34690
34744
|
/**
|
|
34691
|
-
* Two kinds of provider behind one name, the same shape `snapshot`
|
|
34692
|
-
* `doorbell` use:
|
|
34745
|
+
* Two kinds of provider behind one name, the same shape `snapshot` uses:
|
|
34693
34746
|
*
|
|
34694
34747
|
* - **Native**: the camera's own firmware autotrack, registered per device by
|
|
34695
34748
|
* the driver when the probe says it exists (Reolink: yes; Hikvision:
|
|
@@ -34697,7 +34750,7 @@ var ptzAutotrackCapability = {
|
|
|
34697
34750
|
* - **Wrapper**: the emulated implementation (`@camstack/system`'s `autotrack` builtin),
|
|
34698
34751
|
* which follows a subject with `ptz.move` pulses driven by the detection
|
|
34699
34752
|
* pipeline. `defaultActive: false` — the operator binds it per camera in
|
|
34700
|
-
* the bindings UI
|
|
34753
|
+
* the bindings UI.
|
|
34701
34754
|
*
|
|
34702
34755
|
* The binding chooses WHICH implementation answers; `setEnabled` stays the
|
|
34703
34756
|
* one switch for the function either way. A camera never has both driving its
|
|
@@ -35372,7 +35425,7 @@ var ReadGopBytesResultSchema = object({
|
|
|
35372
35425
|
/**
|
|
35373
35426
|
* A time WINDOW of one finalized segment, cut by byte range — the multi-GOP
|
|
35374
35427
|
* twin of {@link ReadGopBytesResultSchema}'s single instant. Built for the
|
|
35375
|
-
* replay clip's `recording` source (`docs/design/plans/2026-08-26-replay-
|
|
35428
|
+
* replay clip's `recording` source (`docs/design/plans/2026-08-26-clip-replay-on-pipeline.md`):
|
|
35376
35429
|
* a replay needs several seconds of native pixels, not one frame.
|
|
35377
35430
|
*
|
|
35378
35431
|
* `ok.data` is standalone-demuxable, same as a GOP read. `ok.reachesRequestedEnd`
|
|
@@ -38736,6 +38789,7 @@ var zoneRulesCapability = {
|
|
|
38736
38789
|
*/
|
|
38737
38790
|
durability: "restored"
|
|
38738
38791
|
};
|
|
38792
|
+
SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
|
|
38739
38793
|
/**
|
|
38740
38794
|
* Accessory device helpers — shared across drivers.
|
|
38741
38795
|
*
|
|
@@ -44761,6 +44815,12 @@ Object.freeze({
|
|
|
44761
44815
|
addonId: null,
|
|
44762
44816
|
access: "view"
|
|
44763
44817
|
},
|
|
44818
|
+
"notificationRules.getAlarmSensors": {
|
|
44819
|
+
capName: "notification-rules",
|
|
44820
|
+
capScope: "system",
|
|
44821
|
+
addonId: null,
|
|
44822
|
+
access: "view"
|
|
44823
|
+
},
|
|
44764
44824
|
"notificationRules.getClipRetentionAsks": {
|
|
44765
44825
|
capName: "notification-rules",
|
|
44766
44826
|
capScope: "system",
|
|
@@ -48339,6 +48399,11 @@ Object.freeze({
|
|
|
48339
48399
|
}
|
|
48340
48400
|
});
|
|
48341
48401
|
Object.freeze({
|
|
48402
|
+
"accessories.getStatus": [{
|
|
48403
|
+
name: "deviceId",
|
|
48404
|
+
form: "single",
|
|
48405
|
+
optional: false
|
|
48406
|
+
}],
|
|
48342
48407
|
"accessories.setChildHidden": [{
|
|
48343
48408
|
name: "childDeviceId",
|
|
48344
48409
|
form: "single",
|
|
@@ -48358,6 +48423,11 @@ Object.freeze({
|
|
|
48358
48423
|
form: "single",
|
|
48359
48424
|
optional: false
|
|
48360
48425
|
}],
|
|
48426
|
+
"airQualitySensor.getStatus": [{
|
|
48427
|
+
name: "deviceId",
|
|
48428
|
+
form: "single",
|
|
48429
|
+
optional: false
|
|
48430
|
+
}],
|
|
48361
48431
|
"alarmPanel.arm": [{
|
|
48362
48432
|
name: "deviceId",
|
|
48363
48433
|
form: "single",
|
|
@@ -48368,11 +48438,36 @@ Object.freeze({
|
|
|
48368
48438
|
form: "single",
|
|
48369
48439
|
optional: false
|
|
48370
48440
|
}],
|
|
48441
|
+
"alarmPanel.getStatus": [{
|
|
48442
|
+
name: "deviceId",
|
|
48443
|
+
form: "single",
|
|
48444
|
+
optional: false
|
|
48445
|
+
}],
|
|
48371
48446
|
"alarmPanel.trigger": [{
|
|
48372
48447
|
name: "deviceId",
|
|
48373
48448
|
form: "single",
|
|
48374
48449
|
optional: false
|
|
48375
48450
|
}],
|
|
48451
|
+
"ambientLightSensor.getStatus": [{
|
|
48452
|
+
name: "deviceId",
|
|
48453
|
+
form: "single",
|
|
48454
|
+
optional: false
|
|
48455
|
+
}],
|
|
48456
|
+
"audioAnalysis.applyDeviceSettingsPatch": [{
|
|
48457
|
+
name: "deviceId",
|
|
48458
|
+
form: "single",
|
|
48459
|
+
optional: false
|
|
48460
|
+
}],
|
|
48461
|
+
"audioAnalysis.getDeviceLiveContribution": [{
|
|
48462
|
+
name: "deviceId",
|
|
48463
|
+
form: "single",
|
|
48464
|
+
optional: false
|
|
48465
|
+
}],
|
|
48466
|
+
"audioAnalysis.getDeviceSettingsContribution": [{
|
|
48467
|
+
name: "deviceId",
|
|
48468
|
+
form: "single",
|
|
48469
|
+
optional: false
|
|
48470
|
+
}],
|
|
48376
48471
|
"audioAnalysis.resolveDeviceSettings": [{
|
|
48377
48472
|
name: "deviceId",
|
|
48378
48473
|
form: "single",
|
|
@@ -48413,16 +48508,36 @@ Object.freeze({
|
|
|
48413
48508
|
form: "single",
|
|
48414
48509
|
optional: false
|
|
48415
48510
|
}],
|
|
48511
|
+
"automationControl.getStatus": [{
|
|
48512
|
+
name: "deviceId",
|
|
48513
|
+
form: "single",
|
|
48514
|
+
optional: false
|
|
48515
|
+
}],
|
|
48416
48516
|
"automationControl.trigger": [{
|
|
48417
48517
|
name: "deviceId",
|
|
48418
48518
|
form: "single",
|
|
48419
48519
|
optional: false
|
|
48420
48520
|
}],
|
|
48521
|
+
"battery.getStatus": [{
|
|
48522
|
+
name: "deviceId",
|
|
48523
|
+
form: "single",
|
|
48524
|
+
optional: false
|
|
48525
|
+
}],
|
|
48421
48526
|
"battery.wakeForStream": [{
|
|
48422
48527
|
name: "deviceId",
|
|
48423
48528
|
form: "single",
|
|
48424
48529
|
optional: false
|
|
48425
48530
|
}],
|
|
48531
|
+
"binary.getStatus": [{
|
|
48532
|
+
name: "deviceId",
|
|
48533
|
+
form: "single",
|
|
48534
|
+
optional: false
|
|
48535
|
+
}],
|
|
48536
|
+
"brightness.getStatus": [{
|
|
48537
|
+
name: "deviceId",
|
|
48538
|
+
form: "single",
|
|
48539
|
+
optional: false
|
|
48540
|
+
}],
|
|
48426
48541
|
"brightness.setBrightness": [{
|
|
48427
48542
|
name: "deviceId",
|
|
48428
48543
|
form: "single",
|
|
@@ -48438,6 +48553,26 @@ Object.freeze({
|
|
|
48438
48553
|
form: "single",
|
|
48439
48554
|
optional: false
|
|
48440
48555
|
}],
|
|
48556
|
+
"cameraCredentials.getStatus": [{
|
|
48557
|
+
name: "deviceId",
|
|
48558
|
+
form: "single",
|
|
48559
|
+
optional: false
|
|
48560
|
+
}],
|
|
48561
|
+
"cameraGridLayout.applyDeviceSettingsPatch": [{
|
|
48562
|
+
name: "deviceId",
|
|
48563
|
+
form: "single",
|
|
48564
|
+
optional: false
|
|
48565
|
+
}],
|
|
48566
|
+
"cameraGridLayout.getDeviceLiveContribution": [{
|
|
48567
|
+
name: "deviceId",
|
|
48568
|
+
form: "single",
|
|
48569
|
+
optional: false
|
|
48570
|
+
}],
|
|
48571
|
+
"cameraGridLayout.getDeviceSettingsContribution": [{
|
|
48572
|
+
name: "deviceId",
|
|
48573
|
+
form: "single",
|
|
48574
|
+
optional: false
|
|
48575
|
+
}],
|
|
48441
48576
|
"cameraGridLayout.getLayout": [{
|
|
48442
48577
|
name: "deviceId",
|
|
48443
48578
|
form: "single",
|
|
@@ -48453,6 +48588,21 @@ Object.freeze({
|
|
|
48453
48588
|
form: "single",
|
|
48454
48589
|
optional: false
|
|
48455
48590
|
}],
|
|
48591
|
+
"cameraPipelineConfig.applyDeviceSettingsPatch": [{
|
|
48592
|
+
name: "deviceId",
|
|
48593
|
+
form: "single",
|
|
48594
|
+
optional: false
|
|
48595
|
+
}],
|
|
48596
|
+
"cameraPipelineConfig.getDeviceLiveContribution": [{
|
|
48597
|
+
name: "deviceId",
|
|
48598
|
+
form: "single",
|
|
48599
|
+
optional: false
|
|
48600
|
+
}],
|
|
48601
|
+
"cameraPipelineConfig.getDeviceSettingsContribution": [{
|
|
48602
|
+
name: "deviceId",
|
|
48603
|
+
form: "single",
|
|
48604
|
+
optional: false
|
|
48605
|
+
}],
|
|
48456
48606
|
"cameraStreams.getBrokerStreams": [{
|
|
48457
48607
|
name: "deviceId",
|
|
48458
48608
|
form: "single",
|
|
@@ -48478,6 +48628,16 @@ Object.freeze({
|
|
|
48478
48628
|
form: "single",
|
|
48479
48629
|
optional: false
|
|
48480
48630
|
}],
|
|
48631
|
+
"carbonMonoxide.getStatus": [{
|
|
48632
|
+
name: "deviceId",
|
|
48633
|
+
form: "single",
|
|
48634
|
+
optional: false
|
|
48635
|
+
}],
|
|
48636
|
+
"climateControl.getStatus": [{
|
|
48637
|
+
name: "deviceId",
|
|
48638
|
+
form: "single",
|
|
48639
|
+
optional: false
|
|
48640
|
+
}],
|
|
48481
48641
|
"climateControl.setFanMode": [{
|
|
48482
48642
|
name: "deviceId",
|
|
48483
48643
|
form: "single",
|
|
@@ -48518,16 +48678,41 @@ Object.freeze({
|
|
|
48518
48678
|
form: "single",
|
|
48519
48679
|
optional: false
|
|
48520
48680
|
}],
|
|
48681
|
+
"color.getStatus": [{
|
|
48682
|
+
name: "deviceId",
|
|
48683
|
+
form: "single",
|
|
48684
|
+
optional: false
|
|
48685
|
+
}],
|
|
48521
48686
|
"color.setColor": [{
|
|
48522
48687
|
name: "deviceId",
|
|
48523
48688
|
form: "single",
|
|
48524
48689
|
optional: false
|
|
48525
48690
|
}],
|
|
48691
|
+
"connectivity.getStatus": [{
|
|
48692
|
+
name: "deviceId",
|
|
48693
|
+
form: "single",
|
|
48694
|
+
optional: false
|
|
48695
|
+
}],
|
|
48696
|
+
"consumables.getStatus": [{
|
|
48697
|
+
name: "deviceId",
|
|
48698
|
+
form: "single",
|
|
48699
|
+
optional: false
|
|
48700
|
+
}],
|
|
48526
48701
|
"consumables.reset": [{
|
|
48527
48702
|
name: "deviceId",
|
|
48528
48703
|
form: "single",
|
|
48529
48704
|
optional: false
|
|
48530
48705
|
}],
|
|
48706
|
+
"contact.getStatus": [{
|
|
48707
|
+
name: "deviceId",
|
|
48708
|
+
form: "single",
|
|
48709
|
+
optional: false
|
|
48710
|
+
}],
|
|
48711
|
+
"control.getStatus": [{
|
|
48712
|
+
name: "deviceId",
|
|
48713
|
+
form: "single",
|
|
48714
|
+
optional: false
|
|
48715
|
+
}],
|
|
48531
48716
|
"control.setValue": [{
|
|
48532
48717
|
name: "deviceId",
|
|
48533
48718
|
form: "single",
|
|
@@ -48538,6 +48723,11 @@ Object.freeze({
|
|
|
48538
48723
|
form: "single",
|
|
48539
48724
|
optional: false
|
|
48540
48725
|
}],
|
|
48726
|
+
"cover.getStatus": [{
|
|
48727
|
+
name: "deviceId",
|
|
48728
|
+
form: "single",
|
|
48729
|
+
optional: false
|
|
48730
|
+
}],
|
|
48541
48731
|
"cover.open": [{
|
|
48542
48732
|
name: "deviceId",
|
|
48543
48733
|
form: "single",
|
|
@@ -48563,6 +48753,11 @@ Object.freeze({
|
|
|
48563
48753
|
form: "single",
|
|
48564
48754
|
optional: false
|
|
48565
48755
|
}],
|
|
48756
|
+
"dayNight.getStatus": [{
|
|
48757
|
+
name: "deviceId",
|
|
48758
|
+
form: "single",
|
|
48759
|
+
optional: false
|
|
48760
|
+
}],
|
|
48566
48761
|
"dayNight.setSettings": [{
|
|
48567
48762
|
name: "deviceId",
|
|
48568
48763
|
form: "single",
|
|
@@ -48573,11 +48768,31 @@ Object.freeze({
|
|
|
48573
48768
|
form: "single",
|
|
48574
48769
|
optional: true
|
|
48575
48770
|
}],
|
|
48771
|
+
"detectionPipeline.applyDeviceSettingsPatch": [{
|
|
48772
|
+
name: "deviceId",
|
|
48773
|
+
form: "single",
|
|
48774
|
+
optional: false
|
|
48775
|
+
}],
|
|
48776
|
+
"detectionPipeline.getDeviceLiveContribution": [{
|
|
48777
|
+
name: "deviceId",
|
|
48778
|
+
form: "single",
|
|
48779
|
+
optional: false
|
|
48780
|
+
}],
|
|
48781
|
+
"detectionPipeline.getDeviceSettingsContribution": [{
|
|
48782
|
+
name: "deviceId",
|
|
48783
|
+
form: "single",
|
|
48784
|
+
optional: false
|
|
48785
|
+
}],
|
|
48576
48786
|
"deviceAdminLink.getAdminLink": [{
|
|
48577
48787
|
name: "deviceId",
|
|
48578
48788
|
form: "single",
|
|
48579
48789
|
optional: false
|
|
48580
48790
|
}],
|
|
48791
|
+
"deviceAdoption.getStatus": [{
|
|
48792
|
+
name: "deviceId",
|
|
48793
|
+
form: "single",
|
|
48794
|
+
optional: false
|
|
48795
|
+
}],
|
|
48581
48796
|
"deviceAdoption.release": [{
|
|
48582
48797
|
name: "camDeviceId",
|
|
48583
48798
|
form: "single",
|
|
@@ -48593,6 +48808,11 @@ Object.freeze({
|
|
|
48593
48808
|
form: "single",
|
|
48594
48809
|
optional: false
|
|
48595
48810
|
}],
|
|
48811
|
+
"deviceDiscovery.getStatus": [{
|
|
48812
|
+
name: "deviceId",
|
|
48813
|
+
form: "single",
|
|
48814
|
+
optional: false
|
|
48815
|
+
}],
|
|
48596
48816
|
"deviceDiscovery.listDiscovered": [{
|
|
48597
48817
|
name: "deviceId",
|
|
48598
48818
|
form: "single",
|
|
@@ -48612,6 +48832,21 @@ Object.freeze({
|
|
|
48612
48832
|
form: "single",
|
|
48613
48833
|
optional: false
|
|
48614
48834
|
}],
|
|
48835
|
+
"deviceExport.applyDeviceSettingsPatch": [{
|
|
48836
|
+
name: "deviceId",
|
|
48837
|
+
form: "single",
|
|
48838
|
+
optional: false
|
|
48839
|
+
}],
|
|
48840
|
+
"deviceExport.getDeviceLiveContribution": [{
|
|
48841
|
+
name: "deviceId",
|
|
48842
|
+
form: "single",
|
|
48843
|
+
optional: false
|
|
48844
|
+
}],
|
|
48845
|
+
"deviceExport.getDeviceSettingsContribution": [{
|
|
48846
|
+
name: "deviceId",
|
|
48847
|
+
form: "single",
|
|
48848
|
+
optional: false
|
|
48849
|
+
}],
|
|
48615
48850
|
"deviceExtension.listCandidates": [{
|
|
48616
48851
|
name: "deviceId",
|
|
48617
48852
|
form: "single",
|
|
@@ -48960,6 +49195,26 @@ Object.freeze({
|
|
|
48960
49195
|
form: "single",
|
|
48961
49196
|
optional: false
|
|
48962
49197
|
}],
|
|
49198
|
+
"deviceStatus.getStatus": [{
|
|
49199
|
+
name: "deviceId",
|
|
49200
|
+
form: "single",
|
|
49201
|
+
optional: false
|
|
49202
|
+
}],
|
|
49203
|
+
"doorbell.getStatus": [{
|
|
49204
|
+
name: "deviceId",
|
|
49205
|
+
form: "single",
|
|
49206
|
+
optional: false
|
|
49207
|
+
}],
|
|
49208
|
+
"enumSensor.getStatus": [{
|
|
49209
|
+
name: "deviceId",
|
|
49210
|
+
form: "single",
|
|
49211
|
+
optional: false
|
|
49212
|
+
}],
|
|
49213
|
+
"eventEmitter.getStatus": [{
|
|
49214
|
+
name: "deviceId",
|
|
49215
|
+
form: "single",
|
|
49216
|
+
optional: false
|
|
49217
|
+
}],
|
|
48963
49218
|
"faceGallery.getFaceByTrack": [{
|
|
48964
49219
|
name: "deviceId",
|
|
48965
49220
|
form: "single",
|
|
@@ -48974,6 +49229,11 @@ Object.freeze({
|
|
|
48974
49229
|
form: "array",
|
|
48975
49230
|
optional: true
|
|
48976
49231
|
}],
|
|
49232
|
+
"fanControl.getStatus": [{
|
|
49233
|
+
name: "deviceId",
|
|
49234
|
+
form: "single",
|
|
49235
|
+
optional: false
|
|
49236
|
+
}],
|
|
48977
49237
|
"fanControl.setDirection": [{
|
|
48978
49238
|
name: "deviceId",
|
|
48979
49239
|
form: "single",
|
|
@@ -48994,6 +49254,26 @@ Object.freeze({
|
|
|
48994
49254
|
form: "single",
|
|
48995
49255
|
optional: false
|
|
48996
49256
|
}],
|
|
49257
|
+
"featureProbe.getStatus": [{
|
|
49258
|
+
name: "deviceId",
|
|
49259
|
+
form: "single",
|
|
49260
|
+
optional: false
|
|
49261
|
+
}],
|
|
49262
|
+
"flood.getStatus": [{
|
|
49263
|
+
name: "deviceId",
|
|
49264
|
+
form: "single",
|
|
49265
|
+
optional: false
|
|
49266
|
+
}],
|
|
49267
|
+
"gas.getStatus": [{
|
|
49268
|
+
name: "deviceId",
|
|
49269
|
+
form: "single",
|
|
49270
|
+
optional: false
|
|
49271
|
+
}],
|
|
49272
|
+
"humidifier.getStatus": [{
|
|
49273
|
+
name: "deviceId",
|
|
49274
|
+
form: "single",
|
|
49275
|
+
optional: false
|
|
49276
|
+
}],
|
|
48997
49277
|
"humidifier.setMode": [{
|
|
48998
49278
|
name: "deviceId",
|
|
48999
49279
|
form: "single",
|
|
@@ -49009,11 +49289,26 @@ Object.freeze({
|
|
|
49009
49289
|
form: "single",
|
|
49010
49290
|
optional: false
|
|
49011
49291
|
}],
|
|
49292
|
+
"humiditySensor.getStatus": [{
|
|
49293
|
+
name: "deviceId",
|
|
49294
|
+
form: "single",
|
|
49295
|
+
optional: false
|
|
49296
|
+
}],
|
|
49297
|
+
"image.getStatus": [{
|
|
49298
|
+
name: "deviceId",
|
|
49299
|
+
form: "single",
|
|
49300
|
+
optional: false
|
|
49301
|
+
}],
|
|
49012
49302
|
"imageSettings.getOptions": [{
|
|
49013
49303
|
name: "deviceId",
|
|
49014
49304
|
form: "single",
|
|
49015
49305
|
optional: false
|
|
49016
49306
|
}],
|
|
49307
|
+
"imageSettings.getStatus": [{
|
|
49308
|
+
name: "deviceId",
|
|
49309
|
+
form: "single",
|
|
49310
|
+
optional: false
|
|
49311
|
+
}],
|
|
49017
49312
|
"imageSettings.setSettings": [{
|
|
49018
49313
|
name: "deviceId",
|
|
49019
49314
|
form: "single",
|
|
@@ -49024,6 +49319,11 @@ Object.freeze({
|
|
|
49024
49319
|
form: "single",
|
|
49025
49320
|
optional: false
|
|
49026
49321
|
}],
|
|
49322
|
+
"intercom.getStatus": [{
|
|
49323
|
+
name: "deviceId",
|
|
49324
|
+
form: "single",
|
|
49325
|
+
optional: false
|
|
49326
|
+
}],
|
|
49027
49327
|
"intercom.handleAnswer": [{
|
|
49028
49328
|
name: "deviceId",
|
|
49029
49329
|
form: "single",
|
|
@@ -49054,6 +49354,11 @@ Object.freeze({
|
|
|
49054
49354
|
form: "single",
|
|
49055
49355
|
optional: false
|
|
49056
49356
|
}],
|
|
49357
|
+
"lawnMowerControl.getStatus": [{
|
|
49358
|
+
name: "deviceId",
|
|
49359
|
+
form: "single",
|
|
49360
|
+
optional: false
|
|
49361
|
+
}],
|
|
49057
49362
|
"lawnMowerControl.pause": [{
|
|
49058
49363
|
name: "deviceId",
|
|
49059
49364
|
form: "single",
|
|
@@ -49064,6 +49369,11 @@ Object.freeze({
|
|
|
49064
49369
|
form: "single",
|
|
49065
49370
|
optional: false
|
|
49066
49371
|
}],
|
|
49372
|
+
"lockControl.getStatus": [{
|
|
49373
|
+
name: "deviceId",
|
|
49374
|
+
form: "single",
|
|
49375
|
+
optional: false
|
|
49376
|
+
}],
|
|
49067
49377
|
"lockControl.lock": [{
|
|
49068
49378
|
name: "deviceId",
|
|
49069
49379
|
form: "single",
|
|
@@ -49079,6 +49389,11 @@ Object.freeze({
|
|
|
49079
49389
|
form: "single",
|
|
49080
49390
|
optional: false
|
|
49081
49391
|
}],
|
|
49392
|
+
"mediaPlayer.getStatus": [{
|
|
49393
|
+
name: "deviceId",
|
|
49394
|
+
form: "single",
|
|
49395
|
+
optional: false
|
|
49396
|
+
}],
|
|
49082
49397
|
"mediaPlayer.next": [{
|
|
49083
49398
|
name: "deviceId",
|
|
49084
49399
|
form: "single",
|
|
@@ -49139,6 +49454,11 @@ Object.freeze({
|
|
|
49139
49454
|
form: "single",
|
|
49140
49455
|
optional: false
|
|
49141
49456
|
}],
|
|
49457
|
+
"motion.getStatus": [{
|
|
49458
|
+
name: "deviceId",
|
|
49459
|
+
form: "single",
|
|
49460
|
+
optional: false
|
|
49461
|
+
}],
|
|
49142
49462
|
"motion.isDetected": [{
|
|
49143
49463
|
name: "deviceId",
|
|
49144
49464
|
form: "single",
|
|
@@ -49149,11 +49469,31 @@ Object.freeze({
|
|
|
49149
49469
|
form: "single",
|
|
49150
49470
|
optional: false
|
|
49151
49471
|
}],
|
|
49472
|
+
"motionDetection.applyDeviceSettingsPatch": [{
|
|
49473
|
+
name: "deviceId",
|
|
49474
|
+
form: "single",
|
|
49475
|
+
optional: false
|
|
49476
|
+
}],
|
|
49477
|
+
"motionDetection.getDeviceLiveContribution": [{
|
|
49478
|
+
name: "deviceId",
|
|
49479
|
+
form: "single",
|
|
49480
|
+
optional: false
|
|
49481
|
+
}],
|
|
49482
|
+
"motionDetection.getDeviceSettingsContribution": [{
|
|
49483
|
+
name: "deviceId",
|
|
49484
|
+
form: "single",
|
|
49485
|
+
optional: false
|
|
49486
|
+
}],
|
|
49152
49487
|
"motionDetection.removeCamera": [{
|
|
49153
49488
|
name: "deviceId",
|
|
49154
49489
|
form: "single",
|
|
49155
49490
|
optional: false
|
|
49156
49491
|
}],
|
|
49492
|
+
"motionTrigger.getStatus": [{
|
|
49493
|
+
name: "deviceId",
|
|
49494
|
+
form: "single",
|
|
49495
|
+
optional: false
|
|
49496
|
+
}],
|
|
49157
49497
|
"motionTrigger.setMotionTrigger": [{
|
|
49158
49498
|
name: "deviceId",
|
|
49159
49499
|
form: "single",
|
|
@@ -49164,6 +49504,11 @@ Object.freeze({
|
|
|
49164
49504
|
form: "single",
|
|
49165
49505
|
optional: false
|
|
49166
49506
|
}],
|
|
49507
|
+
"motionZones.getStatus": [{
|
|
49508
|
+
name: "deviceId",
|
|
49509
|
+
form: "single",
|
|
49510
|
+
optional: false
|
|
49511
|
+
}],
|
|
49167
49512
|
"motionZones.setZone": [{
|
|
49168
49513
|
name: "deviceId",
|
|
49169
49514
|
form: "single",
|
|
@@ -49174,6 +49519,11 @@ Object.freeze({
|
|
|
49174
49519
|
form: "single",
|
|
49175
49520
|
optional: false
|
|
49176
49521
|
}],
|
|
49522
|
+
"nativeObjectDetection.getStatus": [{
|
|
49523
|
+
name: "deviceId",
|
|
49524
|
+
form: "single",
|
|
49525
|
+
optional: false
|
|
49526
|
+
}],
|
|
49177
49527
|
"nativeObjectDetection.setEnabled": [{
|
|
49178
49528
|
name: "deviceId",
|
|
49179
49529
|
form: "single",
|
|
@@ -49189,6 +49539,11 @@ Object.freeze({
|
|
|
49189
49539
|
form: "single",
|
|
49190
49540
|
optional: false
|
|
49191
49541
|
}],
|
|
49542
|
+
"navigation.getStatus": [{
|
|
49543
|
+
name: "deviceId",
|
|
49544
|
+
form: "single",
|
|
49545
|
+
optional: false
|
|
49546
|
+
}],
|
|
49192
49547
|
"navigation.goToPoint": [{
|
|
49193
49548
|
name: "deviceId",
|
|
49194
49549
|
form: "single",
|
|
@@ -49234,6 +49589,11 @@ Object.freeze({
|
|
|
49234
49589
|
form: "single",
|
|
49235
49590
|
optional: false
|
|
49236
49591
|
}],
|
|
49592
|
+
"networkLink.getStatus": [{
|
|
49593
|
+
name: "deviceId",
|
|
49594
|
+
form: "single",
|
|
49595
|
+
optional: false
|
|
49596
|
+
}],
|
|
49237
49597
|
"networkQuality.getDeviceStats": [{
|
|
49238
49598
|
name: "deviceId",
|
|
49239
49599
|
form: "single",
|
|
@@ -49244,6 +49604,11 @@ Object.freeze({
|
|
|
49244
49604
|
form: "single",
|
|
49245
49605
|
optional: false
|
|
49246
49606
|
}],
|
|
49607
|
+
"notificationRules.getAlarmSensors": [{
|
|
49608
|
+
name: "deviceIds",
|
|
49609
|
+
form: "array",
|
|
49610
|
+
optional: false
|
|
49611
|
+
}],
|
|
49247
49612
|
"notificationRules.setDeviceMuted": [{
|
|
49248
49613
|
name: "deviceId",
|
|
49249
49614
|
form: "single",
|
|
@@ -49254,11 +49619,26 @@ Object.freeze({
|
|
|
49254
49619
|
form: "single",
|
|
49255
49620
|
optional: false
|
|
49256
49621
|
}],
|
|
49622
|
+
"notifier.getStatus": [{
|
|
49623
|
+
name: "deviceId",
|
|
49624
|
+
form: "single",
|
|
49625
|
+
optional: false
|
|
49626
|
+
}],
|
|
49257
49627
|
"notifier.send": [{
|
|
49258
49628
|
name: "deviceId",
|
|
49259
49629
|
form: "single",
|
|
49260
49630
|
optional: false
|
|
49261
49631
|
}],
|
|
49632
|
+
"numericSensor.getStatus": [{
|
|
49633
|
+
name: "deviceId",
|
|
49634
|
+
form: "single",
|
|
49635
|
+
optional: false
|
|
49636
|
+
}],
|
|
49637
|
+
"osd.getStatus": [{
|
|
49638
|
+
name: "deviceId",
|
|
49639
|
+
form: "single",
|
|
49640
|
+
optional: false
|
|
49641
|
+
}],
|
|
49262
49642
|
"osd.setOverlay": [{
|
|
49263
49643
|
name: "deviceId",
|
|
49264
49644
|
form: "single",
|
|
@@ -49318,6 +49698,11 @@ Object.freeze({
|
|
|
49318
49698
|
form: "single",
|
|
49319
49699
|
optional: false
|
|
49320
49700
|
}],
|
|
49701
|
+
"petFeeder.getStatus": [{
|
|
49702
|
+
name: "deviceId",
|
|
49703
|
+
form: "single",
|
|
49704
|
+
optional: false
|
|
49705
|
+
}],
|
|
49321
49706
|
"petFeeder.markFoodReplenished": [{
|
|
49322
49707
|
name: "deviceId",
|
|
49323
49708
|
form: "single",
|
|
@@ -49353,6 +49738,11 @@ Object.freeze({
|
|
|
49353
49738
|
form: "single",
|
|
49354
49739
|
optional: false
|
|
49355
49740
|
}],
|
|
49741
|
+
"pipelineAnalytics.applyDeviceSettingsPatch": [{
|
|
49742
|
+
name: "deviceId",
|
|
49743
|
+
form: "single",
|
|
49744
|
+
optional: false
|
|
49745
|
+
}],
|
|
49356
49746
|
"pipelineAnalytics.clearTrackRelation": [{
|
|
49357
49747
|
name: "deviceId",
|
|
49358
49748
|
form: "single",
|
|
@@ -49393,6 +49783,16 @@ Object.freeze({
|
|
|
49393
49783
|
form: "single",
|
|
49394
49784
|
optional: false
|
|
49395
49785
|
}],
|
|
49786
|
+
"pipelineAnalytics.getDeviceLiveContribution": [{
|
|
49787
|
+
name: "deviceId",
|
|
49788
|
+
form: "single",
|
|
49789
|
+
optional: false
|
|
49790
|
+
}],
|
|
49791
|
+
"pipelineAnalytics.getDeviceSettingsContribution": [{
|
|
49792
|
+
name: "deviceId",
|
|
49793
|
+
form: "single",
|
|
49794
|
+
optional: false
|
|
49795
|
+
}],
|
|
49396
49796
|
"pipelineAnalytics.getEventDensity": [{
|
|
49397
49797
|
name: "deviceId",
|
|
49398
49798
|
form: "single",
|
|
@@ -49608,6 +50008,11 @@ Object.freeze({
|
|
|
49608
50008
|
form: "single",
|
|
49609
50009
|
optional: true
|
|
49610
50010
|
}],
|
|
50011
|
+
"pipelineOrchestrator.applyDeviceSettingsPatch": [{
|
|
50012
|
+
name: "deviceId",
|
|
50013
|
+
form: "single",
|
|
50014
|
+
optional: false
|
|
50015
|
+
}],
|
|
49611
50016
|
"pipelineOrchestrator.assignAudio": [{
|
|
49612
50017
|
name: "deviceId",
|
|
49613
50018
|
form: "single",
|
|
@@ -49653,6 +50058,16 @@ Object.freeze({
|
|
|
49653
50058
|
form: "single",
|
|
49654
50059
|
optional: false
|
|
49655
50060
|
}],
|
|
50061
|
+
"pipelineOrchestrator.getDeviceLiveContribution": [{
|
|
50062
|
+
name: "deviceId",
|
|
50063
|
+
form: "single",
|
|
50064
|
+
optional: false
|
|
50065
|
+
}],
|
|
50066
|
+
"pipelineOrchestrator.getDeviceSettingsContribution": [{
|
|
50067
|
+
name: "deviceId",
|
|
50068
|
+
form: "single",
|
|
50069
|
+
optional: false
|
|
50070
|
+
}],
|
|
49656
50071
|
"pipelineOrchestrator.getPipelineAssignment": [{
|
|
49657
50072
|
name: "deviceId",
|
|
49658
50073
|
form: "single",
|
|
@@ -49773,11 +50188,31 @@ Object.freeze({
|
|
|
49773
50188
|
form: "single",
|
|
49774
50189
|
optional: true
|
|
49775
50190
|
}],
|
|
50191
|
+
"powerMeter.getStatus": [{
|
|
50192
|
+
name: "deviceId",
|
|
50193
|
+
form: "single",
|
|
50194
|
+
optional: false
|
|
50195
|
+
}],
|
|
50196
|
+
"presence.getStatus": [{
|
|
50197
|
+
name: "deviceId",
|
|
50198
|
+
form: "single",
|
|
50199
|
+
optional: false
|
|
50200
|
+
}],
|
|
50201
|
+
"pressureSensor.getStatus": [{
|
|
50202
|
+
name: "deviceId",
|
|
50203
|
+
form: "single",
|
|
50204
|
+
optional: false
|
|
50205
|
+
}],
|
|
49776
50206
|
"privacyMask.getOptions": [{
|
|
49777
50207
|
name: "deviceId",
|
|
49778
50208
|
form: "single",
|
|
49779
50209
|
optional: false
|
|
49780
50210
|
}],
|
|
50211
|
+
"privacyMask.getStatus": [{
|
|
50212
|
+
name: "deviceId",
|
|
50213
|
+
form: "single",
|
|
50214
|
+
optional: false
|
|
50215
|
+
}],
|
|
49781
50216
|
"privacyMask.setAudioEnabled": [{
|
|
49782
50217
|
name: "deviceId",
|
|
49783
50218
|
form: "single",
|
|
@@ -49828,6 +50263,11 @@ Object.freeze({
|
|
|
49828
50263
|
form: "single",
|
|
49829
50264
|
optional: false
|
|
49830
50265
|
}],
|
|
50266
|
+
"ptz.getStatus": [{
|
|
50267
|
+
name: "deviceId",
|
|
50268
|
+
form: "single",
|
|
50269
|
+
optional: false
|
|
50270
|
+
}],
|
|
49831
50271
|
"ptz.goHome": [{
|
|
49832
50272
|
name: "deviceId",
|
|
49833
50273
|
form: "single",
|
|
@@ -49918,6 +50358,11 @@ Object.freeze({
|
|
|
49918
50358
|
form: "single",
|
|
49919
50359
|
optional: false
|
|
49920
50360
|
}],
|
|
50361
|
+
"recordingArchive.applyDeviceSettingsPatch": [{
|
|
50362
|
+
name: "deviceId",
|
|
50363
|
+
form: "single",
|
|
50364
|
+
optional: false
|
|
50365
|
+
}],
|
|
49921
50366
|
"recordingArchive.deleteFootprint": [{
|
|
49922
50367
|
name: "deviceId",
|
|
49923
50368
|
form: "single",
|
|
@@ -49938,6 +50383,21 @@ Object.freeze({
|
|
|
49938
50383
|
form: "single",
|
|
49939
50384
|
optional: false
|
|
49940
50385
|
}],
|
|
50386
|
+
"recordingArchive.getDeviceLiveContribution": [{
|
|
50387
|
+
name: "deviceId",
|
|
50388
|
+
form: "single",
|
|
50389
|
+
optional: false
|
|
50390
|
+
}],
|
|
50391
|
+
"recordingArchive.getDeviceSettingsContribution": [{
|
|
50392
|
+
name: "deviceId",
|
|
50393
|
+
form: "single",
|
|
50394
|
+
optional: false
|
|
50395
|
+
}],
|
|
50396
|
+
"recordingArchive.getStatus": [{
|
|
50397
|
+
name: "deviceId",
|
|
50398
|
+
form: "single",
|
|
50399
|
+
optional: false
|
|
50400
|
+
}],
|
|
49941
50401
|
"recordingArchive.listOpsLog": [{
|
|
49942
50402
|
name: "deviceId",
|
|
49943
50403
|
form: "single",
|
|
@@ -50023,6 +50483,11 @@ Object.freeze({
|
|
|
50023
50483
|
form: "single",
|
|
50024
50484
|
optional: false
|
|
50025
50485
|
}],
|
|
50486
|
+
"recordingOnboard.getStatus": [{
|
|
50487
|
+
name: "deviceId",
|
|
50488
|
+
form: "single",
|
|
50489
|
+
optional: false
|
|
50490
|
+
}],
|
|
50026
50491
|
"recordingOnboard.setSettings": [{
|
|
50027
50492
|
name: "deviceId",
|
|
50028
50493
|
form: "single",
|
|
@@ -50053,6 +50518,11 @@ Object.freeze({
|
|
|
50053
50518
|
form: "single",
|
|
50054
50519
|
optional: false
|
|
50055
50520
|
}],
|
|
50521
|
+
"sceneMonitor.getStatus": [{
|
|
50522
|
+
name: "deviceId",
|
|
50523
|
+
form: "single",
|
|
50524
|
+
optional: false
|
|
50525
|
+
}],
|
|
50056
50526
|
"sceneMonitor.listScenes": [{
|
|
50057
50527
|
name: "deviceId",
|
|
50058
50528
|
form: "single",
|
|
@@ -50078,6 +50548,11 @@ Object.freeze({
|
|
|
50078
50548
|
form: "single",
|
|
50079
50549
|
optional: false
|
|
50080
50550
|
}],
|
|
50551
|
+
"scriptRunner.getStatus": [{
|
|
50552
|
+
name: "deviceId",
|
|
50553
|
+
form: "single",
|
|
50554
|
+
optional: false
|
|
50555
|
+
}],
|
|
50081
50556
|
"scriptRunner.run": [{
|
|
50082
50557
|
name: "deviceId",
|
|
50083
50558
|
form: "single",
|
|
@@ -50088,11 +50563,31 @@ Object.freeze({
|
|
|
50088
50563
|
form: "single",
|
|
50089
50564
|
optional: false
|
|
50090
50565
|
}],
|
|
50566
|
+
"smoke.getStatus": [{
|
|
50567
|
+
name: "deviceId",
|
|
50568
|
+
form: "single",
|
|
50569
|
+
optional: false
|
|
50570
|
+
}],
|
|
50571
|
+
"snapshot.applyDeviceSettingsPatch": [{
|
|
50572
|
+
name: "deviceId",
|
|
50573
|
+
form: "single",
|
|
50574
|
+
optional: false
|
|
50575
|
+
}],
|
|
50091
50576
|
"snapshot.getDebugState": [{
|
|
50092
50577
|
name: "deviceId",
|
|
50093
50578
|
form: "single",
|
|
50094
50579
|
optional: false
|
|
50095
50580
|
}],
|
|
50581
|
+
"snapshot.getDeviceLiveContribution": [{
|
|
50582
|
+
name: "deviceId",
|
|
50583
|
+
form: "single",
|
|
50584
|
+
optional: false
|
|
50585
|
+
}],
|
|
50586
|
+
"snapshot.getDeviceSettingsContribution": [{
|
|
50587
|
+
name: "deviceId",
|
|
50588
|
+
form: "single",
|
|
50589
|
+
optional: false
|
|
50590
|
+
}],
|
|
50096
50591
|
"snapshot.getSnapshot": [{
|
|
50097
50592
|
name: "deviceId",
|
|
50098
50593
|
form: "single",
|
|
@@ -50109,6 +50604,11 @@ Object.freeze({
|
|
|
50109
50604
|
form: "array",
|
|
50110
50605
|
optional: false
|
|
50111
50606
|
}],
|
|
50607
|
+
"snapshot.getStatus": [{
|
|
50608
|
+
name: "deviceId",
|
|
50609
|
+
form: "single",
|
|
50610
|
+
optional: false
|
|
50611
|
+
}],
|
|
50112
50612
|
"snapshot.invalidateCache": [{
|
|
50113
50613
|
name: "deviceId",
|
|
50114
50614
|
form: "single",
|
|
@@ -50119,6 +50619,11 @@ Object.freeze({
|
|
|
50119
50619
|
form: "single",
|
|
50120
50620
|
optional: false
|
|
50121
50621
|
}],
|
|
50622
|
+
"streamBroker.applyDeviceSettingsPatch": [{
|
|
50623
|
+
name: "deviceId",
|
|
50624
|
+
form: "single",
|
|
50625
|
+
optional: false
|
|
50626
|
+
}],
|
|
50122
50627
|
"streamBroker.assignProfile": [{
|
|
50123
50628
|
name: "deviceId",
|
|
50124
50629
|
form: "single",
|
|
@@ -50134,6 +50639,16 @@ Object.freeze({
|
|
|
50134
50639
|
form: "single",
|
|
50135
50640
|
optional: false
|
|
50136
50641
|
}],
|
|
50642
|
+
"streamBroker.getDeviceLiveContribution": [{
|
|
50643
|
+
name: "deviceId",
|
|
50644
|
+
form: "single",
|
|
50645
|
+
optional: false
|
|
50646
|
+
}],
|
|
50647
|
+
"streamBroker.getDeviceSettingsContribution": [{
|
|
50648
|
+
name: "deviceId",
|
|
50649
|
+
form: "single",
|
|
50650
|
+
optional: false
|
|
50651
|
+
}],
|
|
50137
50652
|
"streamBroker.getStreamWithCodec": [{
|
|
50138
50653
|
name: "deviceId",
|
|
50139
50654
|
form: "single",
|
|
@@ -50194,16 +50709,46 @@ Object.freeze({
|
|
|
50194
50709
|
form: "single",
|
|
50195
50710
|
optional: false
|
|
50196
50711
|
}],
|
|
50712
|
+
"streamParams.getStatus": [{
|
|
50713
|
+
name: "deviceId",
|
|
50714
|
+
form: "single",
|
|
50715
|
+
optional: false
|
|
50716
|
+
}],
|
|
50197
50717
|
"streamParams.setProfile": [{
|
|
50198
50718
|
name: "deviceId",
|
|
50199
50719
|
form: "single",
|
|
50200
50720
|
optional: false
|
|
50201
50721
|
}],
|
|
50722
|
+
"switch.getStatus": [{
|
|
50723
|
+
name: "deviceId",
|
|
50724
|
+
form: "single",
|
|
50725
|
+
optional: false
|
|
50726
|
+
}],
|
|
50202
50727
|
"switch.setState": [{
|
|
50203
50728
|
name: "deviceId",
|
|
50204
50729
|
form: "single",
|
|
50205
50730
|
optional: false
|
|
50206
50731
|
}],
|
|
50732
|
+
"tamper.getStatus": [{
|
|
50733
|
+
name: "deviceId",
|
|
50734
|
+
form: "single",
|
|
50735
|
+
optional: false
|
|
50736
|
+
}],
|
|
50737
|
+
"temperatureSensor.getStatus": [{
|
|
50738
|
+
name: "deviceId",
|
|
50739
|
+
form: "single",
|
|
50740
|
+
optional: false
|
|
50741
|
+
}],
|
|
50742
|
+
"update.getStatus": [{
|
|
50743
|
+
name: "deviceId",
|
|
50744
|
+
form: "single",
|
|
50745
|
+
optional: false
|
|
50746
|
+
}],
|
|
50747
|
+
"vacuumControl.getStatus": [{
|
|
50748
|
+
name: "deviceId",
|
|
50749
|
+
form: "single",
|
|
50750
|
+
optional: false
|
|
50751
|
+
}],
|
|
50207
50752
|
"vacuumControl.locate": [{
|
|
50208
50753
|
name: "deviceId",
|
|
50209
50754
|
form: "single",
|
|
@@ -50239,6 +50784,11 @@ Object.freeze({
|
|
|
50239
50784
|
form: "single",
|
|
50240
50785
|
optional: false
|
|
50241
50786
|
}],
|
|
50787
|
+
"valve.getStatus": [{
|
|
50788
|
+
name: "deviceId",
|
|
50789
|
+
form: "single",
|
|
50790
|
+
optional: false
|
|
50791
|
+
}],
|
|
50242
50792
|
"valve.open": [{
|
|
50243
50793
|
name: "deviceId",
|
|
50244
50794
|
form: "single",
|
|
@@ -50254,6 +50804,11 @@ Object.freeze({
|
|
|
50254
50804
|
form: "single",
|
|
50255
50805
|
optional: false
|
|
50256
50806
|
}],
|
|
50807
|
+
"vibration.getStatus": [{
|
|
50808
|
+
name: "deviceId",
|
|
50809
|
+
form: "single",
|
|
50810
|
+
optional: false
|
|
50811
|
+
}],
|
|
50257
50812
|
"videoclips.dialClipStream": [{
|
|
50258
50813
|
name: "deviceId",
|
|
50259
50814
|
form: "single",
|
|
@@ -50289,6 +50844,11 @@ Object.freeze({
|
|
|
50289
50844
|
form: "single",
|
|
50290
50845
|
optional: false
|
|
50291
50846
|
}],
|
|
50847
|
+
"waterHeater.getStatus": [{
|
|
50848
|
+
name: "deviceId",
|
|
50849
|
+
form: "single",
|
|
50850
|
+
optional: false
|
|
50851
|
+
}],
|
|
50292
50852
|
"waterHeater.setAway": [{
|
|
50293
50853
|
name: "deviceId",
|
|
50294
50854
|
form: "single",
|
|
@@ -50304,6 +50864,11 @@ Object.freeze({
|
|
|
50304
50864
|
form: "single",
|
|
50305
50865
|
optional: false
|
|
50306
50866
|
}],
|
|
50867
|
+
"weather.getStatus": [{
|
|
50868
|
+
name: "deviceId",
|
|
50869
|
+
form: "single",
|
|
50870
|
+
optional: false
|
|
50871
|
+
}],
|
|
50307
50872
|
"webrtcSession.addIceCandidate": [{
|
|
50308
50873
|
name: "deviceId",
|
|
50309
50874
|
form: "single",
|
|
@@ -51041,7 +51606,7 @@ var PreviewTextField = string().max(200);
|
|
|
51041
51606
|
* Whether the notification's preview is a STILL or a short animation.
|
|
51042
51607
|
*
|
|
51043
51608
|
* The operator's ask, verbatim: *"inviato come gif o video (come per le altre
|
|
51044
|
-
* rule)"* — the other rules already offer an animated preview, and a ten-hour
|
|
51609
|
+
* rule)"* [sent as a gif or video (as for the other rules)] — the other rules already offer an animated preview, and a ten-hour
|
|
51045
51610
|
* night reads better as three seconds of motion than as one frame of it. Both
|
|
51046
51611
|
* modes get the SAME treatment (blurred frame, large centred title); `'gif'`
|
|
51047
51612
|
* simply applies it to a dozen frames sampled across the render and assembles
|
|
@@ -51179,6 +51744,7 @@ TimelapseRuleInputSchema.extend({
|
|
|
51179
51744
|
createdAt: number(),
|
|
51180
51745
|
updatedAt: number()
|
|
51181
51746
|
});
|
|
51747
|
+
MotionOnMotionChangedDataSchema.omit({ triggeredBy: true });
|
|
51182
51748
|
object({
|
|
51183
51749
|
/**
|
|
51184
51750
|
* Fraction of the box's own size added on EACH side before cutting.
|