@camstack/addon-provider-rtsp 1.2.117 → 1.2.118
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
|
@@ -23,7 +23,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
23
23
|
//#endregion
|
|
24
24
|
let node_net = require("node:net");
|
|
25
25
|
node_net = __toESM(node_net);
|
|
26
|
-
//#region ../types/dist/event-category-
|
|
26
|
+
//#region ../types/dist/event-category-BGmz_oxW.mjs
|
|
27
27
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
28
28
|
EventCategory["SystemBoot"] = "system.boot";
|
|
29
29
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -556,6 +556,15 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
556
556
|
*/
|
|
557
557
|
EventCategory["PipelineAudioInferenceResult"] = "pipeline.audio-inference-result";
|
|
558
558
|
EventCategory["DetectionPhaseTransition"] = "detection.phase-transition";
|
|
559
|
+
/**
|
|
560
|
+
* A camera provider's RAW onboard motion push (D673): the `MotionOnMotionChanged`
|
|
561
|
+
* data shape without `triggeredBy`, built by `providerMotionEvent`. Its one
|
|
562
|
+
* consumer is the orchestrator's camera-sensors bridge, which re-emits the
|
|
563
|
+
* camera's EFFECTIVE onboard motion as `MotionOnMotionChanged` (a pass-through
|
|
564
|
+
* for a camera with no attached sensor). Providers must not emit
|
|
565
|
+
* `MotionOnMotionChanged` themselves; `scripts/check-onboard-motion-emitters.ts`
|
|
566
|
+
* keeps it so (camera-grid is a named, deferred exception).
|
|
567
|
+
*/
|
|
559
568
|
EventCategory["ProviderMotion"] = "provider.motion";
|
|
560
569
|
EventCategory["ProviderDetection"] = "provider.detection";
|
|
561
570
|
EventCategory["EnrichmentEmbeddingStored"] = "enrichment.embedding.stored";
|
|
@@ -5394,7 +5403,7 @@ var ZodIssueCode = {
|
|
|
5394
5403
|
var ZodFirstPartyTypeKind;
|
|
5395
5404
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5396
5405
|
//#endregion
|
|
5397
|
-
//#region ../types/dist/sleep-
|
|
5406
|
+
//#region ../types/dist/sleep-CDCONfkt.mjs
|
|
5398
5407
|
/**
|
|
5399
5408
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5400
5409
|
* window to float samples (D455).
|
|
@@ -7437,7 +7446,7 @@ function errMsg(err) {
|
|
|
7437
7446
|
return String(err);
|
|
7438
7447
|
}
|
|
7439
7448
|
//#endregion
|
|
7440
|
-
//#region ../types/dist/composition-
|
|
7449
|
+
//#region ../types/dist/composition-Bzr7GwgP.mjs
|
|
7441
7450
|
/**
|
|
7442
7451
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
7443
7452
|
*
|
|
@@ -7491,21 +7500,20 @@ function portable(target) {
|
|
|
7491
7500
|
}
|
|
7492
7501
|
portable("linux64"), portable("linuxarm64"), portable("macarm64"), portable("mac64");
|
|
7493
7502
|
/**
|
|
7494
|
-
*
|
|
7495
|
-
*
|
|
7503
|
+
* THE table "which boolean of this device type counts as HIGH", and the
|
|
7504
|
+
* pure evaluator of its EDGE.
|
|
7496
7505
|
*
|
|
7497
|
-
*
|
|
7498
|
-
*
|
|
7499
|
-
*
|
|
7500
|
-
*
|
|
7501
|
-
*
|
|
7502
|
-
*
|
|
7503
|
-
* SPOSTA qui e il doorbell la ri-esporta.
|
|
7506
|
+
* ONE table for everyone who asks "is this device HIGH?": the
|
|
7507
|
+
* recorder's `RecordingTriggers.sensorDeviceIds` trigger, the post-analysis
|
|
7508
|
+
* sensor markers, the orchestrator's camera-sensors bridge and
|
|
7509
|
+
* the sources of a composite doorbell (`doorbellFeatureSources`, D671).
|
|
7510
|
+
* A second copy would diverge at the first cap added, and the symptom — "the
|
|
7511
|
+
* sensor rings the doorbell but does not record" — is exactly D62.
|
|
7504
7512
|
*
|
|
7505
|
-
* ⚠
|
|
7506
|
-
*
|
|
7507
|
-
*
|
|
7508
|
-
*
|
|
7513
|
+
* ⚠ NOT `DEVICE_STATE_READERS` (`catalogs/device-state-vocabulary.ts`), and the
|
|
7514
|
+
* two must not be unified: that one answers "what is the state WORD for a
|
|
7515
|
+
* rule" (and includes `presence`, `cover`, `alarm-panel`), this one "which
|
|
7516
|
+
* boolean's EDGE counts". Deliberately different vocabularies.
|
|
7509
7517
|
*/
|
|
7510
7518
|
/**
|
|
7511
7519
|
* Known binary / switch source caps → the boolean slice field whose
|
|
@@ -9146,22 +9154,22 @@ var CLASS_MAP_MACRO_TARGETS = [
|
|
|
9146
9154
|
"package"
|
|
9147
9155
|
];
|
|
9148
9156
|
/**
|
|
9149
|
-
*
|
|
9150
|
-
*
|
|
9157
|
+
* The FIRST-LEVEL macro classes: those an object detector emits and that
|
|
9158
|
+
* an operator can select.
|
|
9151
9159
|
*
|
|
9152
|
-
*
|
|
9160
|
+
* They are the three offered by the `object-detection` step
|
|
9153
9161
|
* (`addon-pipeline/src/detection-pipeline/registry/step-definitions.ts`,
|
|
9154
|
-
* `enabledMacroClasses`). `package`
|
|
9155
|
-
* `MACRO_LABELS` —
|
|
9156
|
-
* `package-detection`,
|
|
9157
|
-
*
|
|
9162
|
+
* `enabledMacroClasses`). `package` is in {@link CLASS_MAP_MACRO_TARGETS} and in
|
|
9163
|
+
* `MACRO_LABELS` — it is a true macro — but NOT here: it belongs to the step
|
|
9164
|
+
* `package-detection`, whose enablement is driven by zones, and offering the
|
|
9165
|
+
* same word twice has already made an operator turn on the COCO proxy
|
|
9158
9166
|
* (suitcase/backpack/handbag) lasciando spento il detector dedicato.
|
|
9159
9167
|
*
|
|
9160
|
-
*
|
|
9161
|
-
*
|
|
9162
|
-
* (`types/detection.ts`);
|
|
9163
|
-
* (`RecordingTriggers.objectClasses`)
|
|
9164
|
-
*
|
|
9168
|
+
* ONE list. Before today the same three were hand-written in the step's offer
|
|
9169
|
+
* and a second time as the union `FirstLevelMacro`
|
|
9170
|
+
* (`types/detection.ts`); a third copy for the recording trigger
|
|
9171
|
+
* (`RecordingTriggers.objectClasses`) would have made the later divergence
|
|
9172
|
+
* invisible.
|
|
9165
9173
|
*/
|
|
9166
9174
|
var FIRST_LEVEL_MACRO_CLASSES = [
|
|
9167
9175
|
"person",
|
|
@@ -9226,17 +9234,17 @@ var RecordingStorageModeSchema = _enum([
|
|
|
9226
9234
|
"on-device-decision"
|
|
9227
9235
|
]);
|
|
9228
9236
|
/**
|
|
9229
|
-
*
|
|
9230
|
-
*
|
|
9237
|
+
* The macro classes that can open a recording window — the same
|
|
9238
|
+
* three offered by the `object-detection` step, from ONE list
|
|
9231
9239
|
* ({@link FIRST_LEVEL_MACRO_CLASSES}).
|
|
9232
9240
|
*/
|
|
9233
9241
|
var RecordingObjectTriggerClassSchema = _enum(FIRST_LEVEL_MACRO_CLASSES);
|
|
9234
9242
|
/**
|
|
9235
|
-
* True
|
|
9243
|
+
* True when `values` does not repeat an element.
|
|
9236
9244
|
*
|
|
9237
|
-
*
|
|
9238
|
-
*
|
|
9239
|
-
*
|
|
9245
|
+
* A duplicate is not harmless: every entry of `objectClasses` / `sensorDeviceIds`
|
|
9246
|
+
* becomes a SOURCE in `bandTriggerSources`, and the same source twice
|
|
9247
|
+
* would count its windows twice in `segmentMissedByMs`.
|
|
9240
9248
|
*/
|
|
9241
9249
|
var noDuplicates = (values) => new Set(values).size === values.length;
|
|
9242
9250
|
/** Which detectors trigger an `events`-mode band. */
|
|
@@ -9244,34 +9252,34 @@ var RecordingTriggersSchema = object({
|
|
|
9244
9252
|
motion: boolean().optional(),
|
|
9245
9253
|
audioThresholdDbfs: number().optional(),
|
|
9246
9254
|
/**
|
|
9247
|
-
*
|
|
9248
|
-
*
|
|
9249
|
-
*
|
|
9250
|
-
*
|
|
9255
|
+
* The macro classes whose detection opens a window. ABSENT = the source
|
|
9256
|
+
* is not listened to; an EMPTY array is rejected, because "events band, object
|
|
9257
|
+
* trigger on, no class" is the same shape "enabled and records
|
|
9258
|
+
* nothing, forever" that `eventsBandCanEverDemand` is written against.
|
|
9251
9259
|
*
|
|
9252
|
-
*
|
|
9253
|
-
*
|
|
9254
|
-
* `minConfidence<Macro>`
|
|
9255
|
-
* (`source: 'onboard'`)
|
|
9256
|
-
*
|
|
9260
|
+
* The signal read is ALREADY FILTERED: only `source: 'pipeline'` detections, i.e.
|
|
9261
|
+
* those that went through `enabledMacroClasses`, the
|
|
9262
|
+
* `minConfidence<Macro>` and the full-frame guard. The camera's onboard AI
|
|
9263
|
+
* (`source: 'onboard'`) goes through none of those gates and does NOT open
|
|
9264
|
+
* windows — see `recorder/object-trigger.ts`.
|
|
9257
9265
|
*/
|
|
9258
9266
|
objectClasses: array(RecordingObjectTriggerClassSchema).min(1).refine(noDuplicates, { message: "objectClasses must not repeat a class" }).optional(),
|
|
9259
9267
|
/**
|
|
9260
|
-
*
|
|
9261
|
-
*
|
|
9268
|
+
* The LINKED devices whose RISING EDGE opens a window. Absent = the source
|
|
9269
|
+
* is not listened to; an empty array is rejected for the same reason as
|
|
9262
9270
|
* `objectClasses`.
|
|
9263
9271
|
*
|
|
9264
|
-
*
|
|
9265
|
-
*
|
|
9266
|
-
*
|
|
9267
|
-
*
|
|
9268
|
-
* device (D12) —
|
|
9272
|
+
* These are SOURCE device ids, not cameras: the band names them, so the
|
|
9273
|
+
* hot path (`DeviceStateChanged`, at bus rate across the whole fleet)
|
|
9274
|
+
* does no RPC. The OFFER from which the operator picks them is another question, and
|
|
9275
|
+
* is resolved with `deviceManager.getLinkedDevices` + `getBindingsBatch` per
|
|
9276
|
+
* device (D12) — never a global list of caps.
|
|
9269
9277
|
*
|
|
9270
|
-
*
|
|
9271
|
-
* `SOURCE_CAP_ACTIVE_FIELD` (`catalogs/sensor-active-state.ts`)
|
|
9272
|
-
*
|
|
9273
|
-
*
|
|
9274
|
-
*
|
|
9278
|
+
* What "high" means depends on the device TYPE and is not decided here:
|
|
9279
|
+
* `SOURCE_CAP_ACTIVE_FIELD` (`catalogs/sensor-active-state.ts`) is THE table,
|
|
9280
|
+
* the same one as the composite doorbell (D671). And it is the EDGE, not
|
|
9281
|
+
* the level: a contact found already open at runner restart does not
|
|
9282
|
+
* record.
|
|
9275
9283
|
*/
|
|
9276
9284
|
sensorDeviceIds: array(number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional()
|
|
9277
9285
|
});
|
|
@@ -10348,7 +10356,7 @@ var DecoderSessionConfigSchema = object({
|
|
|
10348
10356
|
* - **VALUE** — at which level, for which scope, until when. That stays ONE
|
|
10349
10357
|
* thing: the logging settings document on the `system` cap. Two authorities
|
|
10350
10358
|
* over the values is the exact defect
|
|
10351
|
-
* `docs/design/plans/2026-08-26-
|
|
10359
|
+
* `docs/design/plans/2026-08-26-per-component-logging.md` was written to
|
|
10352
10360
|
* remove; re-introducing it from the cure side would be grotesque.
|
|
10353
10361
|
*
|
|
10354
10362
|
* Nothing in this file reads a clock, an env var or a store. The registry is
|
|
@@ -12059,7 +12067,7 @@ var BrokerStatusEnum = _enum([
|
|
|
12059
12067
|
"unreachable",
|
|
12060
12068
|
"error"
|
|
12061
12069
|
]);
|
|
12062
|
-
var BrokerInfoSchema
|
|
12070
|
+
var BrokerInfoSchema = object({
|
|
12063
12071
|
/** Stable broker id. Persisted; survives addon restarts. */
|
|
12064
12072
|
id: string(),
|
|
12065
12073
|
/** Addon id of the provider that OWNS this broker.
|
|
@@ -12192,7 +12200,7 @@ var GetStateInputSchema = object({
|
|
|
12192
12200
|
* HA: entity_id (returns the cached entity state). */
|
|
12193
12201
|
key: string()
|
|
12194
12202
|
});
|
|
12195
|
-
method(ListInputSchema, array(BrokerInfoSchema
|
|
12203
|
+
method(ListInputSchema, array(BrokerInfoSchema)), method(GetInputSchema, BrokerInfoSchema.nullable()), method(_void(), array(BrokerProviderInfoSchema), { auth: "admin" }), method(AddInputSchema, AddResultSchema, {
|
|
12196
12204
|
kind: "mutation",
|
|
12197
12205
|
auth: "admin"
|
|
12198
12206
|
}), method(RemoveInputSchema, _void(), {
|
|
@@ -13903,7 +13911,7 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
|
|
|
13903
13911
|
*
|
|
13904
13912
|
* ⚠ An earlier version of this comment blamed Zod stripping, and that
|
|
13905
13913
|
* was wrong — corrected 2026-08-26 after the hop map
|
|
13906
|
-
* (`docs/design/2026-08-26-
|
|
13914
|
+
* (`docs/design/2026-08-26-topic-hop-map.md`) traced the path.
|
|
13907
13915
|
* There is **no Zod parse at all** between the door and the engine: the
|
|
13908
13916
|
* dispatcher forwards the payload verbatim and UDS carries it whole. A
|
|
13909
13917
|
* field declared here reaches `SqliteSettingsBackend` either way.
|
|
@@ -14766,7 +14774,17 @@ var SiteZoneSchema = object({
|
|
|
14766
14774
|
var ProviderStatusSchema = object({
|
|
14767
14775
|
connected: boolean(),
|
|
14768
14776
|
deviceCount: number(),
|
|
14769
|
-
error: string().optional()
|
|
14777
|
+
error: string().optional(),
|
|
14778
|
+
/**
|
|
14779
|
+
* `'orchestrator'`: this provider writes NO camera's `motion` runtime slice
|
|
14780
|
+
* — the orchestrator is its only writer (D696). Set by `BaseDeviceProvider`,
|
|
14781
|
+
* which every provider bundles, so only a provider BUILT from D696-amended
|
|
14782
|
+
* code says it. ABSENT means an older provider that may still write it (raw
|
|
14783
|
+
* VMD writes, a boot seed), and the orchestrator's provider gate keeps that
|
|
14784
|
+
* provider's cameras unwritten (`camera-sensors/motion-slice-provider-gate.ts`)
|
|
14785
|
+
* — the provider twin of the runner's `getLocalLoad().motionSliceWriter`.
|
|
14786
|
+
*/
|
|
14787
|
+
motionSliceWriter: literal("orchestrator").optional()
|
|
14770
14788
|
});
|
|
14771
14789
|
object({
|
|
14772
14790
|
externalId: string(),
|
|
@@ -15645,109 +15663,10 @@ method(object({
|
|
|
15645
15663
|
deviceIds: array(number()).readonly(),
|
|
15646
15664
|
caps: array(string()).readonly().optional()
|
|
15647
15665
|
}), record(string(), record(string(), unknown().nullable())));
|
|
15648
|
-
|
|
15649
|
-
|
|
15650
|
-
* name (same pattern as `snapshot`):
|
|
15651
|
-
*
|
|
15652
|
-
* - **Native** providers: registered per-device by device-driver
|
|
15653
|
-
* addons via `ctx.registerNativeCap` — either on a
|
|
15654
|
-
* `DeviceType.Button` accessory with `role: DeviceRole.Doorbell`,
|
|
15655
|
-
* or directly on the camera (Reolink registers at camera level).
|
|
15656
|
-
* Emits an `onPressed` event every time the firmware pushes a
|
|
15657
|
-
* ring; status tracks the last press and a pressCount since start
|
|
15658
|
-
* (diagnostic).
|
|
15659
|
-
*
|
|
15660
|
-
* - **Wrapper** provider: the `virtual-doorbell` system builtin
|
|
15661
|
-
* (`@camstack/system/builtins/doorbell`). Turns ANY binary-ish
|
|
15662
|
-
* device (contact / switch / event-emitter …) into a doorbell for
|
|
15663
|
-
* a camera. `defaultActive: false` — the operator explicitly binds
|
|
15664
|
-
* it per camera in the device-bindings UI, then picks the source
|
|
15665
|
-
* device + trigger in the per-device settings.
|
|
15666
|
-
*
|
|
15667
|
-
* The DeviceEventPropagator re-emits `onPressed` on the camera parent
|
|
15668
|
-
* — subscribers listening at the camera level receive ring events
|
|
15669
|
-
* with `via[]` populated. No code on the parent needed.
|
|
15670
|
-
*/
|
|
15671
|
-
var DoorbellStatusSchema = object({
|
|
15672
|
-
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
15673
|
-
lastPressedAt: number().nullable(),
|
|
15674
|
-
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
15675
|
-
pressCountSinceStart: number()
|
|
15676
|
-
});
|
|
15677
|
-
var DoorbellPressEventSchema = object({
|
|
15678
|
-
deviceId: number(),
|
|
15679
|
-
timestamp: number()
|
|
15680
|
-
});
|
|
15681
|
-
/**
|
|
15682
|
-
* The `doorbell-source` extension slot's editable value (D648): the camera's
|
|
15683
|
-
* virtual-doorbell trigger devices, exactly what the wrapper's
|
|
15684
|
-
* `doorbellSources` persists (as `{ deviceId }` records).
|
|
15685
|
-
*/
|
|
15686
|
-
var DoorbellSourceSlotValueSchema = object({ deviceIds: array(number().int().positive()) });
|
|
15687
|
-
/**
|
|
15688
|
-
* The `doorbell-source` slot — which devices ring this camera's VIRTUAL
|
|
15689
|
-
* doorbell, owned by the `virtual-doorbell` wrapper over its
|
|
15690
|
-
* `doorbellSources` store (D648). A source rings when one of its
|
|
15691
|
-
* `SOURCE_CAPS` rises. Whether the wrapper is bound to the camera at all is a
|
|
15692
|
-
* different authority (`deviceManager.setWrapperActive`, D62) — the slot
|
|
15693
|
-
* reports it, it never writes it.
|
|
15694
|
-
*/
|
|
15695
|
-
var DOORBELL_SOURCE_SLOT = {
|
|
15696
|
-
id: "doorbell-source",
|
|
15697
|
-
label: "Doorbell trigger devices",
|
|
15698
|
-
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.",
|
|
15699
|
-
shape: "association",
|
|
15700
|
-
hostDeviceTypes: [DeviceType.Camera],
|
|
15701
|
-
sourceCaps: SOURCE_CAPS,
|
|
15702
|
-
cardinality: "many",
|
|
15703
|
-
value: DoorbellSourceSlotValueSchema
|
|
15704
|
-
};
|
|
15705
|
-
var doorbellCapability = {
|
|
15706
|
-
name: "doorbell",
|
|
15707
|
-
scope: "device",
|
|
15708
|
-
deviceNative: true,
|
|
15709
|
-
mode: "singleton",
|
|
15710
|
-
kind: "wrapper",
|
|
15711
|
-
defaultActive: false,
|
|
15712
|
-
deviceTypes: [DeviceType.Button, DeviceType.Camera],
|
|
15713
|
-
extensionSlots: [DOORBELL_SOURCE_SLOT],
|
|
15714
|
-
methods: {},
|
|
15715
|
-
events: {
|
|
15716
|
-
/**
|
|
15717
|
-
* Fires once per physical press. Reolink delivers via Baichuan
|
|
15718
|
-
* push (`ReolinkSimpleEvent.type === 'doorbell'`). There is no
|
|
15719
|
-
* release/duration — it's a pulse.
|
|
15720
|
-
*/
|
|
15721
|
-
onPressed: {
|
|
15722
|
-
data: DoorbellPressEventSchema,
|
|
15723
|
-
fromState: {
|
|
15724
|
-
field: "lastPressedAt",
|
|
15725
|
-
on: "advance"
|
|
15726
|
-
}
|
|
15727
|
-
} },
|
|
15728
|
-
status: {
|
|
15729
|
-
schema: DoorbellStatusSchema,
|
|
15730
|
-
kind: "push"
|
|
15731
|
-
},
|
|
15732
|
-
/**
|
|
15733
|
-
* Runtime-state slice — last press timestamp + lifetime press count.
|
|
15734
|
-
* Mirrored by the kernel and readable via
|
|
15735
|
-
* `device.state.doorbell.value`. UIs can show "last ring 5m ago"
|
|
15736
|
-
* without subscribing.
|
|
15737
|
-
*/
|
|
15738
|
-
runtimeState: DoorbellStatusSchema,
|
|
15739
|
-
/**
|
|
15740
|
-
* 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.
|
|
15741
|
-
*
|
|
15742
|
-
* See `RuntimeStateDurability`. Enforced by
|
|
15743
|
-
* `scripts/check-runtime-state-durability.ts`.
|
|
15744
|
-
*/
|
|
15745
|
-
durability: "restored"
|
|
15746
|
-
};
|
|
15747
|
-
var ExtensionSlotIdSchema = _enum(["doorbell-source", "linked-devices"]);
|
|
15748
|
-
DeviceType.Camera, DeviceType.Camera;
|
|
15666
|
+
var ExtensionSlotIdSchema = _enum(["linked-devices"]);
|
|
15667
|
+
DeviceType.Camera;
|
|
15749
15668
|
/** A slot's editable value, discriminated on `slot`. */
|
|
15750
|
-
var ExtensionSlotValueSchema = discriminatedUnion("slot", [
|
|
15669
|
+
var ExtensionSlotValueSchema = discriminatedUnion("slot", [LinkedDevicesSlotValueSchema.extend({ slot: literal("linked-devices") })]);
|
|
15751
15670
|
DeviceType.Camera;
|
|
15752
15671
|
var ExtensionSourceAvailabilitySchema = discriminatedUnion("state", [object({ state: literal("ok") }), object({
|
|
15753
15672
|
state: literal("unreachable"),
|
|
@@ -15784,10 +15703,11 @@ var ExtensionSlotSourceSchema = object({
|
|
|
15784
15703
|
});
|
|
15785
15704
|
/**
|
|
15786
15705
|
* A DIFFERENT authority that gates whether the slot's sources do anything —
|
|
15787
|
-
* reported read-only, named, never written through this contract (D62).
|
|
15788
|
-
*
|
|
15789
|
-
*
|
|
15790
|
-
* `unknown` means the gate could
|
|
15706
|
+
* reported read-only, named, never written through this contract (D62) — e.g.
|
|
15707
|
+
* a slot whose sources act only while a wrapper is bound to the host, a
|
|
15708
|
+
* binding that belongs to `deviceManager.setWrapperActive`. No slot reports
|
|
15709
|
+
* one today (`linked-devices` answers `null`). `unknown` means the gate could
|
|
15710
|
+
* not be read; it is not "inactive" (D315).
|
|
15791
15711
|
*/
|
|
15792
15712
|
var ExtensionSlotActivationSchema = object({
|
|
15793
15713
|
state: _enum([
|
|
@@ -15803,7 +15723,7 @@ var ExtensionSlotRowSchema = discriminatedUnion("state", [object({
|
|
|
15803
15723
|
/** `<source>:<slotId>` — the routing key for `listCandidates` / `setSlot`. */
|
|
15804
15724
|
slotRef: string(),
|
|
15805
15725
|
slot: ExtensionSlotIdSchema,
|
|
15806
|
-
/** Names the store written (D62), e.g. `
|
|
15726
|
+
/** Names the store written (D62), e.g. `device-manager:_linkedDeviceIds`. */
|
|
15807
15727
|
authority: string(),
|
|
15808
15728
|
activation: ExtensionSlotActivationSchema.nullable(),
|
|
15809
15729
|
value: ExtensionSlotValueSchema,
|
|
@@ -16081,7 +16001,7 @@ method(object({
|
|
|
16081
16001
|
* per-device window, `KeyFrameCaptureLog`, `bumpCropMetric`. Every one of them
|
|
16082
16002
|
* ends in a log line, and a log line is the thing the operator asked to stop
|
|
16083
16003
|
* needing: *"possiamo armare questi errori intanto? Così al prossimo giro
|
|
16084
|
-
* ricontrolliamo tutti questi punti"
|
|
16004
|
+
* 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
|
|
16085
16005
|
* hand-correlating timestamps, which is how a 22% thumbnail gap and a 3-hour
|
|
16086
16006
|
* media blackout were both diagnosed. The counters stay; this is where they can
|
|
16087
16007
|
* be READ.
|
|
@@ -17457,7 +17377,7 @@ var BrokerStatusSchema$1 = _enum([
|
|
|
17457
17377
|
"unreachable",
|
|
17458
17378
|
"tls-error"
|
|
17459
17379
|
]);
|
|
17460
|
-
var BrokerInfoSchema = object({
|
|
17380
|
+
var BrokerInfoSchema$1 = object({
|
|
17461
17381
|
id: string(),
|
|
17462
17382
|
name: string(),
|
|
17463
17383
|
url: string(),
|
|
@@ -17520,7 +17440,7 @@ var StatusSchema = object({
|
|
|
17520
17440
|
brokerCount: number(),
|
|
17521
17441
|
embeddedRunning: boolean()
|
|
17522
17442
|
});
|
|
17523
|
-
method(_void(), array(BrokerInfoSchema)), method(IdInputSchema, BrokerConnectionDetailsSchema, { auth: "admin" }), method(AddBrokerInputSchema, AddBrokerResultSchema, {
|
|
17443
|
+
method(_void(), array(BrokerInfoSchema$1)), method(IdInputSchema, BrokerConnectionDetailsSchema, { auth: "admin" }), method(AddBrokerInputSchema, AddBrokerResultSchema, {
|
|
17524
17444
|
kind: "mutation",
|
|
17525
17445
|
auth: "admin"
|
|
17526
17446
|
}), method(IdInputSchema, _void(), {
|
|
@@ -19734,78 +19654,16 @@ var NcRuleInputSchema = object({
|
|
|
19734
19654
|
*/
|
|
19735
19655
|
confirm: NcConfirmSchema.optional(),
|
|
19736
19656
|
/**
|
|
19737
|
-
*
|
|
19738
|
-
*
|
|
19739
|
-
*
|
|
19740
|
-
*
|
|
19741
|
-
*
|
|
19742
|
-
*
|
|
19743
|
-
*
|
|
19744
|
-
*
|
|
19745
|
-
*
|
|
19746
|
-
* Only two honest answers exist, and this flag picks between them. It has
|
|
19747
|
-
* effect ONLY on a rule that declares a recognition scope
|
|
19748
|
-
* ({@link NcConditions.identities} or {@link NcConditions.plates}) — on any
|
|
19749
|
-
* other rule there is nothing to wait for and the flag is inert.
|
|
19750
|
-
*
|
|
19751
|
-
* | value | what happens |
|
|
19752
|
-
* | --- | --- |
|
|
19753
|
-
* | `true` | the rule stops firing on the object event and fires at TRACK CLOSE instead, once, with the name — later, and complete |
|
|
19754
|
-
* | 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) |
|
|
19755
|
-
*
|
|
19756
|
-
* `.optional()` and deliberately NOT `.default()`: a Zod default does not run
|
|
19757
|
-
* on the addon cap path, and absent has to keep meaning exactly what every
|
|
19758
|
-
* rule authored before this field meant.
|
|
19759
|
-
*
|
|
19760
|
-
* The cost of `true` is stated here because the editor states it too: a rule
|
|
19761
|
-
* that waits also inherits track-close SEMANTICS — its `zones` condition
|
|
19762
|
-
* tests every zone the track visited and a `crossing` condition can no longer
|
|
19763
|
-
* be satisfied, because a closed track carries no crossing.
|
|
19657
|
+
* IMMEDIATE GROUPED (D692): the first matching subject opens a window of this many
|
|
19658
|
+
* seconds; the rule sends ONE message when the window closes — early, once every
|
|
19659
|
+
* subject in it is final, never before {@link NC_GROUPING_MIN_SEC} — naming everybody
|
|
19660
|
+
* the rule matched, with one mosaic tile per subject.
|
|
19661
|
+
* Absent = plain immediate (one message per track, at the first match).
|
|
19662
|
+
* Only an `immediate` DETECTION rule may carry it (`ruleGroupingApplies`, enforced on
|
|
19663
|
+
* save by the hub's grouping guard). `.optional()`, never `.default()`: the addon cap
|
|
19664
|
+
* path does not run Zod defaults.
|
|
19764
19665
|
*/
|
|
19765
|
-
|
|
19766
|
-
/**
|
|
19767
|
-
* GROUP a burst of subjects into ONE notification that grows.
|
|
19768
|
-
*
|
|
19769
|
-
* Seconds of quiet after the last matching subject before the burst is
|
|
19770
|
-
* considered over. While it is open, the first subject enqueues immediately —
|
|
19771
|
-
* **exactly as today, with no added latency** — and every real growth (a new
|
|
19772
|
-
* subject, or a name confirmed on one already in it) REPLACES that
|
|
19773
|
-
* notification with an updated one naming everybody. The push carries the
|
|
19774
|
-
* group's own coalescing tag, so the phone replaces rather than stacks.
|
|
19775
|
-
*
|
|
19776
|
-
* `0` / absent = off, and off is today's behaviour byte for byte.
|
|
19777
|
-
*
|
|
19778
|
-
* ### Why an idle cutoff and not a window
|
|
19779
|
-
*
|
|
19780
|
-
* The measured seven-person arrival on device 590 spans 110 s with every
|
|
19781
|
-
* internal gap under 30 s. A 12 s fixed window cuts it into three groups; an
|
|
19782
|
-
* idle cutoff holds it as one and ends it when the arrival actually ends.
|
|
19783
|
-
* 30 s is a widely shipped value for the same decision.
|
|
19784
|
-
*
|
|
19785
|
-
* ### What it replaces
|
|
19786
|
-
*
|
|
19787
|
-
* The blind cooldown, which collapses a burst by DISCARDING it. Measured on
|
|
19788
|
-
* device 615 / *Persona su Uscio* over six days: 116 qualifying tracks → 74
|
|
19789
|
-
* notifications, **44 (37.9%) suppressed outright**, 23 of them overlapping a
|
|
19790
|
-
* track that did fire and 7 carrying a confirmed identity nobody heard about.
|
|
19791
|
-
* A group collapses the same volume by MERGING, so the cooldown becomes a
|
|
19792
|
-
* budget over GROUPS — which is what it always meant — and a growth is never
|
|
19793
|
-
* throttled by the window its own first member spent.
|
|
19794
|
-
*
|
|
19795
|
-
* ### Interaction with {@link waitForEnhancement}
|
|
19796
|
-
*
|
|
19797
|
-
* They compose, and the order matters. `waitForEnhancement` defers the rule to
|
|
19798
|
-
* TRACK CLOSE, so with both set the group is opened by the first member to
|
|
19799
|
-
* CLOSE — already carrying its name — and grows as later members close. That
|
|
19800
|
-
* is later, and complete. With grouping alone the group opens on the first
|
|
19801
|
-
* object event and picks up names as they are confirmed, through the growth
|
|
19802
|
-
* path. Neither combination fires twice for one subject.
|
|
19803
|
-
*
|
|
19804
|
-
* `.optional()` and deliberately NOT `.default()`: a Zod default does not run
|
|
19805
|
-
* on the addon cap path, so absent must keep meaning what it meant before this
|
|
19806
|
-
* field existed.
|
|
19807
|
-
*/
|
|
19808
|
-
groupIdleSec: number().int().min(0).max(600).optional()
|
|
19666
|
+
groupingSec: number().int().min(5).max(60).optional()
|
|
19809
19667
|
});
|
|
19810
19668
|
/**
|
|
19811
19669
|
* Partial patch for `updateRule` — any subset of the input fields, plus the
|
|
@@ -19853,9 +19711,10 @@ var NcRuleClearableKeySchema = _enum([
|
|
|
19853
19711
|
"targetUsers",
|
|
19854
19712
|
"snoozeOptions",
|
|
19855
19713
|
"snoozeAllowGlobal",
|
|
19856
|
-
"waitForEnhancement",
|
|
19857
19714
|
"actions",
|
|
19858
19715
|
"confirm",
|
|
19716
|
+
"groupingSec",
|
|
19717
|
+
"waitForEnhancement",
|
|
19859
19718
|
"groupIdleSec"
|
|
19860
19719
|
]);
|
|
19861
19720
|
var NcRuleUpdateInputSchema = object({
|
|
@@ -19877,9 +19736,25 @@ var NcRuleSchema = NcRuleInputSchema.extend({
|
|
|
19877
19736
|
*/
|
|
19878
19737
|
disabledTargetIds: array(string()).default([])
|
|
19879
19738
|
});
|
|
19739
|
+
/**
|
|
19740
|
+
* The state-summary SECTIONS (D647 / D698): the D637 kind groups that report a
|
|
19741
|
+
* still-true state. `backups-exports` and `alarm` are not sections — a completed
|
|
19742
|
+
* job is not an open state, and the alarm stays instant.
|
|
19743
|
+
*/
|
|
19744
|
+
var NcStateSummarySectionIdSchema = _enum([
|
|
19745
|
+
"device-state",
|
|
19746
|
+
"streams",
|
|
19747
|
+
"battery",
|
|
19748
|
+
"consumables",
|
|
19749
|
+
"tanks",
|
|
19750
|
+
"detection-blind",
|
|
19751
|
+
"nodes",
|
|
19752
|
+
"addons",
|
|
19753
|
+
"updates"
|
|
19754
|
+
]);
|
|
19880
19755
|
/** One section of a previewed state summary. `unavailable` = its state could not be read. */
|
|
19881
19756
|
var NcStateSummaryPreviewSectionSchema = object({
|
|
19882
|
-
id:
|
|
19757
|
+
id: NcStateSummarySectionIdSchema,
|
|
19883
19758
|
status: _enum(["read", "unavailable"]),
|
|
19884
19759
|
items: number().int().nonnegative(),
|
|
19885
19760
|
reason: string().optional()
|
|
@@ -19889,7 +19764,7 @@ var NcStateSummaryPreviewSectionSchema = object({
|
|
|
19889
19764
|
* a `rule` split (no `section`), one section's on a `section` split.
|
|
19890
19765
|
*/
|
|
19891
19766
|
var NcStateSummaryPreviewRowSchema = object({
|
|
19892
|
-
section:
|
|
19767
|
+
section: NcStateSummarySectionIdSchema.optional(),
|
|
19893
19768
|
/** The section's name on a per-section row; every reported section's, joined, on a combined one. */
|
|
19894
19769
|
title: string(),
|
|
19895
19770
|
text: string(),
|
|
@@ -20326,6 +20201,29 @@ object({
|
|
|
20326
20201
|
firstAt: number(),
|
|
20327
20202
|
lastAt: number()
|
|
20328
20203
|
});
|
|
20204
|
+
var NC_ALARM_TRIGGERED_MAX_SEC = 3600;
|
|
20205
|
+
var NcAlarmDelaySecSchema = number().int().min(0).max(600);
|
|
20206
|
+
var NcAlarmTriggeredSecSchema = number().int().min(0).max(NC_ALARM_TRIGGERED_MAX_SEC);
|
|
20207
|
+
var uniqueModes = (entries) => new Set(entries.map((e) => e.mode)).size === entries.length;
|
|
20208
|
+
var NcAlarmModeDelaysListSchema = array(object({
|
|
20209
|
+
mode: AlarmArmModeSchema,
|
|
20210
|
+
exitDelaySec: NcAlarmDelaySecSchema.optional(),
|
|
20211
|
+
entryDelaySec: NcAlarmDelaySecSchema.optional(),
|
|
20212
|
+
triggeredDurationSec: NcAlarmTriggeredSecSchema.optional()
|
|
20213
|
+
})).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
|
|
20214
|
+
var NcAlarmModeDelaysEditListSchema = array(object({
|
|
20215
|
+
mode: AlarmArmModeSchema,
|
|
20216
|
+
exitDelaySec: NcAlarmDelaySecSchema.nullable().optional(),
|
|
20217
|
+
entryDelaySec: NcAlarmDelaySecSchema.nullable().optional(),
|
|
20218
|
+
triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional()
|
|
20219
|
+
})).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
|
|
20220
|
+
/** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
|
|
20221
|
+
var NcAlarmNonBlockingEditSchema = object({
|
|
20222
|
+
mode: AlarmArmModeSchema,
|
|
20223
|
+
deviceId: number().int().positive(),
|
|
20224
|
+
/** true = on the list (may be open, does not block); false = off the list (blocks). */
|
|
20225
|
+
nonBlocking: boolean()
|
|
20226
|
+
});
|
|
20329
20227
|
/**
|
|
20330
20228
|
* The per-mode lists, at most one per mode. Two lists for one mode have no
|
|
20331
20229
|
* meaning a reader could agree on (union? the last one?), so they are refused
|
|
@@ -20334,10 +20232,10 @@ object({
|
|
|
20334
20232
|
var NcAlarmNonBlockingListSchema = array(object({
|
|
20335
20233
|
mode: AlarmArmModeSchema,
|
|
20336
20234
|
deviceIds: array(number().int()).max(200)
|
|
20337
|
-
})).max(8).refine(
|
|
20235
|
+
})).max(8).refine(uniqueModes, { message: "nonBlocking: at most one list per arm mode" });
|
|
20338
20236
|
/**
|
|
20339
|
-
* The three durations
|
|
20340
|
-
* transitions, and which openings each mode tolerates.
|
|
20237
|
+
* The three durations — global, and per mode since D697 — the panel's state
|
|
20238
|
+
* machine runs on, who hears about its transitions, and which openings each mode tolerates.
|
|
20341
20239
|
*
|
|
20342
20240
|
* They live on the NOTIFICATION-RULES cap, not on `alarm-panel`, on purpose:
|
|
20343
20241
|
* `alarm-panel` is `deviceNative` and its other provider mirrors somebody
|
|
@@ -20347,15 +20245,15 @@ var NcAlarmNonBlockingListSchema = array(object({
|
|
|
20347
20245
|
*/
|
|
20348
20246
|
var NcAlarmSettingsSchema = object({
|
|
20349
20247
|
/** Grace period between arming and the mode taking effect. 0 = immediate. */
|
|
20350
|
-
exitDelaySec:
|
|
20248
|
+
exitDelaySec: NcAlarmDelaySecSchema,
|
|
20351
20249
|
/** Grace period between a trigger and the alarm firing. 0 = immediate. */
|
|
20352
|
-
entryDelaySec:
|
|
20250
|
+
entryDelaySec: NcAlarmDelaySecSchema,
|
|
20353
20251
|
/**
|
|
20354
20252
|
* How long `triggered` lasts before the panel re-arms itself.
|
|
20355
20253
|
* **0 = until an operator disarms it** — the behaviour before this field
|
|
20356
20254
|
* existed, and therefore what an untouched install keeps doing.
|
|
20357
20255
|
*/
|
|
20358
|
-
triggeredDurationSec:
|
|
20256
|
+
triggeredDurationSec: NcAlarmTriggeredSecSchema,
|
|
20359
20257
|
/**
|
|
20360
20258
|
* Deprecated by D630 — every transition is announced. Parsed, never read;
|
|
20361
20259
|
* remove after one release. Optional so an older admin's patch (which still
|
|
@@ -20378,17 +20276,30 @@ var NcAlarmSettingsSchema = object({
|
|
|
20378
20276
|
* per mode is meaningful. Defaulted to `[]` so a blob stored before D630
|
|
20379
20277
|
* parses as "every opening blocks" — the behaviour it was written under.
|
|
20380
20278
|
*/
|
|
20381
|
-
nonBlocking: NcAlarmNonBlockingListSchema.default([])
|
|
20279
|
+
nonBlocking: NcAlarmNonBlockingListSchema.default([]),
|
|
20280
|
+
/**
|
|
20281
|
+
* Per arm mode, the delays that mode OVERRIDES (D697). A mode with no entry, or an entry
|
|
20282
|
+
* without a field, uses the global value above — so `[]`, the default, is exactly the
|
|
20283
|
+
* behaviour of a blob stored before this field existed. Read through `resolveModeDelays`.
|
|
20284
|
+
*/
|
|
20285
|
+
modeDelays: NcAlarmModeDelaysListSchema.default([])
|
|
20382
20286
|
});
|
|
20383
20287
|
/**
|
|
20384
20288
|
* Every field optional — a tab edits one control at a time.
|
|
20385
20289
|
*
|
|
20386
|
-
* `nonBlocking`
|
|
20387
|
-
* remove an inner `.default()`, so a patch that never
|
|
20388
|
-
* parse to `
|
|
20389
|
-
* (the same trap {@link NcRulePatchSchema} documents).
|
|
20290
|
+
* `nonBlocking` and `modeDelays` are re-declared WITHOUT their defaults:
|
|
20291
|
+
* `.partial()` does not remove an inner `.default()`, so a patch that never
|
|
20292
|
+
* named the field would parse to `[]` and wipe every mode's list on an
|
|
20293
|
+
* unrelated edit (the same trap {@link NcRulePatchSchema} documents). Here
|
|
20294
|
+
* `modeDelays` means EDITS, not the stored overrides.
|
|
20390
20295
|
*/
|
|
20391
|
-
var NcAlarmSettingsPatchSchema = NcAlarmSettingsSchema.extend({
|
|
20296
|
+
var NcAlarmSettingsPatchSchema = NcAlarmSettingsSchema.extend({
|
|
20297
|
+
nonBlocking: NcAlarmNonBlockingListSchema,
|
|
20298
|
+
/** Per-mode, per-field edits — NOT the whole list (see NcAlarmModeDelaysEditSchema). */
|
|
20299
|
+
modeDelays: NcAlarmModeDelaysEditListSchema,
|
|
20300
|
+
/** ONE membership change; the panel applies it to the list it holds at its turn. */
|
|
20301
|
+
nonBlockingEdit: NcAlarmNonBlockingEditSchema
|
|
20302
|
+
}).partial().refine((p) => p.nonBlocking === void 0 || p.nonBlockingEdit === void 0, { message: "nonBlocking and nonBlockingEdit are exclusive — send the whole lists or one edit" });
|
|
20392
20303
|
/**
|
|
20393
20304
|
* What one arm mode actually arms, DERIVED from the enabled rules gated on it.
|
|
20394
20305
|
* Never authored, never stored — see `alarm-mode-coverage.ts` for why a stored
|
|
@@ -20488,6 +20399,28 @@ var NcAlarmConfigSchema = object({
|
|
|
20488
20399
|
*/
|
|
20489
20400
|
live: NcAlarmLiveSchema.optional()
|
|
20490
20401
|
});
|
|
20402
|
+
var NcAlarmSensorReadingSchema = _enum([
|
|
20403
|
+
"open",
|
|
20404
|
+
"closed",
|
|
20405
|
+
"unknown",
|
|
20406
|
+
"not-opening"
|
|
20407
|
+
]);
|
|
20408
|
+
/** One device's state as the alarm reads it — the classifier the arm check uses. */
|
|
20409
|
+
var NcAlarmSensorStateSchema = object({
|
|
20410
|
+
deviceId: number().int().positive(),
|
|
20411
|
+
reading: NcAlarmSensorReadingSchema,
|
|
20412
|
+
/** The word as read (`open`, `closed`, `unlocked`, `stopped`, …); null when unknown / not an opening. */
|
|
20413
|
+
state: string().nullable(),
|
|
20414
|
+
/** Why `unknown`: the read failed, or the slice holds no word its cap defines (a placeholder included). */
|
|
20415
|
+
unknownWhy: _enum(["read-failed", "unknown-word"]).nullable(),
|
|
20416
|
+
/** The device manager's liveness as the centre mirrors it; null = not known. */
|
|
20417
|
+
online: boolean().nullable()
|
|
20418
|
+
});
|
|
20419
|
+
var NcAlarmSensorsInputSchema = object({ deviceIds: array(number().int().positive()).max(500) });
|
|
20420
|
+
var NcAlarmSensorsSchema = object({
|
|
20421
|
+
sensors: array(NcAlarmSensorStateSchema),
|
|
20422
|
+
readAt: number().int().nonnegative()
|
|
20423
|
+
});
|
|
20491
20424
|
/**
|
|
20492
20425
|
* ONE rule's demand on ONE camera's clip ring.
|
|
20493
20426
|
*
|
|
@@ -20578,7 +20511,7 @@ method(object({}), object({ rules: array(NcRuleSchema) }), { auth: "admin" }), m
|
|
|
20578
20511
|
}), method(object({}), NcAlarmConfigSchema, { auth: "admin" }), method(object({ patch: NcAlarmSettingsPatchSchema }), NcAlarmConfigSchema, {
|
|
20579
20512
|
kind: "mutation",
|
|
20580
20513
|
auth: "admin"
|
|
20581
|
-
});
|
|
20514
|
+
}), method(NcAlarmSensorsInputSchema, NcAlarmSensorsSchema, { auth: "admin" });
|
|
20582
20515
|
/**
|
|
20583
20516
|
* Zod schemas for persisted record types.
|
|
20584
20517
|
*
|
|
@@ -20925,12 +20858,26 @@ var CameraSensorRefSchema = object({
|
|
|
20925
20858
|
function cameraSensorRefKey(ref) {
|
|
20926
20859
|
return `${ref.addonId}/${ref.stableId}`;
|
|
20927
20860
|
}
|
|
20928
|
-
/**
|
|
20929
|
-
|
|
20930
|
-
|
|
20931
|
-
|
|
20932
|
-
|
|
20933
|
-
|
|
20861
|
+
/**
|
|
20862
|
+
* A sensor's mode (D673). `in-addition`: its motion is the camera's motion too.
|
|
20863
|
+
* `replace`: its motion is the camera's, and while one is READY the camera's
|
|
20864
|
+
* own motion no longer counts on its own. `confirm`: while one is READY the
|
|
20865
|
+
* camera's own motion counts only while a confirm sensor is active — with or
|
|
20866
|
+
* without a replace sensor (spec C2, the controller's ruling on Q1).
|
|
20867
|
+
*/
|
|
20868
|
+
var CameraSensorModeSchema = _enum([
|
|
20869
|
+
"in-addition",
|
|
20870
|
+
"confirm",
|
|
20871
|
+
"replace"
|
|
20872
|
+
]);
|
|
20873
|
+
/** A stored sensor with no mode — every CS-1 row — is in addition. */
|
|
20874
|
+
var DEFAULT_CAMERA_SENSOR_MODE = "in-addition";
|
|
20875
|
+
/**
|
|
20876
|
+
* A camera's attached sensors. A CS-1 row carried an envelope
|
|
20877
|
+
* `mode: 'in-addition'`: `z.object` drops it on parse, and the PARSED value is
|
|
20878
|
+
* what the write stores (D672 rule 3), so it is never written again.
|
|
20879
|
+
*/
|
|
20880
|
+
var CameraSensorsConfigSchema = object({ sensors: array(CameraSensorRefSchema.extend({ mode: CameraSensorModeSchema.default(DEFAULT_CAMERA_SENSOR_MODE) })).min(1).max(8) }).superRefine((value, ctx) => {
|
|
20934
20881
|
const seen = /* @__PURE__ */ new Set();
|
|
20935
20882
|
value.sensors.forEach((ref, index) => {
|
|
20936
20883
|
const key = cameraSensorRefKey(ref);
|
|
@@ -20942,39 +20889,41 @@ var CameraSensorsConfigSchema = object({
|
|
|
20942
20889
|
seen.add(key);
|
|
20943
20890
|
});
|
|
20944
20891
|
});
|
|
20945
|
-
|
|
20892
|
+
/** Every attachment names its mode; an older orchestrator that does not is in addition. */
|
|
20893
|
+
var AttachmentFields = {
|
|
20946
20894
|
addonId: string(),
|
|
20947
|
-
stableId: string()
|
|
20895
|
+
stableId: string(),
|
|
20896
|
+
mode: CameraSensorModeSchema.default(DEFAULT_CAMERA_SENSOR_MODE)
|
|
20948
20897
|
};
|
|
20949
20898
|
var CameraSensorAttachmentSchema = discriminatedUnion("state", [
|
|
20950
20899
|
object({
|
|
20951
|
-
...
|
|
20900
|
+
...AttachmentFields,
|
|
20952
20901
|
state: literal("ready"),
|
|
20953
20902
|
deviceId: number(),
|
|
20954
20903
|
name: string(),
|
|
20955
20904
|
caps: array(string()).readonly()
|
|
20956
20905
|
}),
|
|
20957
20906
|
object({
|
|
20958
|
-
...
|
|
20907
|
+
...AttachmentFields,
|
|
20959
20908
|
state: literal("offline"),
|
|
20960
20909
|
deviceId: number(),
|
|
20961
20910
|
name: string(),
|
|
20962
20911
|
reason: _enum(["offline", "disabled"])
|
|
20963
20912
|
}),
|
|
20964
20913
|
object({
|
|
20965
|
-
...
|
|
20914
|
+
...AttachmentFields,
|
|
20966
20915
|
state: literal("missing"),
|
|
20967
20916
|
reason: string()
|
|
20968
20917
|
}),
|
|
20969
20918
|
object({
|
|
20970
|
-
...
|
|
20919
|
+
...AttachmentFields,
|
|
20971
20920
|
state: literal("unsupported"),
|
|
20972
20921
|
deviceId: number(),
|
|
20973
20922
|
name: string(),
|
|
20974
20923
|
reason: string()
|
|
20975
20924
|
}),
|
|
20976
20925
|
object({
|
|
20977
|
-
...
|
|
20926
|
+
...AttachmentFields,
|
|
20978
20927
|
state: literal("unreadable"),
|
|
20979
20928
|
reason: string()
|
|
20980
20929
|
})
|
|
@@ -20987,17 +20936,49 @@ var CameraSensorAttachmentSchema = discriminatedUnion("state", [
|
|
|
20987
20936
|
* say.
|
|
20988
20937
|
*/
|
|
20989
20938
|
var CameraSensorsNotForwardedSchema = _enum(["onboard-not-listed", "no-active-detection"]);
|
|
20939
|
+
/** Whether the camera's OWN motion counts on its own (D673 C2), from its READY sensors (C3). */
|
|
20940
|
+
var CameraOwnMotionSchema = _enum([
|
|
20941
|
+
"always",
|
|
20942
|
+
"when-confirmed",
|
|
20943
|
+
"never"
|
|
20944
|
+
]);
|
|
20945
|
+
/** Confirm / Replace cannot suppress this camera's motion: its provider still emits it directly (D673 C13). */
|
|
20946
|
+
var CameraSensorsNotEnforcedSchema = _enum(["provider-not-split"]);
|
|
20947
|
+
/**
|
|
20948
|
+
* The camera's OWN onboard motion (D696): the raw input the bridge combines,
|
|
20949
|
+
* never the effective value. The camera's `motion` slice is the effective one,
|
|
20950
|
+
* so a view of the camera's own row reads this.
|
|
20951
|
+
* - `atMs`: when the bridge received the camera's last own edge.
|
|
20952
|
+
* - `detected`: evaluated WHEN THE STATUS IS ASKED — the last edge said `true`
|
|
20953
|
+
* AND it is younger than the window the bridge counts the camera's own motion
|
|
20954
|
+
* for (`motionCooldownMs`, floored at two sustain ticks). A camera that never
|
|
20955
|
+
* sends a clear (heartbeats only) therefore reads `false` once no push came
|
|
20956
|
+
* within the window; a status read is a snapshot, so a live view re-asks.
|
|
20957
|
+
* Absent = this orchestrator has not received the camera's own motion since it
|
|
20958
|
+
* started (unknown, never "quiet"), or an orchestrator older than D696.
|
|
20959
|
+
*/
|
|
20960
|
+
var CameraRawLevelSchema = object({
|
|
20961
|
+
detected: boolean(),
|
|
20962
|
+
atMs: number()
|
|
20963
|
+
});
|
|
20990
20964
|
var CameraSensorsStatusSchema = discriminatedUnion("state", [
|
|
20991
|
-
object({
|
|
20965
|
+
object({
|
|
20966
|
+
state: literal("not-configured"),
|
|
20967
|
+
cameraLevel: CameraRawLevelSchema.optional()
|
|
20968
|
+
}),
|
|
20992
20969
|
object({
|
|
20993
20970
|
state: literal("unreadable"),
|
|
20994
|
-
reason: string()
|
|
20971
|
+
reason: string(),
|
|
20972
|
+
cameraLevel: CameraRawLevelSchema.optional()
|
|
20995
20973
|
}),
|
|
20996
20974
|
object({
|
|
20997
20975
|
state: literal("configured"),
|
|
20998
|
-
|
|
20976
|
+
cameraLevel: CameraRawLevelSchema.optional(),
|
|
20999
20977
|
sensors: array(CameraSensorAttachmentSchema).readonly(),
|
|
21000
|
-
|
|
20978
|
+
/** Absent = an orchestrator older than CS-2: it does not say (D315). */
|
|
20979
|
+
cameraMotion: CameraOwnMotionSchema.optional(),
|
|
20980
|
+
notForwarded: CameraSensorsNotForwardedSchema.optional(),
|
|
20981
|
+
notEnforced: CameraSensorsNotEnforcedSchema.optional()
|
|
21001
20982
|
})
|
|
21002
20983
|
]);
|
|
21003
20984
|
Object.freeze({
|
|
@@ -21682,14 +21663,14 @@ var TrackSchema = object({
|
|
|
21682
21663
|
* `derive-returned-null tile=standin`,
|
|
21683
21664
|
* `native-tile tile=native no-key-frame-at-close`, …) written at close and
|
|
21684
21665
|
* CLEARED by the late-keyFrame upgrade when a native tile lands after all.
|
|
21685
|
-
* The operator-facing answer to "perché manca l'immagine?" on a track whose
|
|
21666
|
+
* The operator-facing answer to "perché manca l'immagine?" [why is the image missing?] on a track whose
|
|
21686
21667
|
* tile is a face/plate stand-in, a raster crop, or an icon.
|
|
21687
21668
|
*
|
|
21688
21669
|
* **`no-key-frame-at-close` (D400).** The line used to be written ONLY when
|
|
21689
21670
|
* the TILE ranked below native, so a track whose thumbnail landed natively
|
|
21690
21671
|
* while its key frame missed carried no reason at all — three of the four
|
|
21691
21672
|
* `MISSING_KEYFRAME` tracks in the 2026-09-07 operator audit were exactly
|
|
21692
|
-
* that shape, and their "niente ultimo" had no cause anywhere on the row.
|
|
21673
|
+
* that shape, and their "niente ultimo" [no last frame] had no cause anywhere on the row.
|
|
21693
21674
|
* The key frame is the head of a cascade (`keyFrame ⇒ keyFrameSmall ⇒ the
|
|
21694
21675
|
* lastFrame copy source`), so its absence is now on this line whatever the
|
|
21695
21676
|
* tile ended up being.
|
|
@@ -21776,7 +21757,7 @@ var MotionEventSchema = object({
|
|
|
21776
21757
|
/**
|
|
21777
21758
|
* Ms offsets from `timestamp` (the episode's own first rising edge, so the
|
|
21778
21759
|
* first entry is always `0`) of every genuine off→on transition the
|
|
21779
|
-
* episode saw — "ogni evento on si deve salvare" (D475). NOT one entry per
|
|
21760
|
+
* episode saw — "ogni evento on si deve salvare" [every ON event must be saved] (D475). NOT one entry per
|
|
21780
21761
|
* push: a firmware source that keepalives at ~1 Hz for the whole burst
|
|
21781
21762
|
* (Reolink, Hikvision) produces exactly one edge; a source that reports an
|
|
21782
21763
|
* explicit `false` mid-episode and then resumes before the quiet window
|
|
@@ -22300,6 +22281,7 @@ var KeyEventSchema = object({
|
|
|
22300
22281
|
bestEventId: string(),
|
|
22301
22282
|
/** Track lifetime in ms (lastSeen - firstSeen). */
|
|
22302
22283
|
windowMs: number().optional(),
|
|
22284
|
+
audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
|
|
22303
22285
|
...TrackFlagFields,
|
|
22304
22286
|
...TrackRetrainFields
|
|
22305
22287
|
});
|
|
@@ -24228,8 +24210,10 @@ var RunnerCameraConfigSchema = object({
|
|
|
24228
24210
|
* - `analyzer`: ML/frame-diff motion detection (motion-wasm or other
|
|
24229
24211
|
* analyzer providers) running on decoded frames in this runner.
|
|
24230
24212
|
* - `onboard`: camera-native motion pushes (Reolink Baichuan, ONVIF
|
|
24231
|
-
* analytics). The provider emits ProviderMotion
|
|
24232
|
-
*
|
|
24213
|
+
* analytics). The provider emits its raw push as `ProviderMotion`
|
|
24214
|
+
* (D673); the orchestrator's camera-sensors bridge re-emits the camera's
|
|
24215
|
+
* effective motion as `MotionOnMotionChanged`, which is what reaches
|
|
24216
|
+
* `reportMotion`.
|
|
24233
24217
|
*/
|
|
24234
24218
|
motionSources: MotionSourcesSchema.default(["analyzer"]),
|
|
24235
24219
|
/**
|
|
@@ -24406,7 +24390,15 @@ var RunnerLocalLoadSchema = object({
|
|
|
24406
24390
|
hasGpu: boolean(),
|
|
24407
24391
|
inferenceBackend: string().optional(),
|
|
24408
24392
|
cpuCores: number().optional()
|
|
24409
|
-
})
|
|
24393
|
+
}),
|
|
24394
|
+
/**
|
|
24395
|
+
* Who writes a camera's `motion` runtime slice (D696). `'orchestrator'`: this
|
|
24396
|
+
* runner never writes it. ABSENT = a runner older than D696, which still
|
|
24397
|
+
* writes the slice from its phase machine; the orchestrator does not write
|
|
24398
|
+
* while any runner node is absent-or-unanswered, so one slice never has two
|
|
24399
|
+
* writers.
|
|
24400
|
+
*/
|
|
24401
|
+
motionSliceWriter: literal("orchestrator").optional()
|
|
24410
24402
|
});
|
|
24411
24403
|
/**
|
|
24412
24404
|
* Aggregate runtime metrics for the runner's whole local pool. Mirrors the
|
|
@@ -27175,7 +27167,7 @@ var ClipPlaybackSchema = object({
|
|
|
27175
27167
|
* **One authorised yes is one wake.** `next-natural` — take the clip the next
|
|
27176
27168
|
* time the camera is awake for its own reasons — is deliberately not a member:
|
|
27177
27169
|
* it was proposed, it is free on the battery, and the operator declined it on
|
|
27178
|
-
* 2026-09-20 (*"Quando un export viene richiesto si sveglia la camera."
|
|
27170
|
+
* 2026-09-20 (*"Quando un export viene richiesto si sveglia la camera."* [When an export is requested the camera wakes up],
|
|
27179
27171
|
* D558 "Considered and not taken").
|
|
27180
27172
|
*/
|
|
27181
27173
|
var ClipWakeSchema = _enum(["authorised"]);
|
|
@@ -27436,7 +27428,7 @@ DeviceType.Camera, method(object({
|
|
|
27436
27428
|
* It replaced `sources?: string[]`, a VIEW filter over source ids that
|
|
27437
27429
|
* assumed the answer was a fan-out over everything a camera has. The
|
|
27438
27430
|
* operator settled otherwise on 2026-09-20 — *"l'utilizzatore è uno
|
|
27439
|
-
* solo"* — so the list is asked of one provider at a time and there is
|
|
27431
|
+
* solo"* [there is only one user] — so the list is asked of one provider at a time and there is
|
|
27440
27432
|
* nothing to filter out of it.
|
|
27441
27433
|
*/
|
|
27442
27434
|
provider: string().min(1)
|
|
@@ -30039,6 +30031,70 @@ onStatusChanged: { data: object({
|
|
|
30039
30031
|
* whether persisting is worth a SQLite commit. */
|
|
30040
30032
|
volatileStateFields: ["lastChangedAt"]
|
|
30041
30033
|
};
|
|
30034
|
+
var DoorbellStatusSchema = object({
|
|
30035
|
+
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
30036
|
+
lastPressedAt: number().nullable(),
|
|
30037
|
+
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
30038
|
+
pressCountSinceStart: number()
|
|
30039
|
+
});
|
|
30040
|
+
var DoorbellPressEventSchema = object({
|
|
30041
|
+
deviceId: number(),
|
|
30042
|
+
timestamp: number()
|
|
30043
|
+
});
|
|
30044
|
+
/**
|
|
30045
|
+
* Doorbell button cap. Two kinds of provider serve it, and to every consumer
|
|
30046
|
+
* they are the same cap:
|
|
30047
|
+
*
|
|
30048
|
+
* - **Native** providers, registered per device by a driver addon through
|
|
30049
|
+
* `ctx.registerNativeCap` — a `DeviceType.Button` accessory with
|
|
30050
|
+
* `role: DeviceRole.Doorbell`, or the camera itself (Reolink registers at
|
|
30051
|
+
* camera level). They emit `onPressed` on every firmware ring.
|
|
30052
|
+
* - **A composed doorbell** (D670, D671): a camera's customization gives it
|
|
30053
|
+
* the cap, its `lastPressedAt` rising from the sources the operator
|
|
30054
|
+
* assigned in Customize → Doorbell, and the composer emits `onPressed`
|
|
30055
|
+
* from that field's advance (`fromState`).
|
|
30056
|
+
*
|
|
30057
|
+
* The DeviceEventPropagator re-emits `onPressed` on the camera parent.
|
|
30058
|
+
*/
|
|
30059
|
+
var doorbellCapability = {
|
|
30060
|
+
name: "doorbell",
|
|
30061
|
+
scope: "device",
|
|
30062
|
+
deviceNative: true,
|
|
30063
|
+
mode: "singleton",
|
|
30064
|
+
deviceTypes: [DeviceType.Button, DeviceType.Camera],
|
|
30065
|
+
methods: {},
|
|
30066
|
+
events: {
|
|
30067
|
+
/**
|
|
30068
|
+
* Fires once per physical press. Reolink delivers via Baichuan
|
|
30069
|
+
* push (`ReolinkSimpleEvent.type === 'doorbell'`). There is no
|
|
30070
|
+
* release/duration — it's a pulse.
|
|
30071
|
+
*/
|
|
30072
|
+
onPressed: {
|
|
30073
|
+
data: DoorbellPressEventSchema,
|
|
30074
|
+
fromState: {
|
|
30075
|
+
field: "lastPressedAt",
|
|
30076
|
+
on: "advance"
|
|
30077
|
+
}
|
|
30078
|
+
} },
|
|
30079
|
+
status: {
|
|
30080
|
+
schema: DoorbellStatusSchema,
|
|
30081
|
+
kind: "push"
|
|
30082
|
+
},
|
|
30083
|
+
/**
|
|
30084
|
+
* Runtime-state slice — last press timestamp + lifetime press count.
|
|
30085
|
+
* Mirrored by the kernel and readable via
|
|
30086
|
+
* `device.state.doorbell.value`. UIs can show "last ring 5m ago"
|
|
30087
|
+
* without subscribing.
|
|
30088
|
+
*/
|
|
30089
|
+
runtimeState: DoorbellStatusSchema,
|
|
30090
|
+
/**
|
|
30091
|
+
* 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.
|
|
30092
|
+
*
|
|
30093
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
30094
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
30095
|
+
*/
|
|
30096
|
+
durability: "restored"
|
|
30097
|
+
};
|
|
30042
30098
|
/**
|
|
30043
30099
|
* Enum-state sensor — a string value picked from a finite option set.
|
|
30044
30100
|
* Drives HA `sensor` entries with `state_class: enum` (HVAC action
|
|
@@ -32183,9 +32239,9 @@ var MotionStatusSchema = object({
|
|
|
32183
32239
|
/** Ms epoch of the last detected-true observation. Null if never detected. */
|
|
32184
32240
|
lastDetectedAt: number().nullable(),
|
|
32185
32241
|
/**
|
|
32186
|
-
* `MOTION_CLOSE_AFTER_MS` while `detected: true` on a `Camera` device
|
|
32187
|
-
* `null` while false and on every `Sensor`
|
|
32188
|
-
* constant's doc for the one-authority rule.
|
|
32242
|
+
* `MOTION_CLOSE_AFTER_MS` while `detected: true` on a `Camera` device (the
|
|
32243
|
+
* orchestrator writes it, D696), `null` while false and on every `Sensor`
|
|
32244
|
+
* device (D475) — see that constant's doc for the one-authority rule.
|
|
32189
32245
|
*
|
|
32190
32246
|
* ## Reading this field still arms nothing
|
|
32191
32247
|
*
|
|
@@ -32203,34 +32259,31 @@ var MotionStatusSchema = object({
|
|
|
32203
32259
|
* `addon-export-alexa/src/motion-clear-hold.ts` and
|
|
32204
32260
|
* `addon-export-hap`'s `RESET_DEBOUNCE_MS` both do.
|
|
32205
32261
|
*
|
|
32206
|
-
* ## Who writes it
|
|
32207
|
-
*
|
|
32208
|
-
* - **Cameras** — the
|
|
32209
|
-
*
|
|
32210
|
-
* `
|
|
32211
|
-
* `
|
|
32212
|
-
*
|
|
32213
|
-
*
|
|
32214
|
-
* a
|
|
32215
|
-
*
|
|
32216
|
-
*
|
|
32217
|
-
*
|
|
32218
|
-
*
|
|
32219
|
-
*
|
|
32220
|
-
*
|
|
32221
|
-
*
|
|
32222
|
-
*
|
|
32223
|
-
*
|
|
32224
|
-
* `
|
|
32225
|
-
*
|
|
32226
|
-
*
|
|
32227
|
-
*
|
|
32228
|
-
*
|
|
32229
|
-
*
|
|
32230
|
-
*
|
|
32231
|
-
* This predates D475 and is not fixed there: the fix touches every
|
|
32232
|
-
* camera provider. Recorded in D475's Consequences. Do not restore the
|
|
32233
|
-
* "sole writer" wording without also removing the other writers.
|
|
32262
|
+
* ## Who writes it (D696)
|
|
32263
|
+
*
|
|
32264
|
+
* - **Cameras** — the orchestrator, and nothing else. It writes the camera's
|
|
32265
|
+
* EFFECTIVE motion (`addon-pipeline-orchestrator`
|
|
32266
|
+
* `camera-sensors/motion-slice.ts`), alongside the effective
|
|
32267
|
+
* `MotionOnMotionChanged` it emits or receives: the camera-sensors bridge
|
|
32268
|
+
* for a split camera, an unsplit emitter's direct event, the analyzer and
|
|
32269
|
+
* device activity, as the camera's `motionSources` counts them. A source
|
|
32270
|
+
* that never sends a clear falls one window after its last `true`.
|
|
32271
|
+
* `lastDetectedAt` moves only on an effective rise. No camera provider
|
|
32272
|
+
* writes this slice (not even a boot seed), and neither does the runner's
|
|
32273
|
+
* phase machine: its phase is "a session is attached" for every on-motion
|
|
32274
|
+
* session, not motion, and it now has its own `DetectionPhaseTransition`.
|
|
32275
|
+
* A provider's `isDetected` answers from the hub's slice.
|
|
32276
|
+
* - **Sensors** (Home Assistant binary sensors, Homematic, Matter, Alexa
|
|
32277
|
+
* imports) — the provider pushes both edges itself, from the upstream
|
|
32278
|
+
* system's own state change. That is the sensor's own fact.
|
|
32279
|
+
*
|
|
32280
|
+
* `scripts/check-onboard-motion-emitters.ts` refuses any other writer of a
|
|
32281
|
+
* `motion` slice; each sensor writer is a named exemption.
|
|
32282
|
+
*
|
|
32283
|
+
* This replaces the D475 §4 rule ("the phase machine is the sole writer").
|
|
32284
|
+
* That rule was never true: Hikvision and Amcrest wrote the slice raw beside
|
|
32285
|
+
* it, every provider seeded it at boot, and every session left it
|
|
32286
|
+
* `detected: true` after its detach.
|
|
32234
32287
|
*/
|
|
32235
32288
|
autoClearAfterMs: number().nullable()
|
|
32236
32289
|
});
|
|
@@ -32302,11 +32355,12 @@ onMotionChanged: { data: MotionOnMotionChangedDataSchema } },
|
|
|
32302
32355
|
*/
|
|
32303
32356
|
runtimeState: MotionStatusSchema,
|
|
32304
32357
|
/**
|
|
32305
|
-
* Runtime-state durability: **session** —
|
|
32358
|
+
* Runtime-state durability: **session** — the writer of this slice
|
|
32306
32359
|
* writes only on an EDGE, so a restored `detected: true` would stay
|
|
32307
32360
|
* frozen until the next one instead of being corrected. The next edge
|
|
32308
|
-
* re-publishes the real state
|
|
32309
|
-
*
|
|
32361
|
+
* re-publishes the real state, and the orchestrator re-publishes every
|
|
32362
|
+
* camera when it starts writing (D696; on who writes it, see
|
|
32363
|
+
* `autoClearAfterMs` above).
|
|
32310
32364
|
*
|
|
32311
32365
|
* See `RuntimeStateDurability`. Enforced by
|
|
32312
32366
|
* `scripts/check-runtime-state-durability.ts`.
|
|
@@ -34689,8 +34743,7 @@ var ptzAutotrackCapability = {
|
|
|
34689
34743
|
deviceNative: true,
|
|
34690
34744
|
mode: "singleton",
|
|
34691
34745
|
/**
|
|
34692
|
-
* Two kinds of provider behind one name, the same shape `snapshot`
|
|
34693
|
-
* `doorbell` use:
|
|
34746
|
+
* Two kinds of provider behind one name, the same shape `snapshot` uses:
|
|
34694
34747
|
*
|
|
34695
34748
|
* - **Native**: the camera's own firmware autotrack, registered per device by
|
|
34696
34749
|
* the driver when the probe says it exists (Reolink: yes; Hikvision:
|
|
@@ -34698,7 +34751,7 @@ var ptzAutotrackCapability = {
|
|
|
34698
34751
|
* - **Wrapper**: the emulated implementation (`@camstack/system`'s `autotrack` builtin),
|
|
34699
34752
|
* which follows a subject with `ptz.move` pulses driven by the detection
|
|
34700
34753
|
* pipeline. `defaultActive: false` — the operator binds it per camera in
|
|
34701
|
-
* the bindings UI
|
|
34754
|
+
* the bindings UI.
|
|
34702
34755
|
*
|
|
34703
34756
|
* The binding chooses WHICH implementation answers; `setEnabled` stays the
|
|
34704
34757
|
* one switch for the function either way. A camera never has both driving its
|
|
@@ -35373,7 +35426,7 @@ var ReadGopBytesResultSchema = object({
|
|
|
35373
35426
|
/**
|
|
35374
35427
|
* A time WINDOW of one finalized segment, cut by byte range — the multi-GOP
|
|
35375
35428
|
* twin of {@link ReadGopBytesResultSchema}'s single instant. Built for the
|
|
35376
|
-
* replay clip's `recording` source (`docs/design/plans/2026-08-26-replay-
|
|
35429
|
+
* replay clip's `recording` source (`docs/design/plans/2026-08-26-clip-replay-on-pipeline.md`):
|
|
35377
35430
|
* a replay needs several seconds of native pixels, not one frame.
|
|
35378
35431
|
*
|
|
35379
35432
|
* `ok.data` is standalone-demuxable, same as a GOP read. `ok.reachesRequestedEnd`
|
|
@@ -38737,6 +38790,7 @@ var zoneRulesCapability = {
|
|
|
38737
38790
|
*/
|
|
38738
38791
|
durability: "restored"
|
|
38739
38792
|
};
|
|
38793
|
+
SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
|
|
38740
38794
|
/**
|
|
38741
38795
|
* Accessory device helpers — shared across drivers.
|
|
38742
38796
|
*
|
|
@@ -39796,13 +39850,14 @@ var BaseDeviceProvider = class extends BaseAddon {
|
|
|
39796
39850
|
async getStatus() {
|
|
39797
39851
|
const all = await this.ctx.kernel.devices?.getAll() ?? [];
|
|
39798
39852
|
const summary = this.restoreFailureSummary();
|
|
39799
|
-
|
|
39853
|
+
const base = {
|
|
39800
39854
|
connected: true,
|
|
39801
|
-
deviceCount: all.length
|
|
39855
|
+
deviceCount: all.length,
|
|
39856
|
+
motionSliceWriter: "orchestrator"
|
|
39802
39857
|
};
|
|
39858
|
+
if (summary === null) return base;
|
|
39803
39859
|
return {
|
|
39804
|
-
|
|
39805
|
-
deviceCount: all.length,
|
|
39860
|
+
...base,
|
|
39806
39861
|
error: summary
|
|
39807
39862
|
};
|
|
39808
39863
|
}
|
|
@@ -45304,6 +45359,12 @@ Object.freeze({
|
|
|
45304
45359
|
addonId: null,
|
|
45305
45360
|
access: "view"
|
|
45306
45361
|
},
|
|
45362
|
+
"notificationRules.getAlarmSensors": {
|
|
45363
|
+
capName: "notification-rules",
|
|
45364
|
+
capScope: "system",
|
|
45365
|
+
addonId: null,
|
|
45366
|
+
access: "view"
|
|
45367
|
+
},
|
|
45307
45368
|
"notificationRules.getClipRetentionAsks": {
|
|
45308
45369
|
capName: "notification-rules",
|
|
45309
45370
|
capScope: "system",
|
|
@@ -48882,6 +48943,11 @@ Object.freeze({
|
|
|
48882
48943
|
}
|
|
48883
48944
|
});
|
|
48884
48945
|
Object.freeze({
|
|
48946
|
+
"accessories.getStatus": [{
|
|
48947
|
+
name: "deviceId",
|
|
48948
|
+
form: "single",
|
|
48949
|
+
optional: false
|
|
48950
|
+
}],
|
|
48885
48951
|
"accessories.setChildHidden": [{
|
|
48886
48952
|
name: "childDeviceId",
|
|
48887
48953
|
form: "single",
|
|
@@ -48901,6 +48967,11 @@ Object.freeze({
|
|
|
48901
48967
|
form: "single",
|
|
48902
48968
|
optional: false
|
|
48903
48969
|
}],
|
|
48970
|
+
"airQualitySensor.getStatus": [{
|
|
48971
|
+
name: "deviceId",
|
|
48972
|
+
form: "single",
|
|
48973
|
+
optional: false
|
|
48974
|
+
}],
|
|
48904
48975
|
"alarmPanel.arm": [{
|
|
48905
48976
|
name: "deviceId",
|
|
48906
48977
|
form: "single",
|
|
@@ -48911,11 +48982,36 @@ Object.freeze({
|
|
|
48911
48982
|
form: "single",
|
|
48912
48983
|
optional: false
|
|
48913
48984
|
}],
|
|
48985
|
+
"alarmPanel.getStatus": [{
|
|
48986
|
+
name: "deviceId",
|
|
48987
|
+
form: "single",
|
|
48988
|
+
optional: false
|
|
48989
|
+
}],
|
|
48914
48990
|
"alarmPanel.trigger": [{
|
|
48915
48991
|
name: "deviceId",
|
|
48916
48992
|
form: "single",
|
|
48917
48993
|
optional: false
|
|
48918
48994
|
}],
|
|
48995
|
+
"ambientLightSensor.getStatus": [{
|
|
48996
|
+
name: "deviceId",
|
|
48997
|
+
form: "single",
|
|
48998
|
+
optional: false
|
|
48999
|
+
}],
|
|
49000
|
+
"audioAnalysis.applyDeviceSettingsPatch": [{
|
|
49001
|
+
name: "deviceId",
|
|
49002
|
+
form: "single",
|
|
49003
|
+
optional: false
|
|
49004
|
+
}],
|
|
49005
|
+
"audioAnalysis.getDeviceLiveContribution": [{
|
|
49006
|
+
name: "deviceId",
|
|
49007
|
+
form: "single",
|
|
49008
|
+
optional: false
|
|
49009
|
+
}],
|
|
49010
|
+
"audioAnalysis.getDeviceSettingsContribution": [{
|
|
49011
|
+
name: "deviceId",
|
|
49012
|
+
form: "single",
|
|
49013
|
+
optional: false
|
|
49014
|
+
}],
|
|
48919
49015
|
"audioAnalysis.resolveDeviceSettings": [{
|
|
48920
49016
|
name: "deviceId",
|
|
48921
49017
|
form: "single",
|
|
@@ -48956,16 +49052,36 @@ Object.freeze({
|
|
|
48956
49052
|
form: "single",
|
|
48957
49053
|
optional: false
|
|
48958
49054
|
}],
|
|
49055
|
+
"automationControl.getStatus": [{
|
|
49056
|
+
name: "deviceId",
|
|
49057
|
+
form: "single",
|
|
49058
|
+
optional: false
|
|
49059
|
+
}],
|
|
48959
49060
|
"automationControl.trigger": [{
|
|
48960
49061
|
name: "deviceId",
|
|
48961
49062
|
form: "single",
|
|
48962
49063
|
optional: false
|
|
48963
49064
|
}],
|
|
49065
|
+
"battery.getStatus": [{
|
|
49066
|
+
name: "deviceId",
|
|
49067
|
+
form: "single",
|
|
49068
|
+
optional: false
|
|
49069
|
+
}],
|
|
48964
49070
|
"battery.wakeForStream": [{
|
|
48965
49071
|
name: "deviceId",
|
|
48966
49072
|
form: "single",
|
|
48967
49073
|
optional: false
|
|
48968
49074
|
}],
|
|
49075
|
+
"binary.getStatus": [{
|
|
49076
|
+
name: "deviceId",
|
|
49077
|
+
form: "single",
|
|
49078
|
+
optional: false
|
|
49079
|
+
}],
|
|
49080
|
+
"brightness.getStatus": [{
|
|
49081
|
+
name: "deviceId",
|
|
49082
|
+
form: "single",
|
|
49083
|
+
optional: false
|
|
49084
|
+
}],
|
|
48969
49085
|
"brightness.setBrightness": [{
|
|
48970
49086
|
name: "deviceId",
|
|
48971
49087
|
form: "single",
|
|
@@ -48981,6 +49097,26 @@ Object.freeze({
|
|
|
48981
49097
|
form: "single",
|
|
48982
49098
|
optional: false
|
|
48983
49099
|
}],
|
|
49100
|
+
"cameraCredentials.getStatus": [{
|
|
49101
|
+
name: "deviceId",
|
|
49102
|
+
form: "single",
|
|
49103
|
+
optional: false
|
|
49104
|
+
}],
|
|
49105
|
+
"cameraGridLayout.applyDeviceSettingsPatch": [{
|
|
49106
|
+
name: "deviceId",
|
|
49107
|
+
form: "single",
|
|
49108
|
+
optional: false
|
|
49109
|
+
}],
|
|
49110
|
+
"cameraGridLayout.getDeviceLiveContribution": [{
|
|
49111
|
+
name: "deviceId",
|
|
49112
|
+
form: "single",
|
|
49113
|
+
optional: false
|
|
49114
|
+
}],
|
|
49115
|
+
"cameraGridLayout.getDeviceSettingsContribution": [{
|
|
49116
|
+
name: "deviceId",
|
|
49117
|
+
form: "single",
|
|
49118
|
+
optional: false
|
|
49119
|
+
}],
|
|
48984
49120
|
"cameraGridLayout.getLayout": [{
|
|
48985
49121
|
name: "deviceId",
|
|
48986
49122
|
form: "single",
|
|
@@ -48996,6 +49132,21 @@ Object.freeze({
|
|
|
48996
49132
|
form: "single",
|
|
48997
49133
|
optional: false
|
|
48998
49134
|
}],
|
|
49135
|
+
"cameraPipelineConfig.applyDeviceSettingsPatch": [{
|
|
49136
|
+
name: "deviceId",
|
|
49137
|
+
form: "single",
|
|
49138
|
+
optional: false
|
|
49139
|
+
}],
|
|
49140
|
+
"cameraPipelineConfig.getDeviceLiveContribution": [{
|
|
49141
|
+
name: "deviceId",
|
|
49142
|
+
form: "single",
|
|
49143
|
+
optional: false
|
|
49144
|
+
}],
|
|
49145
|
+
"cameraPipelineConfig.getDeviceSettingsContribution": [{
|
|
49146
|
+
name: "deviceId",
|
|
49147
|
+
form: "single",
|
|
49148
|
+
optional: false
|
|
49149
|
+
}],
|
|
48999
49150
|
"cameraStreams.getBrokerStreams": [{
|
|
49000
49151
|
name: "deviceId",
|
|
49001
49152
|
form: "single",
|
|
@@ -49021,6 +49172,16 @@ Object.freeze({
|
|
|
49021
49172
|
form: "single",
|
|
49022
49173
|
optional: false
|
|
49023
49174
|
}],
|
|
49175
|
+
"carbonMonoxide.getStatus": [{
|
|
49176
|
+
name: "deviceId",
|
|
49177
|
+
form: "single",
|
|
49178
|
+
optional: false
|
|
49179
|
+
}],
|
|
49180
|
+
"climateControl.getStatus": [{
|
|
49181
|
+
name: "deviceId",
|
|
49182
|
+
form: "single",
|
|
49183
|
+
optional: false
|
|
49184
|
+
}],
|
|
49024
49185
|
"climateControl.setFanMode": [{
|
|
49025
49186
|
name: "deviceId",
|
|
49026
49187
|
form: "single",
|
|
@@ -49061,16 +49222,41 @@ Object.freeze({
|
|
|
49061
49222
|
form: "single",
|
|
49062
49223
|
optional: false
|
|
49063
49224
|
}],
|
|
49225
|
+
"color.getStatus": [{
|
|
49226
|
+
name: "deviceId",
|
|
49227
|
+
form: "single",
|
|
49228
|
+
optional: false
|
|
49229
|
+
}],
|
|
49064
49230
|
"color.setColor": [{
|
|
49065
49231
|
name: "deviceId",
|
|
49066
49232
|
form: "single",
|
|
49067
49233
|
optional: false
|
|
49068
49234
|
}],
|
|
49235
|
+
"connectivity.getStatus": [{
|
|
49236
|
+
name: "deviceId",
|
|
49237
|
+
form: "single",
|
|
49238
|
+
optional: false
|
|
49239
|
+
}],
|
|
49240
|
+
"consumables.getStatus": [{
|
|
49241
|
+
name: "deviceId",
|
|
49242
|
+
form: "single",
|
|
49243
|
+
optional: false
|
|
49244
|
+
}],
|
|
49069
49245
|
"consumables.reset": [{
|
|
49070
49246
|
name: "deviceId",
|
|
49071
49247
|
form: "single",
|
|
49072
49248
|
optional: false
|
|
49073
49249
|
}],
|
|
49250
|
+
"contact.getStatus": [{
|
|
49251
|
+
name: "deviceId",
|
|
49252
|
+
form: "single",
|
|
49253
|
+
optional: false
|
|
49254
|
+
}],
|
|
49255
|
+
"control.getStatus": [{
|
|
49256
|
+
name: "deviceId",
|
|
49257
|
+
form: "single",
|
|
49258
|
+
optional: false
|
|
49259
|
+
}],
|
|
49074
49260
|
"control.setValue": [{
|
|
49075
49261
|
name: "deviceId",
|
|
49076
49262
|
form: "single",
|
|
@@ -49081,6 +49267,11 @@ Object.freeze({
|
|
|
49081
49267
|
form: "single",
|
|
49082
49268
|
optional: false
|
|
49083
49269
|
}],
|
|
49270
|
+
"cover.getStatus": [{
|
|
49271
|
+
name: "deviceId",
|
|
49272
|
+
form: "single",
|
|
49273
|
+
optional: false
|
|
49274
|
+
}],
|
|
49084
49275
|
"cover.open": [{
|
|
49085
49276
|
name: "deviceId",
|
|
49086
49277
|
form: "single",
|
|
@@ -49106,6 +49297,11 @@ Object.freeze({
|
|
|
49106
49297
|
form: "single",
|
|
49107
49298
|
optional: false
|
|
49108
49299
|
}],
|
|
49300
|
+
"dayNight.getStatus": [{
|
|
49301
|
+
name: "deviceId",
|
|
49302
|
+
form: "single",
|
|
49303
|
+
optional: false
|
|
49304
|
+
}],
|
|
49109
49305
|
"dayNight.setSettings": [{
|
|
49110
49306
|
name: "deviceId",
|
|
49111
49307
|
form: "single",
|
|
@@ -49116,11 +49312,31 @@ Object.freeze({
|
|
|
49116
49312
|
form: "single",
|
|
49117
49313
|
optional: true
|
|
49118
49314
|
}],
|
|
49315
|
+
"detectionPipeline.applyDeviceSettingsPatch": [{
|
|
49316
|
+
name: "deviceId",
|
|
49317
|
+
form: "single",
|
|
49318
|
+
optional: false
|
|
49319
|
+
}],
|
|
49320
|
+
"detectionPipeline.getDeviceLiveContribution": [{
|
|
49321
|
+
name: "deviceId",
|
|
49322
|
+
form: "single",
|
|
49323
|
+
optional: false
|
|
49324
|
+
}],
|
|
49325
|
+
"detectionPipeline.getDeviceSettingsContribution": [{
|
|
49326
|
+
name: "deviceId",
|
|
49327
|
+
form: "single",
|
|
49328
|
+
optional: false
|
|
49329
|
+
}],
|
|
49119
49330
|
"deviceAdminLink.getAdminLink": [{
|
|
49120
49331
|
name: "deviceId",
|
|
49121
49332
|
form: "single",
|
|
49122
49333
|
optional: false
|
|
49123
49334
|
}],
|
|
49335
|
+
"deviceAdoption.getStatus": [{
|
|
49336
|
+
name: "deviceId",
|
|
49337
|
+
form: "single",
|
|
49338
|
+
optional: false
|
|
49339
|
+
}],
|
|
49124
49340
|
"deviceAdoption.release": [{
|
|
49125
49341
|
name: "camDeviceId",
|
|
49126
49342
|
form: "single",
|
|
@@ -49136,6 +49352,11 @@ Object.freeze({
|
|
|
49136
49352
|
form: "single",
|
|
49137
49353
|
optional: false
|
|
49138
49354
|
}],
|
|
49355
|
+
"deviceDiscovery.getStatus": [{
|
|
49356
|
+
name: "deviceId",
|
|
49357
|
+
form: "single",
|
|
49358
|
+
optional: false
|
|
49359
|
+
}],
|
|
49139
49360
|
"deviceDiscovery.listDiscovered": [{
|
|
49140
49361
|
name: "deviceId",
|
|
49141
49362
|
form: "single",
|
|
@@ -49155,6 +49376,21 @@ Object.freeze({
|
|
|
49155
49376
|
form: "single",
|
|
49156
49377
|
optional: false
|
|
49157
49378
|
}],
|
|
49379
|
+
"deviceExport.applyDeviceSettingsPatch": [{
|
|
49380
|
+
name: "deviceId",
|
|
49381
|
+
form: "single",
|
|
49382
|
+
optional: false
|
|
49383
|
+
}],
|
|
49384
|
+
"deviceExport.getDeviceLiveContribution": [{
|
|
49385
|
+
name: "deviceId",
|
|
49386
|
+
form: "single",
|
|
49387
|
+
optional: false
|
|
49388
|
+
}],
|
|
49389
|
+
"deviceExport.getDeviceSettingsContribution": [{
|
|
49390
|
+
name: "deviceId",
|
|
49391
|
+
form: "single",
|
|
49392
|
+
optional: false
|
|
49393
|
+
}],
|
|
49158
49394
|
"deviceExtension.listCandidates": [{
|
|
49159
49395
|
name: "deviceId",
|
|
49160
49396
|
form: "single",
|
|
@@ -49503,6 +49739,26 @@ Object.freeze({
|
|
|
49503
49739
|
form: "single",
|
|
49504
49740
|
optional: false
|
|
49505
49741
|
}],
|
|
49742
|
+
"deviceStatus.getStatus": [{
|
|
49743
|
+
name: "deviceId",
|
|
49744
|
+
form: "single",
|
|
49745
|
+
optional: false
|
|
49746
|
+
}],
|
|
49747
|
+
"doorbell.getStatus": [{
|
|
49748
|
+
name: "deviceId",
|
|
49749
|
+
form: "single",
|
|
49750
|
+
optional: false
|
|
49751
|
+
}],
|
|
49752
|
+
"enumSensor.getStatus": [{
|
|
49753
|
+
name: "deviceId",
|
|
49754
|
+
form: "single",
|
|
49755
|
+
optional: false
|
|
49756
|
+
}],
|
|
49757
|
+
"eventEmitter.getStatus": [{
|
|
49758
|
+
name: "deviceId",
|
|
49759
|
+
form: "single",
|
|
49760
|
+
optional: false
|
|
49761
|
+
}],
|
|
49506
49762
|
"faceGallery.getFaceByTrack": [{
|
|
49507
49763
|
name: "deviceId",
|
|
49508
49764
|
form: "single",
|
|
@@ -49517,6 +49773,11 @@ Object.freeze({
|
|
|
49517
49773
|
form: "array",
|
|
49518
49774
|
optional: true
|
|
49519
49775
|
}],
|
|
49776
|
+
"fanControl.getStatus": [{
|
|
49777
|
+
name: "deviceId",
|
|
49778
|
+
form: "single",
|
|
49779
|
+
optional: false
|
|
49780
|
+
}],
|
|
49520
49781
|
"fanControl.setDirection": [{
|
|
49521
49782
|
name: "deviceId",
|
|
49522
49783
|
form: "single",
|
|
@@ -49537,6 +49798,26 @@ Object.freeze({
|
|
|
49537
49798
|
form: "single",
|
|
49538
49799
|
optional: false
|
|
49539
49800
|
}],
|
|
49801
|
+
"featureProbe.getStatus": [{
|
|
49802
|
+
name: "deviceId",
|
|
49803
|
+
form: "single",
|
|
49804
|
+
optional: false
|
|
49805
|
+
}],
|
|
49806
|
+
"flood.getStatus": [{
|
|
49807
|
+
name: "deviceId",
|
|
49808
|
+
form: "single",
|
|
49809
|
+
optional: false
|
|
49810
|
+
}],
|
|
49811
|
+
"gas.getStatus": [{
|
|
49812
|
+
name: "deviceId",
|
|
49813
|
+
form: "single",
|
|
49814
|
+
optional: false
|
|
49815
|
+
}],
|
|
49816
|
+
"humidifier.getStatus": [{
|
|
49817
|
+
name: "deviceId",
|
|
49818
|
+
form: "single",
|
|
49819
|
+
optional: false
|
|
49820
|
+
}],
|
|
49540
49821
|
"humidifier.setMode": [{
|
|
49541
49822
|
name: "deviceId",
|
|
49542
49823
|
form: "single",
|
|
@@ -49552,11 +49833,26 @@ Object.freeze({
|
|
|
49552
49833
|
form: "single",
|
|
49553
49834
|
optional: false
|
|
49554
49835
|
}],
|
|
49836
|
+
"humiditySensor.getStatus": [{
|
|
49837
|
+
name: "deviceId",
|
|
49838
|
+
form: "single",
|
|
49839
|
+
optional: false
|
|
49840
|
+
}],
|
|
49841
|
+
"image.getStatus": [{
|
|
49842
|
+
name: "deviceId",
|
|
49843
|
+
form: "single",
|
|
49844
|
+
optional: false
|
|
49845
|
+
}],
|
|
49555
49846
|
"imageSettings.getOptions": [{
|
|
49556
49847
|
name: "deviceId",
|
|
49557
49848
|
form: "single",
|
|
49558
49849
|
optional: false
|
|
49559
49850
|
}],
|
|
49851
|
+
"imageSettings.getStatus": [{
|
|
49852
|
+
name: "deviceId",
|
|
49853
|
+
form: "single",
|
|
49854
|
+
optional: false
|
|
49855
|
+
}],
|
|
49560
49856
|
"imageSettings.setSettings": [{
|
|
49561
49857
|
name: "deviceId",
|
|
49562
49858
|
form: "single",
|
|
@@ -49567,6 +49863,11 @@ Object.freeze({
|
|
|
49567
49863
|
form: "single",
|
|
49568
49864
|
optional: false
|
|
49569
49865
|
}],
|
|
49866
|
+
"intercom.getStatus": [{
|
|
49867
|
+
name: "deviceId",
|
|
49868
|
+
form: "single",
|
|
49869
|
+
optional: false
|
|
49870
|
+
}],
|
|
49570
49871
|
"intercom.handleAnswer": [{
|
|
49571
49872
|
name: "deviceId",
|
|
49572
49873
|
form: "single",
|
|
@@ -49597,6 +49898,11 @@ Object.freeze({
|
|
|
49597
49898
|
form: "single",
|
|
49598
49899
|
optional: false
|
|
49599
49900
|
}],
|
|
49901
|
+
"lawnMowerControl.getStatus": [{
|
|
49902
|
+
name: "deviceId",
|
|
49903
|
+
form: "single",
|
|
49904
|
+
optional: false
|
|
49905
|
+
}],
|
|
49600
49906
|
"lawnMowerControl.pause": [{
|
|
49601
49907
|
name: "deviceId",
|
|
49602
49908
|
form: "single",
|
|
@@ -49607,6 +49913,11 @@ Object.freeze({
|
|
|
49607
49913
|
form: "single",
|
|
49608
49914
|
optional: false
|
|
49609
49915
|
}],
|
|
49916
|
+
"lockControl.getStatus": [{
|
|
49917
|
+
name: "deviceId",
|
|
49918
|
+
form: "single",
|
|
49919
|
+
optional: false
|
|
49920
|
+
}],
|
|
49610
49921
|
"lockControl.lock": [{
|
|
49611
49922
|
name: "deviceId",
|
|
49612
49923
|
form: "single",
|
|
@@ -49622,6 +49933,11 @@ Object.freeze({
|
|
|
49622
49933
|
form: "single",
|
|
49623
49934
|
optional: false
|
|
49624
49935
|
}],
|
|
49936
|
+
"mediaPlayer.getStatus": [{
|
|
49937
|
+
name: "deviceId",
|
|
49938
|
+
form: "single",
|
|
49939
|
+
optional: false
|
|
49940
|
+
}],
|
|
49625
49941
|
"mediaPlayer.next": [{
|
|
49626
49942
|
name: "deviceId",
|
|
49627
49943
|
form: "single",
|
|
@@ -49682,6 +49998,11 @@ Object.freeze({
|
|
|
49682
49998
|
form: "single",
|
|
49683
49999
|
optional: false
|
|
49684
50000
|
}],
|
|
50001
|
+
"motion.getStatus": [{
|
|
50002
|
+
name: "deviceId",
|
|
50003
|
+
form: "single",
|
|
50004
|
+
optional: false
|
|
50005
|
+
}],
|
|
49685
50006
|
"motion.isDetected": [{
|
|
49686
50007
|
name: "deviceId",
|
|
49687
50008
|
form: "single",
|
|
@@ -49692,11 +50013,31 @@ Object.freeze({
|
|
|
49692
50013
|
form: "single",
|
|
49693
50014
|
optional: false
|
|
49694
50015
|
}],
|
|
50016
|
+
"motionDetection.applyDeviceSettingsPatch": [{
|
|
50017
|
+
name: "deviceId",
|
|
50018
|
+
form: "single",
|
|
50019
|
+
optional: false
|
|
50020
|
+
}],
|
|
50021
|
+
"motionDetection.getDeviceLiveContribution": [{
|
|
50022
|
+
name: "deviceId",
|
|
50023
|
+
form: "single",
|
|
50024
|
+
optional: false
|
|
50025
|
+
}],
|
|
50026
|
+
"motionDetection.getDeviceSettingsContribution": [{
|
|
50027
|
+
name: "deviceId",
|
|
50028
|
+
form: "single",
|
|
50029
|
+
optional: false
|
|
50030
|
+
}],
|
|
49695
50031
|
"motionDetection.removeCamera": [{
|
|
49696
50032
|
name: "deviceId",
|
|
49697
50033
|
form: "single",
|
|
49698
50034
|
optional: false
|
|
49699
50035
|
}],
|
|
50036
|
+
"motionTrigger.getStatus": [{
|
|
50037
|
+
name: "deviceId",
|
|
50038
|
+
form: "single",
|
|
50039
|
+
optional: false
|
|
50040
|
+
}],
|
|
49700
50041
|
"motionTrigger.setMotionTrigger": [{
|
|
49701
50042
|
name: "deviceId",
|
|
49702
50043
|
form: "single",
|
|
@@ -49707,6 +50048,11 @@ Object.freeze({
|
|
|
49707
50048
|
form: "single",
|
|
49708
50049
|
optional: false
|
|
49709
50050
|
}],
|
|
50051
|
+
"motionZones.getStatus": [{
|
|
50052
|
+
name: "deviceId",
|
|
50053
|
+
form: "single",
|
|
50054
|
+
optional: false
|
|
50055
|
+
}],
|
|
49710
50056
|
"motionZones.setZone": [{
|
|
49711
50057
|
name: "deviceId",
|
|
49712
50058
|
form: "single",
|
|
@@ -49717,6 +50063,11 @@ Object.freeze({
|
|
|
49717
50063
|
form: "single",
|
|
49718
50064
|
optional: false
|
|
49719
50065
|
}],
|
|
50066
|
+
"nativeObjectDetection.getStatus": [{
|
|
50067
|
+
name: "deviceId",
|
|
50068
|
+
form: "single",
|
|
50069
|
+
optional: false
|
|
50070
|
+
}],
|
|
49720
50071
|
"nativeObjectDetection.setEnabled": [{
|
|
49721
50072
|
name: "deviceId",
|
|
49722
50073
|
form: "single",
|
|
@@ -49732,6 +50083,11 @@ Object.freeze({
|
|
|
49732
50083
|
form: "single",
|
|
49733
50084
|
optional: false
|
|
49734
50085
|
}],
|
|
50086
|
+
"navigation.getStatus": [{
|
|
50087
|
+
name: "deviceId",
|
|
50088
|
+
form: "single",
|
|
50089
|
+
optional: false
|
|
50090
|
+
}],
|
|
49735
50091
|
"navigation.goToPoint": [{
|
|
49736
50092
|
name: "deviceId",
|
|
49737
50093
|
form: "single",
|
|
@@ -49777,6 +50133,11 @@ Object.freeze({
|
|
|
49777
50133
|
form: "single",
|
|
49778
50134
|
optional: false
|
|
49779
50135
|
}],
|
|
50136
|
+
"networkLink.getStatus": [{
|
|
50137
|
+
name: "deviceId",
|
|
50138
|
+
form: "single",
|
|
50139
|
+
optional: false
|
|
50140
|
+
}],
|
|
49780
50141
|
"networkQuality.getDeviceStats": [{
|
|
49781
50142
|
name: "deviceId",
|
|
49782
50143
|
form: "single",
|
|
@@ -49787,6 +50148,11 @@ Object.freeze({
|
|
|
49787
50148
|
form: "single",
|
|
49788
50149
|
optional: false
|
|
49789
50150
|
}],
|
|
50151
|
+
"notificationRules.getAlarmSensors": [{
|
|
50152
|
+
name: "deviceIds",
|
|
50153
|
+
form: "array",
|
|
50154
|
+
optional: false
|
|
50155
|
+
}],
|
|
49790
50156
|
"notificationRules.setDeviceMuted": [{
|
|
49791
50157
|
name: "deviceId",
|
|
49792
50158
|
form: "single",
|
|
@@ -49797,11 +50163,26 @@ Object.freeze({
|
|
|
49797
50163
|
form: "single",
|
|
49798
50164
|
optional: false
|
|
49799
50165
|
}],
|
|
50166
|
+
"notifier.getStatus": [{
|
|
50167
|
+
name: "deviceId",
|
|
50168
|
+
form: "single",
|
|
50169
|
+
optional: false
|
|
50170
|
+
}],
|
|
49800
50171
|
"notifier.send": [{
|
|
49801
50172
|
name: "deviceId",
|
|
49802
50173
|
form: "single",
|
|
49803
50174
|
optional: false
|
|
49804
50175
|
}],
|
|
50176
|
+
"numericSensor.getStatus": [{
|
|
50177
|
+
name: "deviceId",
|
|
50178
|
+
form: "single",
|
|
50179
|
+
optional: false
|
|
50180
|
+
}],
|
|
50181
|
+
"osd.getStatus": [{
|
|
50182
|
+
name: "deviceId",
|
|
50183
|
+
form: "single",
|
|
50184
|
+
optional: false
|
|
50185
|
+
}],
|
|
49805
50186
|
"osd.setOverlay": [{
|
|
49806
50187
|
name: "deviceId",
|
|
49807
50188
|
form: "single",
|
|
@@ -49861,6 +50242,11 @@ Object.freeze({
|
|
|
49861
50242
|
form: "single",
|
|
49862
50243
|
optional: false
|
|
49863
50244
|
}],
|
|
50245
|
+
"petFeeder.getStatus": [{
|
|
50246
|
+
name: "deviceId",
|
|
50247
|
+
form: "single",
|
|
50248
|
+
optional: false
|
|
50249
|
+
}],
|
|
49864
50250
|
"petFeeder.markFoodReplenished": [{
|
|
49865
50251
|
name: "deviceId",
|
|
49866
50252
|
form: "single",
|
|
@@ -49896,6 +50282,11 @@ Object.freeze({
|
|
|
49896
50282
|
form: "single",
|
|
49897
50283
|
optional: false
|
|
49898
50284
|
}],
|
|
50285
|
+
"pipelineAnalytics.applyDeviceSettingsPatch": [{
|
|
50286
|
+
name: "deviceId",
|
|
50287
|
+
form: "single",
|
|
50288
|
+
optional: false
|
|
50289
|
+
}],
|
|
49899
50290
|
"pipelineAnalytics.clearTrackRelation": [{
|
|
49900
50291
|
name: "deviceId",
|
|
49901
50292
|
form: "single",
|
|
@@ -49936,6 +50327,16 @@ Object.freeze({
|
|
|
49936
50327
|
form: "single",
|
|
49937
50328
|
optional: false
|
|
49938
50329
|
}],
|
|
50330
|
+
"pipelineAnalytics.getDeviceLiveContribution": [{
|
|
50331
|
+
name: "deviceId",
|
|
50332
|
+
form: "single",
|
|
50333
|
+
optional: false
|
|
50334
|
+
}],
|
|
50335
|
+
"pipelineAnalytics.getDeviceSettingsContribution": [{
|
|
50336
|
+
name: "deviceId",
|
|
50337
|
+
form: "single",
|
|
50338
|
+
optional: false
|
|
50339
|
+
}],
|
|
49939
50340
|
"pipelineAnalytics.getEventDensity": [{
|
|
49940
50341
|
name: "deviceId",
|
|
49941
50342
|
form: "single",
|
|
@@ -50151,6 +50552,11 @@ Object.freeze({
|
|
|
50151
50552
|
form: "single",
|
|
50152
50553
|
optional: true
|
|
50153
50554
|
}],
|
|
50555
|
+
"pipelineOrchestrator.applyDeviceSettingsPatch": [{
|
|
50556
|
+
name: "deviceId",
|
|
50557
|
+
form: "single",
|
|
50558
|
+
optional: false
|
|
50559
|
+
}],
|
|
50154
50560
|
"pipelineOrchestrator.assignAudio": [{
|
|
50155
50561
|
name: "deviceId",
|
|
50156
50562
|
form: "single",
|
|
@@ -50196,6 +50602,16 @@ Object.freeze({
|
|
|
50196
50602
|
form: "single",
|
|
50197
50603
|
optional: false
|
|
50198
50604
|
}],
|
|
50605
|
+
"pipelineOrchestrator.getDeviceLiveContribution": [{
|
|
50606
|
+
name: "deviceId",
|
|
50607
|
+
form: "single",
|
|
50608
|
+
optional: false
|
|
50609
|
+
}],
|
|
50610
|
+
"pipelineOrchestrator.getDeviceSettingsContribution": [{
|
|
50611
|
+
name: "deviceId",
|
|
50612
|
+
form: "single",
|
|
50613
|
+
optional: false
|
|
50614
|
+
}],
|
|
50199
50615
|
"pipelineOrchestrator.getPipelineAssignment": [{
|
|
50200
50616
|
name: "deviceId",
|
|
50201
50617
|
form: "single",
|
|
@@ -50316,11 +50732,31 @@ Object.freeze({
|
|
|
50316
50732
|
form: "single",
|
|
50317
50733
|
optional: true
|
|
50318
50734
|
}],
|
|
50735
|
+
"powerMeter.getStatus": [{
|
|
50736
|
+
name: "deviceId",
|
|
50737
|
+
form: "single",
|
|
50738
|
+
optional: false
|
|
50739
|
+
}],
|
|
50740
|
+
"presence.getStatus": [{
|
|
50741
|
+
name: "deviceId",
|
|
50742
|
+
form: "single",
|
|
50743
|
+
optional: false
|
|
50744
|
+
}],
|
|
50745
|
+
"pressureSensor.getStatus": [{
|
|
50746
|
+
name: "deviceId",
|
|
50747
|
+
form: "single",
|
|
50748
|
+
optional: false
|
|
50749
|
+
}],
|
|
50319
50750
|
"privacyMask.getOptions": [{
|
|
50320
50751
|
name: "deviceId",
|
|
50321
50752
|
form: "single",
|
|
50322
50753
|
optional: false
|
|
50323
50754
|
}],
|
|
50755
|
+
"privacyMask.getStatus": [{
|
|
50756
|
+
name: "deviceId",
|
|
50757
|
+
form: "single",
|
|
50758
|
+
optional: false
|
|
50759
|
+
}],
|
|
50324
50760
|
"privacyMask.setAudioEnabled": [{
|
|
50325
50761
|
name: "deviceId",
|
|
50326
50762
|
form: "single",
|
|
@@ -50371,6 +50807,11 @@ Object.freeze({
|
|
|
50371
50807
|
form: "single",
|
|
50372
50808
|
optional: false
|
|
50373
50809
|
}],
|
|
50810
|
+
"ptz.getStatus": [{
|
|
50811
|
+
name: "deviceId",
|
|
50812
|
+
form: "single",
|
|
50813
|
+
optional: false
|
|
50814
|
+
}],
|
|
50374
50815
|
"ptz.goHome": [{
|
|
50375
50816
|
name: "deviceId",
|
|
50376
50817
|
form: "single",
|
|
@@ -50461,6 +50902,11 @@ Object.freeze({
|
|
|
50461
50902
|
form: "single",
|
|
50462
50903
|
optional: false
|
|
50463
50904
|
}],
|
|
50905
|
+
"recordingArchive.applyDeviceSettingsPatch": [{
|
|
50906
|
+
name: "deviceId",
|
|
50907
|
+
form: "single",
|
|
50908
|
+
optional: false
|
|
50909
|
+
}],
|
|
50464
50910
|
"recordingArchive.deleteFootprint": [{
|
|
50465
50911
|
name: "deviceId",
|
|
50466
50912
|
form: "single",
|
|
@@ -50481,6 +50927,21 @@ Object.freeze({
|
|
|
50481
50927
|
form: "single",
|
|
50482
50928
|
optional: false
|
|
50483
50929
|
}],
|
|
50930
|
+
"recordingArchive.getDeviceLiveContribution": [{
|
|
50931
|
+
name: "deviceId",
|
|
50932
|
+
form: "single",
|
|
50933
|
+
optional: false
|
|
50934
|
+
}],
|
|
50935
|
+
"recordingArchive.getDeviceSettingsContribution": [{
|
|
50936
|
+
name: "deviceId",
|
|
50937
|
+
form: "single",
|
|
50938
|
+
optional: false
|
|
50939
|
+
}],
|
|
50940
|
+
"recordingArchive.getStatus": [{
|
|
50941
|
+
name: "deviceId",
|
|
50942
|
+
form: "single",
|
|
50943
|
+
optional: false
|
|
50944
|
+
}],
|
|
50484
50945
|
"recordingArchive.listOpsLog": [{
|
|
50485
50946
|
name: "deviceId",
|
|
50486
50947
|
form: "single",
|
|
@@ -50566,6 +51027,11 @@ Object.freeze({
|
|
|
50566
51027
|
form: "single",
|
|
50567
51028
|
optional: false
|
|
50568
51029
|
}],
|
|
51030
|
+
"recordingOnboard.getStatus": [{
|
|
51031
|
+
name: "deviceId",
|
|
51032
|
+
form: "single",
|
|
51033
|
+
optional: false
|
|
51034
|
+
}],
|
|
50569
51035
|
"recordingOnboard.setSettings": [{
|
|
50570
51036
|
name: "deviceId",
|
|
50571
51037
|
form: "single",
|
|
@@ -50596,6 +51062,11 @@ Object.freeze({
|
|
|
50596
51062
|
form: "single",
|
|
50597
51063
|
optional: false
|
|
50598
51064
|
}],
|
|
51065
|
+
"sceneMonitor.getStatus": [{
|
|
51066
|
+
name: "deviceId",
|
|
51067
|
+
form: "single",
|
|
51068
|
+
optional: false
|
|
51069
|
+
}],
|
|
50599
51070
|
"sceneMonitor.listScenes": [{
|
|
50600
51071
|
name: "deviceId",
|
|
50601
51072
|
form: "single",
|
|
@@ -50621,6 +51092,11 @@ Object.freeze({
|
|
|
50621
51092
|
form: "single",
|
|
50622
51093
|
optional: false
|
|
50623
51094
|
}],
|
|
51095
|
+
"scriptRunner.getStatus": [{
|
|
51096
|
+
name: "deviceId",
|
|
51097
|
+
form: "single",
|
|
51098
|
+
optional: false
|
|
51099
|
+
}],
|
|
50624
51100
|
"scriptRunner.run": [{
|
|
50625
51101
|
name: "deviceId",
|
|
50626
51102
|
form: "single",
|
|
@@ -50631,11 +51107,31 @@ Object.freeze({
|
|
|
50631
51107
|
form: "single",
|
|
50632
51108
|
optional: false
|
|
50633
51109
|
}],
|
|
51110
|
+
"smoke.getStatus": [{
|
|
51111
|
+
name: "deviceId",
|
|
51112
|
+
form: "single",
|
|
51113
|
+
optional: false
|
|
51114
|
+
}],
|
|
51115
|
+
"snapshot.applyDeviceSettingsPatch": [{
|
|
51116
|
+
name: "deviceId",
|
|
51117
|
+
form: "single",
|
|
51118
|
+
optional: false
|
|
51119
|
+
}],
|
|
50634
51120
|
"snapshot.getDebugState": [{
|
|
50635
51121
|
name: "deviceId",
|
|
50636
51122
|
form: "single",
|
|
50637
51123
|
optional: false
|
|
50638
51124
|
}],
|
|
51125
|
+
"snapshot.getDeviceLiveContribution": [{
|
|
51126
|
+
name: "deviceId",
|
|
51127
|
+
form: "single",
|
|
51128
|
+
optional: false
|
|
51129
|
+
}],
|
|
51130
|
+
"snapshot.getDeviceSettingsContribution": [{
|
|
51131
|
+
name: "deviceId",
|
|
51132
|
+
form: "single",
|
|
51133
|
+
optional: false
|
|
51134
|
+
}],
|
|
50639
51135
|
"snapshot.getSnapshot": [{
|
|
50640
51136
|
name: "deviceId",
|
|
50641
51137
|
form: "single",
|
|
@@ -50652,6 +51148,11 @@ Object.freeze({
|
|
|
50652
51148
|
form: "array",
|
|
50653
51149
|
optional: false
|
|
50654
51150
|
}],
|
|
51151
|
+
"snapshot.getStatus": [{
|
|
51152
|
+
name: "deviceId",
|
|
51153
|
+
form: "single",
|
|
51154
|
+
optional: false
|
|
51155
|
+
}],
|
|
50655
51156
|
"snapshot.invalidateCache": [{
|
|
50656
51157
|
name: "deviceId",
|
|
50657
51158
|
form: "single",
|
|
@@ -50662,6 +51163,11 @@ Object.freeze({
|
|
|
50662
51163
|
form: "single",
|
|
50663
51164
|
optional: false
|
|
50664
51165
|
}],
|
|
51166
|
+
"streamBroker.applyDeviceSettingsPatch": [{
|
|
51167
|
+
name: "deviceId",
|
|
51168
|
+
form: "single",
|
|
51169
|
+
optional: false
|
|
51170
|
+
}],
|
|
50665
51171
|
"streamBroker.assignProfile": [{
|
|
50666
51172
|
name: "deviceId",
|
|
50667
51173
|
form: "single",
|
|
@@ -50677,6 +51183,16 @@ Object.freeze({
|
|
|
50677
51183
|
form: "single",
|
|
50678
51184
|
optional: false
|
|
50679
51185
|
}],
|
|
51186
|
+
"streamBroker.getDeviceLiveContribution": [{
|
|
51187
|
+
name: "deviceId",
|
|
51188
|
+
form: "single",
|
|
51189
|
+
optional: false
|
|
51190
|
+
}],
|
|
51191
|
+
"streamBroker.getDeviceSettingsContribution": [{
|
|
51192
|
+
name: "deviceId",
|
|
51193
|
+
form: "single",
|
|
51194
|
+
optional: false
|
|
51195
|
+
}],
|
|
50680
51196
|
"streamBroker.getStreamWithCodec": [{
|
|
50681
51197
|
name: "deviceId",
|
|
50682
51198
|
form: "single",
|
|
@@ -50737,16 +51253,46 @@ Object.freeze({
|
|
|
50737
51253
|
form: "single",
|
|
50738
51254
|
optional: false
|
|
50739
51255
|
}],
|
|
51256
|
+
"streamParams.getStatus": [{
|
|
51257
|
+
name: "deviceId",
|
|
51258
|
+
form: "single",
|
|
51259
|
+
optional: false
|
|
51260
|
+
}],
|
|
50740
51261
|
"streamParams.setProfile": [{
|
|
50741
51262
|
name: "deviceId",
|
|
50742
51263
|
form: "single",
|
|
50743
51264
|
optional: false
|
|
50744
51265
|
}],
|
|
51266
|
+
"switch.getStatus": [{
|
|
51267
|
+
name: "deviceId",
|
|
51268
|
+
form: "single",
|
|
51269
|
+
optional: false
|
|
51270
|
+
}],
|
|
50745
51271
|
"switch.setState": [{
|
|
50746
51272
|
name: "deviceId",
|
|
50747
51273
|
form: "single",
|
|
50748
51274
|
optional: false
|
|
50749
51275
|
}],
|
|
51276
|
+
"tamper.getStatus": [{
|
|
51277
|
+
name: "deviceId",
|
|
51278
|
+
form: "single",
|
|
51279
|
+
optional: false
|
|
51280
|
+
}],
|
|
51281
|
+
"temperatureSensor.getStatus": [{
|
|
51282
|
+
name: "deviceId",
|
|
51283
|
+
form: "single",
|
|
51284
|
+
optional: false
|
|
51285
|
+
}],
|
|
51286
|
+
"update.getStatus": [{
|
|
51287
|
+
name: "deviceId",
|
|
51288
|
+
form: "single",
|
|
51289
|
+
optional: false
|
|
51290
|
+
}],
|
|
51291
|
+
"vacuumControl.getStatus": [{
|
|
51292
|
+
name: "deviceId",
|
|
51293
|
+
form: "single",
|
|
51294
|
+
optional: false
|
|
51295
|
+
}],
|
|
50750
51296
|
"vacuumControl.locate": [{
|
|
50751
51297
|
name: "deviceId",
|
|
50752
51298
|
form: "single",
|
|
@@ -50782,6 +51328,11 @@ Object.freeze({
|
|
|
50782
51328
|
form: "single",
|
|
50783
51329
|
optional: false
|
|
50784
51330
|
}],
|
|
51331
|
+
"valve.getStatus": [{
|
|
51332
|
+
name: "deviceId",
|
|
51333
|
+
form: "single",
|
|
51334
|
+
optional: false
|
|
51335
|
+
}],
|
|
50785
51336
|
"valve.open": [{
|
|
50786
51337
|
name: "deviceId",
|
|
50787
51338
|
form: "single",
|
|
@@ -50797,6 +51348,11 @@ Object.freeze({
|
|
|
50797
51348
|
form: "single",
|
|
50798
51349
|
optional: false
|
|
50799
51350
|
}],
|
|
51351
|
+
"vibration.getStatus": [{
|
|
51352
|
+
name: "deviceId",
|
|
51353
|
+
form: "single",
|
|
51354
|
+
optional: false
|
|
51355
|
+
}],
|
|
50800
51356
|
"videoclips.dialClipStream": [{
|
|
50801
51357
|
name: "deviceId",
|
|
50802
51358
|
form: "single",
|
|
@@ -50832,6 +51388,11 @@ Object.freeze({
|
|
|
50832
51388
|
form: "single",
|
|
50833
51389
|
optional: false
|
|
50834
51390
|
}],
|
|
51391
|
+
"waterHeater.getStatus": [{
|
|
51392
|
+
name: "deviceId",
|
|
51393
|
+
form: "single",
|
|
51394
|
+
optional: false
|
|
51395
|
+
}],
|
|
50835
51396
|
"waterHeater.setAway": [{
|
|
50836
51397
|
name: "deviceId",
|
|
50837
51398
|
form: "single",
|
|
@@ -50847,6 +51408,11 @@ Object.freeze({
|
|
|
50847
51408
|
form: "single",
|
|
50848
51409
|
optional: false
|
|
50849
51410
|
}],
|
|
51411
|
+
"weather.getStatus": [{
|
|
51412
|
+
name: "deviceId",
|
|
51413
|
+
form: "single",
|
|
51414
|
+
optional: false
|
|
51415
|
+
}],
|
|
50850
51416
|
"webrtcSession.addIceCandidate": [{
|
|
50851
51417
|
name: "deviceId",
|
|
50852
51418
|
form: "single",
|
|
@@ -51584,7 +52150,7 @@ var PreviewTextField = string().max(200);
|
|
|
51584
52150
|
* Whether the notification's preview is a STILL or a short animation.
|
|
51585
52151
|
*
|
|
51586
52152
|
* The operator's ask, verbatim: *"inviato come gif o video (come per le altre
|
|
51587
|
-
* rule)"* — the other rules already offer an animated preview, and a ten-hour
|
|
52153
|
+
* rule)"* [sent as a gif or video (as for the other rules)] — the other rules already offer an animated preview, and a ten-hour
|
|
51588
52154
|
* night reads better as three seconds of motion than as one frame of it. Both
|
|
51589
52155
|
* modes get the SAME treatment (blurred frame, large centred title); `'gif'`
|
|
51590
52156
|
* simply applies it to a dozen frames sampled across the render and assembles
|
|
@@ -51722,6 +52288,7 @@ TimelapseRuleInputSchema.extend({
|
|
|
51722
52288
|
createdAt: number(),
|
|
51723
52289
|
updatedAt: number()
|
|
51724
52290
|
});
|
|
52291
|
+
MotionOnMotionChangedDataSchema.omit({ triggeredBy: true });
|
|
51725
52292
|
object({
|
|
51726
52293
|
/**
|
|
51727
52294
|
* Fraction of the box's own size added on EACH side before cutting.
|