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