@camstack/addon-provider-homeassistant 1.2.151 → 1.2.152
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 +1 -1
- package/dist/addon.mjs +1 -1
- package/dist/{dist-DFsf2z4Q.mjs → dist-BITMr6s5.mjs} +160 -80
- package/dist/{dist-Cn_fSOpM.js → dist-nbfaHTXG.js} +160 -80
- package/dist/ha-export/ha-export.addon.js +15 -15
- package/dist/ha-export/ha-export.addon.mjs +15 -15
- package/package.json +1 -1
package/dist/addon.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_dist = require("./dist-
|
|
2
|
+
const require_dist = require("./dist-nbfaHTXG.js");
|
|
3
3
|
let node_crypto = require("node:crypto");
|
|
4
4
|
let node_zlib = require("node:zlib");
|
|
5
5
|
//#region src/ha-admin-link.ts
|
package/dist/addon.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as parseAdminBase, A as contactCapability, At as union, B as gasCapability, C as buildAddonRouteProvider, Ct as array, D as climateControlCapability, Dt as object, E as carbonMonoxideCapability, Et as number, G as lockControlCapability, H as humiditySensorCapability, I as enumSensorCapability, J as normalizeUnit, K as mediaPlayerCapability, L as eventEmitterCapability, M as coverCapability, Mt as url, N as deviceAdminLinkCapability, Nt as EventCategory, O as colorCapability, Ot as record, P as deviceAdoptionCapability, R as fanControlCapability, S as brokerCapability, St as _enum, T as buttonCapability, Tt as literal, U as imageCapability, V as humidifierCapability, W as lawnMowerControlCapability, X as notifierCapability, Y as notificationOutputCapability, Z as numericSensorCapability, _ as automationControlCapability, _t as DeviceType, at as smokeCapability, b as binaryCapability, bt as createEvent, ct as temperatureSensorCapability, d as TargetSchema, dt as valveCapability, et as powerMeterCapability, f as accessoriesCapability, ft as vibrationCapability, g as ambientLightSensorCapability, gt as DeviceRole, h as alarmPanelCapability, ht as DeviceFeature, it as scriptRunnerCapability, j as controlCapability, jt as unknown, k as connectivityCapability, kt as string, lt as updateCapability, m as airQualitySensorCapability, mt as weatherCapability, n as BaseDevice, nt as presenceCapability, ot as switchCapability, p as addonRoutesCapability, pt as waterHeaterCapability, q as motionCapability, r as BaseDeviceProvider, rt as pressureSensorCapability, s as EnumSensorDateTimeFormatSchema, st as tamperCapability, tt as prepareNotification, ut as vacuumControlCapability, v as batteryCapability, vt as errMsg, w as buildDeviceAdminUrl, wt as discriminatedUnion, x as brightnessCapability, y as bestLocationMatch, z as floodCapability } from "./dist-
|
|
1
|
+
import { $ as parseAdminBase, A as contactCapability, At as union, B as gasCapability, C as buildAddonRouteProvider, Ct as array, D as climateControlCapability, Dt as object, E as carbonMonoxideCapability, Et as number, G as lockControlCapability, H as humiditySensorCapability, I as enumSensorCapability, J as normalizeUnit, K as mediaPlayerCapability, L as eventEmitterCapability, M as coverCapability, Mt as url, N as deviceAdminLinkCapability, Nt as EventCategory, O as colorCapability, Ot as record, P as deviceAdoptionCapability, R as fanControlCapability, S as brokerCapability, St as _enum, T as buttonCapability, Tt as literal, U as imageCapability, V as humidifierCapability, W as lawnMowerControlCapability, X as notifierCapability, Y as notificationOutputCapability, Z as numericSensorCapability, _ as automationControlCapability, _t as DeviceType, at as smokeCapability, b as binaryCapability, bt as createEvent, ct as temperatureSensorCapability, d as TargetSchema, dt as valveCapability, et as powerMeterCapability, f as accessoriesCapability, ft as vibrationCapability, g as ambientLightSensorCapability, gt as DeviceRole, h as alarmPanelCapability, ht as DeviceFeature, it as scriptRunnerCapability, j as controlCapability, jt as unknown, k as connectivityCapability, kt as string, lt as updateCapability, m as airQualitySensorCapability, mt as weatherCapability, n as BaseDevice, nt as presenceCapability, ot as switchCapability, p as addonRoutesCapability, pt as waterHeaterCapability, q as motionCapability, r as BaseDeviceProvider, rt as pressureSensorCapability, s as EnumSensorDateTimeFormatSchema, st as tamperCapability, tt as prepareNotification, ut as vacuumControlCapability, v as batteryCapability, vt as errMsg, w as buildDeviceAdminUrl, wt as discriminatedUnion, x as brightnessCapability, y as bestLocationMatch, z as floodCapability } from "./dist-BITMr6s5.mjs";
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
import { brotliCompressSync, deflateSync, gzipSync } from "node:zlib";
|
|
4
4
|
//#region src/ha-admin-link.ts
|
|
@@ -7480,7 +7480,7 @@ function errMsg(err) {
|
|
|
7480
7480
|
return String(err);
|
|
7481
7481
|
}
|
|
7482
7482
|
//#endregion
|
|
7483
|
-
//#region ../types/dist/composition-
|
|
7483
|
+
//#region ../types/dist/composition-D7ULvLdD.mjs
|
|
7484
7484
|
/**
|
|
7485
7485
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
7486
7486
|
*
|
|
@@ -7534,20 +7534,20 @@ function portable(target) {
|
|
|
7534
7534
|
}
|
|
7535
7535
|
portable("linux64"), portable("linuxarm64"), portable("macarm64"), portable("mac64");
|
|
7536
7536
|
/**
|
|
7537
|
-
*
|
|
7538
|
-
*
|
|
7537
|
+
* THE table "which boolean of this device type counts as HIGH", and the
|
|
7538
|
+
* pure evaluator of its EDGE.
|
|
7539
7539
|
*
|
|
7540
|
-
*
|
|
7541
|
-
*
|
|
7542
|
-
*
|
|
7543
|
-
*
|
|
7544
|
-
*
|
|
7545
|
-
*
|
|
7540
|
+
* ONE table for everyone who asks "is this device HIGH?": the
|
|
7541
|
+
* recorder's `RecordingTriggers.sensorDeviceIds` trigger, the post-analysis
|
|
7542
|
+
* sensor markers, the orchestrator's camera-sensors bridge and
|
|
7543
|
+
* the sources of a composite doorbell (`doorbellFeatureSources`, D671).
|
|
7544
|
+
* A second copy would diverge at the first cap added, and the symptom — "the
|
|
7545
|
+
* sensor rings the doorbell but does not record" — is exactly D62.
|
|
7546
7546
|
*
|
|
7547
|
-
* ⚠
|
|
7548
|
-
*
|
|
7549
|
-
*
|
|
7550
|
-
*
|
|
7547
|
+
* ⚠ NOT `DEVICE_STATE_READERS` (`catalogs/device-state-vocabulary.ts`), and the
|
|
7548
|
+
* two must not be unified: that one answers "what is the state WORD for a
|
|
7549
|
+
* rule" (and includes `presence`, `cover`, `alarm-panel`), this one "which
|
|
7550
|
+
* boolean's EDGE counts". Deliberately different vocabularies.
|
|
7551
7551
|
*/
|
|
7552
7552
|
/**
|
|
7553
7553
|
* Known binary / switch source caps → the boolean slice field whose
|
|
@@ -9298,22 +9298,22 @@ var CLASS_MAP_MACRO_TARGETS = [
|
|
|
9298
9298
|
"package"
|
|
9299
9299
|
];
|
|
9300
9300
|
/**
|
|
9301
|
-
*
|
|
9302
|
-
*
|
|
9301
|
+
* The FIRST-LEVEL macro classes: those an object detector emits and that
|
|
9302
|
+
* an operator can select.
|
|
9303
9303
|
*
|
|
9304
|
-
*
|
|
9304
|
+
* They are the three offered by the `object-detection` step
|
|
9305
9305
|
* (`addon-pipeline/src/detection-pipeline/registry/step-definitions.ts`,
|
|
9306
|
-
* `enabledMacroClasses`). `package`
|
|
9307
|
-
* `MACRO_LABELS` —
|
|
9308
|
-
* `package-detection`,
|
|
9309
|
-
*
|
|
9306
|
+
* `enabledMacroClasses`). `package` is in {@link CLASS_MAP_MACRO_TARGETS} and in
|
|
9307
|
+
* `MACRO_LABELS` — it is a true macro — but NOT here: it belongs to the step
|
|
9308
|
+
* `package-detection`, whose enablement is driven by zones, and offering the
|
|
9309
|
+
* same word twice has already made an operator turn on the COCO proxy
|
|
9310
9310
|
* (suitcase/backpack/handbag) lasciando spento il detector dedicato.
|
|
9311
9311
|
*
|
|
9312
|
-
*
|
|
9313
|
-
*
|
|
9314
|
-
* (`types/detection.ts`);
|
|
9315
|
-
* (`RecordingTriggers.objectClasses`)
|
|
9316
|
-
*
|
|
9312
|
+
* ONE list. Before today the same three were hand-written in the step's offer
|
|
9313
|
+
* and a second time as the union `FirstLevelMacro`
|
|
9314
|
+
* (`types/detection.ts`); a third copy for the recording trigger
|
|
9315
|
+
* (`RecordingTriggers.objectClasses`) would have made the later divergence
|
|
9316
|
+
* invisible.
|
|
9317
9317
|
*/
|
|
9318
9318
|
var FIRST_LEVEL_MACRO_CLASSES = [
|
|
9319
9319
|
"person",
|
|
@@ -9378,17 +9378,17 @@ var RecordingStorageModeSchema = _enum([
|
|
|
9378
9378
|
"on-device-decision"
|
|
9379
9379
|
]);
|
|
9380
9380
|
/**
|
|
9381
|
-
*
|
|
9382
|
-
*
|
|
9381
|
+
* The macro classes that can open a recording window — the same
|
|
9382
|
+
* three offered by the `object-detection` step, from ONE list
|
|
9383
9383
|
* ({@link FIRST_LEVEL_MACRO_CLASSES}).
|
|
9384
9384
|
*/
|
|
9385
9385
|
var RecordingObjectTriggerClassSchema = _enum(FIRST_LEVEL_MACRO_CLASSES);
|
|
9386
9386
|
/**
|
|
9387
|
-
* True
|
|
9387
|
+
* True when `values` does not repeat an element.
|
|
9388
9388
|
*
|
|
9389
|
-
*
|
|
9390
|
-
*
|
|
9391
|
-
*
|
|
9389
|
+
* A duplicate is not harmless: every entry of `objectClasses` / `sensorDeviceIds`
|
|
9390
|
+
* becomes a SOURCE in `bandTriggerSources`, and the same source twice
|
|
9391
|
+
* would count its windows twice in `segmentMissedByMs`.
|
|
9392
9392
|
*/
|
|
9393
9393
|
var noDuplicates = (values) => new Set(values).size === values.length;
|
|
9394
9394
|
/** Which detectors trigger an `events`-mode band. */
|
|
@@ -9396,34 +9396,34 @@ var RecordingTriggersSchema = object({
|
|
|
9396
9396
|
motion: boolean().optional(),
|
|
9397
9397
|
audioThresholdDbfs: number().optional(),
|
|
9398
9398
|
/**
|
|
9399
|
-
*
|
|
9400
|
-
*
|
|
9401
|
-
*
|
|
9402
|
-
*
|
|
9399
|
+
* The macro classes whose detection opens a window. ABSENT = the source
|
|
9400
|
+
* is not listened to; an EMPTY array is rejected, because "events band, object
|
|
9401
|
+
* trigger on, no class" is the same shape "enabled and records
|
|
9402
|
+
* nothing, forever" that `eventsBandCanEverDemand` is written against.
|
|
9403
9403
|
*
|
|
9404
|
-
*
|
|
9405
|
-
*
|
|
9406
|
-
* `minConfidence<Macro>`
|
|
9407
|
-
* (`source: 'onboard'`)
|
|
9408
|
-
*
|
|
9404
|
+
* The signal read is ALREADY FILTERED: only `source: 'pipeline'` detections, i.e.
|
|
9405
|
+
* those that went through `enabledMacroClasses`, the
|
|
9406
|
+
* `minConfidence<Macro>` and the full-frame guard. The camera's onboard AI
|
|
9407
|
+
* (`source: 'onboard'`) goes through none of those gates and does NOT open
|
|
9408
|
+
* windows — see `recorder/object-trigger.ts`.
|
|
9409
9409
|
*/
|
|
9410
9410
|
objectClasses: array(RecordingObjectTriggerClassSchema).min(1).refine(noDuplicates, { message: "objectClasses must not repeat a class" }).optional(),
|
|
9411
9411
|
/**
|
|
9412
|
-
*
|
|
9413
|
-
*
|
|
9412
|
+
* The LINKED devices whose RISING EDGE opens a window. Absent = the source
|
|
9413
|
+
* is not listened to; an empty array is rejected for the same reason as
|
|
9414
9414
|
* `objectClasses`.
|
|
9415
9415
|
*
|
|
9416
|
-
*
|
|
9417
|
-
*
|
|
9418
|
-
*
|
|
9419
|
-
*
|
|
9420
|
-
* device (D12) —
|
|
9416
|
+
* These are SOURCE device ids, not cameras: the band names them, so the
|
|
9417
|
+
* hot path (`DeviceStateChanged`, at bus rate across the whole fleet)
|
|
9418
|
+
* does no RPC. The OFFER from which the operator picks them is another question, and
|
|
9419
|
+
* is resolved with `deviceManager.getLinkedDevices` + `getBindingsBatch` per
|
|
9420
|
+
* device (D12) — never a global list of caps.
|
|
9421
9421
|
*
|
|
9422
|
-
*
|
|
9423
|
-
* `SOURCE_CAP_ACTIVE_FIELD` (`catalogs/sensor-active-state.ts`)
|
|
9424
|
-
*
|
|
9425
|
-
*
|
|
9426
|
-
*
|
|
9422
|
+
* What "high" means depends on the device TYPE and is not decided here:
|
|
9423
|
+
* `SOURCE_CAP_ACTIVE_FIELD` (`catalogs/sensor-active-state.ts`) is THE table,
|
|
9424
|
+
* the same one as the composite doorbell (D671). And it is the EDGE, not
|
|
9425
|
+
* the level: a contact found already open at runner restart does not
|
|
9426
|
+
* record.
|
|
9427
9427
|
*/
|
|
9428
9428
|
sensorDeviceIds: array(number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional()
|
|
9429
9429
|
});
|
|
@@ -10500,7 +10500,7 @@ var DecoderSessionConfigSchema = object({
|
|
|
10500
10500
|
* - **VALUE** — at which level, for which scope, until when. That stays ONE
|
|
10501
10501
|
* thing: the logging settings document on the `system` cap. Two authorities
|
|
10502
10502
|
* over the values is the exact defect
|
|
10503
|
-
* `docs/design/plans/2026-08-26-
|
|
10503
|
+
* `docs/design/plans/2026-08-26-per-component-logging.md` was written to
|
|
10504
10504
|
* remove; re-introducing it from the cure side would be grotesque.
|
|
10505
10505
|
*
|
|
10506
10506
|
* Nothing in this file reads a clock, an env var or a store. The registry is
|
|
@@ -14123,7 +14123,7 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
|
|
|
14123
14123
|
*
|
|
14124
14124
|
* ⚠ An earlier version of this comment blamed Zod stripping, and that
|
|
14125
14125
|
* was wrong — corrected 2026-08-26 after the hop map
|
|
14126
|
-
* (`docs/design/2026-08-26-
|
|
14126
|
+
* (`docs/design/2026-08-26-topic-hop-map.md`) traced the path.
|
|
14127
14127
|
* There is **no Zod parse at all** between the door and the engine: the
|
|
14128
14128
|
* dispatcher forwards the payload verbatim and UDS carries it whole. A
|
|
14129
14129
|
* field declared here reaches `SqliteSettingsBackend` either way.
|
|
@@ -15220,7 +15220,17 @@ var SiteZoneSchema = object({
|
|
|
15220
15220
|
var ProviderStatusSchema = object({
|
|
15221
15221
|
connected: boolean(),
|
|
15222
15222
|
deviceCount: number(),
|
|
15223
|
-
error: string().optional()
|
|
15223
|
+
error: string().optional(),
|
|
15224
|
+
/**
|
|
15225
|
+
* `'orchestrator'`: this provider writes NO camera's `motion` runtime slice
|
|
15226
|
+
* — the orchestrator is its only writer (D696). Set by `BaseDeviceProvider`,
|
|
15227
|
+
* which every provider bundles, so only a provider BUILT from D696-amended
|
|
15228
|
+
* code says it. ABSENT means an older provider that may still write it (raw
|
|
15229
|
+
* VMD writes, a boot seed), and the orchestrator's provider gate keeps that
|
|
15230
|
+
* provider's cameras unwritten (`camera-sensors/motion-slice-provider-gate.ts`)
|
|
15231
|
+
* — the provider twin of the runner's `getLocalLoad().motionSliceWriter`.
|
|
15232
|
+
*/
|
|
15233
|
+
motionSliceWriter: literal("orchestrator").optional()
|
|
15224
15234
|
});
|
|
15225
15235
|
object({
|
|
15226
15236
|
externalId: string(),
|
|
@@ -16437,7 +16447,7 @@ method(object({
|
|
|
16437
16447
|
* per-device window, `KeyFrameCaptureLog`, `bumpCropMetric`. Every one of them
|
|
16438
16448
|
* ends in a log line, and a log line is the thing the operator asked to stop
|
|
16439
16449
|
* needing: *"possiamo armare questi errori intanto? Così al prossimo giro
|
|
16440
|
-
* ricontrolliamo tutti questi punti"
|
|
16450
|
+
* 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
|
|
16441
16451
|
* hand-correlating timestamps, which is how a 22% thumbnail gap and a 3-hour
|
|
16442
16452
|
* media blackout were both diagnosed. The counters stay; this is where they can
|
|
16443
16453
|
* be READ.
|
|
@@ -20696,6 +20706,29 @@ object({
|
|
|
20696
20706
|
firstAt: number(),
|
|
20697
20707
|
lastAt: number()
|
|
20698
20708
|
});
|
|
20709
|
+
var NC_ALARM_TRIGGERED_MAX_SEC = 3600;
|
|
20710
|
+
var NcAlarmDelaySecSchema = number().int().min(0).max(600);
|
|
20711
|
+
var NcAlarmTriggeredSecSchema = number().int().min(0).max(NC_ALARM_TRIGGERED_MAX_SEC);
|
|
20712
|
+
var uniqueModes = (entries) => new Set(entries.map((e) => e.mode)).size === entries.length;
|
|
20713
|
+
var NcAlarmModeDelaysListSchema = array(object({
|
|
20714
|
+
mode: AlarmArmModeSchema,
|
|
20715
|
+
exitDelaySec: NcAlarmDelaySecSchema.optional(),
|
|
20716
|
+
entryDelaySec: NcAlarmDelaySecSchema.optional(),
|
|
20717
|
+
triggeredDurationSec: NcAlarmTriggeredSecSchema.optional()
|
|
20718
|
+
})).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
|
|
20719
|
+
var NcAlarmModeDelaysEditListSchema = array(object({
|
|
20720
|
+
mode: AlarmArmModeSchema,
|
|
20721
|
+
exitDelaySec: NcAlarmDelaySecSchema.nullable().optional(),
|
|
20722
|
+
entryDelaySec: NcAlarmDelaySecSchema.nullable().optional(),
|
|
20723
|
+
triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional()
|
|
20724
|
+
})).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
|
|
20725
|
+
/** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
|
|
20726
|
+
var NcAlarmNonBlockingEditSchema = object({
|
|
20727
|
+
mode: AlarmArmModeSchema,
|
|
20728
|
+
deviceId: number().int().positive(),
|
|
20729
|
+
/** true = on the list (may be open, does not block); false = off the list (blocks). */
|
|
20730
|
+
nonBlocking: boolean()
|
|
20731
|
+
});
|
|
20699
20732
|
/**
|
|
20700
20733
|
* The per-mode lists, at most one per mode. Two lists for one mode have no
|
|
20701
20734
|
* meaning a reader could agree on (union? the last one?), so they are refused
|
|
@@ -20704,10 +20737,10 @@ object({
|
|
|
20704
20737
|
var NcAlarmNonBlockingListSchema = array(object({
|
|
20705
20738
|
mode: AlarmArmModeSchema,
|
|
20706
20739
|
deviceIds: array(number().int()).max(200)
|
|
20707
|
-
})).max(8).refine(
|
|
20740
|
+
})).max(8).refine(uniqueModes, { message: "nonBlocking: at most one list per arm mode" });
|
|
20708
20741
|
/**
|
|
20709
|
-
* The three durations
|
|
20710
|
-
* transitions, and which openings each mode tolerates.
|
|
20742
|
+
* The three durations — global, and per mode since D697 — the panel's state
|
|
20743
|
+
* machine runs on, who hears about its transitions, and which openings each mode tolerates.
|
|
20711
20744
|
*
|
|
20712
20745
|
* They live on the NOTIFICATION-RULES cap, not on `alarm-panel`, on purpose:
|
|
20713
20746
|
* `alarm-panel` is `deviceNative` and its other provider mirrors somebody
|
|
@@ -20717,15 +20750,15 @@ var NcAlarmNonBlockingListSchema = array(object({
|
|
|
20717
20750
|
*/
|
|
20718
20751
|
var NcAlarmSettingsSchema = object({
|
|
20719
20752
|
/** Grace period between arming and the mode taking effect. 0 = immediate. */
|
|
20720
|
-
exitDelaySec:
|
|
20753
|
+
exitDelaySec: NcAlarmDelaySecSchema,
|
|
20721
20754
|
/** Grace period between a trigger and the alarm firing. 0 = immediate. */
|
|
20722
|
-
entryDelaySec:
|
|
20755
|
+
entryDelaySec: NcAlarmDelaySecSchema,
|
|
20723
20756
|
/**
|
|
20724
20757
|
* How long `triggered` lasts before the panel re-arms itself.
|
|
20725
20758
|
* **0 = until an operator disarms it** — the behaviour before this field
|
|
20726
20759
|
* existed, and therefore what an untouched install keeps doing.
|
|
20727
20760
|
*/
|
|
20728
|
-
triggeredDurationSec:
|
|
20761
|
+
triggeredDurationSec: NcAlarmTriggeredSecSchema,
|
|
20729
20762
|
/**
|
|
20730
20763
|
* Deprecated by D630 — every transition is announced. Parsed, never read;
|
|
20731
20764
|
* remove after one release. Optional so an older admin's patch (which still
|
|
@@ -20748,17 +20781,30 @@ var NcAlarmSettingsSchema = object({
|
|
|
20748
20781
|
* per mode is meaningful. Defaulted to `[]` so a blob stored before D630
|
|
20749
20782
|
* parses as "every opening blocks" — the behaviour it was written under.
|
|
20750
20783
|
*/
|
|
20751
|
-
nonBlocking: NcAlarmNonBlockingListSchema.default([])
|
|
20784
|
+
nonBlocking: NcAlarmNonBlockingListSchema.default([]),
|
|
20785
|
+
/**
|
|
20786
|
+
* Per arm mode, the delays that mode OVERRIDES (D697). A mode with no entry, or an entry
|
|
20787
|
+
* without a field, uses the global value above — so `[]`, the default, is exactly the
|
|
20788
|
+
* behaviour of a blob stored before this field existed. Read through `resolveModeDelays`.
|
|
20789
|
+
*/
|
|
20790
|
+
modeDelays: NcAlarmModeDelaysListSchema.default([])
|
|
20752
20791
|
});
|
|
20753
20792
|
/**
|
|
20754
20793
|
* Every field optional — a tab edits one control at a time.
|
|
20755
20794
|
*
|
|
20756
|
-
* `nonBlocking`
|
|
20757
|
-
* remove an inner `.default()`, so a patch that never
|
|
20758
|
-
* parse to `
|
|
20759
|
-
* (the same trap {@link NcRulePatchSchema} documents).
|
|
20795
|
+
* `nonBlocking` and `modeDelays` are re-declared WITHOUT their defaults:
|
|
20796
|
+
* `.partial()` does not remove an inner `.default()`, so a patch that never
|
|
20797
|
+
* named the field would parse to `[]` and wipe every mode's list on an
|
|
20798
|
+
* unrelated edit (the same trap {@link NcRulePatchSchema} documents). Here
|
|
20799
|
+
* `modeDelays` means EDITS, not the stored overrides.
|
|
20760
20800
|
*/
|
|
20761
|
-
var NcAlarmSettingsPatchSchema = NcAlarmSettingsSchema.extend({
|
|
20801
|
+
var NcAlarmSettingsPatchSchema = NcAlarmSettingsSchema.extend({
|
|
20802
|
+
nonBlocking: NcAlarmNonBlockingListSchema,
|
|
20803
|
+
/** Per-mode, per-field edits — NOT the whole list (see NcAlarmModeDelaysEditSchema). */
|
|
20804
|
+
modeDelays: NcAlarmModeDelaysEditListSchema,
|
|
20805
|
+
/** ONE membership change; the panel applies it to the list it holds at its turn. */
|
|
20806
|
+
nonBlockingEdit: NcAlarmNonBlockingEditSchema
|
|
20807
|
+
}).partial().refine((p) => p.nonBlocking === void 0 || p.nonBlockingEdit === void 0, { message: "nonBlocking and nonBlockingEdit are exclusive — send the whole lists or one edit" });
|
|
20762
20808
|
/**
|
|
20763
20809
|
* What one arm mode actually arms, DERIVED from the enabled rules gated on it.
|
|
20764
20810
|
* Never authored, never stored — see `alarm-mode-coverage.ts` for why a stored
|
|
@@ -20858,6 +20904,28 @@ var NcAlarmConfigSchema = object({
|
|
|
20858
20904
|
*/
|
|
20859
20905
|
live: NcAlarmLiveSchema.optional()
|
|
20860
20906
|
});
|
|
20907
|
+
var NcAlarmSensorReadingSchema = _enum([
|
|
20908
|
+
"open",
|
|
20909
|
+
"closed",
|
|
20910
|
+
"unknown",
|
|
20911
|
+
"not-opening"
|
|
20912
|
+
]);
|
|
20913
|
+
/** One device's state as the alarm reads it — the classifier the arm check uses. */
|
|
20914
|
+
var NcAlarmSensorStateSchema = object({
|
|
20915
|
+
deviceId: number().int().positive(),
|
|
20916
|
+
reading: NcAlarmSensorReadingSchema,
|
|
20917
|
+
/** The word as read (`open`, `closed`, `unlocked`, `stopped`, …); null when unknown / not an opening. */
|
|
20918
|
+
state: string().nullable(),
|
|
20919
|
+
/** Why `unknown`: the read failed, or the slice holds no word its cap defines (a placeholder included). */
|
|
20920
|
+
unknownWhy: _enum(["read-failed", "unknown-word"]).nullable(),
|
|
20921
|
+
/** The device manager's liveness as the centre mirrors it; null = not known. */
|
|
20922
|
+
online: boolean().nullable()
|
|
20923
|
+
});
|
|
20924
|
+
var NcAlarmSensorsInputSchema = object({ deviceIds: array(number().int().positive()).max(500) });
|
|
20925
|
+
var NcAlarmSensorsSchema = object({
|
|
20926
|
+
sensors: array(NcAlarmSensorStateSchema),
|
|
20927
|
+
readAt: number().int().nonnegative()
|
|
20928
|
+
});
|
|
20861
20929
|
/**
|
|
20862
20930
|
* ONE rule's demand on ONE camera's clip ring.
|
|
20863
20931
|
*
|
|
@@ -20948,7 +21016,7 @@ method(object({}), object({ rules: array(NcRuleSchema) }), { auth: "admin" }), m
|
|
|
20948
21016
|
}), method(object({}), NcAlarmConfigSchema, { auth: "admin" }), method(object({ patch: NcAlarmSettingsPatchSchema }), NcAlarmConfigSchema, {
|
|
20949
21017
|
kind: "mutation",
|
|
20950
21018
|
auth: "admin"
|
|
20951
|
-
});
|
|
21019
|
+
}), method(NcAlarmSensorsInputSchema, NcAlarmSensorsSchema, { auth: "admin" });
|
|
20952
21020
|
/**
|
|
20953
21021
|
* Zod schemas for persisted record types.
|
|
20954
21022
|
*
|
|
@@ -22116,14 +22184,14 @@ var TrackSchema = object({
|
|
|
22116
22184
|
* `derive-returned-null tile=standin`,
|
|
22117
22185
|
* `native-tile tile=native no-key-frame-at-close`, …) written at close and
|
|
22118
22186
|
* CLEARED by the late-keyFrame upgrade when a native tile lands after all.
|
|
22119
|
-
* The operator-facing answer to "perché manca l'immagine?" on a track whose
|
|
22187
|
+
* The operator-facing answer to "perché manca l'immagine?" [why is the image missing?] on a track whose
|
|
22120
22188
|
* tile is a face/plate stand-in, a raster crop, or an icon.
|
|
22121
22189
|
*
|
|
22122
22190
|
* **`no-key-frame-at-close` (D400).** The line used to be written ONLY when
|
|
22123
22191
|
* the TILE ranked below native, so a track whose thumbnail landed natively
|
|
22124
22192
|
* while its key frame missed carried no reason at all — three of the four
|
|
22125
22193
|
* `MISSING_KEYFRAME` tracks in the 2026-09-07 operator audit were exactly
|
|
22126
|
-
* that shape, and their "niente ultimo" had no cause anywhere on the row.
|
|
22194
|
+
* that shape, and their "niente ultimo" [no last frame] had no cause anywhere on the row.
|
|
22127
22195
|
* The key frame is the head of a cascade (`keyFrame ⇒ keyFrameSmall ⇒ the
|
|
22128
22196
|
* lastFrame copy source`), so its absence is now on this line whatever the
|
|
22129
22197
|
* tile ended up being.
|
|
@@ -22210,7 +22278,7 @@ var MotionEventSchema = object({
|
|
|
22210
22278
|
/**
|
|
22211
22279
|
* Ms offsets from `timestamp` (the episode's own first rising edge, so the
|
|
22212
22280
|
* first entry is always `0`) of every genuine off→on transition the
|
|
22213
|
-
* episode saw — "ogni evento on si deve salvare" (D475). NOT one entry per
|
|
22281
|
+
* episode saw — "ogni evento on si deve salvare" [every ON event must be saved] (D475). NOT one entry per
|
|
22214
22282
|
* push: a firmware source that keepalives at ~1 Hz for the whole burst
|
|
22215
22283
|
* (Reolink, Hikvision) produces exactly one edge; a source that reports an
|
|
22216
22284
|
* explicit `false` mid-episode and then resumes before the quiet window
|
|
@@ -27515,7 +27583,7 @@ var ClipPlaybackSchema = object({
|
|
|
27515
27583
|
* **One authorised yes is one wake.** `next-natural` — take the clip the next
|
|
27516
27584
|
* time the camera is awake for its own reasons — is deliberately not a member:
|
|
27517
27585
|
* it was proposed, it is free on the battery, and the operator declined it on
|
|
27518
|
-
* 2026-09-20 (*"Quando un export viene richiesto si sveglia la camera."
|
|
27586
|
+
* 2026-09-20 (*"Quando un export viene richiesto si sveglia la camera."* [When an export is requested the camera wakes up],
|
|
27519
27587
|
* D558 "Considered and not taken").
|
|
27520
27588
|
*/
|
|
27521
27589
|
var ClipWakeSchema = _enum(["authorised"]);
|
|
@@ -27776,7 +27844,7 @@ DeviceType.Camera, method(object({
|
|
|
27776
27844
|
* It replaced `sources?: string[]`, a VIEW filter over source ids that
|
|
27777
27845
|
* assumed the answer was a fan-out over everything a camera has. The
|
|
27778
27846
|
* operator settled otherwise on 2026-09-20 — *"l'utilizzatore è uno
|
|
27779
|
-
* solo"* — so the list is asked of one provider at a time and there is
|
|
27847
|
+
* solo"* [there is only one user] — so the list is asked of one provider at a time and there is
|
|
27780
27848
|
* nothing to filter out of it.
|
|
27781
27849
|
*/
|
|
27782
27850
|
provider: string().min(1)
|
|
@@ -35855,7 +35923,7 @@ var ReadGopBytesResultSchema = object({
|
|
|
35855
35923
|
/**
|
|
35856
35924
|
* A time WINDOW of one finalized segment, cut by byte range — the multi-GOP
|
|
35857
35925
|
* twin of {@link ReadGopBytesResultSchema}'s single instant. Built for the
|
|
35858
|
-
* replay clip's `recording` source (`docs/design/plans/2026-08-26-replay-
|
|
35926
|
+
* replay clip's `recording` source (`docs/design/plans/2026-08-26-clip-replay-on-pipeline.md`):
|
|
35859
35927
|
* a replay needs several seconds of native pixels, not one frame.
|
|
35860
35928
|
*
|
|
35861
35929
|
* `ok.data` is standalone-demuxable, same as a GOP read. `ok.reachesRequestedEnd`
|
|
@@ -40278,13 +40346,14 @@ var BaseDeviceProvider = class extends BaseAddon {
|
|
|
40278
40346
|
async getStatus() {
|
|
40279
40347
|
const all = await this.ctx.kernel.devices?.getAll() ?? [];
|
|
40280
40348
|
const summary = this.restoreFailureSummary();
|
|
40281
|
-
|
|
40349
|
+
const base = {
|
|
40282
40350
|
connected: true,
|
|
40283
|
-
deviceCount: all.length
|
|
40351
|
+
deviceCount: all.length,
|
|
40352
|
+
motionSliceWriter: "orchestrator"
|
|
40284
40353
|
};
|
|
40354
|
+
if (summary === null) return base;
|
|
40285
40355
|
return {
|
|
40286
|
-
|
|
40287
|
-
deviceCount: all.length,
|
|
40356
|
+
...base,
|
|
40288
40357
|
error: summary
|
|
40289
40358
|
};
|
|
40290
40359
|
}
|
|
@@ -45720,6 +45789,12 @@ Object.freeze({
|
|
|
45720
45789
|
addonId: null,
|
|
45721
45790
|
access: "view"
|
|
45722
45791
|
},
|
|
45792
|
+
"notificationRules.getAlarmSensors": {
|
|
45793
|
+
capName: "notification-rules",
|
|
45794
|
+
capScope: "system",
|
|
45795
|
+
addonId: null,
|
|
45796
|
+
access: "view"
|
|
45797
|
+
},
|
|
45723
45798
|
"notificationRules.getClipRetentionAsks": {
|
|
45724
45799
|
capName: "notification-rules",
|
|
45725
45800
|
capScope: "system",
|
|
@@ -50203,6 +50278,11 @@ Object.freeze({
|
|
|
50203
50278
|
form: "single",
|
|
50204
50279
|
optional: false
|
|
50205
50280
|
}],
|
|
50281
|
+
"notificationRules.getAlarmSensors": [{
|
|
50282
|
+
name: "deviceIds",
|
|
50283
|
+
form: "array",
|
|
50284
|
+
optional: false
|
|
50285
|
+
}],
|
|
50206
50286
|
"notificationRules.setDeviceMuted": [{
|
|
50207
50287
|
name: "deviceId",
|
|
50208
50288
|
form: "single",
|
|
@@ -52207,7 +52287,7 @@ var PreviewTextField = string().max(200);
|
|
|
52207
52287
|
* Whether the notification's preview is a STILL or a short animation.
|
|
52208
52288
|
*
|
|
52209
52289
|
* The operator's ask, verbatim: *"inviato come gif o video (come per le altre
|
|
52210
|
-
* rule)"* — the other rules already offer an animated preview, and a ten-hour
|
|
52290
|
+
* rule)"* [sent as a gif or video (as for the other rules)] — the other rules already offer an animated preview, and a ten-hour
|
|
52211
52291
|
* night reads better as three seconds of motion than as one frame of it. Both
|
|
52212
52292
|
* modes get the SAME treatment (blurred frame, large centred title); `'gif'`
|
|
52213
52293
|
* simply applies it to a dozen frames sampled across the render and assembles
|
|
@@ -7481,7 +7481,7 @@ function errMsg(err) {
|
|
|
7481
7481
|
return String(err);
|
|
7482
7482
|
}
|
|
7483
7483
|
//#endregion
|
|
7484
|
-
//#region ../types/dist/composition-
|
|
7484
|
+
//#region ../types/dist/composition-D7ULvLdD.mjs
|
|
7485
7485
|
/**
|
|
7486
7486
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
7487
7487
|
*
|
|
@@ -7535,20 +7535,20 @@ function portable(target) {
|
|
|
7535
7535
|
}
|
|
7536
7536
|
portable("linux64"), portable("linuxarm64"), portable("macarm64"), portable("mac64");
|
|
7537
7537
|
/**
|
|
7538
|
-
*
|
|
7539
|
-
*
|
|
7538
|
+
* THE table "which boolean of this device type counts as HIGH", and the
|
|
7539
|
+
* pure evaluator of its EDGE.
|
|
7540
7540
|
*
|
|
7541
|
-
*
|
|
7542
|
-
*
|
|
7543
|
-
*
|
|
7544
|
-
*
|
|
7545
|
-
*
|
|
7546
|
-
*
|
|
7541
|
+
* ONE table for everyone who asks "is this device HIGH?": the
|
|
7542
|
+
* recorder's `RecordingTriggers.sensorDeviceIds` trigger, the post-analysis
|
|
7543
|
+
* sensor markers, the orchestrator's camera-sensors bridge and
|
|
7544
|
+
* the sources of a composite doorbell (`doorbellFeatureSources`, D671).
|
|
7545
|
+
* A second copy would diverge at the first cap added, and the symptom — "the
|
|
7546
|
+
* sensor rings the doorbell but does not record" — is exactly D62.
|
|
7547
7547
|
*
|
|
7548
|
-
* ⚠
|
|
7549
|
-
*
|
|
7550
|
-
*
|
|
7551
|
-
*
|
|
7548
|
+
* ⚠ NOT `DEVICE_STATE_READERS` (`catalogs/device-state-vocabulary.ts`), and the
|
|
7549
|
+
* two must not be unified: that one answers "what is the state WORD for a
|
|
7550
|
+
* rule" (and includes `presence`, `cover`, `alarm-panel`), this one "which
|
|
7551
|
+
* boolean's EDGE counts". Deliberately different vocabularies.
|
|
7552
7552
|
*/
|
|
7553
7553
|
/**
|
|
7554
7554
|
* Known binary / switch source caps → the boolean slice field whose
|
|
@@ -9299,22 +9299,22 @@ var CLASS_MAP_MACRO_TARGETS = [
|
|
|
9299
9299
|
"package"
|
|
9300
9300
|
];
|
|
9301
9301
|
/**
|
|
9302
|
-
*
|
|
9303
|
-
*
|
|
9302
|
+
* The FIRST-LEVEL macro classes: those an object detector emits and that
|
|
9303
|
+
* an operator can select.
|
|
9304
9304
|
*
|
|
9305
|
-
*
|
|
9305
|
+
* They are the three offered by the `object-detection` step
|
|
9306
9306
|
* (`addon-pipeline/src/detection-pipeline/registry/step-definitions.ts`,
|
|
9307
|
-
* `enabledMacroClasses`). `package`
|
|
9308
|
-
* `MACRO_LABELS` —
|
|
9309
|
-
* `package-detection`,
|
|
9310
|
-
*
|
|
9307
|
+
* `enabledMacroClasses`). `package` is in {@link CLASS_MAP_MACRO_TARGETS} and in
|
|
9308
|
+
* `MACRO_LABELS` — it is a true macro — but NOT here: it belongs to the step
|
|
9309
|
+
* `package-detection`, whose enablement is driven by zones, and offering the
|
|
9310
|
+
* same word twice has already made an operator turn on the COCO proxy
|
|
9311
9311
|
* (suitcase/backpack/handbag) lasciando spento il detector dedicato.
|
|
9312
9312
|
*
|
|
9313
|
-
*
|
|
9314
|
-
*
|
|
9315
|
-
* (`types/detection.ts`);
|
|
9316
|
-
* (`RecordingTriggers.objectClasses`)
|
|
9317
|
-
*
|
|
9313
|
+
* ONE list. Before today the same three were hand-written in the step's offer
|
|
9314
|
+
* and a second time as the union `FirstLevelMacro`
|
|
9315
|
+
* (`types/detection.ts`); a third copy for the recording trigger
|
|
9316
|
+
* (`RecordingTriggers.objectClasses`) would have made the later divergence
|
|
9317
|
+
* invisible.
|
|
9318
9318
|
*/
|
|
9319
9319
|
var FIRST_LEVEL_MACRO_CLASSES = [
|
|
9320
9320
|
"person",
|
|
@@ -9379,17 +9379,17 @@ var RecordingStorageModeSchema = _enum([
|
|
|
9379
9379
|
"on-device-decision"
|
|
9380
9380
|
]);
|
|
9381
9381
|
/**
|
|
9382
|
-
*
|
|
9383
|
-
*
|
|
9382
|
+
* The macro classes that can open a recording window — the same
|
|
9383
|
+
* three offered by the `object-detection` step, from ONE list
|
|
9384
9384
|
* ({@link FIRST_LEVEL_MACRO_CLASSES}).
|
|
9385
9385
|
*/
|
|
9386
9386
|
var RecordingObjectTriggerClassSchema = _enum(FIRST_LEVEL_MACRO_CLASSES);
|
|
9387
9387
|
/**
|
|
9388
|
-
* True
|
|
9388
|
+
* True when `values` does not repeat an element.
|
|
9389
9389
|
*
|
|
9390
|
-
*
|
|
9391
|
-
*
|
|
9392
|
-
*
|
|
9390
|
+
* A duplicate is not harmless: every entry of `objectClasses` / `sensorDeviceIds`
|
|
9391
|
+
* becomes a SOURCE in `bandTriggerSources`, and the same source twice
|
|
9392
|
+
* would count its windows twice in `segmentMissedByMs`.
|
|
9393
9393
|
*/
|
|
9394
9394
|
var noDuplicates = (values) => new Set(values).size === values.length;
|
|
9395
9395
|
/** Which detectors trigger an `events`-mode band. */
|
|
@@ -9397,34 +9397,34 @@ var RecordingTriggersSchema = object({
|
|
|
9397
9397
|
motion: boolean().optional(),
|
|
9398
9398
|
audioThresholdDbfs: number().optional(),
|
|
9399
9399
|
/**
|
|
9400
|
-
*
|
|
9401
|
-
*
|
|
9402
|
-
*
|
|
9403
|
-
*
|
|
9400
|
+
* The macro classes whose detection opens a window. ABSENT = the source
|
|
9401
|
+
* is not listened to; an EMPTY array is rejected, because "events band, object
|
|
9402
|
+
* trigger on, no class" is the same shape "enabled and records
|
|
9403
|
+
* nothing, forever" that `eventsBandCanEverDemand` is written against.
|
|
9404
9404
|
*
|
|
9405
|
-
*
|
|
9406
|
-
*
|
|
9407
|
-
* `minConfidence<Macro>`
|
|
9408
|
-
* (`source: 'onboard'`)
|
|
9409
|
-
*
|
|
9405
|
+
* The signal read is ALREADY FILTERED: only `source: 'pipeline'` detections, i.e.
|
|
9406
|
+
* those that went through `enabledMacroClasses`, the
|
|
9407
|
+
* `minConfidence<Macro>` and the full-frame guard. The camera's onboard AI
|
|
9408
|
+
* (`source: 'onboard'`) goes through none of those gates and does NOT open
|
|
9409
|
+
* windows — see `recorder/object-trigger.ts`.
|
|
9410
9410
|
*/
|
|
9411
9411
|
objectClasses: array(RecordingObjectTriggerClassSchema).min(1).refine(noDuplicates, { message: "objectClasses must not repeat a class" }).optional(),
|
|
9412
9412
|
/**
|
|
9413
|
-
*
|
|
9414
|
-
*
|
|
9413
|
+
* The LINKED devices whose RISING EDGE opens a window. Absent = the source
|
|
9414
|
+
* is not listened to; an empty array is rejected for the same reason as
|
|
9415
9415
|
* `objectClasses`.
|
|
9416
9416
|
*
|
|
9417
|
-
*
|
|
9418
|
-
*
|
|
9419
|
-
*
|
|
9420
|
-
*
|
|
9421
|
-
* device (D12) —
|
|
9417
|
+
* These are SOURCE device ids, not cameras: the band names them, so the
|
|
9418
|
+
* hot path (`DeviceStateChanged`, at bus rate across the whole fleet)
|
|
9419
|
+
* does no RPC. The OFFER from which the operator picks them is another question, and
|
|
9420
|
+
* is resolved with `deviceManager.getLinkedDevices` + `getBindingsBatch` per
|
|
9421
|
+
* device (D12) — never a global list of caps.
|
|
9422
9422
|
*
|
|
9423
|
-
*
|
|
9424
|
-
* `SOURCE_CAP_ACTIVE_FIELD` (`catalogs/sensor-active-state.ts`)
|
|
9425
|
-
*
|
|
9426
|
-
*
|
|
9427
|
-
*
|
|
9423
|
+
* What "high" means depends on the device TYPE and is not decided here:
|
|
9424
|
+
* `SOURCE_CAP_ACTIVE_FIELD` (`catalogs/sensor-active-state.ts`) is THE table,
|
|
9425
|
+
* the same one as the composite doorbell (D671). And it is the EDGE, not
|
|
9426
|
+
* the level: a contact found already open at runner restart does not
|
|
9427
|
+
* record.
|
|
9428
9428
|
*/
|
|
9429
9429
|
sensorDeviceIds: array(number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional()
|
|
9430
9430
|
});
|
|
@@ -10501,7 +10501,7 @@ var DecoderSessionConfigSchema = object({
|
|
|
10501
10501
|
* - **VALUE** — at which level, for which scope, until when. That stays ONE
|
|
10502
10502
|
* thing: the logging settings document on the `system` cap. Two authorities
|
|
10503
10503
|
* over the values is the exact defect
|
|
10504
|
-
* `docs/design/plans/2026-08-26-
|
|
10504
|
+
* `docs/design/plans/2026-08-26-per-component-logging.md` was written to
|
|
10505
10505
|
* remove; re-introducing it from the cure side would be grotesque.
|
|
10506
10506
|
*
|
|
10507
10507
|
* Nothing in this file reads a clock, an env var or a store. The registry is
|
|
@@ -14124,7 +14124,7 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
|
|
|
14124
14124
|
*
|
|
14125
14125
|
* ⚠ An earlier version of this comment blamed Zod stripping, and that
|
|
14126
14126
|
* was wrong — corrected 2026-08-26 after the hop map
|
|
14127
|
-
* (`docs/design/2026-08-26-
|
|
14127
|
+
* (`docs/design/2026-08-26-topic-hop-map.md`) traced the path.
|
|
14128
14128
|
* There is **no Zod parse at all** between the door and the engine: the
|
|
14129
14129
|
* dispatcher forwards the payload verbatim and UDS carries it whole. A
|
|
14130
14130
|
* field declared here reaches `SqliteSettingsBackend` either way.
|
|
@@ -15221,7 +15221,17 @@ var SiteZoneSchema = object({
|
|
|
15221
15221
|
var ProviderStatusSchema = object({
|
|
15222
15222
|
connected: boolean(),
|
|
15223
15223
|
deviceCount: number(),
|
|
15224
|
-
error: string().optional()
|
|
15224
|
+
error: string().optional(),
|
|
15225
|
+
/**
|
|
15226
|
+
* `'orchestrator'`: this provider writes NO camera's `motion` runtime slice
|
|
15227
|
+
* — the orchestrator is its only writer (D696). Set by `BaseDeviceProvider`,
|
|
15228
|
+
* which every provider bundles, so only a provider BUILT from D696-amended
|
|
15229
|
+
* code says it. ABSENT means an older provider that may still write it (raw
|
|
15230
|
+
* VMD writes, a boot seed), and the orchestrator's provider gate keeps that
|
|
15231
|
+
* provider's cameras unwritten (`camera-sensors/motion-slice-provider-gate.ts`)
|
|
15232
|
+
* — the provider twin of the runner's `getLocalLoad().motionSliceWriter`.
|
|
15233
|
+
*/
|
|
15234
|
+
motionSliceWriter: literal("orchestrator").optional()
|
|
15225
15235
|
});
|
|
15226
15236
|
object({
|
|
15227
15237
|
externalId: string(),
|
|
@@ -16438,7 +16448,7 @@ method(object({
|
|
|
16438
16448
|
* per-device window, `KeyFrameCaptureLog`, `bumpCropMetric`. Every one of them
|
|
16439
16449
|
* ends in a log line, and a log line is the thing the operator asked to stop
|
|
16440
16450
|
* needing: *"possiamo armare questi errori intanto? Così al prossimo giro
|
|
16441
|
-
* ricontrolliamo tutti questi punti"
|
|
16451
|
+
* 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
|
|
16442
16452
|
* hand-correlating timestamps, which is how a 22% thumbnail gap and a 3-hour
|
|
16443
16453
|
* media blackout were both diagnosed. The counters stay; this is where they can
|
|
16444
16454
|
* be READ.
|
|
@@ -20697,6 +20707,29 @@ object({
|
|
|
20697
20707
|
firstAt: number(),
|
|
20698
20708
|
lastAt: number()
|
|
20699
20709
|
});
|
|
20710
|
+
var NC_ALARM_TRIGGERED_MAX_SEC = 3600;
|
|
20711
|
+
var NcAlarmDelaySecSchema = number().int().min(0).max(600);
|
|
20712
|
+
var NcAlarmTriggeredSecSchema = number().int().min(0).max(NC_ALARM_TRIGGERED_MAX_SEC);
|
|
20713
|
+
var uniqueModes = (entries) => new Set(entries.map((e) => e.mode)).size === entries.length;
|
|
20714
|
+
var NcAlarmModeDelaysListSchema = array(object({
|
|
20715
|
+
mode: AlarmArmModeSchema,
|
|
20716
|
+
exitDelaySec: NcAlarmDelaySecSchema.optional(),
|
|
20717
|
+
entryDelaySec: NcAlarmDelaySecSchema.optional(),
|
|
20718
|
+
triggeredDurationSec: NcAlarmTriggeredSecSchema.optional()
|
|
20719
|
+
})).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
|
|
20720
|
+
var NcAlarmModeDelaysEditListSchema = array(object({
|
|
20721
|
+
mode: AlarmArmModeSchema,
|
|
20722
|
+
exitDelaySec: NcAlarmDelaySecSchema.nullable().optional(),
|
|
20723
|
+
entryDelaySec: NcAlarmDelaySecSchema.nullable().optional(),
|
|
20724
|
+
triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional()
|
|
20725
|
+
})).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
|
|
20726
|
+
/** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
|
|
20727
|
+
var NcAlarmNonBlockingEditSchema = object({
|
|
20728
|
+
mode: AlarmArmModeSchema,
|
|
20729
|
+
deviceId: number().int().positive(),
|
|
20730
|
+
/** true = on the list (may be open, does not block); false = off the list (blocks). */
|
|
20731
|
+
nonBlocking: boolean()
|
|
20732
|
+
});
|
|
20700
20733
|
/**
|
|
20701
20734
|
* The per-mode lists, at most one per mode. Two lists for one mode have no
|
|
20702
20735
|
* meaning a reader could agree on (union? the last one?), so they are refused
|
|
@@ -20705,10 +20738,10 @@ object({
|
|
|
20705
20738
|
var NcAlarmNonBlockingListSchema = array(object({
|
|
20706
20739
|
mode: AlarmArmModeSchema,
|
|
20707
20740
|
deviceIds: array(number().int()).max(200)
|
|
20708
|
-
})).max(8).refine(
|
|
20741
|
+
})).max(8).refine(uniqueModes, { message: "nonBlocking: at most one list per arm mode" });
|
|
20709
20742
|
/**
|
|
20710
|
-
* The three durations
|
|
20711
|
-
* transitions, and which openings each mode tolerates.
|
|
20743
|
+
* The three durations — global, and per mode since D697 — the panel's state
|
|
20744
|
+
* machine runs on, who hears about its transitions, and which openings each mode tolerates.
|
|
20712
20745
|
*
|
|
20713
20746
|
* They live on the NOTIFICATION-RULES cap, not on `alarm-panel`, on purpose:
|
|
20714
20747
|
* `alarm-panel` is `deviceNative` and its other provider mirrors somebody
|
|
@@ -20718,15 +20751,15 @@ var NcAlarmNonBlockingListSchema = array(object({
|
|
|
20718
20751
|
*/
|
|
20719
20752
|
var NcAlarmSettingsSchema = object({
|
|
20720
20753
|
/** Grace period between arming and the mode taking effect. 0 = immediate. */
|
|
20721
|
-
exitDelaySec:
|
|
20754
|
+
exitDelaySec: NcAlarmDelaySecSchema,
|
|
20722
20755
|
/** Grace period between a trigger and the alarm firing. 0 = immediate. */
|
|
20723
|
-
entryDelaySec:
|
|
20756
|
+
entryDelaySec: NcAlarmDelaySecSchema,
|
|
20724
20757
|
/**
|
|
20725
20758
|
* How long `triggered` lasts before the panel re-arms itself.
|
|
20726
20759
|
* **0 = until an operator disarms it** — the behaviour before this field
|
|
20727
20760
|
* existed, and therefore what an untouched install keeps doing.
|
|
20728
20761
|
*/
|
|
20729
|
-
triggeredDurationSec:
|
|
20762
|
+
triggeredDurationSec: NcAlarmTriggeredSecSchema,
|
|
20730
20763
|
/**
|
|
20731
20764
|
* Deprecated by D630 — every transition is announced. Parsed, never read;
|
|
20732
20765
|
* remove after one release. Optional so an older admin's patch (which still
|
|
@@ -20749,17 +20782,30 @@ var NcAlarmSettingsSchema = object({
|
|
|
20749
20782
|
* per mode is meaningful. Defaulted to `[]` so a blob stored before D630
|
|
20750
20783
|
* parses as "every opening blocks" — the behaviour it was written under.
|
|
20751
20784
|
*/
|
|
20752
|
-
nonBlocking: NcAlarmNonBlockingListSchema.default([])
|
|
20785
|
+
nonBlocking: NcAlarmNonBlockingListSchema.default([]),
|
|
20786
|
+
/**
|
|
20787
|
+
* Per arm mode, the delays that mode OVERRIDES (D697). A mode with no entry, or an entry
|
|
20788
|
+
* without a field, uses the global value above — so `[]`, the default, is exactly the
|
|
20789
|
+
* behaviour of a blob stored before this field existed. Read through `resolveModeDelays`.
|
|
20790
|
+
*/
|
|
20791
|
+
modeDelays: NcAlarmModeDelaysListSchema.default([])
|
|
20753
20792
|
});
|
|
20754
20793
|
/**
|
|
20755
20794
|
* Every field optional — a tab edits one control at a time.
|
|
20756
20795
|
*
|
|
20757
|
-
* `nonBlocking`
|
|
20758
|
-
* remove an inner `.default()`, so a patch that never
|
|
20759
|
-
* parse to `
|
|
20760
|
-
* (the same trap {@link NcRulePatchSchema} documents).
|
|
20796
|
+
* `nonBlocking` and `modeDelays` are re-declared WITHOUT their defaults:
|
|
20797
|
+
* `.partial()` does not remove an inner `.default()`, so a patch that never
|
|
20798
|
+
* named the field would parse to `[]` and wipe every mode's list on an
|
|
20799
|
+
* unrelated edit (the same trap {@link NcRulePatchSchema} documents). Here
|
|
20800
|
+
* `modeDelays` means EDITS, not the stored overrides.
|
|
20761
20801
|
*/
|
|
20762
|
-
var NcAlarmSettingsPatchSchema = NcAlarmSettingsSchema.extend({
|
|
20802
|
+
var NcAlarmSettingsPatchSchema = NcAlarmSettingsSchema.extend({
|
|
20803
|
+
nonBlocking: NcAlarmNonBlockingListSchema,
|
|
20804
|
+
/** Per-mode, per-field edits — NOT the whole list (see NcAlarmModeDelaysEditSchema). */
|
|
20805
|
+
modeDelays: NcAlarmModeDelaysEditListSchema,
|
|
20806
|
+
/** ONE membership change; the panel applies it to the list it holds at its turn. */
|
|
20807
|
+
nonBlockingEdit: NcAlarmNonBlockingEditSchema
|
|
20808
|
+
}).partial().refine((p) => p.nonBlocking === void 0 || p.nonBlockingEdit === void 0, { message: "nonBlocking and nonBlockingEdit are exclusive — send the whole lists or one edit" });
|
|
20763
20809
|
/**
|
|
20764
20810
|
* What one arm mode actually arms, DERIVED from the enabled rules gated on it.
|
|
20765
20811
|
* Never authored, never stored — see `alarm-mode-coverage.ts` for why a stored
|
|
@@ -20859,6 +20905,28 @@ var NcAlarmConfigSchema = object({
|
|
|
20859
20905
|
*/
|
|
20860
20906
|
live: NcAlarmLiveSchema.optional()
|
|
20861
20907
|
});
|
|
20908
|
+
var NcAlarmSensorReadingSchema = _enum([
|
|
20909
|
+
"open",
|
|
20910
|
+
"closed",
|
|
20911
|
+
"unknown",
|
|
20912
|
+
"not-opening"
|
|
20913
|
+
]);
|
|
20914
|
+
/** One device's state as the alarm reads it — the classifier the arm check uses. */
|
|
20915
|
+
var NcAlarmSensorStateSchema = object({
|
|
20916
|
+
deviceId: number().int().positive(),
|
|
20917
|
+
reading: NcAlarmSensorReadingSchema,
|
|
20918
|
+
/** The word as read (`open`, `closed`, `unlocked`, `stopped`, …); null when unknown / not an opening. */
|
|
20919
|
+
state: string().nullable(),
|
|
20920
|
+
/** Why `unknown`: the read failed, or the slice holds no word its cap defines (a placeholder included). */
|
|
20921
|
+
unknownWhy: _enum(["read-failed", "unknown-word"]).nullable(),
|
|
20922
|
+
/** The device manager's liveness as the centre mirrors it; null = not known. */
|
|
20923
|
+
online: boolean().nullable()
|
|
20924
|
+
});
|
|
20925
|
+
var NcAlarmSensorsInputSchema = object({ deviceIds: array(number().int().positive()).max(500) });
|
|
20926
|
+
var NcAlarmSensorsSchema = object({
|
|
20927
|
+
sensors: array(NcAlarmSensorStateSchema),
|
|
20928
|
+
readAt: number().int().nonnegative()
|
|
20929
|
+
});
|
|
20862
20930
|
/**
|
|
20863
20931
|
* ONE rule's demand on ONE camera's clip ring.
|
|
20864
20932
|
*
|
|
@@ -20949,7 +21017,7 @@ method(object({}), object({ rules: array(NcRuleSchema) }), { auth: "admin" }), m
|
|
|
20949
21017
|
}), method(object({}), NcAlarmConfigSchema, { auth: "admin" }), method(object({ patch: NcAlarmSettingsPatchSchema }), NcAlarmConfigSchema, {
|
|
20950
21018
|
kind: "mutation",
|
|
20951
21019
|
auth: "admin"
|
|
20952
|
-
});
|
|
21020
|
+
}), method(NcAlarmSensorsInputSchema, NcAlarmSensorsSchema, { auth: "admin" });
|
|
20953
21021
|
/**
|
|
20954
21022
|
* Zod schemas for persisted record types.
|
|
20955
21023
|
*
|
|
@@ -22117,14 +22185,14 @@ var TrackSchema = object({
|
|
|
22117
22185
|
* `derive-returned-null tile=standin`,
|
|
22118
22186
|
* `native-tile tile=native no-key-frame-at-close`, …) written at close and
|
|
22119
22187
|
* CLEARED by the late-keyFrame upgrade when a native tile lands after all.
|
|
22120
|
-
* The operator-facing answer to "perché manca l'immagine?" on a track whose
|
|
22188
|
+
* The operator-facing answer to "perché manca l'immagine?" [why is the image missing?] on a track whose
|
|
22121
22189
|
* tile is a face/plate stand-in, a raster crop, or an icon.
|
|
22122
22190
|
*
|
|
22123
22191
|
* **`no-key-frame-at-close` (D400).** The line used to be written ONLY when
|
|
22124
22192
|
* the TILE ranked below native, so a track whose thumbnail landed natively
|
|
22125
22193
|
* while its key frame missed carried no reason at all — three of the four
|
|
22126
22194
|
* `MISSING_KEYFRAME` tracks in the 2026-09-07 operator audit were exactly
|
|
22127
|
-
* that shape, and their "niente ultimo" had no cause anywhere on the row.
|
|
22195
|
+
* that shape, and their "niente ultimo" [no last frame] had no cause anywhere on the row.
|
|
22128
22196
|
* The key frame is the head of a cascade (`keyFrame ⇒ keyFrameSmall ⇒ the
|
|
22129
22197
|
* lastFrame copy source`), so its absence is now on this line whatever the
|
|
22130
22198
|
* tile ended up being.
|
|
@@ -22211,7 +22279,7 @@ var MotionEventSchema = object({
|
|
|
22211
22279
|
/**
|
|
22212
22280
|
* Ms offsets from `timestamp` (the episode's own first rising edge, so the
|
|
22213
22281
|
* first entry is always `0`) of every genuine off→on transition the
|
|
22214
|
-
* episode saw — "ogni evento on si deve salvare" (D475). NOT one entry per
|
|
22282
|
+
* episode saw — "ogni evento on si deve salvare" [every ON event must be saved] (D475). NOT one entry per
|
|
22215
22283
|
* push: a firmware source that keepalives at ~1 Hz for the whole burst
|
|
22216
22284
|
* (Reolink, Hikvision) produces exactly one edge; a source that reports an
|
|
22217
22285
|
* explicit `false` mid-episode and then resumes before the quiet window
|
|
@@ -27516,7 +27584,7 @@ var ClipPlaybackSchema = object({
|
|
|
27516
27584
|
* **One authorised yes is one wake.** `next-natural` — take the clip the next
|
|
27517
27585
|
* time the camera is awake for its own reasons — is deliberately not a member:
|
|
27518
27586
|
* it was proposed, it is free on the battery, and the operator declined it on
|
|
27519
|
-
* 2026-09-20 (*"Quando un export viene richiesto si sveglia la camera."
|
|
27587
|
+
* 2026-09-20 (*"Quando un export viene richiesto si sveglia la camera."* [When an export is requested the camera wakes up],
|
|
27520
27588
|
* D558 "Considered and not taken").
|
|
27521
27589
|
*/
|
|
27522
27590
|
var ClipWakeSchema = _enum(["authorised"]);
|
|
@@ -27777,7 +27845,7 @@ DeviceType.Camera, method(object({
|
|
|
27777
27845
|
* It replaced `sources?: string[]`, a VIEW filter over source ids that
|
|
27778
27846
|
* assumed the answer was a fan-out over everything a camera has. The
|
|
27779
27847
|
* operator settled otherwise on 2026-09-20 — *"l'utilizzatore è uno
|
|
27780
|
-
* solo"* — so the list is asked of one provider at a time and there is
|
|
27848
|
+
* solo"* [there is only one user] — so the list is asked of one provider at a time and there is
|
|
27781
27849
|
* nothing to filter out of it.
|
|
27782
27850
|
*/
|
|
27783
27851
|
provider: string().min(1)
|
|
@@ -35856,7 +35924,7 @@ var ReadGopBytesResultSchema = object({
|
|
|
35856
35924
|
/**
|
|
35857
35925
|
* A time WINDOW of one finalized segment, cut by byte range — the multi-GOP
|
|
35858
35926
|
* twin of {@link ReadGopBytesResultSchema}'s single instant. Built for the
|
|
35859
|
-
* replay clip's `recording` source (`docs/design/plans/2026-08-26-replay-
|
|
35927
|
+
* replay clip's `recording` source (`docs/design/plans/2026-08-26-clip-replay-on-pipeline.md`):
|
|
35860
35928
|
* a replay needs several seconds of native pixels, not one frame.
|
|
35861
35929
|
*
|
|
35862
35930
|
* `ok.data` is standalone-demuxable, same as a GOP read. `ok.reachesRequestedEnd`
|
|
@@ -40279,13 +40347,14 @@ var BaseDeviceProvider = class extends BaseAddon {
|
|
|
40279
40347
|
async getStatus() {
|
|
40280
40348
|
const all = await this.ctx.kernel.devices?.getAll() ?? [];
|
|
40281
40349
|
const summary = this.restoreFailureSummary();
|
|
40282
|
-
|
|
40350
|
+
const base = {
|
|
40283
40351
|
connected: true,
|
|
40284
|
-
deviceCount: all.length
|
|
40352
|
+
deviceCount: all.length,
|
|
40353
|
+
motionSliceWriter: "orchestrator"
|
|
40285
40354
|
};
|
|
40355
|
+
if (summary === null) return base;
|
|
40286
40356
|
return {
|
|
40287
|
-
|
|
40288
|
-
deviceCount: all.length,
|
|
40357
|
+
...base,
|
|
40289
40358
|
error: summary
|
|
40290
40359
|
};
|
|
40291
40360
|
}
|
|
@@ -45721,6 +45790,12 @@ Object.freeze({
|
|
|
45721
45790
|
addonId: null,
|
|
45722
45791
|
access: "view"
|
|
45723
45792
|
},
|
|
45793
|
+
"notificationRules.getAlarmSensors": {
|
|
45794
|
+
capName: "notification-rules",
|
|
45795
|
+
capScope: "system",
|
|
45796
|
+
addonId: null,
|
|
45797
|
+
access: "view"
|
|
45798
|
+
},
|
|
45724
45799
|
"notificationRules.getClipRetentionAsks": {
|
|
45725
45800
|
capName: "notification-rules",
|
|
45726
45801
|
capScope: "system",
|
|
@@ -50204,6 +50279,11 @@ Object.freeze({
|
|
|
50204
50279
|
form: "single",
|
|
50205
50280
|
optional: false
|
|
50206
50281
|
}],
|
|
50282
|
+
"notificationRules.getAlarmSensors": [{
|
|
50283
|
+
name: "deviceIds",
|
|
50284
|
+
form: "array",
|
|
50285
|
+
optional: false
|
|
50286
|
+
}],
|
|
50207
50287
|
"notificationRules.setDeviceMuted": [{
|
|
50208
50288
|
name: "deviceId",
|
|
50209
50289
|
form: "single",
|
|
@@ -52208,7 +52288,7 @@ var PreviewTextField = string().max(200);
|
|
|
52208
52288
|
* Whether the notification's preview is a STILL or a short animation.
|
|
52209
52289
|
*
|
|
52210
52290
|
* The operator's ask, verbatim: *"inviato come gif o video (come per le altre
|
|
52211
|
-
* rule)"* — the other rules already offer an animated preview, and a ten-hour
|
|
52291
|
+
* rule)"* [sent as a gif or video (as for the other rules)] — the other rules already offer an animated preview, and a ten-hour
|
|
52212
52292
|
* night reads better as three seconds of motion than as one frame of it. Both
|
|
52213
52293
|
* modes get the SAME treatment (blurred frame, large centred title); `'gif'`
|
|
52214
52294
|
* simply applies it to a dozen frames sampled across the render and assembles
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
//#endregion
|
|
6
|
-
const require_dist = require("../dist-
|
|
6
|
+
const require_dist = require("../dist-nbfaHTXG.js");
|
|
7
7
|
let node_crypto = require("node:crypto");
|
|
8
8
|
//#region src/ha-export/topics.ts
|
|
9
9
|
/**
|
|
@@ -4022,12 +4022,12 @@ async function call(slice, capName, make) {
|
|
|
4022
4022
|
//#endregion
|
|
4023
4023
|
//#region src/ha-export/camera-function-writes.ts
|
|
4024
4024
|
/**
|
|
4025
|
-
*
|
|
4025
|
+
* Performs the WRITE of a camera function on the authority that owns it.
|
|
4026
4026
|
*
|
|
4027
4027
|
* `deriveCameraFunctions`/`resolveCameraFunctionWrite` (`camera-functions.ts`)
|
|
4028
|
-
*
|
|
4029
|
-
* `scripts/check-switch-successor-surfaces.ts`
|
|
4030
|
-
*
|
|
4028
|
+
* decide; this module acts. It is the file that
|
|
4029
|
+
* `scripts/check-switch-successor-surfaces.ts` points to as the successor of the
|
|
4030
|
+
* deprecated pair `getCameraSwitches` / `setCameraSwitch` (D113 phase 4).
|
|
4031
4031
|
*/
|
|
4032
4032
|
async function applyCameraFunctionWrite(api, deviceId, write, sourceNodeId) {
|
|
4033
4033
|
switch (write.kind) {
|
|
@@ -4087,9 +4087,9 @@ async function applyCameraFunctionWrite(api, deviceId, write, sourceNodeId) {
|
|
|
4087
4087
|
//#region src/ha-export/camera-functions.ts
|
|
4088
4088
|
var DETECTION_CAP = "detection-pipeline";
|
|
4089
4089
|
var AUDIO_ANALYSIS_CAP = "audio-analysis";
|
|
4090
|
-
/**
|
|
4090
|
+
/** The wrapper that WRITES the history: tracks, events and their media. */
|
|
4091
4091
|
var PIPELINE_ANALYTICS_CAP = "pipeline-analytics";
|
|
4092
|
-
/**
|
|
4092
|
+
/** Render order: widest reach first, source before consumer. */
|
|
4093
4093
|
var ORDER = [
|
|
4094
4094
|
"stream-broker",
|
|
4095
4095
|
"object-detection",
|
|
@@ -4113,9 +4113,9 @@ var LABELS = {
|
|
|
4113
4113
|
notifications: "Notifications"
|
|
4114
4114
|
};
|
|
4115
4115
|
/**
|
|
4116
|
-
*
|
|
4117
|
-
*
|
|
4118
|
-
*
|
|
4116
|
+
* Which cap stands behind each wrapper-backed switch. A map instead of a
|
|
4117
|
+
* ternary: with three entries the ternary became a chain, and the next entry
|
|
4118
|
+
* would have silently landed on the wrong branch.
|
|
4119
4119
|
*/
|
|
4120
4120
|
var WRAPPER_CAP_BY_ID = {
|
|
4121
4121
|
"object-detection": DETECTION_CAP,
|
|
@@ -4173,7 +4173,7 @@ function deriveCameraFunctions(reads) {
|
|
|
4173
4173
|
...resolveOne(id, reads)
|
|
4174
4174
|
}));
|
|
4175
4175
|
}
|
|
4176
|
-
/** `null` =
|
|
4176
|
+
/** `null` = not available: the write must be REFUSED, not approximated. */
|
|
4177
4177
|
function resolveCameraFunctionWrite(id, on, reads) {
|
|
4178
4178
|
if (!resolveOne(id, reads).available) return null;
|
|
4179
4179
|
switch (id) {
|
|
@@ -5333,7 +5333,7 @@ function notificationCenterSpecs(input) {
|
|
|
5333
5333
|
(
|
|
5334
5334
|
/**
|
|
5335
5335
|
* The last trigger, six entities: five facts plus its picture — "conoscere
|
|
5336
|
-
* gli ultimi trigger, le ultime immagini... e da quale label" (operator,
|
|
5336
|
+
* gli ultimi trigger, le ultime immagini... e da quale label" [know the latest triggers, the latest images... and from which label] (operator,
|
|
5337
5337
|
* 2026-08-25). ENABLED by default like every other entity on this device
|
|
5338
5338
|
* (see {@link buildComponents}'s docblock): a rule the operator wrote is a
|
|
5339
5339
|
* rule they want to watch fire.
|
|
@@ -6355,7 +6355,7 @@ var HaExportAddon = class extends require_dist.BaseAddon {
|
|
|
6355
6355
|
* `className` and no `confidence`; reading those invented names mapped
|
|
6356
6356
|
* every window to `[]`, so `audio_last_sound` sat at `unknown` for ever
|
|
6357
6357
|
* while the analyzer was classifying happily (found 2026-08-09, symptom:
|
|
6358
|
-
* "le audio labels sembrano non arrivare").
|
|
6358
|
+
* "le audio labels sembrano non arrivare" [the audio labels seem not to arrive]).
|
|
6359
6359
|
*
|
|
6360
6360
|
* The best LABEL wins over the macro: `audio` as a value tells an operator
|
|
6361
6361
|
* nothing, `dog` or `crying` is the whole point. Falls back to the macro
|
|
@@ -6724,8 +6724,8 @@ var HaExportAddon = class extends require_dist.BaseAddon {
|
|
|
6724
6724
|
/**
|
|
6725
6725
|
* The most recent notification-rule trigger, GLOBAL and PER RULE —
|
|
6726
6726
|
* "conoscere gli ultimi trigger, le ultime immagini... e da quale label"
|
|
6727
|
-
* (operator, 2026-08-25), extended to "l'ultimo trigger PER REGOLA, con
|
|
6728
|
-
* immagine e metadati" (operator, 2026-08-27).
|
|
6727
|
+
* [know the latest triggers, the latest images... and from which label] (operator, 2026-08-25), extended to "l'ultimo trigger PER REGOLA, con
|
|
6728
|
+
* immagine e metadati" [the latest trigger PER RULE, with image and metadata] (operator, 2026-08-27).
|
|
6729
6729
|
*
|
|
6730
6730
|
* ONE `getHistory` read serves BOTH: `reduceLastTriggers`
|
|
6731
6731
|
* (`rule-triggers.ts`) reduces the same newest-first page into "the very
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as buildAddonRouteProvider, F as deviceExportCapability, Nt as EventCategory, Q as oauthIntegrationCapability, a as COCO_TO_MACRO, c as FanDirectionSchema, i as CAMERA_SWITCH_ORDER, kt as string, l as HvacModeSchema, o as CameraSwitchIdSchema, p as addonRoutesCapability, t as AlarmArmModeSchema, u as MediaPlayerRepeatSchema, xt as nodePin, yt as BaseAddon } from "../dist-
|
|
1
|
+
import { C as buildAddonRouteProvider, F as deviceExportCapability, Nt as EventCategory, Q as oauthIntegrationCapability, a as COCO_TO_MACRO, c as FanDirectionSchema, i as CAMERA_SWITCH_ORDER, kt as string, l as HvacModeSchema, o as CameraSwitchIdSchema, p as addonRoutesCapability, t as AlarmArmModeSchema, u as MediaPlayerRepeatSchema, xt as nodePin, yt as BaseAddon } from "../dist-BITMr6s5.mjs";
|
|
2
2
|
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
3
3
|
//#region src/ha-export/topics.ts
|
|
4
4
|
/**
|
|
@@ -4017,12 +4017,12 @@ async function call(slice, capName, make) {
|
|
|
4017
4017
|
//#endregion
|
|
4018
4018
|
//#region src/ha-export/camera-function-writes.ts
|
|
4019
4019
|
/**
|
|
4020
|
-
*
|
|
4020
|
+
* Performs the WRITE of a camera function on the authority that owns it.
|
|
4021
4021
|
*
|
|
4022
4022
|
* `deriveCameraFunctions`/`resolveCameraFunctionWrite` (`camera-functions.ts`)
|
|
4023
|
-
*
|
|
4024
|
-
* `scripts/check-switch-successor-surfaces.ts`
|
|
4025
|
-
*
|
|
4023
|
+
* decide; this module acts. It is the file that
|
|
4024
|
+
* `scripts/check-switch-successor-surfaces.ts` points to as the successor of the
|
|
4025
|
+
* deprecated pair `getCameraSwitches` / `setCameraSwitch` (D113 phase 4).
|
|
4026
4026
|
*/
|
|
4027
4027
|
async function applyCameraFunctionWrite(api, deviceId, write, sourceNodeId) {
|
|
4028
4028
|
switch (write.kind) {
|
|
@@ -4082,9 +4082,9 @@ async function applyCameraFunctionWrite(api, deviceId, write, sourceNodeId) {
|
|
|
4082
4082
|
//#region src/ha-export/camera-functions.ts
|
|
4083
4083
|
var DETECTION_CAP = "detection-pipeline";
|
|
4084
4084
|
var AUDIO_ANALYSIS_CAP = "audio-analysis";
|
|
4085
|
-
/**
|
|
4085
|
+
/** The wrapper that WRITES the history: tracks, events and their media. */
|
|
4086
4086
|
var PIPELINE_ANALYTICS_CAP = "pipeline-analytics";
|
|
4087
|
-
/**
|
|
4087
|
+
/** Render order: widest reach first, source before consumer. */
|
|
4088
4088
|
var ORDER = [
|
|
4089
4089
|
"stream-broker",
|
|
4090
4090
|
"object-detection",
|
|
@@ -4108,9 +4108,9 @@ var LABELS = {
|
|
|
4108
4108
|
notifications: "Notifications"
|
|
4109
4109
|
};
|
|
4110
4110
|
/**
|
|
4111
|
-
*
|
|
4112
|
-
*
|
|
4113
|
-
*
|
|
4111
|
+
* Which cap stands behind each wrapper-backed switch. A map instead of a
|
|
4112
|
+
* ternary: with three entries the ternary became a chain, and the next entry
|
|
4113
|
+
* would have silently landed on the wrong branch.
|
|
4114
4114
|
*/
|
|
4115
4115
|
var WRAPPER_CAP_BY_ID = {
|
|
4116
4116
|
"object-detection": DETECTION_CAP,
|
|
@@ -4168,7 +4168,7 @@ function deriveCameraFunctions(reads) {
|
|
|
4168
4168
|
...resolveOne(id, reads)
|
|
4169
4169
|
}));
|
|
4170
4170
|
}
|
|
4171
|
-
/** `null` =
|
|
4171
|
+
/** `null` = not available: the write must be REFUSED, not approximated. */
|
|
4172
4172
|
function resolveCameraFunctionWrite(id, on, reads) {
|
|
4173
4173
|
if (!resolveOne(id, reads).available) return null;
|
|
4174
4174
|
switch (id) {
|
|
@@ -5328,7 +5328,7 @@ function notificationCenterSpecs(input) {
|
|
|
5328
5328
|
(
|
|
5329
5329
|
/**
|
|
5330
5330
|
* The last trigger, six entities: five facts plus its picture — "conoscere
|
|
5331
|
-
* gli ultimi trigger, le ultime immagini... e da quale label" (operator,
|
|
5331
|
+
* gli ultimi trigger, le ultime immagini... e da quale label" [know the latest triggers, the latest images... and from which label] (operator,
|
|
5332
5332
|
* 2026-08-25). ENABLED by default like every other entity on this device
|
|
5333
5333
|
* (see {@link buildComponents}'s docblock): a rule the operator wrote is a
|
|
5334
5334
|
* rule they want to watch fire.
|
|
@@ -6350,7 +6350,7 @@ var HaExportAddon = class extends BaseAddon {
|
|
|
6350
6350
|
* `className` and no `confidence`; reading those invented names mapped
|
|
6351
6351
|
* every window to `[]`, so `audio_last_sound` sat at `unknown` for ever
|
|
6352
6352
|
* while the analyzer was classifying happily (found 2026-08-09, symptom:
|
|
6353
|
-
* "le audio labels sembrano non arrivare").
|
|
6353
|
+
* "le audio labels sembrano non arrivare" [the audio labels seem not to arrive]).
|
|
6354
6354
|
*
|
|
6355
6355
|
* The best LABEL wins over the macro: `audio` as a value tells an operator
|
|
6356
6356
|
* nothing, `dog` or `crying` is the whole point. Falls back to the macro
|
|
@@ -6719,8 +6719,8 @@ var HaExportAddon = class extends BaseAddon {
|
|
|
6719
6719
|
/**
|
|
6720
6720
|
* The most recent notification-rule trigger, GLOBAL and PER RULE —
|
|
6721
6721
|
* "conoscere gli ultimi trigger, le ultime immagini... e da quale label"
|
|
6722
|
-
* (operator, 2026-08-25), extended to "l'ultimo trigger PER REGOLA, con
|
|
6723
|
-
* immagine e metadati" (operator, 2026-08-27).
|
|
6722
|
+
* [know the latest triggers, the latest images... and from which label] (operator, 2026-08-25), extended to "l'ultimo trigger PER REGOLA, con
|
|
6723
|
+
* immagine e metadati" [the latest trigger PER RULE, with image and metadata] (operator, 2026-08-27).
|
|
6724
6724
|
*
|
|
6725
6725
|
* ONE `getHistory` read serves BOTH: `reduceLastTriggers`
|
|
6726
6726
|
* (`rule-triggers.ts`) reduces the same newest-first page into "the very
|