@camstack/addon-provider-tuya 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
|
@@ -818,7 +818,7 @@ async function discoverDevices(options = {}, binder = createDgramBinder()) {
|
|
|
818
818
|
return [...byId.values()];
|
|
819
819
|
}
|
|
820
820
|
//#endregion
|
|
821
|
-
//#region ../types/dist/event-category-
|
|
821
|
+
//#region ../types/dist/event-category-BGmz_oxW.mjs
|
|
822
822
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
823
823
|
EventCategory["SystemBoot"] = "system.boot";
|
|
824
824
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -1351,6 +1351,15 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
1351
1351
|
*/
|
|
1352
1352
|
EventCategory["PipelineAudioInferenceResult"] = "pipeline.audio-inference-result";
|
|
1353
1353
|
EventCategory["DetectionPhaseTransition"] = "detection.phase-transition";
|
|
1354
|
+
/**
|
|
1355
|
+
* A camera provider's RAW onboard motion push (D673): the `MotionOnMotionChanged`
|
|
1356
|
+
* data shape without `triggeredBy`, built by `providerMotionEvent`. Its one
|
|
1357
|
+
* consumer is the orchestrator's camera-sensors bridge, which re-emits the
|
|
1358
|
+
* camera's EFFECTIVE onboard motion as `MotionOnMotionChanged` (a pass-through
|
|
1359
|
+
* for a camera with no attached sensor). Providers must not emit
|
|
1360
|
+
* `MotionOnMotionChanged` themselves; `scripts/check-onboard-motion-emitters.ts`
|
|
1361
|
+
* keeps it so (camera-grid is a named, deferred exception).
|
|
1362
|
+
*/
|
|
1354
1363
|
EventCategory["ProviderMotion"] = "provider.motion";
|
|
1355
1364
|
EventCategory["ProviderDetection"] = "provider.detection";
|
|
1356
1365
|
EventCategory["EnrichmentEmbeddingStored"] = "enrichment.embedding.stored";
|
|
@@ -6189,7 +6198,7 @@ var ZodIssueCode = {
|
|
|
6189
6198
|
var ZodFirstPartyTypeKind;
|
|
6190
6199
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
6191
6200
|
//#endregion
|
|
6192
|
-
//#region ../types/dist/sleep-
|
|
6201
|
+
//#region ../types/dist/sleep-CDCONfkt.mjs
|
|
6193
6202
|
/**
|
|
6194
6203
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
6195
6204
|
* window to float samples (D455).
|
|
@@ -8232,7 +8241,7 @@ function errMsg(err) {
|
|
|
8232
8241
|
return String(err);
|
|
8233
8242
|
}
|
|
8234
8243
|
//#endregion
|
|
8235
|
-
//#region ../types/dist/composition-
|
|
8244
|
+
//#region ../types/dist/composition-Bzr7GwgP.mjs
|
|
8236
8245
|
/**
|
|
8237
8246
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
8238
8247
|
*
|
|
@@ -8286,21 +8295,20 @@ function portable(target) {
|
|
|
8286
8295
|
}
|
|
8287
8296
|
portable("linux64"), portable("linuxarm64"), portable("macarm64"), portable("mac64");
|
|
8288
8297
|
/**
|
|
8289
|
-
*
|
|
8290
|
-
*
|
|
8298
|
+
* THE table "which boolean of this device type counts as HIGH", and the
|
|
8299
|
+
* pure evaluator of its EDGE.
|
|
8291
8300
|
*
|
|
8292
|
-
*
|
|
8293
|
-
*
|
|
8294
|
-
*
|
|
8295
|
-
*
|
|
8296
|
-
*
|
|
8297
|
-
*
|
|
8298
|
-
* SPOSTA qui e il doorbell la ri-esporta.
|
|
8301
|
+
* ONE table for everyone who asks "is this device HIGH?": the
|
|
8302
|
+
* recorder's `RecordingTriggers.sensorDeviceIds` trigger, the post-analysis
|
|
8303
|
+
* sensor markers, the orchestrator's camera-sensors bridge and
|
|
8304
|
+
* the sources of a composite doorbell (`doorbellFeatureSources`, D671).
|
|
8305
|
+
* A second copy would diverge at the first cap added, and the symptom — "the
|
|
8306
|
+
* sensor rings the doorbell but does not record" — is exactly D62.
|
|
8299
8307
|
*
|
|
8300
|
-
* ⚠
|
|
8301
|
-
*
|
|
8302
|
-
*
|
|
8303
|
-
*
|
|
8308
|
+
* ⚠ NOT `DEVICE_STATE_READERS` (`catalogs/device-state-vocabulary.ts`), and the
|
|
8309
|
+
* two must not be unified: that one answers "what is the state WORD for a
|
|
8310
|
+
* rule" (and includes `presence`, `cover`, `alarm-panel`), this one "which
|
|
8311
|
+
* boolean's EDGE counts". Deliberately different vocabularies.
|
|
8304
8312
|
*/
|
|
8305
8313
|
/**
|
|
8306
8314
|
* Known binary / switch source caps → the boolean slice field whose
|
|
@@ -9909,22 +9917,22 @@ var CLASS_MAP_MACRO_TARGETS = [
|
|
|
9909
9917
|
"package"
|
|
9910
9918
|
];
|
|
9911
9919
|
/**
|
|
9912
|
-
*
|
|
9913
|
-
*
|
|
9920
|
+
* The FIRST-LEVEL macro classes: those an object detector emits and that
|
|
9921
|
+
* an operator can select.
|
|
9914
9922
|
*
|
|
9915
|
-
*
|
|
9923
|
+
* They are the three offered by the `object-detection` step
|
|
9916
9924
|
* (`addon-pipeline/src/detection-pipeline/registry/step-definitions.ts`,
|
|
9917
|
-
* `enabledMacroClasses`). `package`
|
|
9918
|
-
* `MACRO_LABELS` —
|
|
9919
|
-
* `package-detection`,
|
|
9920
|
-
*
|
|
9925
|
+
* `enabledMacroClasses`). `package` is in {@link CLASS_MAP_MACRO_TARGETS} and in
|
|
9926
|
+
* `MACRO_LABELS` — it is a true macro — but NOT here: it belongs to the step
|
|
9927
|
+
* `package-detection`, whose enablement is driven by zones, and offering the
|
|
9928
|
+
* same word twice has already made an operator turn on the COCO proxy
|
|
9921
9929
|
* (suitcase/backpack/handbag) lasciando spento il detector dedicato.
|
|
9922
9930
|
*
|
|
9923
|
-
*
|
|
9924
|
-
*
|
|
9925
|
-
* (`types/detection.ts`);
|
|
9926
|
-
* (`RecordingTriggers.objectClasses`)
|
|
9927
|
-
*
|
|
9931
|
+
* ONE list. Before today the same three were hand-written in the step's offer
|
|
9932
|
+
* and a second time as the union `FirstLevelMacro`
|
|
9933
|
+
* (`types/detection.ts`); a third copy for the recording trigger
|
|
9934
|
+
* (`RecordingTriggers.objectClasses`) would have made the later divergence
|
|
9935
|
+
* invisible.
|
|
9928
9936
|
*/
|
|
9929
9937
|
var FIRST_LEVEL_MACRO_CLASSES = [
|
|
9930
9938
|
"person",
|
|
@@ -9989,17 +9997,17 @@ var RecordingStorageModeSchema = _enum([
|
|
|
9989
9997
|
"on-device-decision"
|
|
9990
9998
|
]);
|
|
9991
9999
|
/**
|
|
9992
|
-
*
|
|
9993
|
-
*
|
|
10000
|
+
* The macro classes that can open a recording window — the same
|
|
10001
|
+
* three offered by the `object-detection` step, from ONE list
|
|
9994
10002
|
* ({@link FIRST_LEVEL_MACRO_CLASSES}).
|
|
9995
10003
|
*/
|
|
9996
10004
|
var RecordingObjectTriggerClassSchema = _enum(FIRST_LEVEL_MACRO_CLASSES);
|
|
9997
10005
|
/**
|
|
9998
|
-
* True
|
|
10006
|
+
* True when `values` does not repeat an element.
|
|
9999
10007
|
*
|
|
10000
|
-
*
|
|
10001
|
-
*
|
|
10002
|
-
*
|
|
10008
|
+
* A duplicate is not harmless: every entry of `objectClasses` / `sensorDeviceIds`
|
|
10009
|
+
* becomes a SOURCE in `bandTriggerSources`, and the same source twice
|
|
10010
|
+
* would count its windows twice in `segmentMissedByMs`.
|
|
10003
10011
|
*/
|
|
10004
10012
|
var noDuplicates = (values) => new Set(values).size === values.length;
|
|
10005
10013
|
/** Which detectors trigger an `events`-mode band. */
|
|
@@ -10007,34 +10015,34 @@ var RecordingTriggersSchema = object({
|
|
|
10007
10015
|
motion: boolean().optional(),
|
|
10008
10016
|
audioThresholdDbfs: number().optional(),
|
|
10009
10017
|
/**
|
|
10010
|
-
*
|
|
10011
|
-
*
|
|
10012
|
-
*
|
|
10013
|
-
*
|
|
10018
|
+
* The macro classes whose detection opens a window. ABSENT = the source
|
|
10019
|
+
* is not listened to; an EMPTY array is rejected, because "events band, object
|
|
10020
|
+
* trigger on, no class" is the same shape "enabled and records
|
|
10021
|
+
* nothing, forever" that `eventsBandCanEverDemand` is written against.
|
|
10014
10022
|
*
|
|
10015
|
-
*
|
|
10016
|
-
*
|
|
10017
|
-
* `minConfidence<Macro>`
|
|
10018
|
-
* (`source: 'onboard'`)
|
|
10019
|
-
*
|
|
10023
|
+
* The signal read is ALREADY FILTERED: only `source: 'pipeline'` detections, i.e.
|
|
10024
|
+
* those that went through `enabledMacroClasses`, the
|
|
10025
|
+
* `minConfidence<Macro>` and the full-frame guard. The camera's onboard AI
|
|
10026
|
+
* (`source: 'onboard'`) goes through none of those gates and does NOT open
|
|
10027
|
+
* windows — see `recorder/object-trigger.ts`.
|
|
10020
10028
|
*/
|
|
10021
10029
|
objectClasses: array(RecordingObjectTriggerClassSchema).min(1).refine(noDuplicates, { message: "objectClasses must not repeat a class" }).optional(),
|
|
10022
10030
|
/**
|
|
10023
|
-
*
|
|
10024
|
-
*
|
|
10031
|
+
* The LINKED devices whose RISING EDGE opens a window. Absent = the source
|
|
10032
|
+
* is not listened to; an empty array is rejected for the same reason as
|
|
10025
10033
|
* `objectClasses`.
|
|
10026
10034
|
*
|
|
10027
|
-
*
|
|
10028
|
-
*
|
|
10029
|
-
*
|
|
10030
|
-
*
|
|
10031
|
-
* device (D12) —
|
|
10035
|
+
* These are SOURCE device ids, not cameras: the band names them, so the
|
|
10036
|
+
* hot path (`DeviceStateChanged`, at bus rate across the whole fleet)
|
|
10037
|
+
* does no RPC. The OFFER from which the operator picks them is another question, and
|
|
10038
|
+
* is resolved with `deviceManager.getLinkedDevices` + `getBindingsBatch` per
|
|
10039
|
+
* device (D12) — never a global list of caps.
|
|
10032
10040
|
*
|
|
10033
|
-
*
|
|
10034
|
-
* `SOURCE_CAP_ACTIVE_FIELD` (`catalogs/sensor-active-state.ts`)
|
|
10035
|
-
*
|
|
10036
|
-
*
|
|
10037
|
-
*
|
|
10041
|
+
* What "high" means depends on the device TYPE and is not decided here:
|
|
10042
|
+
* `SOURCE_CAP_ACTIVE_FIELD` (`catalogs/sensor-active-state.ts`) is THE table,
|
|
10043
|
+
* the same one as the composite doorbell (D671). And it is the EDGE, not
|
|
10044
|
+
* the level: a contact found already open at runner restart does not
|
|
10045
|
+
* record.
|
|
10038
10046
|
*/
|
|
10039
10047
|
sensorDeviceIds: array(number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional()
|
|
10040
10048
|
});
|
|
@@ -11111,7 +11119,7 @@ var DecoderSessionConfigSchema = object({
|
|
|
11111
11119
|
* - **VALUE** — at which level, for which scope, until when. That stays ONE
|
|
11112
11120
|
* thing: the logging settings document on the `system` cap. Two authorities
|
|
11113
11121
|
* over the values is the exact defect
|
|
11114
|
-
* `docs/design/plans/2026-08-26-
|
|
11122
|
+
* `docs/design/plans/2026-08-26-per-component-logging.md` was written to
|
|
11115
11123
|
* remove; re-introducing it from the cure side would be grotesque.
|
|
11116
11124
|
*
|
|
11117
11125
|
* Nothing in this file reads a clock, an env var or a store. The registry is
|
|
@@ -12822,7 +12830,7 @@ var BrokerStatusEnum = _enum([
|
|
|
12822
12830
|
"unreachable",
|
|
12823
12831
|
"error"
|
|
12824
12832
|
]);
|
|
12825
|
-
var BrokerInfoSchema
|
|
12833
|
+
var BrokerInfoSchema = object({
|
|
12826
12834
|
/** Stable broker id. Persisted; survives addon restarts. */
|
|
12827
12835
|
id: string(),
|
|
12828
12836
|
/** Addon id of the provider that OWNS this broker.
|
|
@@ -12955,7 +12963,7 @@ var GetStateInputSchema = object({
|
|
|
12955
12963
|
* HA: entity_id (returns the cached entity state). */
|
|
12956
12964
|
key: string()
|
|
12957
12965
|
});
|
|
12958
|
-
method(ListInputSchema, array(BrokerInfoSchema
|
|
12966
|
+
method(ListInputSchema, array(BrokerInfoSchema)), method(GetInputSchema, BrokerInfoSchema.nullable()), method(_void(), array(BrokerProviderInfoSchema), { auth: "admin" }), method(AddInputSchema, AddResultSchema, {
|
|
12959
12967
|
kind: "mutation",
|
|
12960
12968
|
auth: "admin"
|
|
12961
12969
|
}), method(RemoveInputSchema, _void(), {
|
|
@@ -14666,7 +14674,7 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
|
|
|
14666
14674
|
*
|
|
14667
14675
|
* ⚠ An earlier version of this comment blamed Zod stripping, and that
|
|
14668
14676
|
* was wrong — corrected 2026-08-26 after the hop map
|
|
14669
|
-
* (`docs/design/2026-08-26-
|
|
14677
|
+
* (`docs/design/2026-08-26-topic-hop-map.md`) traced the path.
|
|
14670
14678
|
* There is **no Zod parse at all** between the door and the engine: the
|
|
14671
14679
|
* dispatcher forwards the payload verbatim and UDS carries it whole. A
|
|
14672
14680
|
* field declared here reaches `SqliteSettingsBackend` either way.
|
|
@@ -15546,7 +15554,17 @@ var SiteZoneSchema = object({
|
|
|
15546
15554
|
var ProviderStatusSchema = object({
|
|
15547
15555
|
connected: boolean(),
|
|
15548
15556
|
deviceCount: number(),
|
|
15549
|
-
error: string().optional()
|
|
15557
|
+
error: string().optional(),
|
|
15558
|
+
/**
|
|
15559
|
+
* `'orchestrator'`: this provider writes NO camera's `motion` runtime slice
|
|
15560
|
+
* — the orchestrator is its only writer (D696). Set by `BaseDeviceProvider`,
|
|
15561
|
+
* which every provider bundles, so only a provider BUILT from D696-amended
|
|
15562
|
+
* code says it. ABSENT means an older provider that may still write it (raw
|
|
15563
|
+
* VMD writes, a boot seed), and the orchestrator's provider gate keeps that
|
|
15564
|
+
* provider's cameras unwritten (`camera-sensors/motion-slice-provider-gate.ts`)
|
|
15565
|
+
* — the provider twin of the runner's `getLocalLoad().motionSliceWriter`.
|
|
15566
|
+
*/
|
|
15567
|
+
motionSliceWriter: literal("orchestrator").optional()
|
|
15550
15568
|
});
|
|
15551
15569
|
object({
|
|
15552
15570
|
externalId: string(),
|
|
@@ -16425,109 +16443,10 @@ method(object({
|
|
|
16425
16443
|
deviceIds: array(number()).readonly(),
|
|
16426
16444
|
caps: array(string()).readonly().optional()
|
|
16427
16445
|
}), record(string(), record(string(), unknown().nullable())));
|
|
16428
|
-
|
|
16429
|
-
|
|
16430
|
-
* name (same pattern as `snapshot`):
|
|
16431
|
-
*
|
|
16432
|
-
* - **Native** providers: registered per-device by device-driver
|
|
16433
|
-
* addons via `ctx.registerNativeCap` — either on a
|
|
16434
|
-
* `DeviceType.Button` accessory with `role: DeviceRole.Doorbell`,
|
|
16435
|
-
* or directly on the camera (Reolink registers at camera level).
|
|
16436
|
-
* Emits an `onPressed` event every time the firmware pushes a
|
|
16437
|
-
* ring; status tracks the last press and a pressCount since start
|
|
16438
|
-
* (diagnostic).
|
|
16439
|
-
*
|
|
16440
|
-
* - **Wrapper** provider: the `virtual-doorbell` system builtin
|
|
16441
|
-
* (`@camstack/system/builtins/doorbell`). Turns ANY binary-ish
|
|
16442
|
-
* device (contact / switch / event-emitter …) into a doorbell for
|
|
16443
|
-
* a camera. `defaultActive: false` — the operator explicitly binds
|
|
16444
|
-
* it per camera in the device-bindings UI, then picks the source
|
|
16445
|
-
* device + trigger in the per-device settings.
|
|
16446
|
-
*
|
|
16447
|
-
* The DeviceEventPropagator re-emits `onPressed` on the camera parent
|
|
16448
|
-
* — subscribers listening at the camera level receive ring events
|
|
16449
|
-
* with `via[]` populated. No code on the parent needed.
|
|
16450
|
-
*/
|
|
16451
|
-
var DoorbellStatusSchema = object({
|
|
16452
|
-
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
16453
|
-
lastPressedAt: number().nullable(),
|
|
16454
|
-
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
16455
|
-
pressCountSinceStart: number()
|
|
16456
|
-
});
|
|
16457
|
-
var DoorbellPressEventSchema = object({
|
|
16458
|
-
deviceId: number(),
|
|
16459
|
-
timestamp: number()
|
|
16460
|
-
});
|
|
16461
|
-
/**
|
|
16462
|
-
* The `doorbell-source` extension slot's editable value (D648): the camera's
|
|
16463
|
-
* virtual-doorbell trigger devices, exactly what the wrapper's
|
|
16464
|
-
* `doorbellSources` persists (as `{ deviceId }` records).
|
|
16465
|
-
*/
|
|
16466
|
-
var DoorbellSourceSlotValueSchema = object({ deviceIds: array(number().int().positive()) });
|
|
16467
|
-
/**
|
|
16468
|
-
* The `doorbell-source` slot — which devices ring this camera's VIRTUAL
|
|
16469
|
-
* doorbell, owned by the `virtual-doorbell` wrapper over its
|
|
16470
|
-
* `doorbellSources` store (D648). A source rings when one of its
|
|
16471
|
-
* `SOURCE_CAPS` rises. Whether the wrapper is bound to the camera at all is a
|
|
16472
|
-
* different authority (`deviceManager.setWrapperActive`, D62) — the slot
|
|
16473
|
-
* reports it, it never writes it.
|
|
16474
|
-
*/
|
|
16475
|
-
var DOORBELL_SOURCE_SLOT = {
|
|
16476
|
-
id: "doorbell-source",
|
|
16477
|
-
label: "Doorbell trigger devices",
|
|
16478
|
-
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.",
|
|
16479
|
-
shape: "association",
|
|
16480
|
-
hostDeviceTypes: [DeviceType.Camera],
|
|
16481
|
-
sourceCaps: SOURCE_CAPS,
|
|
16482
|
-
cardinality: "many",
|
|
16483
|
-
value: DoorbellSourceSlotValueSchema
|
|
16484
|
-
};
|
|
16485
|
-
var doorbellCapability = {
|
|
16486
|
-
name: "doorbell",
|
|
16487
|
-
scope: "device",
|
|
16488
|
-
deviceNative: true,
|
|
16489
|
-
mode: "singleton",
|
|
16490
|
-
kind: "wrapper",
|
|
16491
|
-
defaultActive: false,
|
|
16492
|
-
deviceTypes: [DeviceType.Button, DeviceType.Camera],
|
|
16493
|
-
extensionSlots: [DOORBELL_SOURCE_SLOT],
|
|
16494
|
-
methods: {},
|
|
16495
|
-
events: {
|
|
16496
|
-
/**
|
|
16497
|
-
* Fires once per physical press. Reolink delivers via Baichuan
|
|
16498
|
-
* push (`ReolinkSimpleEvent.type === 'doorbell'`). There is no
|
|
16499
|
-
* release/duration — it's a pulse.
|
|
16500
|
-
*/
|
|
16501
|
-
onPressed: {
|
|
16502
|
-
data: DoorbellPressEventSchema,
|
|
16503
|
-
fromState: {
|
|
16504
|
-
field: "lastPressedAt",
|
|
16505
|
-
on: "advance"
|
|
16506
|
-
}
|
|
16507
|
-
} },
|
|
16508
|
-
status: {
|
|
16509
|
-
schema: DoorbellStatusSchema,
|
|
16510
|
-
kind: "push"
|
|
16511
|
-
},
|
|
16512
|
-
/**
|
|
16513
|
-
* Runtime-state slice — last press timestamp + lifetime press count.
|
|
16514
|
-
* Mirrored by the kernel and readable via
|
|
16515
|
-
* `device.state.doorbell.value`. UIs can show "last ring 5m ago"
|
|
16516
|
-
* without subscribing.
|
|
16517
|
-
*/
|
|
16518
|
-
runtimeState: DoorbellStatusSchema,
|
|
16519
|
-
/**
|
|
16520
|
-
* 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.
|
|
16521
|
-
*
|
|
16522
|
-
* See `RuntimeStateDurability`. Enforced by
|
|
16523
|
-
* `scripts/check-runtime-state-durability.ts`.
|
|
16524
|
-
*/
|
|
16525
|
-
durability: "restored"
|
|
16526
|
-
};
|
|
16527
|
-
var ExtensionSlotIdSchema = _enum(["doorbell-source", "linked-devices"]);
|
|
16528
|
-
DeviceType.Camera, DeviceType.Camera;
|
|
16446
|
+
var ExtensionSlotIdSchema = _enum(["linked-devices"]);
|
|
16447
|
+
DeviceType.Camera;
|
|
16529
16448
|
/** A slot's editable value, discriminated on `slot`. */
|
|
16530
|
-
var ExtensionSlotValueSchema = discriminatedUnion("slot", [
|
|
16449
|
+
var ExtensionSlotValueSchema = discriminatedUnion("slot", [LinkedDevicesSlotValueSchema.extend({ slot: literal("linked-devices") })]);
|
|
16531
16450
|
DeviceType.Camera;
|
|
16532
16451
|
var ExtensionSourceAvailabilitySchema = discriminatedUnion("state", [object({ state: literal("ok") }), object({
|
|
16533
16452
|
state: literal("unreachable"),
|
|
@@ -16564,10 +16483,11 @@ var ExtensionSlotSourceSchema = object({
|
|
|
16564
16483
|
});
|
|
16565
16484
|
/**
|
|
16566
16485
|
* A DIFFERENT authority that gates whether the slot's sources do anything —
|
|
16567
|
-
* reported read-only, named, never written through this contract (D62).
|
|
16568
|
-
*
|
|
16569
|
-
*
|
|
16570
|
-
* `unknown` means the gate could
|
|
16486
|
+
* reported read-only, named, never written through this contract (D62) — e.g.
|
|
16487
|
+
* a slot whose sources act only while a wrapper is bound to the host, a
|
|
16488
|
+
* binding that belongs to `deviceManager.setWrapperActive`. No slot reports
|
|
16489
|
+
* one today (`linked-devices` answers `null`). `unknown` means the gate could
|
|
16490
|
+
* not be read; it is not "inactive" (D315).
|
|
16571
16491
|
*/
|
|
16572
16492
|
var ExtensionSlotActivationSchema = object({
|
|
16573
16493
|
state: _enum([
|
|
@@ -16583,7 +16503,7 @@ var ExtensionSlotRowSchema = discriminatedUnion("state", [object({
|
|
|
16583
16503
|
/** `<source>:<slotId>` — the routing key for `listCandidates` / `setSlot`. */
|
|
16584
16504
|
slotRef: string(),
|
|
16585
16505
|
slot: ExtensionSlotIdSchema,
|
|
16586
|
-
/** Names the store written (D62), e.g. `
|
|
16506
|
+
/** Names the store written (D62), e.g. `device-manager:_linkedDeviceIds`. */
|
|
16587
16507
|
authority: string(),
|
|
16588
16508
|
activation: ExtensionSlotActivationSchema.nullable(),
|
|
16589
16509
|
value: ExtensionSlotValueSchema,
|
|
@@ -16861,7 +16781,7 @@ method(object({
|
|
|
16861
16781
|
* per-device window, `KeyFrameCaptureLog`, `bumpCropMetric`. Every one of them
|
|
16862
16782
|
* ends in a log line, and a log line is the thing the operator asked to stop
|
|
16863
16783
|
* needing: *"possiamo armare questi errori intanto? Così al prossimo giro
|
|
16864
|
-
* ricontrolliamo tutti questi punti"
|
|
16784
|
+
* 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
|
|
16865
16785
|
* hand-correlating timestamps, which is how a 22% thumbnail gap and a 3-hour
|
|
16866
16786
|
* media blackout were both diagnosed. The counters stay; this is where they can
|
|
16867
16787
|
* be READ.
|
|
@@ -18237,7 +18157,7 @@ var BrokerStatusSchema$1 = _enum([
|
|
|
18237
18157
|
"unreachable",
|
|
18238
18158
|
"tls-error"
|
|
18239
18159
|
]);
|
|
18240
|
-
var BrokerInfoSchema = object({
|
|
18160
|
+
var BrokerInfoSchema$1 = object({
|
|
18241
18161
|
id: string(),
|
|
18242
18162
|
name: string(),
|
|
18243
18163
|
url: string(),
|
|
@@ -18300,7 +18220,7 @@ var StatusSchema = object({
|
|
|
18300
18220
|
brokerCount: number(),
|
|
18301
18221
|
embeddedRunning: boolean()
|
|
18302
18222
|
});
|
|
18303
|
-
method(_void(), array(BrokerInfoSchema)), method(IdInputSchema, BrokerConnectionDetailsSchema, { auth: "admin" }), method(AddBrokerInputSchema, AddBrokerResultSchema, {
|
|
18223
|
+
method(_void(), array(BrokerInfoSchema$1)), method(IdInputSchema, BrokerConnectionDetailsSchema, { auth: "admin" }), method(AddBrokerInputSchema, AddBrokerResultSchema, {
|
|
18304
18224
|
kind: "mutation",
|
|
18305
18225
|
auth: "admin"
|
|
18306
18226
|
}), method(IdInputSchema, _void(), {
|
|
@@ -20514,78 +20434,16 @@ var NcRuleInputSchema = object({
|
|
|
20514
20434
|
*/
|
|
20515
20435
|
confirm: NcConfirmSchema.optional(),
|
|
20516
20436
|
/**
|
|
20517
|
-
*
|
|
20518
|
-
*
|
|
20519
|
-
*
|
|
20520
|
-
*
|
|
20521
|
-
*
|
|
20522
|
-
*
|
|
20523
|
-
*
|
|
20524
|
-
*
|
|
20525
|
-
*
|
|
20526
|
-
* Only two honest answers exist, and this flag picks between them. It has
|
|
20527
|
-
* effect ONLY on a rule that declares a recognition scope
|
|
20528
|
-
* ({@link NcConditions.identities} or {@link NcConditions.plates}) — on any
|
|
20529
|
-
* other rule there is nothing to wait for and the flag is inert.
|
|
20530
|
-
*
|
|
20531
|
-
* | value | what happens |
|
|
20532
|
-
* | --- | --- |
|
|
20533
|
-
* | `true` | the rule stops firing on the object event and fires at TRACK CLOSE instead, once, with the name — later, and complete |
|
|
20534
|
-
* | 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) |
|
|
20535
|
-
*
|
|
20536
|
-
* `.optional()` and deliberately NOT `.default()`: a Zod default does not run
|
|
20537
|
-
* on the addon cap path, and absent has to keep meaning exactly what every
|
|
20538
|
-
* rule authored before this field meant.
|
|
20539
|
-
*
|
|
20540
|
-
* The cost of `true` is stated here because the editor states it too: a rule
|
|
20541
|
-
* that waits also inherits track-close SEMANTICS — its `zones` condition
|
|
20542
|
-
* tests every zone the track visited and a `crossing` condition can no longer
|
|
20543
|
-
* be satisfied, because a closed track carries no crossing.
|
|
20437
|
+
* IMMEDIATE GROUPED (D692): the first matching subject opens a window of this many
|
|
20438
|
+
* seconds; the rule sends ONE message when the window closes — early, once every
|
|
20439
|
+
* subject in it is final, never before {@link NC_GROUPING_MIN_SEC} — naming everybody
|
|
20440
|
+
* the rule matched, with one mosaic tile per subject.
|
|
20441
|
+
* Absent = plain immediate (one message per track, at the first match).
|
|
20442
|
+
* Only an `immediate` DETECTION rule may carry it (`ruleGroupingApplies`, enforced on
|
|
20443
|
+
* save by the hub's grouping guard). `.optional()`, never `.default()`: the addon cap
|
|
20444
|
+
* path does not run Zod defaults.
|
|
20544
20445
|
*/
|
|
20545
|
-
|
|
20546
|
-
/**
|
|
20547
|
-
* GROUP a burst of subjects into ONE notification that grows.
|
|
20548
|
-
*
|
|
20549
|
-
* Seconds of quiet after the last matching subject before the burst is
|
|
20550
|
-
* considered over. While it is open, the first subject enqueues immediately —
|
|
20551
|
-
* **exactly as today, with no added latency** — and every real growth (a new
|
|
20552
|
-
* subject, or a name confirmed on one already in it) REPLACES that
|
|
20553
|
-
* notification with an updated one naming everybody. The push carries the
|
|
20554
|
-
* group's own coalescing tag, so the phone replaces rather than stacks.
|
|
20555
|
-
*
|
|
20556
|
-
* `0` / absent = off, and off is today's behaviour byte for byte.
|
|
20557
|
-
*
|
|
20558
|
-
* ### Why an idle cutoff and not a window
|
|
20559
|
-
*
|
|
20560
|
-
* The measured seven-person arrival on device 590 spans 110 s with every
|
|
20561
|
-
* internal gap under 30 s. A 12 s fixed window cuts it into three groups; an
|
|
20562
|
-
* idle cutoff holds it as one and ends it when the arrival actually ends.
|
|
20563
|
-
* 30 s is a widely shipped value for the same decision.
|
|
20564
|
-
*
|
|
20565
|
-
* ### What it replaces
|
|
20566
|
-
*
|
|
20567
|
-
* The blind cooldown, which collapses a burst by DISCARDING it. Measured on
|
|
20568
|
-
* device 615 / *Persona su Uscio* over six days: 116 qualifying tracks → 74
|
|
20569
|
-
* notifications, **44 (37.9%) suppressed outright**, 23 of them overlapping a
|
|
20570
|
-
* track that did fire and 7 carrying a confirmed identity nobody heard about.
|
|
20571
|
-
* A group collapses the same volume by MERGING, so the cooldown becomes a
|
|
20572
|
-
* budget over GROUPS — which is what it always meant — and a growth is never
|
|
20573
|
-
* throttled by the window its own first member spent.
|
|
20574
|
-
*
|
|
20575
|
-
* ### Interaction with {@link waitForEnhancement}
|
|
20576
|
-
*
|
|
20577
|
-
* They compose, and the order matters. `waitForEnhancement` defers the rule to
|
|
20578
|
-
* TRACK CLOSE, so with both set the group is opened by the first member to
|
|
20579
|
-
* CLOSE — already carrying its name — and grows as later members close. That
|
|
20580
|
-
* is later, and complete. With grouping alone the group opens on the first
|
|
20581
|
-
* object event and picks up names as they are confirmed, through the growth
|
|
20582
|
-
* path. Neither combination fires twice for one subject.
|
|
20583
|
-
*
|
|
20584
|
-
* `.optional()` and deliberately NOT `.default()`: a Zod default does not run
|
|
20585
|
-
* on the addon cap path, so absent must keep meaning what it meant before this
|
|
20586
|
-
* field existed.
|
|
20587
|
-
*/
|
|
20588
|
-
groupIdleSec: number().int().min(0).max(600).optional()
|
|
20446
|
+
groupingSec: number().int().min(5).max(60).optional()
|
|
20589
20447
|
});
|
|
20590
20448
|
/**
|
|
20591
20449
|
* Partial patch for `updateRule` — any subset of the input fields, plus the
|
|
@@ -20633,9 +20491,10 @@ var NcRuleClearableKeySchema = _enum([
|
|
|
20633
20491
|
"targetUsers",
|
|
20634
20492
|
"snoozeOptions",
|
|
20635
20493
|
"snoozeAllowGlobal",
|
|
20636
|
-
"waitForEnhancement",
|
|
20637
20494
|
"actions",
|
|
20638
20495
|
"confirm",
|
|
20496
|
+
"groupingSec",
|
|
20497
|
+
"waitForEnhancement",
|
|
20639
20498
|
"groupIdleSec"
|
|
20640
20499
|
]);
|
|
20641
20500
|
var NcRuleUpdateInputSchema = object({
|
|
@@ -20657,9 +20516,25 @@ var NcRuleSchema = NcRuleInputSchema.extend({
|
|
|
20657
20516
|
*/
|
|
20658
20517
|
disabledTargetIds: array(string()).default([])
|
|
20659
20518
|
});
|
|
20519
|
+
/**
|
|
20520
|
+
* The state-summary SECTIONS (D647 / D698): the D637 kind groups that report a
|
|
20521
|
+
* still-true state. `backups-exports` and `alarm` are not sections — a completed
|
|
20522
|
+
* job is not an open state, and the alarm stays instant.
|
|
20523
|
+
*/
|
|
20524
|
+
var NcStateSummarySectionIdSchema = _enum([
|
|
20525
|
+
"device-state",
|
|
20526
|
+
"streams",
|
|
20527
|
+
"battery",
|
|
20528
|
+
"consumables",
|
|
20529
|
+
"tanks",
|
|
20530
|
+
"detection-blind",
|
|
20531
|
+
"nodes",
|
|
20532
|
+
"addons",
|
|
20533
|
+
"updates"
|
|
20534
|
+
]);
|
|
20660
20535
|
/** One section of a previewed state summary. `unavailable` = its state could not be read. */
|
|
20661
20536
|
var NcStateSummaryPreviewSectionSchema = object({
|
|
20662
|
-
id:
|
|
20537
|
+
id: NcStateSummarySectionIdSchema,
|
|
20663
20538
|
status: _enum(["read", "unavailable"]),
|
|
20664
20539
|
items: number().int().nonnegative(),
|
|
20665
20540
|
reason: string().optional()
|
|
@@ -20669,7 +20544,7 @@ var NcStateSummaryPreviewSectionSchema = object({
|
|
|
20669
20544
|
* a `rule` split (no `section`), one section's on a `section` split.
|
|
20670
20545
|
*/
|
|
20671
20546
|
var NcStateSummaryPreviewRowSchema = object({
|
|
20672
|
-
section:
|
|
20547
|
+
section: NcStateSummarySectionIdSchema.optional(),
|
|
20673
20548
|
/** The section's name on a per-section row; every reported section's, joined, on a combined one. */
|
|
20674
20549
|
title: string(),
|
|
20675
20550
|
text: string(),
|
|
@@ -21106,6 +20981,29 @@ object({
|
|
|
21106
20981
|
firstAt: number(),
|
|
21107
20982
|
lastAt: number()
|
|
21108
20983
|
});
|
|
20984
|
+
var NC_ALARM_TRIGGERED_MAX_SEC = 3600;
|
|
20985
|
+
var NcAlarmDelaySecSchema = number().int().min(0).max(600);
|
|
20986
|
+
var NcAlarmTriggeredSecSchema = number().int().min(0).max(NC_ALARM_TRIGGERED_MAX_SEC);
|
|
20987
|
+
var uniqueModes = (entries) => new Set(entries.map((e) => e.mode)).size === entries.length;
|
|
20988
|
+
var NcAlarmModeDelaysListSchema = array(object({
|
|
20989
|
+
mode: AlarmArmModeSchema,
|
|
20990
|
+
exitDelaySec: NcAlarmDelaySecSchema.optional(),
|
|
20991
|
+
entryDelaySec: NcAlarmDelaySecSchema.optional(),
|
|
20992
|
+
triggeredDurationSec: NcAlarmTriggeredSecSchema.optional()
|
|
20993
|
+
})).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
|
|
20994
|
+
var NcAlarmModeDelaysEditListSchema = array(object({
|
|
20995
|
+
mode: AlarmArmModeSchema,
|
|
20996
|
+
exitDelaySec: NcAlarmDelaySecSchema.nullable().optional(),
|
|
20997
|
+
entryDelaySec: NcAlarmDelaySecSchema.nullable().optional(),
|
|
20998
|
+
triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional()
|
|
20999
|
+
})).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
|
|
21000
|
+
/** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
|
|
21001
|
+
var NcAlarmNonBlockingEditSchema = object({
|
|
21002
|
+
mode: AlarmArmModeSchema,
|
|
21003
|
+
deviceId: number().int().positive(),
|
|
21004
|
+
/** true = on the list (may be open, does not block); false = off the list (blocks). */
|
|
21005
|
+
nonBlocking: boolean()
|
|
21006
|
+
});
|
|
21109
21007
|
/**
|
|
21110
21008
|
* The per-mode lists, at most one per mode. Two lists for one mode have no
|
|
21111
21009
|
* meaning a reader could agree on (union? the last one?), so they are refused
|
|
@@ -21114,10 +21012,10 @@ object({
|
|
|
21114
21012
|
var NcAlarmNonBlockingListSchema = array(object({
|
|
21115
21013
|
mode: AlarmArmModeSchema,
|
|
21116
21014
|
deviceIds: array(number().int()).max(200)
|
|
21117
|
-
})).max(8).refine(
|
|
21015
|
+
})).max(8).refine(uniqueModes, { message: "nonBlocking: at most one list per arm mode" });
|
|
21118
21016
|
/**
|
|
21119
|
-
* The three durations
|
|
21120
|
-
* transitions, and which openings each mode tolerates.
|
|
21017
|
+
* The three durations — global, and per mode since D697 — the panel's state
|
|
21018
|
+
* machine runs on, who hears about its transitions, and which openings each mode tolerates.
|
|
21121
21019
|
*
|
|
21122
21020
|
* They live on the NOTIFICATION-RULES cap, not on `alarm-panel`, on purpose:
|
|
21123
21021
|
* `alarm-panel` is `deviceNative` and its other provider mirrors somebody
|
|
@@ -21127,15 +21025,15 @@ var NcAlarmNonBlockingListSchema = array(object({
|
|
|
21127
21025
|
*/
|
|
21128
21026
|
var NcAlarmSettingsSchema = object({
|
|
21129
21027
|
/** Grace period between arming and the mode taking effect. 0 = immediate. */
|
|
21130
|
-
exitDelaySec:
|
|
21028
|
+
exitDelaySec: NcAlarmDelaySecSchema,
|
|
21131
21029
|
/** Grace period between a trigger and the alarm firing. 0 = immediate. */
|
|
21132
|
-
entryDelaySec:
|
|
21030
|
+
entryDelaySec: NcAlarmDelaySecSchema,
|
|
21133
21031
|
/**
|
|
21134
21032
|
* How long `triggered` lasts before the panel re-arms itself.
|
|
21135
21033
|
* **0 = until an operator disarms it** — the behaviour before this field
|
|
21136
21034
|
* existed, and therefore what an untouched install keeps doing.
|
|
21137
21035
|
*/
|
|
21138
|
-
triggeredDurationSec:
|
|
21036
|
+
triggeredDurationSec: NcAlarmTriggeredSecSchema,
|
|
21139
21037
|
/**
|
|
21140
21038
|
* Deprecated by D630 — every transition is announced. Parsed, never read;
|
|
21141
21039
|
* remove after one release. Optional so an older admin's patch (which still
|
|
@@ -21158,17 +21056,30 @@ var NcAlarmSettingsSchema = object({
|
|
|
21158
21056
|
* per mode is meaningful. Defaulted to `[]` so a blob stored before D630
|
|
21159
21057
|
* parses as "every opening blocks" — the behaviour it was written under.
|
|
21160
21058
|
*/
|
|
21161
|
-
nonBlocking: NcAlarmNonBlockingListSchema.default([])
|
|
21059
|
+
nonBlocking: NcAlarmNonBlockingListSchema.default([]),
|
|
21060
|
+
/**
|
|
21061
|
+
* Per arm mode, the delays that mode OVERRIDES (D697). A mode with no entry, or an entry
|
|
21062
|
+
* without a field, uses the global value above — so `[]`, the default, is exactly the
|
|
21063
|
+
* behaviour of a blob stored before this field existed. Read through `resolveModeDelays`.
|
|
21064
|
+
*/
|
|
21065
|
+
modeDelays: NcAlarmModeDelaysListSchema.default([])
|
|
21162
21066
|
});
|
|
21163
21067
|
/**
|
|
21164
21068
|
* Every field optional — a tab edits one control at a time.
|
|
21165
21069
|
*
|
|
21166
|
-
* `nonBlocking`
|
|
21167
|
-
* remove an inner `.default()`, so a patch that never
|
|
21168
|
-
* parse to `
|
|
21169
|
-
* (the same trap {@link NcRulePatchSchema} documents).
|
|
21070
|
+
* `nonBlocking` and `modeDelays` are re-declared WITHOUT their defaults:
|
|
21071
|
+
* `.partial()` does not remove an inner `.default()`, so a patch that never
|
|
21072
|
+
* named the field would parse to `[]` and wipe every mode's list on an
|
|
21073
|
+
* unrelated edit (the same trap {@link NcRulePatchSchema} documents). Here
|
|
21074
|
+
* `modeDelays` means EDITS, not the stored overrides.
|
|
21170
21075
|
*/
|
|
21171
|
-
var NcAlarmSettingsPatchSchema = NcAlarmSettingsSchema.extend({
|
|
21076
|
+
var NcAlarmSettingsPatchSchema = NcAlarmSettingsSchema.extend({
|
|
21077
|
+
nonBlocking: NcAlarmNonBlockingListSchema,
|
|
21078
|
+
/** Per-mode, per-field edits — NOT the whole list (see NcAlarmModeDelaysEditSchema). */
|
|
21079
|
+
modeDelays: NcAlarmModeDelaysEditListSchema,
|
|
21080
|
+
/** ONE membership change; the panel applies it to the list it holds at its turn. */
|
|
21081
|
+
nonBlockingEdit: NcAlarmNonBlockingEditSchema
|
|
21082
|
+
}).partial().refine((p) => p.nonBlocking === void 0 || p.nonBlockingEdit === void 0, { message: "nonBlocking and nonBlockingEdit are exclusive — send the whole lists or one edit" });
|
|
21172
21083
|
/**
|
|
21173
21084
|
* What one arm mode actually arms, DERIVED from the enabled rules gated on it.
|
|
21174
21085
|
* Never authored, never stored — see `alarm-mode-coverage.ts` for why a stored
|
|
@@ -21268,6 +21179,28 @@ var NcAlarmConfigSchema = object({
|
|
|
21268
21179
|
*/
|
|
21269
21180
|
live: NcAlarmLiveSchema.optional()
|
|
21270
21181
|
});
|
|
21182
|
+
var NcAlarmSensorReadingSchema = _enum([
|
|
21183
|
+
"open",
|
|
21184
|
+
"closed",
|
|
21185
|
+
"unknown",
|
|
21186
|
+
"not-opening"
|
|
21187
|
+
]);
|
|
21188
|
+
/** One device's state as the alarm reads it — the classifier the arm check uses. */
|
|
21189
|
+
var NcAlarmSensorStateSchema = object({
|
|
21190
|
+
deviceId: number().int().positive(),
|
|
21191
|
+
reading: NcAlarmSensorReadingSchema,
|
|
21192
|
+
/** The word as read (`open`, `closed`, `unlocked`, `stopped`, …); null when unknown / not an opening. */
|
|
21193
|
+
state: string().nullable(),
|
|
21194
|
+
/** Why `unknown`: the read failed, or the slice holds no word its cap defines (a placeholder included). */
|
|
21195
|
+
unknownWhy: _enum(["read-failed", "unknown-word"]).nullable(),
|
|
21196
|
+
/** The device manager's liveness as the centre mirrors it; null = not known. */
|
|
21197
|
+
online: boolean().nullable()
|
|
21198
|
+
});
|
|
21199
|
+
var NcAlarmSensorsInputSchema = object({ deviceIds: array(number().int().positive()).max(500) });
|
|
21200
|
+
var NcAlarmSensorsSchema = object({
|
|
21201
|
+
sensors: array(NcAlarmSensorStateSchema),
|
|
21202
|
+
readAt: number().int().nonnegative()
|
|
21203
|
+
});
|
|
21271
21204
|
/**
|
|
21272
21205
|
* ONE rule's demand on ONE camera's clip ring.
|
|
21273
21206
|
*
|
|
@@ -21358,7 +21291,7 @@ method(object({}), object({ rules: array(NcRuleSchema) }), { auth: "admin" }), m
|
|
|
21358
21291
|
}), method(object({}), NcAlarmConfigSchema, { auth: "admin" }), method(object({ patch: NcAlarmSettingsPatchSchema }), NcAlarmConfigSchema, {
|
|
21359
21292
|
kind: "mutation",
|
|
21360
21293
|
auth: "admin"
|
|
21361
|
-
});
|
|
21294
|
+
}), method(NcAlarmSensorsInputSchema, NcAlarmSensorsSchema, { auth: "admin" });
|
|
21362
21295
|
/**
|
|
21363
21296
|
* Zod schemas for persisted record types.
|
|
21364
21297
|
*
|
|
@@ -21705,12 +21638,26 @@ var CameraSensorRefSchema = object({
|
|
|
21705
21638
|
function cameraSensorRefKey(ref) {
|
|
21706
21639
|
return `${ref.addonId}/${ref.stableId}`;
|
|
21707
21640
|
}
|
|
21708
|
-
/**
|
|
21709
|
-
|
|
21710
|
-
|
|
21711
|
-
|
|
21712
|
-
|
|
21713
|
-
|
|
21641
|
+
/**
|
|
21642
|
+
* A sensor's mode (D673). `in-addition`: its motion is the camera's motion too.
|
|
21643
|
+
* `replace`: its motion is the camera's, and while one is READY the camera's
|
|
21644
|
+
* own motion no longer counts on its own. `confirm`: while one is READY the
|
|
21645
|
+
* camera's own motion counts only while a confirm sensor is active — with or
|
|
21646
|
+
* without a replace sensor (spec C2, the controller's ruling on Q1).
|
|
21647
|
+
*/
|
|
21648
|
+
var CameraSensorModeSchema = _enum([
|
|
21649
|
+
"in-addition",
|
|
21650
|
+
"confirm",
|
|
21651
|
+
"replace"
|
|
21652
|
+
]);
|
|
21653
|
+
/** A stored sensor with no mode — every CS-1 row — is in addition. */
|
|
21654
|
+
var DEFAULT_CAMERA_SENSOR_MODE = "in-addition";
|
|
21655
|
+
/**
|
|
21656
|
+
* A camera's attached sensors. A CS-1 row carried an envelope
|
|
21657
|
+
* `mode: 'in-addition'`: `z.object` drops it on parse, and the PARSED value is
|
|
21658
|
+
* what the write stores (D672 rule 3), so it is never written again.
|
|
21659
|
+
*/
|
|
21660
|
+
var CameraSensorsConfigSchema = object({ sensors: array(CameraSensorRefSchema.extend({ mode: CameraSensorModeSchema.default(DEFAULT_CAMERA_SENSOR_MODE) })).min(1).max(8) }).superRefine((value, ctx) => {
|
|
21714
21661
|
const seen = /* @__PURE__ */ new Set();
|
|
21715
21662
|
value.sensors.forEach((ref, index) => {
|
|
21716
21663
|
const key = cameraSensorRefKey(ref);
|
|
@@ -21722,39 +21669,41 @@ var CameraSensorsConfigSchema = object({
|
|
|
21722
21669
|
seen.add(key);
|
|
21723
21670
|
});
|
|
21724
21671
|
});
|
|
21725
|
-
|
|
21672
|
+
/** Every attachment names its mode; an older orchestrator that does not is in addition. */
|
|
21673
|
+
var AttachmentFields = {
|
|
21726
21674
|
addonId: string(),
|
|
21727
|
-
stableId: string()
|
|
21675
|
+
stableId: string(),
|
|
21676
|
+
mode: CameraSensorModeSchema.default(DEFAULT_CAMERA_SENSOR_MODE)
|
|
21728
21677
|
};
|
|
21729
21678
|
var CameraSensorAttachmentSchema = discriminatedUnion("state", [
|
|
21730
21679
|
object({
|
|
21731
|
-
...
|
|
21680
|
+
...AttachmentFields,
|
|
21732
21681
|
state: literal("ready"),
|
|
21733
21682
|
deviceId: number(),
|
|
21734
21683
|
name: string(),
|
|
21735
21684
|
caps: array(string()).readonly()
|
|
21736
21685
|
}),
|
|
21737
21686
|
object({
|
|
21738
|
-
...
|
|
21687
|
+
...AttachmentFields,
|
|
21739
21688
|
state: literal("offline"),
|
|
21740
21689
|
deviceId: number(),
|
|
21741
21690
|
name: string(),
|
|
21742
21691
|
reason: _enum(["offline", "disabled"])
|
|
21743
21692
|
}),
|
|
21744
21693
|
object({
|
|
21745
|
-
...
|
|
21694
|
+
...AttachmentFields,
|
|
21746
21695
|
state: literal("missing"),
|
|
21747
21696
|
reason: string()
|
|
21748
21697
|
}),
|
|
21749
21698
|
object({
|
|
21750
|
-
...
|
|
21699
|
+
...AttachmentFields,
|
|
21751
21700
|
state: literal("unsupported"),
|
|
21752
21701
|
deviceId: number(),
|
|
21753
21702
|
name: string(),
|
|
21754
21703
|
reason: string()
|
|
21755
21704
|
}),
|
|
21756
21705
|
object({
|
|
21757
|
-
...
|
|
21706
|
+
...AttachmentFields,
|
|
21758
21707
|
state: literal("unreadable"),
|
|
21759
21708
|
reason: string()
|
|
21760
21709
|
})
|
|
@@ -21767,17 +21716,49 @@ var CameraSensorAttachmentSchema = discriminatedUnion("state", [
|
|
|
21767
21716
|
* say.
|
|
21768
21717
|
*/
|
|
21769
21718
|
var CameraSensorsNotForwardedSchema = _enum(["onboard-not-listed", "no-active-detection"]);
|
|
21719
|
+
/** Whether the camera's OWN motion counts on its own (D673 C2), from its READY sensors (C3). */
|
|
21720
|
+
var CameraOwnMotionSchema = _enum([
|
|
21721
|
+
"always",
|
|
21722
|
+
"when-confirmed",
|
|
21723
|
+
"never"
|
|
21724
|
+
]);
|
|
21725
|
+
/** Confirm / Replace cannot suppress this camera's motion: its provider still emits it directly (D673 C13). */
|
|
21726
|
+
var CameraSensorsNotEnforcedSchema = _enum(["provider-not-split"]);
|
|
21727
|
+
/**
|
|
21728
|
+
* The camera's OWN onboard motion (D696): the raw input the bridge combines,
|
|
21729
|
+
* never the effective value. The camera's `motion` slice is the effective one,
|
|
21730
|
+
* so a view of the camera's own row reads this.
|
|
21731
|
+
* - `atMs`: when the bridge received the camera's last own edge.
|
|
21732
|
+
* - `detected`: evaluated WHEN THE STATUS IS ASKED — the last edge said `true`
|
|
21733
|
+
* AND it is younger than the window the bridge counts the camera's own motion
|
|
21734
|
+
* for (`motionCooldownMs`, floored at two sustain ticks). A camera that never
|
|
21735
|
+
* sends a clear (heartbeats only) therefore reads `false` once no push came
|
|
21736
|
+
* within the window; a status read is a snapshot, so a live view re-asks.
|
|
21737
|
+
* Absent = this orchestrator has not received the camera's own motion since it
|
|
21738
|
+
* started (unknown, never "quiet"), or an orchestrator older than D696.
|
|
21739
|
+
*/
|
|
21740
|
+
var CameraRawLevelSchema = object({
|
|
21741
|
+
detected: boolean(),
|
|
21742
|
+
atMs: number()
|
|
21743
|
+
});
|
|
21770
21744
|
var CameraSensorsStatusSchema = discriminatedUnion("state", [
|
|
21771
|
-
object({
|
|
21745
|
+
object({
|
|
21746
|
+
state: literal("not-configured"),
|
|
21747
|
+
cameraLevel: CameraRawLevelSchema.optional()
|
|
21748
|
+
}),
|
|
21772
21749
|
object({
|
|
21773
21750
|
state: literal("unreadable"),
|
|
21774
|
-
reason: string()
|
|
21751
|
+
reason: string(),
|
|
21752
|
+
cameraLevel: CameraRawLevelSchema.optional()
|
|
21775
21753
|
}),
|
|
21776
21754
|
object({
|
|
21777
21755
|
state: literal("configured"),
|
|
21778
|
-
|
|
21756
|
+
cameraLevel: CameraRawLevelSchema.optional(),
|
|
21779
21757
|
sensors: array(CameraSensorAttachmentSchema).readonly(),
|
|
21780
|
-
|
|
21758
|
+
/** Absent = an orchestrator older than CS-2: it does not say (D315). */
|
|
21759
|
+
cameraMotion: CameraOwnMotionSchema.optional(),
|
|
21760
|
+
notForwarded: CameraSensorsNotForwardedSchema.optional(),
|
|
21761
|
+
notEnforced: CameraSensorsNotEnforcedSchema.optional()
|
|
21781
21762
|
})
|
|
21782
21763
|
]);
|
|
21783
21764
|
Object.freeze({
|
|
@@ -22462,14 +22443,14 @@ var TrackSchema = object({
|
|
|
22462
22443
|
* `derive-returned-null tile=standin`,
|
|
22463
22444
|
* `native-tile tile=native no-key-frame-at-close`, …) written at close and
|
|
22464
22445
|
* CLEARED by the late-keyFrame upgrade when a native tile lands after all.
|
|
22465
|
-
* The operator-facing answer to "perché manca l'immagine?" on a track whose
|
|
22446
|
+
* The operator-facing answer to "perché manca l'immagine?" [why is the image missing?] on a track whose
|
|
22466
22447
|
* tile is a face/plate stand-in, a raster crop, or an icon.
|
|
22467
22448
|
*
|
|
22468
22449
|
* **`no-key-frame-at-close` (D400).** The line used to be written ONLY when
|
|
22469
22450
|
* the TILE ranked below native, so a track whose thumbnail landed natively
|
|
22470
22451
|
* while its key frame missed carried no reason at all — three of the four
|
|
22471
22452
|
* `MISSING_KEYFRAME` tracks in the 2026-09-07 operator audit were exactly
|
|
22472
|
-
* that shape, and their "niente ultimo" had no cause anywhere on the row.
|
|
22453
|
+
* that shape, and their "niente ultimo" [no last frame] had no cause anywhere on the row.
|
|
22473
22454
|
* The key frame is the head of a cascade (`keyFrame ⇒ keyFrameSmall ⇒ the
|
|
22474
22455
|
* lastFrame copy source`), so its absence is now on this line whatever the
|
|
22475
22456
|
* tile ended up being.
|
|
@@ -22556,7 +22537,7 @@ var MotionEventSchema = object({
|
|
|
22556
22537
|
/**
|
|
22557
22538
|
* Ms offsets from `timestamp` (the episode's own first rising edge, so the
|
|
22558
22539
|
* first entry is always `0`) of every genuine off→on transition the
|
|
22559
|
-
* episode saw — "ogni evento on si deve salvare" (D475). NOT one entry per
|
|
22540
|
+
* episode saw — "ogni evento on si deve salvare" [every ON event must be saved] (D475). NOT one entry per
|
|
22560
22541
|
* push: a firmware source that keepalives at ~1 Hz for the whole burst
|
|
22561
22542
|
* (Reolink, Hikvision) produces exactly one edge; a source that reports an
|
|
22562
22543
|
* explicit `false` mid-episode and then resumes before the quiet window
|
|
@@ -23080,6 +23061,7 @@ var KeyEventSchema = object({
|
|
|
23080
23061
|
bestEventId: string(),
|
|
23081
23062
|
/** Track lifetime in ms (lastSeen - firstSeen). */
|
|
23082
23063
|
windowMs: number().optional(),
|
|
23064
|
+
audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
|
|
23083
23065
|
...TrackFlagFields,
|
|
23084
23066
|
...TrackRetrainFields
|
|
23085
23067
|
});
|
|
@@ -25008,8 +24990,10 @@ var RunnerCameraConfigSchema = object({
|
|
|
25008
24990
|
* - `analyzer`: ML/frame-diff motion detection (motion-wasm or other
|
|
25009
24991
|
* analyzer providers) running on decoded frames in this runner.
|
|
25010
24992
|
* - `onboard`: camera-native motion pushes (Reolink Baichuan, ONVIF
|
|
25011
|
-
* analytics). The provider emits ProviderMotion
|
|
25012
|
-
*
|
|
24993
|
+
* analytics). The provider emits its raw push as `ProviderMotion`
|
|
24994
|
+
* (D673); the orchestrator's camera-sensors bridge re-emits the camera's
|
|
24995
|
+
* effective motion as `MotionOnMotionChanged`, which is what reaches
|
|
24996
|
+
* `reportMotion`.
|
|
25013
24997
|
*/
|
|
25014
24998
|
motionSources: MotionSourcesSchema.default(["analyzer"]),
|
|
25015
24999
|
/**
|
|
@@ -25186,7 +25170,15 @@ var RunnerLocalLoadSchema = object({
|
|
|
25186
25170
|
hasGpu: boolean(),
|
|
25187
25171
|
inferenceBackend: string().optional(),
|
|
25188
25172
|
cpuCores: number().optional()
|
|
25189
|
-
})
|
|
25173
|
+
}),
|
|
25174
|
+
/**
|
|
25175
|
+
* Who writes a camera's `motion` runtime slice (D696). `'orchestrator'`: this
|
|
25176
|
+
* runner never writes it. ABSENT = a runner older than D696, which still
|
|
25177
|
+
* writes the slice from its phase machine; the orchestrator does not write
|
|
25178
|
+
* while any runner node is absent-or-unanswered, so one slice never has two
|
|
25179
|
+
* writers.
|
|
25180
|
+
*/
|
|
25181
|
+
motionSliceWriter: literal("orchestrator").optional()
|
|
25190
25182
|
});
|
|
25191
25183
|
/**
|
|
25192
25184
|
* Aggregate runtime metrics for the runner's whole local pool. Mirrors the
|
|
@@ -27851,7 +27843,7 @@ var ClipPlaybackSchema = object({
|
|
|
27851
27843
|
* **One authorised yes is one wake.** `next-natural` — take the clip the next
|
|
27852
27844
|
* time the camera is awake for its own reasons — is deliberately not a member:
|
|
27853
27845
|
* it was proposed, it is free on the battery, and the operator declined it on
|
|
27854
|
-
* 2026-09-20 (*"Quando un export viene richiesto si sveglia la camera."
|
|
27846
|
+
* 2026-09-20 (*"Quando un export viene richiesto si sveglia la camera."* [When an export is requested the camera wakes up],
|
|
27855
27847
|
* D558 "Considered and not taken").
|
|
27856
27848
|
*/
|
|
27857
27849
|
var ClipWakeSchema = _enum(["authorised"]);
|
|
@@ -28112,7 +28104,7 @@ DeviceType.Camera, method(object({
|
|
|
28112
28104
|
* It replaced `sources?: string[]`, a VIEW filter over source ids that
|
|
28113
28105
|
* assumed the answer was a fan-out over everything a camera has. The
|
|
28114
28106
|
* operator settled otherwise on 2026-09-20 — *"l'utilizzatore è uno
|
|
28115
|
-
* solo"* — so the list is asked of one provider at a time and there is
|
|
28107
|
+
* solo"* [there is only one user] — so the list is asked of one provider at a time and there is
|
|
28116
28108
|
* nothing to filter out of it.
|
|
28117
28109
|
*/
|
|
28118
28110
|
provider: string().min(1)
|
|
@@ -30715,6 +30707,70 @@ onStatusChanged: { data: object({
|
|
|
30715
30707
|
* whether persisting is worth a SQLite commit. */
|
|
30716
30708
|
volatileStateFields: ["lastChangedAt"]
|
|
30717
30709
|
};
|
|
30710
|
+
var DoorbellStatusSchema = object({
|
|
30711
|
+
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
30712
|
+
lastPressedAt: number().nullable(),
|
|
30713
|
+
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
30714
|
+
pressCountSinceStart: number()
|
|
30715
|
+
});
|
|
30716
|
+
var DoorbellPressEventSchema = object({
|
|
30717
|
+
deviceId: number(),
|
|
30718
|
+
timestamp: number()
|
|
30719
|
+
});
|
|
30720
|
+
/**
|
|
30721
|
+
* Doorbell button cap. Two kinds of provider serve it, and to every consumer
|
|
30722
|
+
* they are the same cap:
|
|
30723
|
+
*
|
|
30724
|
+
* - **Native** providers, registered per device by a driver addon through
|
|
30725
|
+
* `ctx.registerNativeCap` — a `DeviceType.Button` accessory with
|
|
30726
|
+
* `role: DeviceRole.Doorbell`, or the camera itself (Reolink registers at
|
|
30727
|
+
* camera level). They emit `onPressed` on every firmware ring.
|
|
30728
|
+
* - **A composed doorbell** (D670, D671): a camera's customization gives it
|
|
30729
|
+
* the cap, its `lastPressedAt` rising from the sources the operator
|
|
30730
|
+
* assigned in Customize → Doorbell, and the composer emits `onPressed`
|
|
30731
|
+
* from that field's advance (`fromState`).
|
|
30732
|
+
*
|
|
30733
|
+
* The DeviceEventPropagator re-emits `onPressed` on the camera parent.
|
|
30734
|
+
*/
|
|
30735
|
+
var doorbellCapability = {
|
|
30736
|
+
name: "doorbell",
|
|
30737
|
+
scope: "device",
|
|
30738
|
+
deviceNative: true,
|
|
30739
|
+
mode: "singleton",
|
|
30740
|
+
deviceTypes: [DeviceType.Button, DeviceType.Camera],
|
|
30741
|
+
methods: {},
|
|
30742
|
+
events: {
|
|
30743
|
+
/**
|
|
30744
|
+
* Fires once per physical press. Reolink delivers via Baichuan
|
|
30745
|
+
* push (`ReolinkSimpleEvent.type === 'doorbell'`). There is no
|
|
30746
|
+
* release/duration — it's a pulse.
|
|
30747
|
+
*/
|
|
30748
|
+
onPressed: {
|
|
30749
|
+
data: DoorbellPressEventSchema,
|
|
30750
|
+
fromState: {
|
|
30751
|
+
field: "lastPressedAt",
|
|
30752
|
+
on: "advance"
|
|
30753
|
+
}
|
|
30754
|
+
} },
|
|
30755
|
+
status: {
|
|
30756
|
+
schema: DoorbellStatusSchema,
|
|
30757
|
+
kind: "push"
|
|
30758
|
+
},
|
|
30759
|
+
/**
|
|
30760
|
+
* Runtime-state slice — last press timestamp + lifetime press count.
|
|
30761
|
+
* Mirrored by the kernel and readable via
|
|
30762
|
+
* `device.state.doorbell.value`. UIs can show "last ring 5m ago"
|
|
30763
|
+
* without subscribing.
|
|
30764
|
+
*/
|
|
30765
|
+
runtimeState: DoorbellStatusSchema,
|
|
30766
|
+
/**
|
|
30767
|
+
* 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.
|
|
30768
|
+
*
|
|
30769
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
30770
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
30771
|
+
*/
|
|
30772
|
+
durability: "restored"
|
|
30773
|
+
};
|
|
30718
30774
|
/**
|
|
30719
30775
|
* Enum-state sensor — a string value picked from a finite option set.
|
|
30720
30776
|
* Drives HA `sensor` entries with `state_class: enum` (HVAC action
|
|
@@ -32859,9 +32915,9 @@ var MotionStatusSchema = object({
|
|
|
32859
32915
|
/** Ms epoch of the last detected-true observation. Null if never detected. */
|
|
32860
32916
|
lastDetectedAt: number().nullable(),
|
|
32861
32917
|
/**
|
|
32862
|
-
* `MOTION_CLOSE_AFTER_MS` while `detected: true` on a `Camera` device
|
|
32863
|
-
* `null` while false and on every `Sensor`
|
|
32864
|
-
* constant's doc for the one-authority rule.
|
|
32918
|
+
* `MOTION_CLOSE_AFTER_MS` while `detected: true` on a `Camera` device (the
|
|
32919
|
+
* orchestrator writes it, D696), `null` while false and on every `Sensor`
|
|
32920
|
+
* device (D475) — see that constant's doc for the one-authority rule.
|
|
32865
32921
|
*
|
|
32866
32922
|
* ## Reading this field still arms nothing
|
|
32867
32923
|
*
|
|
@@ -32879,34 +32935,31 @@ var MotionStatusSchema = object({
|
|
|
32879
32935
|
* `addon-export-alexa/src/motion-clear-hold.ts` and
|
|
32880
32936
|
* `addon-export-hap`'s `RESET_DEBOUNCE_MS` both do.
|
|
32881
32937
|
*
|
|
32882
|
-
* ## Who writes it
|
|
32883
|
-
*
|
|
32884
|
-
* - **Cameras** — the
|
|
32885
|
-
*
|
|
32886
|
-
* `
|
|
32887
|
-
* `
|
|
32888
|
-
*
|
|
32889
|
-
*
|
|
32890
|
-
* a
|
|
32891
|
-
*
|
|
32892
|
-
*
|
|
32893
|
-
*
|
|
32894
|
-
*
|
|
32895
|
-
*
|
|
32896
|
-
*
|
|
32897
|
-
*
|
|
32898
|
-
*
|
|
32899
|
-
*
|
|
32900
|
-
* `
|
|
32901
|
-
*
|
|
32902
|
-
*
|
|
32903
|
-
*
|
|
32904
|
-
*
|
|
32905
|
-
*
|
|
32906
|
-
*
|
|
32907
|
-
* This predates D475 and is not fixed there: the fix touches every
|
|
32908
|
-
* camera provider. Recorded in D475's Consequences. Do not restore the
|
|
32909
|
-
* "sole writer" wording without also removing the other writers.
|
|
32938
|
+
* ## Who writes it (D696)
|
|
32939
|
+
*
|
|
32940
|
+
* - **Cameras** — the orchestrator, and nothing else. It writes the camera's
|
|
32941
|
+
* EFFECTIVE motion (`addon-pipeline-orchestrator`
|
|
32942
|
+
* `camera-sensors/motion-slice.ts`), alongside the effective
|
|
32943
|
+
* `MotionOnMotionChanged` it emits or receives: the camera-sensors bridge
|
|
32944
|
+
* for a split camera, an unsplit emitter's direct event, the analyzer and
|
|
32945
|
+
* device activity, as the camera's `motionSources` counts them. A source
|
|
32946
|
+
* that never sends a clear falls one window after its last `true`.
|
|
32947
|
+
* `lastDetectedAt` moves only on an effective rise. No camera provider
|
|
32948
|
+
* writes this slice (not even a boot seed), and neither does the runner's
|
|
32949
|
+
* phase machine: its phase is "a session is attached" for every on-motion
|
|
32950
|
+
* session, not motion, and it now has its own `DetectionPhaseTransition`.
|
|
32951
|
+
* A provider's `isDetected` answers from the hub's slice.
|
|
32952
|
+
* - **Sensors** (Home Assistant binary sensors, Homematic, Matter, Alexa
|
|
32953
|
+
* imports) — the provider pushes both edges itself, from the upstream
|
|
32954
|
+
* system's own state change. That is the sensor's own fact.
|
|
32955
|
+
*
|
|
32956
|
+
* `scripts/check-onboard-motion-emitters.ts` refuses any other writer of a
|
|
32957
|
+
* `motion` slice; each sensor writer is a named exemption.
|
|
32958
|
+
*
|
|
32959
|
+
* This replaces the D475 §4 rule ("the phase machine is the sole writer").
|
|
32960
|
+
* That rule was never true: Hikvision and Amcrest wrote the slice raw beside
|
|
32961
|
+
* it, every provider seeded it at boot, and every session left it
|
|
32962
|
+
* `detected: true` after its detach.
|
|
32910
32963
|
*/
|
|
32911
32964
|
autoClearAfterMs: number().nullable()
|
|
32912
32965
|
});
|
|
@@ -32978,11 +33031,12 @@ onMotionChanged: { data: MotionOnMotionChangedDataSchema } },
|
|
|
32978
33031
|
*/
|
|
32979
33032
|
runtimeState: MotionStatusSchema,
|
|
32980
33033
|
/**
|
|
32981
|
-
* Runtime-state durability: **session** —
|
|
33034
|
+
* Runtime-state durability: **session** — the writer of this slice
|
|
32982
33035
|
* writes only on an EDGE, so a restored `detected: true` would stay
|
|
32983
33036
|
* frozen until the next one instead of being corrected. The next edge
|
|
32984
|
-
* re-publishes the real state
|
|
32985
|
-
*
|
|
33037
|
+
* re-publishes the real state, and the orchestrator re-publishes every
|
|
33038
|
+
* camera when it starts writing (D696; on who writes it, see
|
|
33039
|
+
* `autoClearAfterMs` above).
|
|
32986
33040
|
*
|
|
32987
33041
|
* See `RuntimeStateDurability`. Enforced by
|
|
32988
33042
|
* `scripts/check-runtime-state-durability.ts`.
|
|
@@ -35365,8 +35419,7 @@ var ptzAutotrackCapability = {
|
|
|
35365
35419
|
deviceNative: true,
|
|
35366
35420
|
mode: "singleton",
|
|
35367
35421
|
/**
|
|
35368
|
-
* Two kinds of provider behind one name, the same shape `snapshot`
|
|
35369
|
-
* `doorbell` use:
|
|
35422
|
+
* Two kinds of provider behind one name, the same shape `snapshot` uses:
|
|
35370
35423
|
*
|
|
35371
35424
|
* - **Native**: the camera's own firmware autotrack, registered per device by
|
|
35372
35425
|
* the driver when the probe says it exists (Reolink: yes; Hikvision:
|
|
@@ -35374,7 +35427,7 @@ var ptzAutotrackCapability = {
|
|
|
35374
35427
|
* - **Wrapper**: the emulated implementation (`@camstack/system`'s `autotrack` builtin),
|
|
35375
35428
|
* which follows a subject with `ptz.move` pulses driven by the detection
|
|
35376
35429
|
* pipeline. `defaultActive: false` — the operator binds it per camera in
|
|
35377
|
-
* the bindings UI
|
|
35430
|
+
* the bindings UI.
|
|
35378
35431
|
*
|
|
35379
35432
|
* The binding chooses WHICH implementation answers; `setEnabled` stays the
|
|
35380
35433
|
* one switch for the function either way. A camera never has both driving its
|
|
@@ -36049,7 +36102,7 @@ var ReadGopBytesResultSchema = object({
|
|
|
36049
36102
|
/**
|
|
36050
36103
|
* A time WINDOW of one finalized segment, cut by byte range — the multi-GOP
|
|
36051
36104
|
* twin of {@link ReadGopBytesResultSchema}'s single instant. Built for the
|
|
36052
|
-
* replay clip's `recording` source (`docs/design/plans/2026-08-26-replay-
|
|
36105
|
+
* replay clip's `recording` source (`docs/design/plans/2026-08-26-clip-replay-on-pipeline.md`):
|
|
36053
36106
|
* a replay needs several seconds of native pixels, not one frame.
|
|
36054
36107
|
*
|
|
36055
36108
|
* `ok.data` is standalone-demuxable, same as a GOP read. `ok.reachesRequestedEnd`
|
|
@@ -39413,6 +39466,7 @@ var zoneRulesCapability = {
|
|
|
39413
39466
|
*/
|
|
39414
39467
|
durability: "restored"
|
|
39415
39468
|
};
|
|
39469
|
+
SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
|
|
39416
39470
|
/**
|
|
39417
39471
|
* Accessory device helpers — shared across drivers.
|
|
39418
39472
|
*
|
|
@@ -40472,13 +40526,14 @@ var BaseDeviceProvider = class extends BaseAddon {
|
|
|
40472
40526
|
async getStatus() {
|
|
40473
40527
|
const all = await this.ctx.kernel.devices?.getAll() ?? [];
|
|
40474
40528
|
const summary = this.restoreFailureSummary();
|
|
40475
|
-
|
|
40529
|
+
const base = {
|
|
40476
40530
|
connected: true,
|
|
40477
|
-
deviceCount: all.length
|
|
40531
|
+
deviceCount: all.length,
|
|
40532
|
+
motionSliceWriter: "orchestrator"
|
|
40478
40533
|
};
|
|
40534
|
+
if (summary === null) return base;
|
|
40479
40535
|
return {
|
|
40480
|
-
|
|
40481
|
-
deviceCount: all.length,
|
|
40536
|
+
...base,
|
|
40482
40537
|
error: summary
|
|
40483
40538
|
};
|
|
40484
40539
|
}
|
|
@@ -45914,6 +45969,12 @@ Object.freeze({
|
|
|
45914
45969
|
addonId: null,
|
|
45915
45970
|
access: "view"
|
|
45916
45971
|
},
|
|
45972
|
+
"notificationRules.getAlarmSensors": {
|
|
45973
|
+
capName: "notification-rules",
|
|
45974
|
+
capScope: "system",
|
|
45975
|
+
addonId: null,
|
|
45976
|
+
access: "view"
|
|
45977
|
+
},
|
|
45917
45978
|
"notificationRules.getClipRetentionAsks": {
|
|
45918
45979
|
capName: "notification-rules",
|
|
45919
45980
|
capScope: "system",
|
|
@@ -49492,6 +49553,11 @@ Object.freeze({
|
|
|
49492
49553
|
}
|
|
49493
49554
|
});
|
|
49494
49555
|
Object.freeze({
|
|
49556
|
+
"accessories.getStatus": [{
|
|
49557
|
+
name: "deviceId",
|
|
49558
|
+
form: "single",
|
|
49559
|
+
optional: false
|
|
49560
|
+
}],
|
|
49495
49561
|
"accessories.setChildHidden": [{
|
|
49496
49562
|
name: "childDeviceId",
|
|
49497
49563
|
form: "single",
|
|
@@ -49511,6 +49577,11 @@ Object.freeze({
|
|
|
49511
49577
|
form: "single",
|
|
49512
49578
|
optional: false
|
|
49513
49579
|
}],
|
|
49580
|
+
"airQualitySensor.getStatus": [{
|
|
49581
|
+
name: "deviceId",
|
|
49582
|
+
form: "single",
|
|
49583
|
+
optional: false
|
|
49584
|
+
}],
|
|
49514
49585
|
"alarmPanel.arm": [{
|
|
49515
49586
|
name: "deviceId",
|
|
49516
49587
|
form: "single",
|
|
@@ -49521,11 +49592,36 @@ Object.freeze({
|
|
|
49521
49592
|
form: "single",
|
|
49522
49593
|
optional: false
|
|
49523
49594
|
}],
|
|
49595
|
+
"alarmPanel.getStatus": [{
|
|
49596
|
+
name: "deviceId",
|
|
49597
|
+
form: "single",
|
|
49598
|
+
optional: false
|
|
49599
|
+
}],
|
|
49524
49600
|
"alarmPanel.trigger": [{
|
|
49525
49601
|
name: "deviceId",
|
|
49526
49602
|
form: "single",
|
|
49527
49603
|
optional: false
|
|
49528
49604
|
}],
|
|
49605
|
+
"ambientLightSensor.getStatus": [{
|
|
49606
|
+
name: "deviceId",
|
|
49607
|
+
form: "single",
|
|
49608
|
+
optional: false
|
|
49609
|
+
}],
|
|
49610
|
+
"audioAnalysis.applyDeviceSettingsPatch": [{
|
|
49611
|
+
name: "deviceId",
|
|
49612
|
+
form: "single",
|
|
49613
|
+
optional: false
|
|
49614
|
+
}],
|
|
49615
|
+
"audioAnalysis.getDeviceLiveContribution": [{
|
|
49616
|
+
name: "deviceId",
|
|
49617
|
+
form: "single",
|
|
49618
|
+
optional: false
|
|
49619
|
+
}],
|
|
49620
|
+
"audioAnalysis.getDeviceSettingsContribution": [{
|
|
49621
|
+
name: "deviceId",
|
|
49622
|
+
form: "single",
|
|
49623
|
+
optional: false
|
|
49624
|
+
}],
|
|
49529
49625
|
"audioAnalysis.resolveDeviceSettings": [{
|
|
49530
49626
|
name: "deviceId",
|
|
49531
49627
|
form: "single",
|
|
@@ -49566,16 +49662,36 @@ Object.freeze({
|
|
|
49566
49662
|
form: "single",
|
|
49567
49663
|
optional: false
|
|
49568
49664
|
}],
|
|
49665
|
+
"automationControl.getStatus": [{
|
|
49666
|
+
name: "deviceId",
|
|
49667
|
+
form: "single",
|
|
49668
|
+
optional: false
|
|
49669
|
+
}],
|
|
49569
49670
|
"automationControl.trigger": [{
|
|
49570
49671
|
name: "deviceId",
|
|
49571
49672
|
form: "single",
|
|
49572
49673
|
optional: false
|
|
49573
49674
|
}],
|
|
49675
|
+
"battery.getStatus": [{
|
|
49676
|
+
name: "deviceId",
|
|
49677
|
+
form: "single",
|
|
49678
|
+
optional: false
|
|
49679
|
+
}],
|
|
49574
49680
|
"battery.wakeForStream": [{
|
|
49575
49681
|
name: "deviceId",
|
|
49576
49682
|
form: "single",
|
|
49577
49683
|
optional: false
|
|
49578
49684
|
}],
|
|
49685
|
+
"binary.getStatus": [{
|
|
49686
|
+
name: "deviceId",
|
|
49687
|
+
form: "single",
|
|
49688
|
+
optional: false
|
|
49689
|
+
}],
|
|
49690
|
+
"brightness.getStatus": [{
|
|
49691
|
+
name: "deviceId",
|
|
49692
|
+
form: "single",
|
|
49693
|
+
optional: false
|
|
49694
|
+
}],
|
|
49579
49695
|
"brightness.setBrightness": [{
|
|
49580
49696
|
name: "deviceId",
|
|
49581
49697
|
form: "single",
|
|
@@ -49591,6 +49707,26 @@ Object.freeze({
|
|
|
49591
49707
|
form: "single",
|
|
49592
49708
|
optional: false
|
|
49593
49709
|
}],
|
|
49710
|
+
"cameraCredentials.getStatus": [{
|
|
49711
|
+
name: "deviceId",
|
|
49712
|
+
form: "single",
|
|
49713
|
+
optional: false
|
|
49714
|
+
}],
|
|
49715
|
+
"cameraGridLayout.applyDeviceSettingsPatch": [{
|
|
49716
|
+
name: "deviceId",
|
|
49717
|
+
form: "single",
|
|
49718
|
+
optional: false
|
|
49719
|
+
}],
|
|
49720
|
+
"cameraGridLayout.getDeviceLiveContribution": [{
|
|
49721
|
+
name: "deviceId",
|
|
49722
|
+
form: "single",
|
|
49723
|
+
optional: false
|
|
49724
|
+
}],
|
|
49725
|
+
"cameraGridLayout.getDeviceSettingsContribution": [{
|
|
49726
|
+
name: "deviceId",
|
|
49727
|
+
form: "single",
|
|
49728
|
+
optional: false
|
|
49729
|
+
}],
|
|
49594
49730
|
"cameraGridLayout.getLayout": [{
|
|
49595
49731
|
name: "deviceId",
|
|
49596
49732
|
form: "single",
|
|
@@ -49606,6 +49742,21 @@ Object.freeze({
|
|
|
49606
49742
|
form: "single",
|
|
49607
49743
|
optional: false
|
|
49608
49744
|
}],
|
|
49745
|
+
"cameraPipelineConfig.applyDeviceSettingsPatch": [{
|
|
49746
|
+
name: "deviceId",
|
|
49747
|
+
form: "single",
|
|
49748
|
+
optional: false
|
|
49749
|
+
}],
|
|
49750
|
+
"cameraPipelineConfig.getDeviceLiveContribution": [{
|
|
49751
|
+
name: "deviceId",
|
|
49752
|
+
form: "single",
|
|
49753
|
+
optional: false
|
|
49754
|
+
}],
|
|
49755
|
+
"cameraPipelineConfig.getDeviceSettingsContribution": [{
|
|
49756
|
+
name: "deviceId",
|
|
49757
|
+
form: "single",
|
|
49758
|
+
optional: false
|
|
49759
|
+
}],
|
|
49609
49760
|
"cameraStreams.getBrokerStreams": [{
|
|
49610
49761
|
name: "deviceId",
|
|
49611
49762
|
form: "single",
|
|
@@ -49631,6 +49782,16 @@ Object.freeze({
|
|
|
49631
49782
|
form: "single",
|
|
49632
49783
|
optional: false
|
|
49633
49784
|
}],
|
|
49785
|
+
"carbonMonoxide.getStatus": [{
|
|
49786
|
+
name: "deviceId",
|
|
49787
|
+
form: "single",
|
|
49788
|
+
optional: false
|
|
49789
|
+
}],
|
|
49790
|
+
"climateControl.getStatus": [{
|
|
49791
|
+
name: "deviceId",
|
|
49792
|
+
form: "single",
|
|
49793
|
+
optional: false
|
|
49794
|
+
}],
|
|
49634
49795
|
"climateControl.setFanMode": [{
|
|
49635
49796
|
name: "deviceId",
|
|
49636
49797
|
form: "single",
|
|
@@ -49671,16 +49832,41 @@ Object.freeze({
|
|
|
49671
49832
|
form: "single",
|
|
49672
49833
|
optional: false
|
|
49673
49834
|
}],
|
|
49835
|
+
"color.getStatus": [{
|
|
49836
|
+
name: "deviceId",
|
|
49837
|
+
form: "single",
|
|
49838
|
+
optional: false
|
|
49839
|
+
}],
|
|
49674
49840
|
"color.setColor": [{
|
|
49675
49841
|
name: "deviceId",
|
|
49676
49842
|
form: "single",
|
|
49677
49843
|
optional: false
|
|
49678
49844
|
}],
|
|
49845
|
+
"connectivity.getStatus": [{
|
|
49846
|
+
name: "deviceId",
|
|
49847
|
+
form: "single",
|
|
49848
|
+
optional: false
|
|
49849
|
+
}],
|
|
49850
|
+
"consumables.getStatus": [{
|
|
49851
|
+
name: "deviceId",
|
|
49852
|
+
form: "single",
|
|
49853
|
+
optional: false
|
|
49854
|
+
}],
|
|
49679
49855
|
"consumables.reset": [{
|
|
49680
49856
|
name: "deviceId",
|
|
49681
49857
|
form: "single",
|
|
49682
49858
|
optional: false
|
|
49683
49859
|
}],
|
|
49860
|
+
"contact.getStatus": [{
|
|
49861
|
+
name: "deviceId",
|
|
49862
|
+
form: "single",
|
|
49863
|
+
optional: false
|
|
49864
|
+
}],
|
|
49865
|
+
"control.getStatus": [{
|
|
49866
|
+
name: "deviceId",
|
|
49867
|
+
form: "single",
|
|
49868
|
+
optional: false
|
|
49869
|
+
}],
|
|
49684
49870
|
"control.setValue": [{
|
|
49685
49871
|
name: "deviceId",
|
|
49686
49872
|
form: "single",
|
|
@@ -49691,6 +49877,11 @@ Object.freeze({
|
|
|
49691
49877
|
form: "single",
|
|
49692
49878
|
optional: false
|
|
49693
49879
|
}],
|
|
49880
|
+
"cover.getStatus": [{
|
|
49881
|
+
name: "deviceId",
|
|
49882
|
+
form: "single",
|
|
49883
|
+
optional: false
|
|
49884
|
+
}],
|
|
49694
49885
|
"cover.open": [{
|
|
49695
49886
|
name: "deviceId",
|
|
49696
49887
|
form: "single",
|
|
@@ -49716,6 +49907,11 @@ Object.freeze({
|
|
|
49716
49907
|
form: "single",
|
|
49717
49908
|
optional: false
|
|
49718
49909
|
}],
|
|
49910
|
+
"dayNight.getStatus": [{
|
|
49911
|
+
name: "deviceId",
|
|
49912
|
+
form: "single",
|
|
49913
|
+
optional: false
|
|
49914
|
+
}],
|
|
49719
49915
|
"dayNight.setSettings": [{
|
|
49720
49916
|
name: "deviceId",
|
|
49721
49917
|
form: "single",
|
|
@@ -49726,11 +49922,31 @@ Object.freeze({
|
|
|
49726
49922
|
form: "single",
|
|
49727
49923
|
optional: true
|
|
49728
49924
|
}],
|
|
49925
|
+
"detectionPipeline.applyDeviceSettingsPatch": [{
|
|
49926
|
+
name: "deviceId",
|
|
49927
|
+
form: "single",
|
|
49928
|
+
optional: false
|
|
49929
|
+
}],
|
|
49930
|
+
"detectionPipeline.getDeviceLiveContribution": [{
|
|
49931
|
+
name: "deviceId",
|
|
49932
|
+
form: "single",
|
|
49933
|
+
optional: false
|
|
49934
|
+
}],
|
|
49935
|
+
"detectionPipeline.getDeviceSettingsContribution": [{
|
|
49936
|
+
name: "deviceId",
|
|
49937
|
+
form: "single",
|
|
49938
|
+
optional: false
|
|
49939
|
+
}],
|
|
49729
49940
|
"deviceAdminLink.getAdminLink": [{
|
|
49730
49941
|
name: "deviceId",
|
|
49731
49942
|
form: "single",
|
|
49732
49943
|
optional: false
|
|
49733
49944
|
}],
|
|
49945
|
+
"deviceAdoption.getStatus": [{
|
|
49946
|
+
name: "deviceId",
|
|
49947
|
+
form: "single",
|
|
49948
|
+
optional: false
|
|
49949
|
+
}],
|
|
49734
49950
|
"deviceAdoption.release": [{
|
|
49735
49951
|
name: "camDeviceId",
|
|
49736
49952
|
form: "single",
|
|
@@ -49746,6 +49962,11 @@ Object.freeze({
|
|
|
49746
49962
|
form: "single",
|
|
49747
49963
|
optional: false
|
|
49748
49964
|
}],
|
|
49965
|
+
"deviceDiscovery.getStatus": [{
|
|
49966
|
+
name: "deviceId",
|
|
49967
|
+
form: "single",
|
|
49968
|
+
optional: false
|
|
49969
|
+
}],
|
|
49749
49970
|
"deviceDiscovery.listDiscovered": [{
|
|
49750
49971
|
name: "deviceId",
|
|
49751
49972
|
form: "single",
|
|
@@ -49765,6 +49986,21 @@ Object.freeze({
|
|
|
49765
49986
|
form: "single",
|
|
49766
49987
|
optional: false
|
|
49767
49988
|
}],
|
|
49989
|
+
"deviceExport.applyDeviceSettingsPatch": [{
|
|
49990
|
+
name: "deviceId",
|
|
49991
|
+
form: "single",
|
|
49992
|
+
optional: false
|
|
49993
|
+
}],
|
|
49994
|
+
"deviceExport.getDeviceLiveContribution": [{
|
|
49995
|
+
name: "deviceId",
|
|
49996
|
+
form: "single",
|
|
49997
|
+
optional: false
|
|
49998
|
+
}],
|
|
49999
|
+
"deviceExport.getDeviceSettingsContribution": [{
|
|
50000
|
+
name: "deviceId",
|
|
50001
|
+
form: "single",
|
|
50002
|
+
optional: false
|
|
50003
|
+
}],
|
|
49768
50004
|
"deviceExtension.listCandidates": [{
|
|
49769
50005
|
name: "deviceId",
|
|
49770
50006
|
form: "single",
|
|
@@ -50113,6 +50349,26 @@ Object.freeze({
|
|
|
50113
50349
|
form: "single",
|
|
50114
50350
|
optional: false
|
|
50115
50351
|
}],
|
|
50352
|
+
"deviceStatus.getStatus": [{
|
|
50353
|
+
name: "deviceId",
|
|
50354
|
+
form: "single",
|
|
50355
|
+
optional: false
|
|
50356
|
+
}],
|
|
50357
|
+
"doorbell.getStatus": [{
|
|
50358
|
+
name: "deviceId",
|
|
50359
|
+
form: "single",
|
|
50360
|
+
optional: false
|
|
50361
|
+
}],
|
|
50362
|
+
"enumSensor.getStatus": [{
|
|
50363
|
+
name: "deviceId",
|
|
50364
|
+
form: "single",
|
|
50365
|
+
optional: false
|
|
50366
|
+
}],
|
|
50367
|
+
"eventEmitter.getStatus": [{
|
|
50368
|
+
name: "deviceId",
|
|
50369
|
+
form: "single",
|
|
50370
|
+
optional: false
|
|
50371
|
+
}],
|
|
50116
50372
|
"faceGallery.getFaceByTrack": [{
|
|
50117
50373
|
name: "deviceId",
|
|
50118
50374
|
form: "single",
|
|
@@ -50127,6 +50383,11 @@ Object.freeze({
|
|
|
50127
50383
|
form: "array",
|
|
50128
50384
|
optional: true
|
|
50129
50385
|
}],
|
|
50386
|
+
"fanControl.getStatus": [{
|
|
50387
|
+
name: "deviceId",
|
|
50388
|
+
form: "single",
|
|
50389
|
+
optional: false
|
|
50390
|
+
}],
|
|
50130
50391
|
"fanControl.setDirection": [{
|
|
50131
50392
|
name: "deviceId",
|
|
50132
50393
|
form: "single",
|
|
@@ -50147,6 +50408,26 @@ Object.freeze({
|
|
|
50147
50408
|
form: "single",
|
|
50148
50409
|
optional: false
|
|
50149
50410
|
}],
|
|
50411
|
+
"featureProbe.getStatus": [{
|
|
50412
|
+
name: "deviceId",
|
|
50413
|
+
form: "single",
|
|
50414
|
+
optional: false
|
|
50415
|
+
}],
|
|
50416
|
+
"flood.getStatus": [{
|
|
50417
|
+
name: "deviceId",
|
|
50418
|
+
form: "single",
|
|
50419
|
+
optional: false
|
|
50420
|
+
}],
|
|
50421
|
+
"gas.getStatus": [{
|
|
50422
|
+
name: "deviceId",
|
|
50423
|
+
form: "single",
|
|
50424
|
+
optional: false
|
|
50425
|
+
}],
|
|
50426
|
+
"humidifier.getStatus": [{
|
|
50427
|
+
name: "deviceId",
|
|
50428
|
+
form: "single",
|
|
50429
|
+
optional: false
|
|
50430
|
+
}],
|
|
50150
50431
|
"humidifier.setMode": [{
|
|
50151
50432
|
name: "deviceId",
|
|
50152
50433
|
form: "single",
|
|
@@ -50162,11 +50443,26 @@ Object.freeze({
|
|
|
50162
50443
|
form: "single",
|
|
50163
50444
|
optional: false
|
|
50164
50445
|
}],
|
|
50446
|
+
"humiditySensor.getStatus": [{
|
|
50447
|
+
name: "deviceId",
|
|
50448
|
+
form: "single",
|
|
50449
|
+
optional: false
|
|
50450
|
+
}],
|
|
50451
|
+
"image.getStatus": [{
|
|
50452
|
+
name: "deviceId",
|
|
50453
|
+
form: "single",
|
|
50454
|
+
optional: false
|
|
50455
|
+
}],
|
|
50165
50456
|
"imageSettings.getOptions": [{
|
|
50166
50457
|
name: "deviceId",
|
|
50167
50458
|
form: "single",
|
|
50168
50459
|
optional: false
|
|
50169
50460
|
}],
|
|
50461
|
+
"imageSettings.getStatus": [{
|
|
50462
|
+
name: "deviceId",
|
|
50463
|
+
form: "single",
|
|
50464
|
+
optional: false
|
|
50465
|
+
}],
|
|
50170
50466
|
"imageSettings.setSettings": [{
|
|
50171
50467
|
name: "deviceId",
|
|
50172
50468
|
form: "single",
|
|
@@ -50177,6 +50473,11 @@ Object.freeze({
|
|
|
50177
50473
|
form: "single",
|
|
50178
50474
|
optional: false
|
|
50179
50475
|
}],
|
|
50476
|
+
"intercom.getStatus": [{
|
|
50477
|
+
name: "deviceId",
|
|
50478
|
+
form: "single",
|
|
50479
|
+
optional: false
|
|
50480
|
+
}],
|
|
50180
50481
|
"intercom.handleAnswer": [{
|
|
50181
50482
|
name: "deviceId",
|
|
50182
50483
|
form: "single",
|
|
@@ -50207,6 +50508,11 @@ Object.freeze({
|
|
|
50207
50508
|
form: "single",
|
|
50208
50509
|
optional: false
|
|
50209
50510
|
}],
|
|
50511
|
+
"lawnMowerControl.getStatus": [{
|
|
50512
|
+
name: "deviceId",
|
|
50513
|
+
form: "single",
|
|
50514
|
+
optional: false
|
|
50515
|
+
}],
|
|
50210
50516
|
"lawnMowerControl.pause": [{
|
|
50211
50517
|
name: "deviceId",
|
|
50212
50518
|
form: "single",
|
|
@@ -50217,6 +50523,11 @@ Object.freeze({
|
|
|
50217
50523
|
form: "single",
|
|
50218
50524
|
optional: false
|
|
50219
50525
|
}],
|
|
50526
|
+
"lockControl.getStatus": [{
|
|
50527
|
+
name: "deviceId",
|
|
50528
|
+
form: "single",
|
|
50529
|
+
optional: false
|
|
50530
|
+
}],
|
|
50220
50531
|
"lockControl.lock": [{
|
|
50221
50532
|
name: "deviceId",
|
|
50222
50533
|
form: "single",
|
|
@@ -50232,6 +50543,11 @@ Object.freeze({
|
|
|
50232
50543
|
form: "single",
|
|
50233
50544
|
optional: false
|
|
50234
50545
|
}],
|
|
50546
|
+
"mediaPlayer.getStatus": [{
|
|
50547
|
+
name: "deviceId",
|
|
50548
|
+
form: "single",
|
|
50549
|
+
optional: false
|
|
50550
|
+
}],
|
|
50235
50551
|
"mediaPlayer.next": [{
|
|
50236
50552
|
name: "deviceId",
|
|
50237
50553
|
form: "single",
|
|
@@ -50292,6 +50608,11 @@ Object.freeze({
|
|
|
50292
50608
|
form: "single",
|
|
50293
50609
|
optional: false
|
|
50294
50610
|
}],
|
|
50611
|
+
"motion.getStatus": [{
|
|
50612
|
+
name: "deviceId",
|
|
50613
|
+
form: "single",
|
|
50614
|
+
optional: false
|
|
50615
|
+
}],
|
|
50295
50616
|
"motion.isDetected": [{
|
|
50296
50617
|
name: "deviceId",
|
|
50297
50618
|
form: "single",
|
|
@@ -50302,11 +50623,31 @@ Object.freeze({
|
|
|
50302
50623
|
form: "single",
|
|
50303
50624
|
optional: false
|
|
50304
50625
|
}],
|
|
50626
|
+
"motionDetection.applyDeviceSettingsPatch": [{
|
|
50627
|
+
name: "deviceId",
|
|
50628
|
+
form: "single",
|
|
50629
|
+
optional: false
|
|
50630
|
+
}],
|
|
50631
|
+
"motionDetection.getDeviceLiveContribution": [{
|
|
50632
|
+
name: "deviceId",
|
|
50633
|
+
form: "single",
|
|
50634
|
+
optional: false
|
|
50635
|
+
}],
|
|
50636
|
+
"motionDetection.getDeviceSettingsContribution": [{
|
|
50637
|
+
name: "deviceId",
|
|
50638
|
+
form: "single",
|
|
50639
|
+
optional: false
|
|
50640
|
+
}],
|
|
50305
50641
|
"motionDetection.removeCamera": [{
|
|
50306
50642
|
name: "deviceId",
|
|
50307
50643
|
form: "single",
|
|
50308
50644
|
optional: false
|
|
50309
50645
|
}],
|
|
50646
|
+
"motionTrigger.getStatus": [{
|
|
50647
|
+
name: "deviceId",
|
|
50648
|
+
form: "single",
|
|
50649
|
+
optional: false
|
|
50650
|
+
}],
|
|
50310
50651
|
"motionTrigger.setMotionTrigger": [{
|
|
50311
50652
|
name: "deviceId",
|
|
50312
50653
|
form: "single",
|
|
@@ -50317,6 +50658,11 @@ Object.freeze({
|
|
|
50317
50658
|
form: "single",
|
|
50318
50659
|
optional: false
|
|
50319
50660
|
}],
|
|
50661
|
+
"motionZones.getStatus": [{
|
|
50662
|
+
name: "deviceId",
|
|
50663
|
+
form: "single",
|
|
50664
|
+
optional: false
|
|
50665
|
+
}],
|
|
50320
50666
|
"motionZones.setZone": [{
|
|
50321
50667
|
name: "deviceId",
|
|
50322
50668
|
form: "single",
|
|
@@ -50327,6 +50673,11 @@ Object.freeze({
|
|
|
50327
50673
|
form: "single",
|
|
50328
50674
|
optional: false
|
|
50329
50675
|
}],
|
|
50676
|
+
"nativeObjectDetection.getStatus": [{
|
|
50677
|
+
name: "deviceId",
|
|
50678
|
+
form: "single",
|
|
50679
|
+
optional: false
|
|
50680
|
+
}],
|
|
50330
50681
|
"nativeObjectDetection.setEnabled": [{
|
|
50331
50682
|
name: "deviceId",
|
|
50332
50683
|
form: "single",
|
|
@@ -50342,6 +50693,11 @@ Object.freeze({
|
|
|
50342
50693
|
form: "single",
|
|
50343
50694
|
optional: false
|
|
50344
50695
|
}],
|
|
50696
|
+
"navigation.getStatus": [{
|
|
50697
|
+
name: "deviceId",
|
|
50698
|
+
form: "single",
|
|
50699
|
+
optional: false
|
|
50700
|
+
}],
|
|
50345
50701
|
"navigation.goToPoint": [{
|
|
50346
50702
|
name: "deviceId",
|
|
50347
50703
|
form: "single",
|
|
@@ -50387,6 +50743,11 @@ Object.freeze({
|
|
|
50387
50743
|
form: "single",
|
|
50388
50744
|
optional: false
|
|
50389
50745
|
}],
|
|
50746
|
+
"networkLink.getStatus": [{
|
|
50747
|
+
name: "deviceId",
|
|
50748
|
+
form: "single",
|
|
50749
|
+
optional: false
|
|
50750
|
+
}],
|
|
50390
50751
|
"networkQuality.getDeviceStats": [{
|
|
50391
50752
|
name: "deviceId",
|
|
50392
50753
|
form: "single",
|
|
@@ -50397,6 +50758,11 @@ Object.freeze({
|
|
|
50397
50758
|
form: "single",
|
|
50398
50759
|
optional: false
|
|
50399
50760
|
}],
|
|
50761
|
+
"notificationRules.getAlarmSensors": [{
|
|
50762
|
+
name: "deviceIds",
|
|
50763
|
+
form: "array",
|
|
50764
|
+
optional: false
|
|
50765
|
+
}],
|
|
50400
50766
|
"notificationRules.setDeviceMuted": [{
|
|
50401
50767
|
name: "deviceId",
|
|
50402
50768
|
form: "single",
|
|
@@ -50407,11 +50773,26 @@ Object.freeze({
|
|
|
50407
50773
|
form: "single",
|
|
50408
50774
|
optional: false
|
|
50409
50775
|
}],
|
|
50776
|
+
"notifier.getStatus": [{
|
|
50777
|
+
name: "deviceId",
|
|
50778
|
+
form: "single",
|
|
50779
|
+
optional: false
|
|
50780
|
+
}],
|
|
50410
50781
|
"notifier.send": [{
|
|
50411
50782
|
name: "deviceId",
|
|
50412
50783
|
form: "single",
|
|
50413
50784
|
optional: false
|
|
50414
50785
|
}],
|
|
50786
|
+
"numericSensor.getStatus": [{
|
|
50787
|
+
name: "deviceId",
|
|
50788
|
+
form: "single",
|
|
50789
|
+
optional: false
|
|
50790
|
+
}],
|
|
50791
|
+
"osd.getStatus": [{
|
|
50792
|
+
name: "deviceId",
|
|
50793
|
+
form: "single",
|
|
50794
|
+
optional: false
|
|
50795
|
+
}],
|
|
50415
50796
|
"osd.setOverlay": [{
|
|
50416
50797
|
name: "deviceId",
|
|
50417
50798
|
form: "single",
|
|
@@ -50471,6 +50852,11 @@ Object.freeze({
|
|
|
50471
50852
|
form: "single",
|
|
50472
50853
|
optional: false
|
|
50473
50854
|
}],
|
|
50855
|
+
"petFeeder.getStatus": [{
|
|
50856
|
+
name: "deviceId",
|
|
50857
|
+
form: "single",
|
|
50858
|
+
optional: false
|
|
50859
|
+
}],
|
|
50474
50860
|
"petFeeder.markFoodReplenished": [{
|
|
50475
50861
|
name: "deviceId",
|
|
50476
50862
|
form: "single",
|
|
@@ -50506,6 +50892,11 @@ Object.freeze({
|
|
|
50506
50892
|
form: "single",
|
|
50507
50893
|
optional: false
|
|
50508
50894
|
}],
|
|
50895
|
+
"pipelineAnalytics.applyDeviceSettingsPatch": [{
|
|
50896
|
+
name: "deviceId",
|
|
50897
|
+
form: "single",
|
|
50898
|
+
optional: false
|
|
50899
|
+
}],
|
|
50509
50900
|
"pipelineAnalytics.clearTrackRelation": [{
|
|
50510
50901
|
name: "deviceId",
|
|
50511
50902
|
form: "single",
|
|
@@ -50546,6 +50937,16 @@ Object.freeze({
|
|
|
50546
50937
|
form: "single",
|
|
50547
50938
|
optional: false
|
|
50548
50939
|
}],
|
|
50940
|
+
"pipelineAnalytics.getDeviceLiveContribution": [{
|
|
50941
|
+
name: "deviceId",
|
|
50942
|
+
form: "single",
|
|
50943
|
+
optional: false
|
|
50944
|
+
}],
|
|
50945
|
+
"pipelineAnalytics.getDeviceSettingsContribution": [{
|
|
50946
|
+
name: "deviceId",
|
|
50947
|
+
form: "single",
|
|
50948
|
+
optional: false
|
|
50949
|
+
}],
|
|
50549
50950
|
"pipelineAnalytics.getEventDensity": [{
|
|
50550
50951
|
name: "deviceId",
|
|
50551
50952
|
form: "single",
|
|
@@ -50761,6 +51162,11 @@ Object.freeze({
|
|
|
50761
51162
|
form: "single",
|
|
50762
51163
|
optional: true
|
|
50763
51164
|
}],
|
|
51165
|
+
"pipelineOrchestrator.applyDeviceSettingsPatch": [{
|
|
51166
|
+
name: "deviceId",
|
|
51167
|
+
form: "single",
|
|
51168
|
+
optional: false
|
|
51169
|
+
}],
|
|
50764
51170
|
"pipelineOrchestrator.assignAudio": [{
|
|
50765
51171
|
name: "deviceId",
|
|
50766
51172
|
form: "single",
|
|
@@ -50806,6 +51212,16 @@ Object.freeze({
|
|
|
50806
51212
|
form: "single",
|
|
50807
51213
|
optional: false
|
|
50808
51214
|
}],
|
|
51215
|
+
"pipelineOrchestrator.getDeviceLiveContribution": [{
|
|
51216
|
+
name: "deviceId",
|
|
51217
|
+
form: "single",
|
|
51218
|
+
optional: false
|
|
51219
|
+
}],
|
|
51220
|
+
"pipelineOrchestrator.getDeviceSettingsContribution": [{
|
|
51221
|
+
name: "deviceId",
|
|
51222
|
+
form: "single",
|
|
51223
|
+
optional: false
|
|
51224
|
+
}],
|
|
50809
51225
|
"pipelineOrchestrator.getPipelineAssignment": [{
|
|
50810
51226
|
name: "deviceId",
|
|
50811
51227
|
form: "single",
|
|
@@ -50926,11 +51342,31 @@ Object.freeze({
|
|
|
50926
51342
|
form: "single",
|
|
50927
51343
|
optional: true
|
|
50928
51344
|
}],
|
|
51345
|
+
"powerMeter.getStatus": [{
|
|
51346
|
+
name: "deviceId",
|
|
51347
|
+
form: "single",
|
|
51348
|
+
optional: false
|
|
51349
|
+
}],
|
|
51350
|
+
"presence.getStatus": [{
|
|
51351
|
+
name: "deviceId",
|
|
51352
|
+
form: "single",
|
|
51353
|
+
optional: false
|
|
51354
|
+
}],
|
|
51355
|
+
"pressureSensor.getStatus": [{
|
|
51356
|
+
name: "deviceId",
|
|
51357
|
+
form: "single",
|
|
51358
|
+
optional: false
|
|
51359
|
+
}],
|
|
50929
51360
|
"privacyMask.getOptions": [{
|
|
50930
51361
|
name: "deviceId",
|
|
50931
51362
|
form: "single",
|
|
50932
51363
|
optional: false
|
|
50933
51364
|
}],
|
|
51365
|
+
"privacyMask.getStatus": [{
|
|
51366
|
+
name: "deviceId",
|
|
51367
|
+
form: "single",
|
|
51368
|
+
optional: false
|
|
51369
|
+
}],
|
|
50934
51370
|
"privacyMask.setAudioEnabled": [{
|
|
50935
51371
|
name: "deviceId",
|
|
50936
51372
|
form: "single",
|
|
@@ -50981,6 +51417,11 @@ Object.freeze({
|
|
|
50981
51417
|
form: "single",
|
|
50982
51418
|
optional: false
|
|
50983
51419
|
}],
|
|
51420
|
+
"ptz.getStatus": [{
|
|
51421
|
+
name: "deviceId",
|
|
51422
|
+
form: "single",
|
|
51423
|
+
optional: false
|
|
51424
|
+
}],
|
|
50984
51425
|
"ptz.goHome": [{
|
|
50985
51426
|
name: "deviceId",
|
|
50986
51427
|
form: "single",
|
|
@@ -51071,6 +51512,11 @@ Object.freeze({
|
|
|
51071
51512
|
form: "single",
|
|
51072
51513
|
optional: false
|
|
51073
51514
|
}],
|
|
51515
|
+
"recordingArchive.applyDeviceSettingsPatch": [{
|
|
51516
|
+
name: "deviceId",
|
|
51517
|
+
form: "single",
|
|
51518
|
+
optional: false
|
|
51519
|
+
}],
|
|
51074
51520
|
"recordingArchive.deleteFootprint": [{
|
|
51075
51521
|
name: "deviceId",
|
|
51076
51522
|
form: "single",
|
|
@@ -51091,6 +51537,21 @@ Object.freeze({
|
|
|
51091
51537
|
form: "single",
|
|
51092
51538
|
optional: false
|
|
51093
51539
|
}],
|
|
51540
|
+
"recordingArchive.getDeviceLiveContribution": [{
|
|
51541
|
+
name: "deviceId",
|
|
51542
|
+
form: "single",
|
|
51543
|
+
optional: false
|
|
51544
|
+
}],
|
|
51545
|
+
"recordingArchive.getDeviceSettingsContribution": [{
|
|
51546
|
+
name: "deviceId",
|
|
51547
|
+
form: "single",
|
|
51548
|
+
optional: false
|
|
51549
|
+
}],
|
|
51550
|
+
"recordingArchive.getStatus": [{
|
|
51551
|
+
name: "deviceId",
|
|
51552
|
+
form: "single",
|
|
51553
|
+
optional: false
|
|
51554
|
+
}],
|
|
51094
51555
|
"recordingArchive.listOpsLog": [{
|
|
51095
51556
|
name: "deviceId",
|
|
51096
51557
|
form: "single",
|
|
@@ -51176,6 +51637,11 @@ Object.freeze({
|
|
|
51176
51637
|
form: "single",
|
|
51177
51638
|
optional: false
|
|
51178
51639
|
}],
|
|
51640
|
+
"recordingOnboard.getStatus": [{
|
|
51641
|
+
name: "deviceId",
|
|
51642
|
+
form: "single",
|
|
51643
|
+
optional: false
|
|
51644
|
+
}],
|
|
51179
51645
|
"recordingOnboard.setSettings": [{
|
|
51180
51646
|
name: "deviceId",
|
|
51181
51647
|
form: "single",
|
|
@@ -51206,6 +51672,11 @@ Object.freeze({
|
|
|
51206
51672
|
form: "single",
|
|
51207
51673
|
optional: false
|
|
51208
51674
|
}],
|
|
51675
|
+
"sceneMonitor.getStatus": [{
|
|
51676
|
+
name: "deviceId",
|
|
51677
|
+
form: "single",
|
|
51678
|
+
optional: false
|
|
51679
|
+
}],
|
|
51209
51680
|
"sceneMonitor.listScenes": [{
|
|
51210
51681
|
name: "deviceId",
|
|
51211
51682
|
form: "single",
|
|
@@ -51231,6 +51702,11 @@ Object.freeze({
|
|
|
51231
51702
|
form: "single",
|
|
51232
51703
|
optional: false
|
|
51233
51704
|
}],
|
|
51705
|
+
"scriptRunner.getStatus": [{
|
|
51706
|
+
name: "deviceId",
|
|
51707
|
+
form: "single",
|
|
51708
|
+
optional: false
|
|
51709
|
+
}],
|
|
51234
51710
|
"scriptRunner.run": [{
|
|
51235
51711
|
name: "deviceId",
|
|
51236
51712
|
form: "single",
|
|
@@ -51241,11 +51717,31 @@ Object.freeze({
|
|
|
51241
51717
|
form: "single",
|
|
51242
51718
|
optional: false
|
|
51243
51719
|
}],
|
|
51720
|
+
"smoke.getStatus": [{
|
|
51721
|
+
name: "deviceId",
|
|
51722
|
+
form: "single",
|
|
51723
|
+
optional: false
|
|
51724
|
+
}],
|
|
51725
|
+
"snapshot.applyDeviceSettingsPatch": [{
|
|
51726
|
+
name: "deviceId",
|
|
51727
|
+
form: "single",
|
|
51728
|
+
optional: false
|
|
51729
|
+
}],
|
|
51244
51730
|
"snapshot.getDebugState": [{
|
|
51245
51731
|
name: "deviceId",
|
|
51246
51732
|
form: "single",
|
|
51247
51733
|
optional: false
|
|
51248
51734
|
}],
|
|
51735
|
+
"snapshot.getDeviceLiveContribution": [{
|
|
51736
|
+
name: "deviceId",
|
|
51737
|
+
form: "single",
|
|
51738
|
+
optional: false
|
|
51739
|
+
}],
|
|
51740
|
+
"snapshot.getDeviceSettingsContribution": [{
|
|
51741
|
+
name: "deviceId",
|
|
51742
|
+
form: "single",
|
|
51743
|
+
optional: false
|
|
51744
|
+
}],
|
|
51249
51745
|
"snapshot.getSnapshot": [{
|
|
51250
51746
|
name: "deviceId",
|
|
51251
51747
|
form: "single",
|
|
@@ -51262,6 +51758,11 @@ Object.freeze({
|
|
|
51262
51758
|
form: "array",
|
|
51263
51759
|
optional: false
|
|
51264
51760
|
}],
|
|
51761
|
+
"snapshot.getStatus": [{
|
|
51762
|
+
name: "deviceId",
|
|
51763
|
+
form: "single",
|
|
51764
|
+
optional: false
|
|
51765
|
+
}],
|
|
51265
51766
|
"snapshot.invalidateCache": [{
|
|
51266
51767
|
name: "deviceId",
|
|
51267
51768
|
form: "single",
|
|
@@ -51272,6 +51773,11 @@ Object.freeze({
|
|
|
51272
51773
|
form: "single",
|
|
51273
51774
|
optional: false
|
|
51274
51775
|
}],
|
|
51776
|
+
"streamBroker.applyDeviceSettingsPatch": [{
|
|
51777
|
+
name: "deviceId",
|
|
51778
|
+
form: "single",
|
|
51779
|
+
optional: false
|
|
51780
|
+
}],
|
|
51275
51781
|
"streamBroker.assignProfile": [{
|
|
51276
51782
|
name: "deviceId",
|
|
51277
51783
|
form: "single",
|
|
@@ -51287,6 +51793,16 @@ Object.freeze({
|
|
|
51287
51793
|
form: "single",
|
|
51288
51794
|
optional: false
|
|
51289
51795
|
}],
|
|
51796
|
+
"streamBroker.getDeviceLiveContribution": [{
|
|
51797
|
+
name: "deviceId",
|
|
51798
|
+
form: "single",
|
|
51799
|
+
optional: false
|
|
51800
|
+
}],
|
|
51801
|
+
"streamBroker.getDeviceSettingsContribution": [{
|
|
51802
|
+
name: "deviceId",
|
|
51803
|
+
form: "single",
|
|
51804
|
+
optional: false
|
|
51805
|
+
}],
|
|
51290
51806
|
"streamBroker.getStreamWithCodec": [{
|
|
51291
51807
|
name: "deviceId",
|
|
51292
51808
|
form: "single",
|
|
@@ -51347,16 +51863,46 @@ Object.freeze({
|
|
|
51347
51863
|
form: "single",
|
|
51348
51864
|
optional: false
|
|
51349
51865
|
}],
|
|
51866
|
+
"streamParams.getStatus": [{
|
|
51867
|
+
name: "deviceId",
|
|
51868
|
+
form: "single",
|
|
51869
|
+
optional: false
|
|
51870
|
+
}],
|
|
51350
51871
|
"streamParams.setProfile": [{
|
|
51351
51872
|
name: "deviceId",
|
|
51352
51873
|
form: "single",
|
|
51353
51874
|
optional: false
|
|
51354
51875
|
}],
|
|
51876
|
+
"switch.getStatus": [{
|
|
51877
|
+
name: "deviceId",
|
|
51878
|
+
form: "single",
|
|
51879
|
+
optional: false
|
|
51880
|
+
}],
|
|
51355
51881
|
"switch.setState": [{
|
|
51356
51882
|
name: "deviceId",
|
|
51357
51883
|
form: "single",
|
|
51358
51884
|
optional: false
|
|
51359
51885
|
}],
|
|
51886
|
+
"tamper.getStatus": [{
|
|
51887
|
+
name: "deviceId",
|
|
51888
|
+
form: "single",
|
|
51889
|
+
optional: false
|
|
51890
|
+
}],
|
|
51891
|
+
"temperatureSensor.getStatus": [{
|
|
51892
|
+
name: "deviceId",
|
|
51893
|
+
form: "single",
|
|
51894
|
+
optional: false
|
|
51895
|
+
}],
|
|
51896
|
+
"update.getStatus": [{
|
|
51897
|
+
name: "deviceId",
|
|
51898
|
+
form: "single",
|
|
51899
|
+
optional: false
|
|
51900
|
+
}],
|
|
51901
|
+
"vacuumControl.getStatus": [{
|
|
51902
|
+
name: "deviceId",
|
|
51903
|
+
form: "single",
|
|
51904
|
+
optional: false
|
|
51905
|
+
}],
|
|
51360
51906
|
"vacuumControl.locate": [{
|
|
51361
51907
|
name: "deviceId",
|
|
51362
51908
|
form: "single",
|
|
@@ -51392,6 +51938,11 @@ Object.freeze({
|
|
|
51392
51938
|
form: "single",
|
|
51393
51939
|
optional: false
|
|
51394
51940
|
}],
|
|
51941
|
+
"valve.getStatus": [{
|
|
51942
|
+
name: "deviceId",
|
|
51943
|
+
form: "single",
|
|
51944
|
+
optional: false
|
|
51945
|
+
}],
|
|
51395
51946
|
"valve.open": [{
|
|
51396
51947
|
name: "deviceId",
|
|
51397
51948
|
form: "single",
|
|
@@ -51407,6 +51958,11 @@ Object.freeze({
|
|
|
51407
51958
|
form: "single",
|
|
51408
51959
|
optional: false
|
|
51409
51960
|
}],
|
|
51961
|
+
"vibration.getStatus": [{
|
|
51962
|
+
name: "deviceId",
|
|
51963
|
+
form: "single",
|
|
51964
|
+
optional: false
|
|
51965
|
+
}],
|
|
51410
51966
|
"videoclips.dialClipStream": [{
|
|
51411
51967
|
name: "deviceId",
|
|
51412
51968
|
form: "single",
|
|
@@ -51442,6 +51998,11 @@ Object.freeze({
|
|
|
51442
51998
|
form: "single",
|
|
51443
51999
|
optional: false
|
|
51444
52000
|
}],
|
|
52001
|
+
"waterHeater.getStatus": [{
|
|
52002
|
+
name: "deviceId",
|
|
52003
|
+
form: "single",
|
|
52004
|
+
optional: false
|
|
52005
|
+
}],
|
|
51445
52006
|
"waterHeater.setAway": [{
|
|
51446
52007
|
name: "deviceId",
|
|
51447
52008
|
form: "single",
|
|
@@ -51457,6 +52018,11 @@ Object.freeze({
|
|
|
51457
52018
|
form: "single",
|
|
51458
52019
|
optional: false
|
|
51459
52020
|
}],
|
|
52021
|
+
"weather.getStatus": [{
|
|
52022
|
+
name: "deviceId",
|
|
52023
|
+
form: "single",
|
|
52024
|
+
optional: false
|
|
52025
|
+
}],
|
|
51460
52026
|
"webrtcSession.addIceCandidate": [{
|
|
51461
52027
|
name: "deviceId",
|
|
51462
52028
|
form: "single",
|
|
@@ -52194,7 +52760,7 @@ var PreviewTextField = string().max(200);
|
|
|
52194
52760
|
* Whether the notification's preview is a STILL or a short animation.
|
|
52195
52761
|
*
|
|
52196
52762
|
* The operator's ask, verbatim: *"inviato come gif o video (come per le altre
|
|
52197
|
-
* rule)"* — the other rules already offer an animated preview, and a ten-hour
|
|
52763
|
+
* rule)"* [sent as a gif or video (as for the other rules)] — the other rules already offer an animated preview, and a ten-hour
|
|
52198
52764
|
* night reads better as three seconds of motion than as one frame of it. Both
|
|
52199
52765
|
* modes get the SAME treatment (blurred frame, large centred title); `'gif'`
|
|
52200
52766
|
* simply applies it to a dozen frames sampled across the render and assembles
|
|
@@ -52332,6 +52898,7 @@ TimelapseRuleInputSchema.extend({
|
|
|
52332
52898
|
createdAt: number(),
|
|
52333
52899
|
updatedAt: number()
|
|
52334
52900
|
});
|
|
52901
|
+
MotionOnMotionChangedDataSchema.omit({ triggeredBy: true });
|
|
52335
52902
|
object({
|
|
52336
52903
|
/**
|
|
52337
52904
|
* Fraction of the box's own size added on EACH side before cutting.
|