@camstack/system 1.1.52 → 1.1.54
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-runner.js +2 -2
- package/dist/addon-runner.mjs +2 -2
- package/dist/addon-utils.d.ts +1 -0
- package/dist/addon-utils.js +2 -0
- package/dist/addon-utils.mjs +2 -2
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
- package/dist/builtins/alerts/alerts.addon.js +1 -1
- package/dist/builtins/alerts/alerts.addon.mjs +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
- package/dist/builtins/console-logging/index.js +1 -1
- package/dist/builtins/console-logging/index.mjs +1 -1
- package/dist/builtins/device-manager/device-linked-devices.d.ts +1 -1
- package/dist/builtins/device-manager/device-manager.addon.js +1608 -1589
- package/dist/builtins/device-manager/device-manager.addon.mjs +1608 -1589
- package/dist/builtins/device-manager/device-store-sections.d.ts +26 -0
- package/dist/builtins/doorbell/doorbell-settings.d.ts +58 -0
- package/dist/builtins/doorbell/trigger-engine.d.ts +32 -30
- package/dist/builtins/doorbell/virtual-doorbell.addon.d.ts +39 -22
- package/dist/builtins/doorbell/virtual-doorbell.addon.js +207 -191
- package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +207 -191
- package/dist/builtins/hub-forwarder/index.js +1 -1
- package/dist/builtins/hub-forwarder/index.mjs +1 -1
- package/dist/builtins/local-auth/local-auth.addon.js +1 -1
- package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
- package/dist/builtins/local-network/local-network.addon.js +1 -1
- package/dist/builtins/local-network/local-network.addon.mjs +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
- package/dist/builtins/platform-probe/index.js +1 -1
- package/dist/builtins/platform-probe/index.mjs +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
- package/dist/builtins/snapshot/index.js +1 -1
- package/dist/builtins/snapshot/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +11 -3
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +11 -3
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
- package/dist/builtins/system-config/system-config.addon.js +1 -1
- package/dist/builtins/system-config/system-config.addon.mjs +1 -1
- package/dist/builtins/winston-logging/index.js +1 -1
- package/dist/builtins/winston-logging/index.mjs +1 -1
- package/dist/{dist-BduBhv6N.js → dist-B5C4dVvO.js} +293 -23
- package/dist/{dist-B_PSvr-m.mjs → dist-DssImRC5.mjs} +293 -23
- package/dist/index.js +22 -5
- package/dist/index.mjs +22 -6
- package/dist/kernel/index.d.ts +1 -1
- package/dist/kernel/moleculer/readiness-context.d.ts +12 -8
- package/dist/kernel/moleculer/readiness-service.d.ts +16 -1
- package/dist/{manifest-python-deps-CIyvuHAB.mjs → manifest-python-deps-CWom-eqp.mjs} +35 -9
- package/dist/{manifest-python-deps-CPAMH5gV.js → manifest-python-deps-kkvku9yU.js} +35 -9
- package/package.json +2 -2
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ProviderContext } from './device-provider-context.js';
|
|
2
|
+
/** One device-store-backed section: the keys it owns + how to persist them. */
|
|
3
|
+
export interface DeviceStoreSection {
|
|
4
|
+
/** Reserved config keys this section owns (must not reach the driver). */
|
|
5
|
+
readonly keys: readonly string[];
|
|
6
|
+
/** Persist this section's slice of a save into the device-store blob. */
|
|
7
|
+
apply(pctx: Pick<ProviderContext, 'settings'>, deviceId: number, patch: Record<string, unknown>): Promise<unknown>;
|
|
8
|
+
}
|
|
9
|
+
/** The device-manager's device-store-backed sections. Add an entry to extend. */
|
|
10
|
+
export declare const DEVICE_STORE_SECTIONS: readonly DeviceStoreSection[];
|
|
11
|
+
/** Result of splitting a `device-manager`-writer patch by persistence target. */
|
|
12
|
+
export interface DeviceStoreSplit {
|
|
13
|
+
/** Per-section slices that persist to the device-store blob. */
|
|
14
|
+
readonly storeGroups: ReadonlyArray<{
|
|
15
|
+
section: DeviceStoreSection;
|
|
16
|
+
patch: Record<string, unknown>;
|
|
17
|
+
}>;
|
|
18
|
+
/** The remaining keys, destined for the device driver's own config. */
|
|
19
|
+
readonly driverPatch: Record<string, unknown>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Split a `writerCapName: 'device-manager'` patch into device-store slices
|
|
23
|
+
* (one per matching registered section) and the leftover driver patch.
|
|
24
|
+
* Generic — consults {@link DEVICE_STORE_SECTIONS}, no hardcoded key list.
|
|
25
|
+
*/
|
|
26
|
+
export declare function splitDeviceStoreKeys(patch: Record<string, unknown>): DeviceStoreSplit;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure per-camera settings parsing/normalization for the virtual-doorbell
|
|
3
|
+
* builtin. Kept separate from the addon class (and the runtime trigger
|
|
4
|
+
* engine) so the persisted-shape handling — including tolerant migration of
|
|
5
|
+
* the legacy single-source blob — is unit-testable in isolation.
|
|
6
|
+
*
|
|
7
|
+
* PERSISTED SHAPE (extensible by design):
|
|
8
|
+
* doorbellSources: Array<{ deviceId: number }>
|
|
9
|
+
*
|
|
10
|
+
* The source is an OBJECT rather than a bare id so future per-source options
|
|
11
|
+
* (a custom trigger override, an event-type match, a per-source debounce)
|
|
12
|
+
* can be added without another migration. Today only `deviceId` is stored;
|
|
13
|
+
* the reaction is DERIVED at runtime from the source device's cap (see
|
|
14
|
+
* `trigger-engine.ts`).
|
|
15
|
+
*/
|
|
16
|
+
/** Device-store key holding the source list. */
|
|
17
|
+
export declare const KEY_SOURCES = "doorbellSources";
|
|
18
|
+
/**
|
|
19
|
+
* Legacy device-store keys from the pre-simplification shape (single source
|
|
20
|
+
* device + explicit trigger + event type). Retained ONLY for tolerant
|
|
21
|
+
* migration on read and cleanup on write — never written afresh.
|
|
22
|
+
*/
|
|
23
|
+
export declare const LEGACY_KEY_SOURCE = "doorbellSourceDeviceId";
|
|
24
|
+
export declare const LEGACY_KEY_TRIGGER = "doorbellTrigger";
|
|
25
|
+
export declare const LEGACY_KEY_EVENT_TYPE = "doorbellEventType";
|
|
26
|
+
/**
|
|
27
|
+
* One source device driving a camera's virtual doorbell. Intentionally an
|
|
28
|
+
* object so it can grow (custom trigger, event type) without a migration.
|
|
29
|
+
*/
|
|
30
|
+
export interface DoorbellSource {
|
|
31
|
+
readonly deviceId: number;
|
|
32
|
+
}
|
|
33
|
+
/** Coerce a persisted / form-supplied id (number or numeric string) to a
|
|
34
|
+
* positive integer device id, or null when it is not a usable id. */
|
|
35
|
+
export declare function coerceDeviceId(value: unknown): number | null;
|
|
36
|
+
/**
|
|
37
|
+
* Parse the persisted doorbell sources for one camera. Tolerant of BOTH:
|
|
38
|
+
* - the new `doorbellSources: [{deviceId}]` shape (ids may arrive as
|
|
39
|
+
* numbers, numeric strings, or `{deviceId}` records); and
|
|
40
|
+
* - the legacy single `doorbellSourceDeviceId` scalar, mapped onto one
|
|
41
|
+
* source (the old trigger/eventType are dropped — the reaction is now
|
|
42
|
+
* derived at runtime).
|
|
43
|
+
*
|
|
44
|
+
* Never throws on malformed data — unknown entries are skipped.
|
|
45
|
+
*/
|
|
46
|
+
export declare function parseDoorbellSources(blob: Record<string, unknown>): readonly DoorbellSource[];
|
|
47
|
+
/**
|
|
48
|
+
* Normalize a settings-patch value for the `doorbellSources` multiselect
|
|
49
|
+
* (a `string[]` of device ids from the form, or an already-shaped
|
|
50
|
+
* `{deviceId}[]` / `number[]`) into the persisted extensible shape.
|
|
51
|
+
*/
|
|
52
|
+
export declare function normalizeDoorbellSources(value: unknown): DoorbellSource[];
|
|
53
|
+
/**
|
|
54
|
+
* Produce the next device-store blob after applying a doorbell-sources
|
|
55
|
+
* patch: writes the normalized new shape and strips every legacy key so a
|
|
56
|
+
* migrated camera never carries stale single-source fields.
|
|
57
|
+
*/
|
|
58
|
+
export declare function applyDoorbellSourcesPatch(current: Record<string, unknown>, patchValue: unknown): Record<string, unknown>;
|
|
@@ -1,26 +1,35 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Pure trigger logic for the virtual-doorbell builtin — edge detection
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
2
|
+
* Pure trigger logic for the virtual-doorbell builtin — edge detection over
|
|
3
|
+
* runtime-state slices with per-camera debounce. Extracted from the addon
|
|
4
|
+
* class so the behaviour is unit-testable without instantiating the addon or
|
|
5
|
+
* mocking the event bus.
|
|
6
|
+
*
|
|
7
|
+
* REACTION MODEL (simplified — operator picks a source, the system reacts
|
|
8
|
+
* with a sensible default): a source device rings a camera's doorbell when a
|
|
9
|
+
* known binary / switch cap on it RISES to its active state (false→true) — a
|
|
10
|
+
* contact opening, a switch turning on, an alarm sensor firing. There is no
|
|
11
|
+
* per-source trigger configuration today; the shape stays extensible for a
|
|
12
|
+
* future custom-trigger override (see `doorbell-settings.ts`).
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Known binary / switch source caps → the boolean slice field whose
|
|
16
|
+
* false→true rise rings the doorbell. Every entry is "ring on active".
|
|
17
|
+
* Sensors whose "active" reading is not a plain boolean (presence's string
|
|
18
|
+
* state, connectivity's connected flag) are deliberately excluded — a
|
|
19
|
+
* reconnect is not a doorbell press.
|
|
7
20
|
*/
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
export declare const
|
|
11
|
-
/**
|
|
12
|
-
export declare function
|
|
21
|
+
export declare const SOURCE_CAP_ACTIVE_FIELD: Readonly<Record<string, string>>;
|
|
22
|
+
/** Cap names whose presence in a device's bindings qualify it as a source. */
|
|
23
|
+
export declare const SOURCE_CAPS: readonly string[];
|
|
24
|
+
/** True when a cap is a recognised binary/switch doorbell source. */
|
|
25
|
+
export declare function isSourceCap(capName: string): boolean;
|
|
13
26
|
/**
|
|
14
|
-
* One camera's virtual-doorbell wiring:
|
|
15
|
-
*
|
|
27
|
+
* One camera's virtual-doorbell wiring: a source device that rings it. A
|
|
28
|
+
* camera with several sources produces several assignments (one per source).
|
|
16
29
|
*/
|
|
17
30
|
export interface DoorbellAssignment {
|
|
18
31
|
readonly cameraId: number;
|
|
19
32
|
readonly sourceDeviceId: number;
|
|
20
|
-
readonly trigger: DoorbellTrigger;
|
|
21
|
-
/** Only meaningful when `trigger === 'event'` — matched verbatim
|
|
22
|
-
* against the event-emitter `onEvent` payload `eventType`. */
|
|
23
|
-
readonly eventType: string | null;
|
|
24
33
|
}
|
|
25
34
|
/** Debounce window guarding against sensor chatter (reed-switch bounce,
|
|
26
35
|
* duplicate HA state pushes). One ring per camera per window. */
|
|
@@ -29,10 +38,10 @@ export declare const DEFAULT_DEBOUNCE_MS = 2000;
|
|
|
29
38
|
* Stateful (but side-effect-free towards the outside) trigger engine.
|
|
30
39
|
*
|
|
31
40
|
* Tracks the last observed binary value per (sourceDevice, cap) so a
|
|
32
|
-
* `DeviceStateChanged` re-emission (the slice's `lastChangedAt` moves
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
41
|
+
* `DeviceStateChanged` re-emission (the slice's `lastChangedAt` moves while
|
|
42
|
+
* the binary value does not) never double-fires, and the FIRST observation
|
|
43
|
+
* after boot only seeds the baseline — a state hydration at startup must not
|
|
44
|
+
* ring anybody's doorbell.
|
|
36
45
|
*/
|
|
37
46
|
export declare class DoorbellTriggerEngine {
|
|
38
47
|
private assignments;
|
|
@@ -53,17 +62,10 @@ export declare class DoorbellTriggerEngine {
|
|
|
53
62
|
hasSource(deviceId: number): boolean;
|
|
54
63
|
/**
|
|
55
64
|
* Feed one `DeviceStateChanged` slice. Returns the camera ids whose
|
|
56
|
-
* doorbell should ring (already debounced).
|
|
57
|
-
*
|
|
65
|
+
* doorbell should ring (already debounced). Only a false→true rise on a
|
|
66
|
+
* recognised source cap fires; baseline-only sightings, re-emissions, and
|
|
67
|
+
* the falling edge return an empty array.
|
|
58
68
|
*/
|
|
59
69
|
onStateSlice(deviceId: number, capName: string, slice: Record<string, unknown>): number[];
|
|
60
|
-
/**
|
|
61
|
-
* Feed one event-emitter `onEvent` firing. Returns the camera ids to
|
|
62
|
-
* ring — assignments with `trigger: 'event'`, a matching source and a
|
|
63
|
-
* verbatim `eventType` match. An assignment with no configured
|
|
64
|
-
* eventType never matches (misconfiguration must not ring on every
|
|
65
|
-
* event the device emits).
|
|
66
|
-
*/
|
|
67
|
-
onEmitterEvent(deviceId: number, eventType: string): number[];
|
|
68
70
|
private matchAndDebounce;
|
|
69
71
|
}
|
|
@@ -6,26 +6,29 @@ interface VirtualDoorbellAddonConfig {
|
|
|
6
6
|
/**
|
|
7
7
|
* VirtualDoorbellAddon — WRAPPER over the `doorbell` capability.
|
|
8
8
|
*
|
|
9
|
-
* Turns any binary
|
|
10
|
-
*
|
|
9
|
+
* Turns any binary sensor or switch (contact, motion, flood/gas/CO/smoke,
|
|
10
|
+
* vibration, tamper, generic binary, or a switch) into a doorbell for a
|
|
11
|
+
* camera:
|
|
11
12
|
*
|
|
12
13
|
* 1. The operator binds the wrapper to a camera in the bindings UI
|
|
13
14
|
* (`defaultActive: false` — never auto-bound).
|
|
14
|
-
* 2.
|
|
15
|
-
*
|
|
16
|
-
*
|
|
15
|
+
* 2. In the camera's GENERAL settings (next to "Linked devices") the
|
|
16
|
+
* operator picks one or more SOURCE devices from a searchable list —
|
|
17
|
+
* that is the ONLY choice. The reaction is derived automatically per
|
|
18
|
+
* device type: a binary sensor rings when it goes active, a switch
|
|
19
|
+
* rings when it turns on (see `trigger-engine.ts`). The persisted
|
|
20
|
+
* shape (`doorbellSources: [{deviceId}]`) stays extensible for a
|
|
21
|
+
* future custom-trigger override.
|
|
17
22
|
* 3. At runtime the addon watches `EventCategory.DeviceStateChanged`
|
|
18
|
-
* (
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* `doorbell` runtime-state counters via the standard
|
|
25
|
-
* `deviceState.setCapSlice` plumbing.
|
|
23
|
+
* (binary/switch slice transitions — false→true edge detected). On a
|
|
24
|
+
* matching, debounced rise it emits `EventCategory.DoorbellOnPressed`
|
|
25
|
+
* with the CAMERA as source (`{deviceId: cameraId, timestamp}` — the
|
|
26
|
+
* same shape Reolink's native `emitDoorbellPressed` produces) and
|
|
27
|
+
* bumps the camera's `doorbell` runtime-state counters via the
|
|
28
|
+
* standard `deviceState.setCapSlice` plumbing.
|
|
26
29
|
*
|
|
27
30
|
* Fires ONLY for cameras where the wrapper is BOUND (checked against
|
|
28
|
-
* `deviceManager.getBindings`) and
|
|
31
|
+
* `deviceManager.getBindings`) and at least one source device is configured.
|
|
29
32
|
*/
|
|
30
33
|
export declare class VirtualDoorbellAddon extends BaseAddon<VirtualDoorbellAddonConfig> {
|
|
31
34
|
private readonly engine;
|
|
@@ -35,7 +38,6 @@ export declare class VirtualDoorbellAddon extends BaseAddon<VirtualDoorbellAddon
|
|
|
35
38
|
constructor();
|
|
36
39
|
protected onInitialize(): Promise<ProviderRegistration[]>;
|
|
37
40
|
private handleStateChanged;
|
|
38
|
-
private handleEmitterEvent;
|
|
39
41
|
/**
|
|
40
42
|
* Ring the camera's virtual doorbell: verify the wrapper is BOUND to
|
|
41
43
|
* the camera, bump the `doorbell` runtime-state counters through the
|
|
@@ -62,7 +64,11 @@ export declare class VirtualDoorbellAddon extends BaseAddon<VirtualDoorbellAddon
|
|
|
62
64
|
* single source of truth, persisted across restarts).
|
|
63
65
|
*/
|
|
64
66
|
private getStatus;
|
|
65
|
-
|
|
67
|
+
/**
|
|
68
|
+
* The camera's configured doorbell sources, parsed tolerantly (new
|
|
69
|
+
* `doorbellSources` shape + legacy single-source migration).
|
|
70
|
+
*/
|
|
71
|
+
private readDeviceSources;
|
|
66
72
|
/**
|
|
67
73
|
* Single-trip, non-throwing device lookup (mirrors snapshot's
|
|
68
74
|
* `lookupDeviceMeta`). Null on any failure — callers fall back to
|
|
@@ -71,15 +77,26 @@ export declare class VirtualDoorbellAddon extends BaseAddon<VirtualDoorbellAddon
|
|
|
71
77
|
*/
|
|
72
78
|
private lookupDevice;
|
|
73
79
|
/**
|
|
74
|
-
* Settings section for the device-detail page
|
|
75
|
-
*
|
|
76
|
-
*
|
|
80
|
+
* Settings section for the device-detail page — contributed into the
|
|
81
|
+
* GENERAL settings surface (no `tab`, so it lands in the same tab as
|
|
82
|
+
* "Linked devices", ordered just after it). Camera-only: the doorbell
|
|
83
|
+
* cap also applies to Button accessories (native providers) where a
|
|
84
|
+
* virtual-source picker is meaningless.
|
|
85
|
+
*
|
|
86
|
+
* A SINGLE `multiselect` field lists every eligible binary/switch
|
|
87
|
+
* device; at ≥8 options the admin-ui form-builder auto-swaps it for the
|
|
88
|
+
* searchable multi-select (same idiom as "Linked devices"). The reaction
|
|
89
|
+
* is derived automatically per device type — no trigger/eventType
|
|
90
|
+
* controls.
|
|
77
91
|
*/
|
|
78
92
|
private buildDeviceSettingsContribution;
|
|
79
93
|
/**
|
|
80
|
-
* Cluster-wide picker options: every device whose BINDINGS expose one
|
|
81
|
-
*
|
|
82
|
-
* sourced) because cap names are exactly what the runtime
|
|
94
|
+
* Cluster-wide picker options: every device whose BINDINGS expose one of
|
|
95
|
+
* the recognised binary/switch source caps. Binding-sourced (not
|
|
96
|
+
* feature-flag sourced) because cap names are exactly what the runtime
|
|
97
|
+
* consumes. Labelled `Name (Location)` (id carried in the option value)
|
|
98
|
+
* so the searchable multi-select matches on name, location, or id — the
|
|
99
|
+
* same shape "Linked devices" uses.
|
|
83
100
|
*/
|
|
84
101
|
private listSourceDeviceOptions;
|
|
85
102
|
private saveDeviceSettingsPatch;
|