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