@camstack/types 1.2.282 → 1.2.284
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 +2 -2
- package/dist/addon.mjs +2 -2
- package/dist/capabilities/device-extension.cap.d.ts +8 -25
- package/dist/capabilities/device-manager.cap.d.ts +2 -2
- package/dist/capabilities/device-state.cap.d.ts +2 -2
- package/dist/capabilities/doorbell.cap.d.ts +13 -64
- package/dist/capabilities/index.d.ts +2 -2
- package/dist/capabilities/motion.cap.d.ts +9 -8
- package/dist/capabilities/notification-rules.cap.d.ts +97 -2
- package/dist/capabilities/pipeline-orchestrator.cap.d.ts +147 -15
- package/dist/capabilities/pipeline-runner.cap.d.ts +2 -0
- package/dist/capabilities/ptz-autotrack.cap.d.ts +2 -3
- package/dist/catalogs/sensor-active-state.d.ts +8 -10
- package/dist/composition/presets/doorbell-feature.d.ts +1 -1
- package/dist/{composition-Dq42XWp0.mjs → composition-43aqsZQj.mjs} +6 -7
- package/dist/{composition-DG4jVTfB.js → composition-w3gBWMer.js} +6 -7
- package/dist/device/hub-motion-read.d.ts +22 -0
- package/dist/device-extension/slot-descriptor.d.ts +3 -3
- package/dist/enums/event-category.d.ts +9 -0
- package/dist/enums.js +1 -1
- package/dist/enums.mjs +1 -1
- package/dist/{event-category-C5xZWqz6.mjs → event-category-BGmz_oxW.mjs} +9 -0
- package/dist/{event-category-MbnB-6AN.js → event-category-DmS_tLsU.js} +9 -0
- package/dist/generated/extension-slots.d.ts +2 -6
- package/dist/index.d.ts +5 -2
- package/dist/index.js +302 -205
- package/dist/index.mjs +290 -203
- package/dist/interfaces/event-bus.d.ts +5 -3
- package/dist/interfaces/pipeline-runner-capability.d.ts +2 -0
- package/dist/node.js +1 -1
- package/dist/node.mjs +1 -1
- package/dist/notification/system-event-summary.d.ts +7 -1
- package/dist/pipeline/camera-sensors.d.ts +133 -9
- package/dist/pipeline/motion-ownership.d.ts +13 -0
- package/dist/pipeline/provider-motion.d.ts +33 -0
- package/dist/{sleep-gU6hqv4_.mjs → sleep-CDCONfkt.mjs} +1 -1
- package/dist/{sleep-DCbD8sdg.js → sleep-G4F3X9X_.js} +1 -1
- package/dist/utils/addon-id.d.ts +2 -2
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_sleep = require("./sleep-
|
|
3
|
-
const require_event_category = require("./event-category-
|
|
4
|
-
const require_composition = require("./composition-
|
|
2
|
+
const require_sleep = require("./sleep-G4F3X9X_.js");
|
|
3
|
+
const require_event_category = require("./event-category-DmS_tLsU.js");
|
|
4
|
+
const require_composition = require("./composition-w3gBWMer.js");
|
|
5
5
|
const require_err_msg = require("./err-msg-Dx2Kor0g.js");
|
|
6
6
|
const require_enums = require("./enums.js");
|
|
7
7
|
let zod = require("zod");
|
|
@@ -2538,7 +2538,7 @@ var RecordingTriggersSchema = zod.z.object({
|
|
|
2538
2538
|
*
|
|
2539
2539
|
* Cosa vuol dire "alto" dipende dal TIPO di device e non è deciso qui:
|
|
2540
2540
|
* `SOURCE_CAP_ACTIVE_FIELD` (`catalogs/sensor-active-state.ts`) è LA tabella,
|
|
2541
|
-
* la stessa
|
|
2541
|
+
* la stessa del campanello composto (D671). Ed è il FRONTE, non
|
|
2542
2542
|
* il livello: un contatto trovato già aperto al riavvio del runner non fa
|
|
2543
2543
|
* registrare.
|
|
2544
2544
|
*/
|
|
@@ -14541,8 +14541,8 @@ var deviceManagerCapability = {
|
|
|
14541
14541
|
* (`value` / `missing` / `failed`, see {@link WrapperActivationReadSchema}).
|
|
14542
14542
|
*
|
|
14543
14543
|
* The narrow read of the durable authority behind `getBindings`: a
|
|
14544
|
-
* consumer that must know what the operator PERSISTED (
|
|
14545
|
-
*
|
|
14544
|
+
* consumer that must know what the operator PERSISTED (before it drops
|
|
14545
|
+
* work on the strength of an unbind) asks this instead of pulling device-manager's
|
|
14546
14546
|
* whole addon store through `addonSettingsRaw.getGlobal` — which answered
|
|
14547
14547
|
* `{}` on every isolated-engine hub and so never worked (D675). It reads
|
|
14548
14548
|
* ONE row (the activation map, ~1.6 KB), never the ~625 KB store.
|
|
@@ -14833,107 +14833,6 @@ var deviceManagerCapability = {
|
|
|
14833
14833
|
}
|
|
14834
14834
|
};
|
|
14835
14835
|
//#endregion
|
|
14836
|
-
//#region src/capabilities/doorbell.cap.ts
|
|
14837
|
-
/**
|
|
14838
|
-
* Doorbell button cap. Two kinds of providers coexist behind this cap
|
|
14839
|
-
* name (same pattern as `snapshot`):
|
|
14840
|
-
*
|
|
14841
|
-
* - **Native** providers: registered per-device by device-driver
|
|
14842
|
-
* addons via `ctx.registerNativeCap` — either on a
|
|
14843
|
-
* `DeviceType.Button` accessory with `role: DeviceRole.Doorbell`,
|
|
14844
|
-
* or directly on the camera (Reolink registers at camera level).
|
|
14845
|
-
* Emits an `onPressed` event every time the firmware pushes a
|
|
14846
|
-
* ring; status tracks the last press and a pressCount since start
|
|
14847
|
-
* (diagnostic).
|
|
14848
|
-
*
|
|
14849
|
-
* - **Wrapper** provider: the `virtual-doorbell` system builtin
|
|
14850
|
-
* (`@camstack/system/builtins/doorbell`). Turns ANY binary-ish
|
|
14851
|
-
* device (contact / switch / event-emitter …) into a doorbell for
|
|
14852
|
-
* a camera. `defaultActive: false` — the operator explicitly binds
|
|
14853
|
-
* it per camera in the device-bindings UI, then picks the source
|
|
14854
|
-
* device + trigger in the per-device settings.
|
|
14855
|
-
*
|
|
14856
|
-
* The DeviceEventPropagator re-emits `onPressed` on the camera parent
|
|
14857
|
-
* — subscribers listening at the camera level receive ring events
|
|
14858
|
-
* with `via[]` populated. No code on the parent needed.
|
|
14859
|
-
*/
|
|
14860
|
-
var DoorbellStatusSchema = zod.z.object({
|
|
14861
|
-
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
14862
|
-
lastPressedAt: zod.z.number().nullable(),
|
|
14863
|
-
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
14864
|
-
pressCountSinceStart: zod.z.number()
|
|
14865
|
-
});
|
|
14866
|
-
var DoorbellPressEventSchema = zod.z.object({
|
|
14867
|
-
deviceId: zod.z.number(),
|
|
14868
|
-
timestamp: zod.z.number()
|
|
14869
|
-
});
|
|
14870
|
-
/**
|
|
14871
|
-
* The `doorbell-source` extension slot's editable value (D648): the camera's
|
|
14872
|
-
* virtual-doorbell trigger devices, exactly what the wrapper's
|
|
14873
|
-
* `doorbellSources` persists (as `{ deviceId }` records).
|
|
14874
|
-
*/
|
|
14875
|
-
var DoorbellSourceSlotValueSchema = zod.z.object({ deviceIds: zod.z.array(zod.z.number().int().positive()) });
|
|
14876
|
-
/**
|
|
14877
|
-
* The `doorbell-source` slot — which devices ring this camera's VIRTUAL
|
|
14878
|
-
* doorbell, owned by the `virtual-doorbell` wrapper over its
|
|
14879
|
-
* `doorbellSources` store (D648). A source rings when one of its
|
|
14880
|
-
* `SOURCE_CAPS` rises. Whether the wrapper is bound to the camera at all is a
|
|
14881
|
-
* different authority (`deviceManager.setWrapperActive`, D62) — the slot
|
|
14882
|
-
* reports it, it never writes it.
|
|
14883
|
-
*/
|
|
14884
|
-
var DOORBELL_SOURCE_SLOT = {
|
|
14885
|
-
id: "doorbell-source",
|
|
14886
|
-
label: "Doorbell trigger devices",
|
|
14887
|
-
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.",
|
|
14888
|
-
shape: "association",
|
|
14889
|
-
hostDeviceTypes: [require_err_msg.DeviceType.Camera],
|
|
14890
|
-
sourceCaps: require_composition.SOURCE_CAPS,
|
|
14891
|
-
cardinality: "many",
|
|
14892
|
-
value: DoorbellSourceSlotValueSchema
|
|
14893
|
-
};
|
|
14894
|
-
var doorbellCapability = {
|
|
14895
|
-
name: "doorbell",
|
|
14896
|
-
scope: "device",
|
|
14897
|
-
deviceNative: true,
|
|
14898
|
-
mode: "singleton",
|
|
14899
|
-
kind: "wrapper",
|
|
14900
|
-
defaultActive: false,
|
|
14901
|
-
deviceTypes: [require_err_msg.DeviceType.Button, require_err_msg.DeviceType.Camera],
|
|
14902
|
-
extensionSlots: [DOORBELL_SOURCE_SLOT],
|
|
14903
|
-
methods: {},
|
|
14904
|
-
events: {
|
|
14905
|
-
/**
|
|
14906
|
-
* Fires once per physical press. Reolink delivers via Baichuan
|
|
14907
|
-
* push (`ReolinkSimpleEvent.type === 'doorbell'`). There is no
|
|
14908
|
-
* release/duration — it's a pulse.
|
|
14909
|
-
*/
|
|
14910
|
-
onPressed: {
|
|
14911
|
-
data: DoorbellPressEventSchema,
|
|
14912
|
-
fromState: {
|
|
14913
|
-
field: "lastPressedAt",
|
|
14914
|
-
on: "advance"
|
|
14915
|
-
}
|
|
14916
|
-
} },
|
|
14917
|
-
status: {
|
|
14918
|
-
schema: DoorbellStatusSchema,
|
|
14919
|
-
kind: "push"
|
|
14920
|
-
},
|
|
14921
|
-
/**
|
|
14922
|
-
* Runtime-state slice — last press timestamp + lifetime press count.
|
|
14923
|
-
* Mirrored by the kernel and readable via
|
|
14924
|
-
* `device.state.doorbell.value`. UIs can show "last ring 5m ago"
|
|
14925
|
-
* without subscribing.
|
|
14926
|
-
*/
|
|
14927
|
-
runtimeState: DoorbellStatusSchema,
|
|
14928
|
-
/**
|
|
14929
|
-
* 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.
|
|
14930
|
-
*
|
|
14931
|
-
* See `RuntimeStateDurability`. Enforced by
|
|
14932
|
-
* `scripts/check-runtime-state-durability.ts`.
|
|
14933
|
-
*/
|
|
14934
|
-
durability: "restored"
|
|
14935
|
-
};
|
|
14936
|
-
//#endregion
|
|
14937
14836
|
//#region src/generated/extension-slots.ts
|
|
14938
14837
|
/**
|
|
14939
14838
|
* AUTO-GENERATED by scripts/generate-extension-slots.ts — DO NOT EDIT.
|
|
@@ -14943,25 +14842,18 @@ onPressed: {
|
|
|
14943
14842
|
* caps' descriptors and value schemas — never the caps barrel — so
|
|
14944
14843
|
* `device-extension.cap.ts` can import this module without a cycle.
|
|
14945
14844
|
*
|
|
14946
|
-
* Coverage:
|
|
14845
|
+
* Coverage: 1 slot(s).
|
|
14947
14846
|
*/
|
|
14948
14847
|
/** Every declared slot id, in table order. */
|
|
14949
|
-
var EXTENSION_SLOT_IDS = ["
|
|
14848
|
+
var EXTENSION_SLOT_IDS = ["linked-devices"];
|
|
14950
14849
|
var ExtensionSlotIdSchema = zod.z.enum(EXTENSION_SLOT_IDS);
|
|
14951
|
-
var EXTENSION_SLOTS = {
|
|
14952
|
-
|
|
14953
|
-
|
|
14954
|
-
|
|
14955
|
-
|
|
14956
|
-
},
|
|
14957
|
-
"linked-devices": {
|
|
14958
|
-
descriptor: LINKED_DEVICES_SLOT,
|
|
14959
|
-
declaringCap: "device-manager",
|
|
14960
|
-
hostDeviceTypes: [require_err_msg.DeviceType.Camera]
|
|
14961
|
-
}
|
|
14962
|
-
};
|
|
14850
|
+
var EXTENSION_SLOTS = { "linked-devices": {
|
|
14851
|
+
descriptor: LINKED_DEVICES_SLOT,
|
|
14852
|
+
declaringCap: "device-manager",
|
|
14853
|
+
hostDeviceTypes: [require_err_msg.DeviceType.Camera]
|
|
14854
|
+
} };
|
|
14963
14855
|
/** A slot's editable value, discriminated on `slot`. */
|
|
14964
|
-
var ExtensionSlotValueSchema = zod.z.discriminatedUnion("slot", [
|
|
14856
|
+
var ExtensionSlotValueSchema = zod.z.discriminatedUnion("slot", [LinkedDevicesSlotValueSchema.extend({ slot: zod.z.literal("linked-devices") })]);
|
|
14965
14857
|
/** Every device type at least one slot is offered on — `device-extension`'s `deviceTypes`. */
|
|
14966
14858
|
var EXTENSION_HOST_DEVICE_TYPES = [require_err_msg.DeviceType.Camera];
|
|
14967
14859
|
//#endregion
|
|
@@ -14970,8 +14862,8 @@ var EXTENSION_HOST_DEVICE_TYPES = [require_err_msg.DeviceType.Camera];
|
|
|
14970
14862
|
* `device-extension` — ONE place to see and author what a device is extended
|
|
14971
14863
|
* with by OTHER devices (D648).
|
|
14972
14864
|
*
|
|
14973
|
-
* **A contract, not a store.** Every slot (`linked-devices
|
|
14974
|
-
*
|
|
14865
|
+
* **A contract, not a store.** Every slot (today one: `linked-devices`) is
|
|
14866
|
+
* declared by the cap that owns the function (`extensionSlots` in its
|
|
14975
14867
|
* `*.cap.ts`, D4) and SERVED by the addon that already owns its store, over
|
|
14976
14868
|
* that store and its existing write path. This cap persists nothing and has no config method (guarded by
|
|
14977
14869
|
* `scripts/check-extension-slots.ts`): D62 applied to the whole feature, and
|
|
@@ -14980,7 +14872,7 @@ var EXTENSION_HOST_DEVICE_TYPES = [require_err_msg.DeviceType.Camera];
|
|
|
14980
14872
|
* **Shape.** A device-scoped wrapper COLLECTION, the D554 shape `videoclips`
|
|
14981
14873
|
* uses: `resolveCapMount` gives it the `device-scoped` mount and
|
|
14982
14874
|
* `requireDeviceCollection` dispatches it. Its providers are the slot owners
|
|
14983
|
-
* (device-manager
|
|
14875
|
+
* (today device-manager alone), and a device's sources are its
|
|
14984
14876
|
* bindings (step 0 of `getBindings`, derived, persisted nowhere).
|
|
14985
14877
|
*
|
|
14986
14878
|
* - `listSources` — one row per provider, the D554 source-listing convention
|
|
@@ -15040,10 +14932,11 @@ var ExtensionSlotSourceSchema = zod.z.object({
|
|
|
15040
14932
|
});
|
|
15041
14933
|
/**
|
|
15042
14934
|
* A DIFFERENT authority that gates whether the slot's sources do anything —
|
|
15043
|
-
* reported read-only, named, never written through this contract (D62).
|
|
15044
|
-
*
|
|
15045
|
-
*
|
|
15046
|
-
* `unknown` means the gate could
|
|
14935
|
+
* reported read-only, named, never written through this contract (D62) — e.g.
|
|
14936
|
+
* a slot whose sources act only while a wrapper is bound to the host, a
|
|
14937
|
+
* binding that belongs to `deviceManager.setWrapperActive`. No slot reports
|
|
14938
|
+
* one today (`linked-devices` answers `null`). `unknown` means the gate could
|
|
14939
|
+
* not be read; it is not "inactive" (D315).
|
|
15047
14940
|
*/
|
|
15048
14941
|
var ExtensionSlotActivationSchema = zod.z.object({
|
|
15049
14942
|
state: zod.z.enum([
|
|
@@ -15060,7 +14953,7 @@ var ExtensionSlotStateSchema = zod.z.object({
|
|
|
15060
14953
|
/** `<source>:<slotId>` — the routing key for `listCandidates` / `setSlot`. */
|
|
15061
14954
|
slotRef: zod.z.string(),
|
|
15062
14955
|
slot: ExtensionSlotIdSchema,
|
|
15063
|
-
/** Names the store written (D62), e.g. `
|
|
14956
|
+
/** Names the store written (D62), e.g. `device-manager:_linkedDeviceIds`. */
|
|
15064
14957
|
authority: zod.z.string(),
|
|
15065
14958
|
activation: ExtensionSlotActivationSchema.nullable(),
|
|
15066
14959
|
value: ExtensionSlotValueSchema,
|
|
@@ -15264,8 +15157,8 @@ var deviceStateCapability = {
|
|
|
15264
15157
|
* Canonical cross-layer WRITE for one cap-keyed slice. Used by
|
|
15265
15158
|
* everyone who needs to publish runtime state for a device:
|
|
15266
15159
|
* device providers (via `BaseDevice.runtimeState.setCapState`
|
|
15267
|
-
* which delegates here), system-scope addons (e.g. the
|
|
15268
|
-
*
|
|
15160
|
+
* which delegates here), system-scope addons (e.g. the orchestrator
|
|
15161
|
+
* writing a camera's effective `motion` slice, D696), and
|
|
15269
15162
|
* direct cap-router callers in tests.
|
|
15270
15163
|
*
|
|
15271
15164
|
* Behavior on the hub:
|
|
@@ -19331,17 +19224,25 @@ var NcScheduleSchema = zod.z.object({
|
|
|
19331
19224
|
*/
|
|
19332
19225
|
var NcSystemEventDeliveryModeSchema = zod.z.enum(["instant", "summary"]);
|
|
19333
19226
|
/**
|
|
19227
|
+
* How a summary window is SENT (D698): `rule` (absent) = ONE notification with
|
|
19228
|
+
* every section; `section` = one notification per section with something to
|
|
19229
|
+
* say (an unavailable section included), each titled by its section.
|
|
19230
|
+
*/
|
|
19231
|
+
var NcStateSummarySplitSchema = zod.z.enum(["rule", "section"]);
|
|
19232
|
+
/**
|
|
19334
19233
|
* `summary`: the rule sends NOTHING per event. When a window of `schedule`
|
|
19335
19234
|
* CLOSES, it sends one notification with the current state of its kinds
|
|
19336
19235
|
* (low batteries, consumables to replace, devices offline, updates
|
|
19337
|
-
* available, ...), after its own filters
|
|
19236
|
+
* available, ...), after its own filters — or, with `split: 'section'`
|
|
19237
|
+
* (D698), one notification per section. Nothing to report sends nothing.
|
|
19338
19238
|
* The schedule is the ordinary `NcSchedule` (weekly windows, IANA timezone,
|
|
19339
19239
|
* midnight crossing); the send time is each window's END. Refused on the
|
|
19340
19240
|
* `alarm` family, which stays instant (`systemEventDeliveryProblems`).
|
|
19341
19241
|
*/
|
|
19342
19242
|
var NcSystemEventDeliverySchema = zod.z.discriminatedUnion("mode", [zod.z.object({ mode: zod.z.literal("instant") }), zod.z.object({
|
|
19343
19243
|
mode: zod.z.literal("summary"),
|
|
19344
|
-
schedule: NcScheduleSchema
|
|
19244
|
+
schedule: NcScheduleSchema,
|
|
19245
|
+
split: NcStateSummarySplitSchema.optional()
|
|
19345
19246
|
})]);
|
|
19346
19247
|
/** Fuzzy plate matcher — OCR noise makes exact match useless (spec row 12/13). */
|
|
19347
19248
|
var NcPlateMatcherSchema = zod.z.object({
|
|
@@ -20388,11 +20289,23 @@ var NcStateSummaryPreviewSectionSchema = zod.z.object({
|
|
|
20388
20289
|
reason: zod.z.string().optional()
|
|
20389
20290
|
});
|
|
20390
20291
|
/**
|
|
20292
|
+
* One notification a previewed summary would send (D698): the whole summary on
|
|
20293
|
+
* a `rule` split (no `section`), one section's on a `section` split.
|
|
20294
|
+
*/
|
|
20295
|
+
var NcStateSummaryPreviewRowSchema = zod.z.object({
|
|
20296
|
+
section: zod.z.string().optional(),
|
|
20297
|
+
/** The section's name on a per-section row; every reported section's, joined, on a combined one. */
|
|
20298
|
+
title: zod.z.string(),
|
|
20299
|
+
text: zod.z.string(),
|
|
20300
|
+
count: zod.z.number().int().nonnegative()
|
|
20301
|
+
});
|
|
20302
|
+
/**
|
|
20391
20303
|
* The summary a rule would send now. `empty` = nothing to report and every
|
|
20392
20304
|
* section read: such a summary is NOT sent. `dropped` counts the open states
|
|
20393
20305
|
* the rule's own filters (or a camera mute) left out, by reason.
|
|
20394
20306
|
* `excludedGroups` names the kind groups selected that have no state to report
|
|
20395
|
-
* (backups & exports).
|
|
20307
|
+
* (backups & exports). `split` and `rows` (D698) say how it would be sent —
|
|
20308
|
+
* optional, so an older hub's answer still parses.
|
|
20396
20309
|
*/
|
|
20397
20310
|
var NcStateSummaryPreviewSchema = zod.z.object({
|
|
20398
20311
|
empty: zod.z.boolean(),
|
|
@@ -20400,7 +20313,9 @@ var NcStateSummaryPreviewSchema = zod.z.object({
|
|
|
20400
20313
|
text: zod.z.string(),
|
|
20401
20314
|
sections: zod.z.array(NcStateSummaryPreviewSectionSchema),
|
|
20402
20315
|
dropped: zod.z.record(zod.z.string(), zod.z.number().int().nonnegative()),
|
|
20403
|
-
excludedGroups: zod.z.array(zod.z.string())
|
|
20316
|
+
excludedGroups: zod.z.array(zod.z.string()),
|
|
20317
|
+
split: NcStateSummarySplitSchema.optional(),
|
|
20318
|
+
rows: zod.z.array(NcStateSummaryPreviewRowSchema).optional()
|
|
20404
20319
|
});
|
|
20405
20320
|
var NcTestResultSchema = zod.z.object({
|
|
20406
20321
|
recordId: zod.z.string(),
|
|
@@ -22193,12 +22108,27 @@ var CameraSensorRefSchema = zod.z.object({
|
|
|
22193
22108
|
function cameraSensorRefKey(ref) {
|
|
22194
22109
|
return `${ref.addonId}/${ref.stableId}`;
|
|
22195
22110
|
}
|
|
22196
|
-
/**
|
|
22197
|
-
|
|
22198
|
-
|
|
22199
|
-
|
|
22200
|
-
|
|
22201
|
-
|
|
22111
|
+
/**
|
|
22112
|
+
* A sensor's mode (D673). `in-addition`: its motion is the camera's motion too.
|
|
22113
|
+
* `replace`: its motion is the camera's, and while one is READY the camera's
|
|
22114
|
+
* own motion no longer counts on its own. `confirm`: while one is READY the
|
|
22115
|
+
* camera's own motion counts only while a confirm sensor is active — with or
|
|
22116
|
+
* without a replace sensor (spec C2, the controller's ruling on Q1).
|
|
22117
|
+
*/
|
|
22118
|
+
var CameraSensorModeSchema = zod.z.enum([
|
|
22119
|
+
"in-addition",
|
|
22120
|
+
"confirm",
|
|
22121
|
+
"replace"
|
|
22122
|
+
]);
|
|
22123
|
+
/** A stored sensor with no mode — every CS-1 row — is in addition. */
|
|
22124
|
+
var DEFAULT_CAMERA_SENSOR_MODE = "in-addition";
|
|
22125
|
+
var CameraSensorEntrySchema = CameraSensorRefSchema.extend({ mode: CameraSensorModeSchema.default(DEFAULT_CAMERA_SENSOR_MODE) });
|
|
22126
|
+
/**
|
|
22127
|
+
* A camera's attached sensors. A CS-1 row carried an envelope
|
|
22128
|
+
* `mode: 'in-addition'`: `z.object` drops it on parse, and the PARSED value is
|
|
22129
|
+
* what the write stores (D672 rule 3), so it is never written again.
|
|
22130
|
+
*/
|
|
22131
|
+
var CameraSensorsConfigSchema = zod.z.object({ sensors: zod.z.array(CameraSensorEntrySchema).min(1).max(8) }).superRefine((value, ctx) => {
|
|
22202
22132
|
const seen = /* @__PURE__ */ new Set();
|
|
22203
22133
|
value.sensors.forEach((ref, index) => {
|
|
22204
22134
|
const key = cameraSensorRefKey(ref);
|
|
@@ -22210,39 +22140,41 @@ var CameraSensorsConfigSchema = zod.z.object({
|
|
|
22210
22140
|
seen.add(key);
|
|
22211
22141
|
});
|
|
22212
22142
|
});
|
|
22213
|
-
|
|
22143
|
+
/** Every attachment names its mode; an older orchestrator that does not is in addition. */
|
|
22144
|
+
var AttachmentFields = {
|
|
22214
22145
|
addonId: zod.z.string(),
|
|
22215
|
-
stableId: zod.z.string()
|
|
22146
|
+
stableId: zod.z.string(),
|
|
22147
|
+
mode: CameraSensorModeSchema.default(DEFAULT_CAMERA_SENSOR_MODE)
|
|
22216
22148
|
};
|
|
22217
22149
|
var CameraSensorAttachmentSchema = zod.z.discriminatedUnion("state", [
|
|
22218
22150
|
zod.z.object({
|
|
22219
|
-
...
|
|
22151
|
+
...AttachmentFields,
|
|
22220
22152
|
state: zod.z.literal("ready"),
|
|
22221
22153
|
deviceId: zod.z.number(),
|
|
22222
22154
|
name: zod.z.string(),
|
|
22223
22155
|
caps: zod.z.array(zod.z.string()).readonly()
|
|
22224
22156
|
}),
|
|
22225
22157
|
zod.z.object({
|
|
22226
|
-
...
|
|
22158
|
+
...AttachmentFields,
|
|
22227
22159
|
state: zod.z.literal("offline"),
|
|
22228
22160
|
deviceId: zod.z.number(),
|
|
22229
22161
|
name: zod.z.string(),
|
|
22230
22162
|
reason: zod.z.enum(["offline", "disabled"])
|
|
22231
22163
|
}),
|
|
22232
22164
|
zod.z.object({
|
|
22233
|
-
...
|
|
22165
|
+
...AttachmentFields,
|
|
22234
22166
|
state: zod.z.literal("missing"),
|
|
22235
22167
|
reason: zod.z.string()
|
|
22236
22168
|
}),
|
|
22237
22169
|
zod.z.object({
|
|
22238
|
-
...
|
|
22170
|
+
...AttachmentFields,
|
|
22239
22171
|
state: zod.z.literal("unsupported"),
|
|
22240
22172
|
deviceId: zod.z.number(),
|
|
22241
22173
|
name: zod.z.string(),
|
|
22242
22174
|
reason: zod.z.string()
|
|
22243
22175
|
}),
|
|
22244
22176
|
zod.z.object({
|
|
22245
|
-
...
|
|
22177
|
+
...AttachmentFields,
|
|
22246
22178
|
state: zod.z.literal("unreadable"),
|
|
22247
22179
|
reason: zod.z.string()
|
|
22248
22180
|
})
|
|
@@ -22255,17 +22187,49 @@ var CameraSensorAttachmentSchema = zod.z.discriminatedUnion("state", [
|
|
|
22255
22187
|
* say.
|
|
22256
22188
|
*/
|
|
22257
22189
|
var CameraSensorsNotForwardedSchema = zod.z.enum(["onboard-not-listed", "no-active-detection"]);
|
|
22190
|
+
/** Whether the camera's OWN motion counts on its own (D673 C2), from its READY sensors (C3). */
|
|
22191
|
+
var CameraOwnMotionSchema = zod.z.enum([
|
|
22192
|
+
"always",
|
|
22193
|
+
"when-confirmed",
|
|
22194
|
+
"never"
|
|
22195
|
+
]);
|
|
22196
|
+
/** Confirm / Replace cannot suppress this camera's motion: its provider still emits it directly (D673 C13). */
|
|
22197
|
+
var CameraSensorsNotEnforcedSchema = zod.z.enum(["provider-not-split"]);
|
|
22198
|
+
/**
|
|
22199
|
+
* The camera's OWN onboard motion (D696): the raw input the bridge combines,
|
|
22200
|
+
* never the effective value. The camera's `motion` slice is the effective one,
|
|
22201
|
+
* so a view of the camera's own row reads this.
|
|
22202
|
+
* - `atMs`: when the bridge received the camera's last own edge.
|
|
22203
|
+
* - `detected`: evaluated WHEN THE STATUS IS ASKED — the last edge said `true`
|
|
22204
|
+
* AND it is younger than the window the bridge counts the camera's own motion
|
|
22205
|
+
* for (`motionCooldownMs`, floored at two sustain ticks). A camera that never
|
|
22206
|
+
* sends a clear (heartbeats only) therefore reads `false` once no push came
|
|
22207
|
+
* within the window; a status read is a snapshot, so a live view re-asks.
|
|
22208
|
+
* Absent = this orchestrator has not received the camera's own motion since it
|
|
22209
|
+
* started (unknown, never "quiet"), or an orchestrator older than D696.
|
|
22210
|
+
*/
|
|
22211
|
+
var CameraRawLevelSchema = zod.z.object({
|
|
22212
|
+
detected: zod.z.boolean(),
|
|
22213
|
+
atMs: zod.z.number()
|
|
22214
|
+
});
|
|
22258
22215
|
var CameraSensorsStatusSchema = zod.z.discriminatedUnion("state", [
|
|
22259
|
-
zod.z.object({
|
|
22216
|
+
zod.z.object({
|
|
22217
|
+
state: zod.z.literal("not-configured"),
|
|
22218
|
+
cameraLevel: CameraRawLevelSchema.optional()
|
|
22219
|
+
}),
|
|
22260
22220
|
zod.z.object({
|
|
22261
22221
|
state: zod.z.literal("unreadable"),
|
|
22262
|
-
reason: zod.z.string()
|
|
22222
|
+
reason: zod.z.string(),
|
|
22223
|
+
cameraLevel: CameraRawLevelSchema.optional()
|
|
22263
22224
|
}),
|
|
22264
22225
|
zod.z.object({
|
|
22265
22226
|
state: zod.z.literal("configured"),
|
|
22266
|
-
|
|
22227
|
+
cameraLevel: CameraRawLevelSchema.optional(),
|
|
22267
22228
|
sensors: zod.z.array(CameraSensorAttachmentSchema).readonly(),
|
|
22268
|
-
|
|
22229
|
+
/** Absent = an orchestrator older than CS-2: it does not say (D315). */
|
|
22230
|
+
cameraMotion: CameraOwnMotionSchema.optional(),
|
|
22231
|
+
notForwarded: CameraSensorsNotForwardedSchema.optional(),
|
|
22232
|
+
notEnforced: CameraSensorsNotEnforcedSchema.optional()
|
|
22269
22233
|
})
|
|
22270
22234
|
]);
|
|
22271
22235
|
/** What a camera reads before its first settings read ANSWERED (D315). */
|
|
@@ -26609,8 +26573,10 @@ var RunnerCameraConfigSchema = zod.z.object({
|
|
|
26609
26573
|
* - `analyzer`: ML/frame-diff motion detection (motion-wasm or other
|
|
26610
26574
|
* analyzer providers) running on decoded frames in this runner.
|
|
26611
26575
|
* - `onboard`: camera-native motion pushes (Reolink Baichuan, ONVIF
|
|
26612
|
-
* analytics). The provider emits ProviderMotion
|
|
26613
|
-
*
|
|
26576
|
+
* analytics). The provider emits its raw push as `ProviderMotion`
|
|
26577
|
+
* (D673); the orchestrator's camera-sensors bridge re-emits the camera's
|
|
26578
|
+
* effective motion as `MotionOnMotionChanged`, which is what reaches
|
|
26579
|
+
* `reportMotion`.
|
|
26614
26580
|
*/
|
|
26615
26581
|
motionSources: MotionSourcesSchema.default(["analyzer"]),
|
|
26616
26582
|
/**
|
|
@@ -26975,7 +26941,15 @@ var RunnerLocalLoadSchema = zod.z.object({
|
|
|
26975
26941
|
hasGpu: zod.z.boolean(),
|
|
26976
26942
|
inferenceBackend: zod.z.string().optional(),
|
|
26977
26943
|
cpuCores: zod.z.number().optional()
|
|
26978
|
-
})
|
|
26944
|
+
}),
|
|
26945
|
+
/**
|
|
26946
|
+
* Who writes a camera's `motion` runtime slice (D696). `'orchestrator'`: this
|
|
26947
|
+
* runner never writes it. ABSENT = a runner older than D696, which still
|
|
26948
|
+
* writes the slice from its phase machine; the orchestrator does not write
|
|
26949
|
+
* while any runner node is absent-or-unanswered, so one slice never has two
|
|
26950
|
+
* writers.
|
|
26951
|
+
*/
|
|
26952
|
+
motionSliceWriter: zod.z.literal("orchestrator").optional()
|
|
26979
26953
|
});
|
|
26980
26954
|
/**
|
|
26981
26955
|
* Aggregate runtime metrics for the runner's whole local pool. Mirrors the
|
|
@@ -34837,6 +34811,72 @@ onStatusChanged: { data: zod.z.object({
|
|
|
34837
34811
|
volatileStateFields: ["lastChangedAt"]
|
|
34838
34812
|
};
|
|
34839
34813
|
//#endregion
|
|
34814
|
+
//#region src/capabilities/doorbell.cap.ts
|
|
34815
|
+
var DoorbellStatusSchema = zod.z.object({
|
|
34816
|
+
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
34817
|
+
lastPressedAt: zod.z.number().nullable(),
|
|
34818
|
+
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
34819
|
+
pressCountSinceStart: zod.z.number()
|
|
34820
|
+
});
|
|
34821
|
+
var DoorbellPressEventSchema = zod.z.object({
|
|
34822
|
+
deviceId: zod.z.number(),
|
|
34823
|
+
timestamp: zod.z.number()
|
|
34824
|
+
});
|
|
34825
|
+
/**
|
|
34826
|
+
* Doorbell button cap. Two kinds of provider serve it, and to every consumer
|
|
34827
|
+
* they are the same cap:
|
|
34828
|
+
*
|
|
34829
|
+
* - **Native** providers, registered per device by a driver addon through
|
|
34830
|
+
* `ctx.registerNativeCap` — a `DeviceType.Button` accessory with
|
|
34831
|
+
* `role: DeviceRole.Doorbell`, or the camera itself (Reolink registers at
|
|
34832
|
+
* camera level). They emit `onPressed` on every firmware ring.
|
|
34833
|
+
* - **A composed doorbell** (D670, D671): a camera's customization gives it
|
|
34834
|
+
* the cap, its `lastPressedAt` rising from the sources the operator
|
|
34835
|
+
* assigned in Customize → Doorbell, and the composer emits `onPressed`
|
|
34836
|
+
* from that field's advance (`fromState`).
|
|
34837
|
+
*
|
|
34838
|
+
* The DeviceEventPropagator re-emits `onPressed` on the camera parent.
|
|
34839
|
+
*/
|
|
34840
|
+
var doorbellCapability = {
|
|
34841
|
+
name: "doorbell",
|
|
34842
|
+
scope: "device",
|
|
34843
|
+
deviceNative: true,
|
|
34844
|
+
mode: "singleton",
|
|
34845
|
+
deviceTypes: [require_err_msg.DeviceType.Button, require_err_msg.DeviceType.Camera],
|
|
34846
|
+
methods: {},
|
|
34847
|
+
events: {
|
|
34848
|
+
/**
|
|
34849
|
+
* Fires once per physical press. Reolink delivers via Baichuan
|
|
34850
|
+
* push (`ReolinkSimpleEvent.type === 'doorbell'`). There is no
|
|
34851
|
+
* release/duration — it's a pulse.
|
|
34852
|
+
*/
|
|
34853
|
+
onPressed: {
|
|
34854
|
+
data: DoorbellPressEventSchema,
|
|
34855
|
+
fromState: {
|
|
34856
|
+
field: "lastPressedAt",
|
|
34857
|
+
on: "advance"
|
|
34858
|
+
}
|
|
34859
|
+
} },
|
|
34860
|
+
status: {
|
|
34861
|
+
schema: DoorbellStatusSchema,
|
|
34862
|
+
kind: "push"
|
|
34863
|
+
},
|
|
34864
|
+
/**
|
|
34865
|
+
* Runtime-state slice — last press timestamp + lifetime press count.
|
|
34866
|
+
* Mirrored by the kernel and readable via
|
|
34867
|
+
* `device.state.doorbell.value`. UIs can show "last ring 5m ago"
|
|
34868
|
+
* without subscribing.
|
|
34869
|
+
*/
|
|
34870
|
+
runtimeState: DoorbellStatusSchema,
|
|
34871
|
+
/**
|
|
34872
|
+
* 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.
|
|
34873
|
+
*
|
|
34874
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
34875
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
34876
|
+
*/
|
|
34877
|
+
durability: "restored"
|
|
34878
|
+
};
|
|
34879
|
+
//#endregion
|
|
34840
34880
|
//#region src/capabilities/enum-sensor.cap.ts
|
|
34841
34881
|
/**
|
|
34842
34882
|
* Enum-state sensor — a string value picked from a finite option set.
|
|
@@ -37284,11 +37324,11 @@ authKey: zod.z.string().optional() }), zod.z.object({
|
|
|
37284
37324
|
/**
|
|
37285
37325
|
* How long after a camera's last rising edge `pipeline-analytics` closes the
|
|
37286
37326
|
* motion EPISODE row it kept open for it (D475) — "il delay della cap", in
|
|
37287
|
-
* the operator's words. One authority for the whole system:
|
|
37288
|
-
*
|
|
37289
|
-
*
|
|
37290
|
-
* seed its internal 3 s inactivity timer here,
|
|
37291
|
-
* a different purpose), and `MotionEpisodeTracker` imports it directly rather
|
|
37327
|
+
* the operator's words. One authority for the whole system: the writer of a
|
|
37328
|
+
* `Camera` device's slice (the orchestrator, D696) writes this SAME constant
|
|
37329
|
+
* in `autoClearAfterMs` while `detected: true` (never a camera's own clock —
|
|
37330
|
+
* Hikvision used to seed its internal 3 s inactivity timer here, a different
|
|
37331
|
+
* clock for a different purpose), and `MotionEpisodeTracker` imports it directly rather
|
|
37292
37332
|
* than reading the live cap value on the hot path. A `Sensor` device (HA
|
|
37293
37333
|
* binary sensor, Homematic) gets a genuine push both ways and has no episode
|
|
37294
37334
|
* to close on a timer, so it writes `null`, never this constant.
|
|
@@ -37299,9 +37339,9 @@ var MotionStatusSchema = zod.z.object({
|
|
|
37299
37339
|
/** Ms epoch of the last detected-true observation. Null if never detected. */
|
|
37300
37340
|
lastDetectedAt: zod.z.number().nullable(),
|
|
37301
37341
|
/**
|
|
37302
|
-
* `MOTION_CLOSE_AFTER_MS` while `detected: true` on a `Camera` device
|
|
37303
|
-
* `null` while false and on every `Sensor`
|
|
37304
|
-
* constant's doc for the one-authority rule.
|
|
37342
|
+
* `MOTION_CLOSE_AFTER_MS` while `detected: true` on a `Camera` device (the
|
|
37343
|
+
* orchestrator writes it, D696), `null` while false and on every `Sensor`
|
|
37344
|
+
* device (D475) — see that constant's doc for the one-authority rule.
|
|
37305
37345
|
*
|
|
37306
37346
|
* ## Reading this field still arms nothing
|
|
37307
37347
|
*
|
|
@@ -37319,34 +37359,31 @@ var MotionStatusSchema = zod.z.object({
|
|
|
37319
37359
|
* `addon-export-alexa/src/motion-clear-hold.ts` and
|
|
37320
37360
|
* `addon-export-hap`'s `RESET_DEBOUNCE_MS` both do.
|
|
37321
37361
|
*
|
|
37322
|
-
* ## Who writes it
|
|
37362
|
+
* ## Who writes it (D696)
|
|
37323
37363
|
*
|
|
37324
|
-
* - **Cameras** — the
|
|
37325
|
-
*
|
|
37326
|
-
* `
|
|
37327
|
-
* `
|
|
37328
|
-
*
|
|
37329
|
-
*
|
|
37330
|
-
* a
|
|
37331
|
-
*
|
|
37332
|
-
*
|
|
37333
|
-
*
|
|
37364
|
+
* - **Cameras** — the orchestrator, and nothing else. It writes the camera's
|
|
37365
|
+
* EFFECTIVE motion (`addon-pipeline-orchestrator`
|
|
37366
|
+
* `camera-sensors/motion-slice.ts`), alongside the effective
|
|
37367
|
+
* `MotionOnMotionChanged` it emits or receives: the camera-sensors bridge
|
|
37368
|
+
* for a split camera, an unsplit emitter's direct event, the analyzer and
|
|
37369
|
+
* device activity, as the camera's `motionSources` counts them. A source
|
|
37370
|
+
* that never sends a clear falls one window after its last `true`.
|
|
37371
|
+
* `lastDetectedAt` moves only on an effective rise. No camera provider
|
|
37372
|
+
* writes this slice (not even a boot seed), and neither does the runner's
|
|
37373
|
+
* phase machine: its phase is "a session is attached" for every on-motion
|
|
37374
|
+
* session, not motion, and it now has its own `DetectionPhaseTransition`.
|
|
37375
|
+
* A provider's `isDetected` answers from the hub's slice.
|
|
37376
|
+
* - **Sensors** (Home Assistant binary sensors, Homematic, Matter, Alexa
|
|
37377
|
+
* imports) — the provider pushes both edges itself, from the upstream
|
|
37378
|
+
* system's own state change. That is the sensor's own fact.
|
|
37334
37379
|
*
|
|
37335
|
-
*
|
|
37380
|
+
* `scripts/check-onboard-motion-emitters.ts` refuses any other writer of a
|
|
37381
|
+
* `motion` slice; each sensor writer is a named exemption.
|
|
37336
37382
|
*
|
|
37337
|
-
*
|
|
37338
|
-
*
|
|
37339
|
-
*
|
|
37340
|
-
* `
|
|
37341
|
-
* Hikvision's comment says why: it read THIS docblock, agreed the
|
|
37342
|
-
* runner is canonical, and wrote anyway to avoid per-tick churn. So
|
|
37343
|
-
* two authorities can disagree about one slice, which this repo
|
|
37344
|
-
* forbids, and the doc said otherwise — which is worse than saying
|
|
37345
|
-
* nothing, because it reads as verification.
|
|
37346
|
-
*
|
|
37347
|
-
* This predates D475 and is not fixed there: the fix touches every
|
|
37348
|
-
* camera provider. Recorded in D475's Consequences. Do not restore the
|
|
37349
|
-
* "sole writer" wording without also removing the other writers.
|
|
37383
|
+
* This replaces the D475 §4 rule ("the phase machine is the sole writer").
|
|
37384
|
+
* That rule was never true: Hikvision and Amcrest wrote the slice raw beside
|
|
37385
|
+
* it, every provider seeded it at boot, and every session left it
|
|
37386
|
+
* `detected: true` after its detach.
|
|
37350
37387
|
*/
|
|
37351
37388
|
autoClearAfterMs: zod.z.number().nullable()
|
|
37352
37389
|
});
|
|
@@ -37418,11 +37455,12 @@ onMotionChanged: { data: MotionOnMotionChangedDataSchema } },
|
|
|
37418
37455
|
*/
|
|
37419
37456
|
runtimeState: MotionStatusSchema,
|
|
37420
37457
|
/**
|
|
37421
|
-
* Runtime-state durability: **session** —
|
|
37458
|
+
* Runtime-state durability: **session** — the writer of this slice
|
|
37422
37459
|
* writes only on an EDGE, so a restored `detected: true` would stay
|
|
37423
37460
|
* frozen until the next one instead of being corrected. The next edge
|
|
37424
|
-
* re-publishes the real state
|
|
37425
|
-
*
|
|
37461
|
+
* re-publishes the real state, and the orchestrator re-publishes every
|
|
37462
|
+
* camera when it starts writing (D696; on who writes it, see
|
|
37463
|
+
* `autoClearAfterMs` above).
|
|
37426
37464
|
*
|
|
37427
37465
|
* See `RuntimeStateDurability`. Enforced by
|
|
37428
37466
|
* `scripts/check-runtime-state-durability.ts`.
|
|
@@ -40405,8 +40443,7 @@ var ptzAutotrackCapability = {
|
|
|
40405
40443
|
deviceNative: true,
|
|
40406
40444
|
mode: "singleton",
|
|
40407
40445
|
/**
|
|
40408
|
-
* Two kinds of provider behind one name, the same shape `snapshot`
|
|
40409
|
-
* `doorbell` use:
|
|
40446
|
+
* Two kinds of provider behind one name, the same shape `snapshot` uses:
|
|
40410
40447
|
*
|
|
40411
40448
|
* - **Native**: the camera's own firmware autotrack, registered per device by
|
|
40412
40449
|
* the driver when the probe says it exists (Reolink: yes; Hikvision:
|
|
@@ -40414,7 +40451,7 @@ var ptzAutotrackCapability = {
|
|
|
40414
40451
|
* - **Wrapper**: the emulated implementation (`@camstack/system`'s `autotrack` builtin),
|
|
40415
40452
|
* which follows a subject with `ptz.move` pulses driven by the detection
|
|
40416
40453
|
* pipeline. `defaultActive: false` — the operator binds it per camera in
|
|
40417
|
-
* the bindings UI
|
|
40454
|
+
* the bindings UI.
|
|
40418
40455
|
*
|
|
40419
40456
|
* The binding chooses WHICH implementation answers; `setEnabled` stays the
|
|
40420
40457
|
* one switch for the function either way. A camera never has both driving its
|
|
@@ -46637,10 +46674,10 @@ function feederCustomizationExample(sources) {
|
|
|
46637
46674
|
//#endregion
|
|
46638
46675
|
//#region src/composition/presets/doorbell-feature.ts
|
|
46639
46676
|
/**
|
|
46640
|
-
* The doorbell of a camera as a customization (D671). ONE builder: the
|
|
46641
|
-
*
|
|
46642
|
-
*
|
|
46643
|
-
*
|
|
46677
|
+
* The doorbell of a camera as a customization (D671). ONE builder: the admin
|
|
46678
|
+
* UI's Customize → Doorbell card writes every doorbell feature through it, and
|
|
46679
|
+
* edits one only when it is exactly what this builds (`isDoorbellPresetFeature`)
|
|
46680
|
+
* — a composed doorbell has one canonical shape.
|
|
46644
46681
|
*/
|
|
46645
46682
|
/** A rise closer than this to the previous one is the same press (D671). */
|
|
46646
46683
|
var DOORBELL_RISE_DEBOUNCE_MS = 2e3;
|
|
@@ -46657,7 +46694,7 @@ function doorbellFeatureSources(source, boundCaps) {
|
|
|
46657
46694
|
}];
|
|
46658
46695
|
});
|
|
46659
46696
|
}
|
|
46660
|
-
/** The D671 feature
|
|
46697
|
+
/** The canonical D671 doorbell feature. Throws on zero sources. */
|
|
46661
46698
|
function buildDoorbellCompositionFeature(input) {
|
|
46662
46699
|
const sources = [...input.sources].toSorted((a, b) => `${a.source.addonId}/${a.source.stableId}#${a.cap}`.localeCompare(`${b.source.addonId}/${b.source.stableId}#${b.cap}`));
|
|
46663
46700
|
if (sources.length === 0) throw new Error("doorbell composition needs at least one source");
|
|
@@ -65625,6 +65662,18 @@ var STATE_SUMMARY_VARS = [
|
|
|
65625
65662
|
systemEventKinds: [...SUMMARISABLE],
|
|
65626
65663
|
systemEventDeliveries: ["summary"]
|
|
65627
65664
|
},
|
|
65665
|
+
{
|
|
65666
|
+
name: "summarySection",
|
|
65667
|
+
label: "Summary: this section",
|
|
65668
|
+
description: "The section a per-section summary row is about (D698); on a summary sent as one message, every section it reports, comma-separated.",
|
|
65669
|
+
example: "Batterie scariche",
|
|
65670
|
+
group: "system",
|
|
65671
|
+
families: ["rule"],
|
|
65672
|
+
fields: [...RULE_TEXT],
|
|
65673
|
+
kinds: ["system"],
|
|
65674
|
+
systemEventKinds: [...SUMMARISABLE],
|
|
65675
|
+
systemEventDeliveries: ["summary"]
|
|
65676
|
+
},
|
|
65628
65677
|
...STATE_SUMMARY_SECTION_VARS.map((v) => ({
|
|
65629
65678
|
name: v.name,
|
|
65630
65679
|
label: v.label,
|
|
@@ -66467,6 +66516,15 @@ function systemEventSummaryScheduleOf(rule) {
|
|
|
66467
66516
|
const delivery = rule.systemEventDelivery;
|
|
66468
66517
|
return delivery?.mode === "summary" ? delivery.schedule : null;
|
|
66469
66518
|
}
|
|
66519
|
+
/**
|
|
66520
|
+
* How a summary rule's window is sent (D698): `section` = one notification per
|
|
66521
|
+
* section; absent (every rule before D698) and any non-summary rule = `rule`.
|
|
66522
|
+
* The ONE reader — the scheduler, the rule test, the preview and both editors.
|
|
66523
|
+
*/
|
|
66524
|
+
function systemEventSummarySplitOf(rule) {
|
|
66525
|
+
const delivery = rule.systemEventDelivery;
|
|
66526
|
+
return delivery?.mode === "summary" ? delivery.split ?? "rule" : "rule";
|
|
66527
|
+
}
|
|
66470
66528
|
/** Absent and `instant` are the same answer: a notification per event. */
|
|
66471
66529
|
function isSystemEventSummaryRule(rule) {
|
|
66472
66530
|
return systemEventSummaryScheduleOf(rule) !== null;
|
|
@@ -67107,6 +67165,35 @@ function readTimelapseGeneratedAt(rule, deviceId) {
|
|
|
67107
67165
|
return rule.lastGeneratedAt ?? 0;
|
|
67108
67166
|
}
|
|
67109
67167
|
//#endregion
|
|
67168
|
+
//#region src/pipeline/motion-ownership.ts
|
|
67169
|
+
function cameraOwnsMotionViaSensor(motionSources) {
|
|
67170
|
+
return motionSources.some((s) => s !== "analyzer");
|
|
67171
|
+
}
|
|
67172
|
+
//#endregion
|
|
67173
|
+
//#region src/device/hub-motion-read.ts
|
|
67174
|
+
async function readHubMotionDetected(deviceState, deviceId) {
|
|
67175
|
+
let slice;
|
|
67176
|
+
try {
|
|
67177
|
+
slice = await deviceState.getCapSlice.query({
|
|
67178
|
+
deviceId,
|
|
67179
|
+
capName: "motion"
|
|
67180
|
+
});
|
|
67181
|
+
} catch (err) {
|
|
67182
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
67183
|
+
throw new Error(`motion state of device ${deviceId} is unreadable: ${reason}`, { cause: err });
|
|
67184
|
+
}
|
|
67185
|
+
const detected = slice?.["detected"];
|
|
67186
|
+
if (typeof detected !== "boolean") throw new Error(`motion state of device ${deviceId} is not published yet (unknown)`);
|
|
67187
|
+
return detected;
|
|
67188
|
+
}
|
|
67189
|
+
//#endregion
|
|
67190
|
+
//#region src/pipeline/provider-motion.ts
|
|
67191
|
+
/** The motion event's data without `triggeredBy`: only the bridge names a trigger. */
|
|
67192
|
+
var ProviderMotionDataSchema = MotionOnMotionChangedDataSchema.omit({ triggeredBy: true });
|
|
67193
|
+
function providerMotionEvent(source, data) {
|
|
67194
|
+
return require_sleep.createEvent(require_event_category.EventCategory.ProviderMotion, source, data);
|
|
67195
|
+
}
|
|
67196
|
+
//#endregion
|
|
67110
67197
|
//#region src/pipeline/step-format-runnable.ts
|
|
67111
67198
|
/** True when `model` ships a build for `format`. */
|
|
67112
67199
|
function hasBuild(model, format) {
|
|
@@ -67996,8 +68083,8 @@ function bestLocationMatch(externalName, existing, threshold = .8) {
|
|
|
67996
68083
|
* So `entry.providerAddonId === this.ctx.id` is silently, permanently false
|
|
67997
68084
|
* for a builtin — and only for a builtin, which is why it survives a green
|
|
67998
68085
|
* suite whose fake supplies the bare id. That is exactly how camera 615's
|
|
67999
|
-
* virtual doorbell latched `unbound` for twelve hours on
|
|
68000
|
-
* binding was intact ([D72](../../../../docs/decisions/adr-0072.md)).
|
|
68086
|
+
* virtual doorbell (retired since, D671) latched `unbound` for twelve hours on
|
|
68087
|
+
* 2026-08-07 while its binding was intact ([D72](../../../../docs/decisions/adr-0072.md)).
|
|
68001
68088
|
*
|
|
68002
68089
|
* Route every comparison between `ctx.id` and a registry/store addon id
|
|
68003
68090
|
* through {@link isSameAddonId}. `scripts/check-addon-id-comparison.ts`
|
|
@@ -69423,12 +69510,16 @@ exports.CameraMetricsSchema = CameraMetricsSchema;
|
|
|
69423
69510
|
exports.CameraMetricsWithDeviceIdSchema = CameraMetricsWithDeviceIdSchema;
|
|
69424
69511
|
exports.CameraMotionStatusSchema = CameraMotionStatusSchema;
|
|
69425
69512
|
exports.CameraOccupancySnapshotForDeviceSchema = CameraOccupancySnapshotForDeviceSchema;
|
|
69513
|
+
exports.CameraOwnMotionSchema = CameraOwnMotionSchema;
|
|
69514
|
+
exports.CameraRawLevelSchema = CameraRawLevelSchema;
|
|
69426
69515
|
exports.CameraRecordingModeSchema = CameraRecordingModeSchema;
|
|
69427
69516
|
exports.CameraRecordingStatusSchema = CameraRecordingStatusSchema;
|
|
69428
69517
|
exports.CameraSensorAttachmentSchema = CameraSensorAttachmentSchema;
|
|
69518
|
+
exports.CameraSensorEntrySchema = CameraSensorEntrySchema;
|
|
69519
|
+
exports.CameraSensorModeSchema = CameraSensorModeSchema;
|
|
69429
69520
|
exports.CameraSensorRefSchema = CameraSensorRefSchema;
|
|
69430
69521
|
exports.CameraSensorsConfigSchema = CameraSensorsConfigSchema;
|
|
69431
|
-
exports.
|
|
69522
|
+
exports.CameraSensorsNotEnforcedSchema = CameraSensorsNotEnforcedSchema;
|
|
69432
69523
|
exports.CameraSensorsNotForwardedSchema = CameraSensorsNotForwardedSchema;
|
|
69433
69524
|
exports.CameraSensorsStatusSchema = CameraSensorsStatusSchema;
|
|
69434
69525
|
exports.CameraSourceStatusSchema = CameraSourceStatusSchema;
|
|
@@ -69568,6 +69659,7 @@ exports.DECLARED_DEVICE_SWEEP_LIMIT = DECLARED_DEVICE_SWEEP_LIMIT;
|
|
|
69568
69659
|
exports.DECLARED_INTEGRATION_FIXED_KEY = DECLARED_INTEGRATION_FIXED_KEY;
|
|
69569
69660
|
exports.DEFAULT_ADDON_PLACEMENT = DEFAULT_ADDON_PLACEMENT;
|
|
69570
69661
|
exports.DEFAULT_AUDIO_ANALYZER_CONFIG = DEFAULT_AUDIO_ANALYZER_CONFIG;
|
|
69662
|
+
exports.DEFAULT_CAMERA_SENSOR_MODE = DEFAULT_CAMERA_SENSOR_MODE;
|
|
69571
69663
|
exports.DEFAULT_CLUSTER_STEP_MODELS = DEFAULT_CLUSTER_STEP_MODELS;
|
|
69572
69664
|
exports.DEFAULT_CLUSTER_STEP_SETTINGS = DEFAULT_CLUSTER_STEP_SETTINGS;
|
|
69573
69665
|
exports.DEFAULT_DECODER_HWACCEL_CONFIG = DEFAULT_DECODER_HWACCEL_CONFIG;
|
|
@@ -69609,7 +69701,6 @@ exports.DISPLAY_ICON_KEYS = DISPLAY_ICON_KEYS;
|
|
|
69609
69701
|
exports.DISPLAY_ICON_OFFERED_KEYS = DISPLAY_ICON_OFFERED_KEYS;
|
|
69610
69702
|
exports.DISPLAY_ICON_VOCABULARY = DISPLAY_ICON_VOCABULARY;
|
|
69611
69703
|
exports.DOORBELL_RISE_DEBOUNCE_MS = DOORBELL_RISE_DEBOUNCE_MS;
|
|
69612
|
-
exports.DOORBELL_SOURCE_SLOT = DOORBELL_SOURCE_SLOT;
|
|
69613
69704
|
exports.DataStoreEngineInfoSchema = EngineInfoSchema;
|
|
69614
69705
|
exports.DatabaseSnapshotResultSchema = DatabaseSnapshotResultSchema;
|
|
69615
69706
|
exports.DatabaseSnapshotTableSchema = DatabaseSnapshotTableSchema;
|
|
@@ -69654,7 +69745,6 @@ exports.DiscoveredTargetSchema = DiscoveredTargetSchema;
|
|
|
69654
69745
|
exports.DiskReconcileJobSchema = DiskReconcileJobSchema;
|
|
69655
69746
|
exports.DisposerChain = require_sleep.DisposerChain;
|
|
69656
69747
|
exports.DoorbellPressEventSchema = DoorbellPressEventSchema;
|
|
69657
|
-
exports.DoorbellSourceSlotValueSchema = DoorbellSourceSlotValueSchema;
|
|
69658
69748
|
exports.DoorbellStatusSchema = DoorbellStatusSchema;
|
|
69659
69749
|
exports.EMBEDDING_MODEL_FAILED = EMBEDDING_MODEL_FAILED;
|
|
69660
69750
|
exports.EMBEDDING_REQUIREMENTS_FAILED = EMBEDDING_REQUIREMENTS_FAILED;
|
|
@@ -70128,8 +70218,10 @@ exports.NcSnoozeInputSchema = NcSnoozeInputSchema;
|
|
|
70128
70218
|
exports.NcSnoozeSchema = NcSnoozeSchema;
|
|
70129
70219
|
exports.NcSnoozeScopeSchema = NcSnoozeScopeSchema;
|
|
70130
70220
|
exports.NcSnoozeSuppressedSchema = NcSnoozeSuppressedSchema;
|
|
70221
|
+
exports.NcStateSummaryPreviewRowSchema = NcStateSummaryPreviewRowSchema;
|
|
70131
70222
|
exports.NcStateSummaryPreviewSchema = NcStateSummaryPreviewSchema;
|
|
70132
70223
|
exports.NcStateSummaryPreviewSectionSchema = NcStateSummaryPreviewSectionSchema;
|
|
70224
|
+
exports.NcStateSummarySplitSchema = NcStateSummarySplitSchema;
|
|
70133
70225
|
exports.NcSystemEventConditionSchema = NcSystemEventConditionSchema;
|
|
70134
70226
|
exports.NcSystemEventDeliveryModeSchema = NcSystemEventDeliveryModeSchema;
|
|
70135
70227
|
exports.NcSystemEventDeliverySchema = NcSystemEventDeliverySchema;
|
|
@@ -70245,6 +70337,7 @@ exports.PrivacyMaskStatusSchema = PrivacyMaskStatusSchema;
|
|
|
70245
70337
|
exports.ProfileRtspEntrySchema = require_sleep.ProfileRtspEntrySchema;
|
|
70246
70338
|
exports.ProfileSlotSchema = require_sleep.ProfileSlotSchema;
|
|
70247
70339
|
exports.ProfileSlotStatusSchema = require_sleep.ProfileSlotStatusSchema;
|
|
70340
|
+
exports.ProviderMotionDataSchema = ProviderMotionDataSchema;
|
|
70248
70341
|
exports.ProviderStatusSchema = ProviderStatusSchema;
|
|
70249
70342
|
exports.PtzAutotrackRuntimeStateSchema = PtzAutotrackRuntimeStateSchema;
|
|
70250
70343
|
exports.PtzAutotrackSettingsSchema = PtzAutotrackSettingsSchema;
|
|
@@ -70700,6 +70793,7 @@ exports.builtCapabilityBlockers = builtCapabilityBlockers;
|
|
|
70700
70793
|
exports.buttonCapability = buttonCapability;
|
|
70701
70794
|
exports.cameraCredentialsCapability = cameraCredentialsCapability;
|
|
70702
70795
|
exports.cameraGridLayoutCapability = cameraGridLayoutCapability;
|
|
70796
|
+
exports.cameraOwnsMotionViaSensor = cameraOwnsMotionViaSensor;
|
|
70703
70797
|
exports.cameraPipelineConfigCapability = cameraPipelineConfigCapability;
|
|
70704
70798
|
exports.cameraSensorRefKey = cameraSensorRefKey;
|
|
70705
70799
|
exports.cameraStreamsCapability = cameraStreamsCapability;
|
|
@@ -71074,6 +71168,7 @@ exports.pressureSensorCapability = pressureSensorCapability;
|
|
|
71074
71168
|
exports.principalMayReachAddon = principalMayReachAddon;
|
|
71075
71169
|
exports.privacyMaskCapability = privacyMaskCapability;
|
|
71076
71170
|
exports.procedureAuthKey = procedureAuthKey;
|
|
71171
|
+
exports.providerMotionEvent = providerMotionEvent;
|
|
71077
71172
|
exports.ptzAutotrackCapability = ptzAutotrackCapability;
|
|
71078
71173
|
exports.ptzCapability = ptzCapability;
|
|
71079
71174
|
exports.publicEventCategories = require_event_category.publicEventCategories;
|
|
@@ -71083,6 +71178,7 @@ exports.readClusterStepModels = readClusterStepModels;
|
|
|
71083
71178
|
exports.readClusterStepSettings = readClusterStepSettings;
|
|
71084
71179
|
exports.readDetailCropConvention = readDetailCropConvention;
|
|
71085
71180
|
exports.readDeviceStateFrom = readDeviceStateFrom;
|
|
71181
|
+
exports.readHubMotionDetected = readHubMotionDetected;
|
|
71086
71182
|
exports.readMotionTriggeredBy = readMotionTriggeredBy;
|
|
71087
71183
|
exports.readNativeLeaseOverride = readNativeLeaseOverride;
|
|
71088
71184
|
exports.readNodePin = require_sleep.readNodePin;
|
|
@@ -71204,6 +71300,7 @@ exports.systemEventFilterAppliesToAnyKind = systemEventFilterAppliesToAnyKind;
|
|
|
71204
71300
|
exports.systemEventKindNamesOf = systemEventKindNamesOf;
|
|
71205
71301
|
exports.systemEventKindsOfFamily = systemEventKindsOfFamily;
|
|
71206
71302
|
exports.systemEventSummaryScheduleOf = systemEventSummaryScheduleOf;
|
|
71303
|
+
exports.systemEventSummarySplitOf = systemEventSummarySplitOf;
|
|
71207
71304
|
exports.systemFamilyOfKind = systemFamilyOfKind;
|
|
71208
71305
|
exports.systemRuleKindOf = systemRuleKindOf;
|
|
71209
71306
|
exports.tamperCapability = tamperCapability;
|