@camera.ui/sdk 0.0.3 → 0.0.5
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/README.md +2 -2
- package/dist/camera/events.js +2 -0
- package/dist/camera/index.js +3 -1
- package/dist/external.js +7 -0
- package/dist/index.d.ts +7132 -4248
- package/dist/index.js +3 -11
- package/dist/internal/contract-validators.js +21 -0
- package/dist/internal/index.d.ts +915 -0
- package/dist/internal/index.js +9 -0
- package/dist/internal/sensor-triggers.js +2 -0
- package/dist/internal/shared-utils.js +86 -0
- package/dist/internal/streaming-internal.js +1 -0
- package/dist/manager/index.js +1 -1
- package/dist/observable/index.js +419 -0
- package/dist/plugin/api.js +21 -0
- package/dist/plugin/contract.js +101 -114
- package/dist/plugin/helper.js +277 -0
- package/dist/plugin/index.js +4 -1
- package/dist/plugin/interfaces.js +51 -1
- package/dist/plugin/notifier.js +23 -0
- package/dist/plugin/oauth.js +1 -0
- package/dist/sensor/audio.js +103 -81
- package/dist/sensor/base.js +350 -318
- package/dist/sensor/battery.js +73 -59
- package/dist/sensor/classifier.js +117 -0
- package/dist/sensor/clip.js +30 -0
- package/dist/sensor/contact.js +37 -18
- package/dist/sensor/detection.js +4 -0
- package/dist/sensor/doorbell.js +52 -38
- package/dist/sensor/face.js +71 -86
- package/dist/sensor/garage.js +121 -0
- package/dist/sensor/humidity.js +52 -0
- package/dist/sensor/index.js +17 -11
- package/dist/sensor/leak.js +52 -0
- package/dist/sensor/licensePlate.js +70 -79
- package/dist/sensor/light.js +82 -38
- package/dist/sensor/lock.js +99 -0
- package/dist/sensor/motion.js +85 -70
- package/dist/sensor/object.js +73 -94
- package/dist/sensor/occupancy.js +52 -0
- package/dist/sensor/ptz.js +114 -100
- package/dist/sensor/securitySystem.js +98 -0
- package/dist/sensor/siren.js +75 -43
- package/dist/sensor/smoke.js +52 -0
- package/dist/sensor/spec.js +1 -0
- package/dist/sensor/switch.js +72 -0
- package/dist/sensor/temperature.js +52 -0
- package/dist/storage/index.js +1 -2
- package/dist/types.js +1 -0
- package/package.json +36 -23
- package/CHANGELOG.md +0 -8
- package/CONTRIBUTING.md +0 -1
- package/LICENSE.md +0 -22
- package/dist/sensor/guards.js +0 -133
- package/dist/sensor/types.js +0 -46
- package/dist/service/base.js +0 -96
- package/dist/service/index.js +0 -3
- package/tsconfig.node.json +0 -30
- /package/dist/camera/{types.js → enums.js} +0 -0
- /package/dist/{manager/types.js → camera/frames.js} +0 -0
- /package/dist/{plugin/types.js → internal/camera-config-internal.js} +0 -0
- /package/dist/{service/services.js → internal/camera-enums.js} +0 -0
- /package/dist/{service/types.js → internal/camera-wire.js} +0 -0
- /package/dist/{storage/schema.js → internal/manager-rpc.js} +0 -0
- /package/dist/{storage/storages.js → internal/sensor-rpc.js} +0 -0
package/dist/sensor/light.js
CHANGED
|
@@ -1,66 +1,110 @@
|
|
|
1
|
-
import { Sensor } from './base.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Light Capability enum
|
|
5
|
-
* Describes what Light features this sensor supports
|
|
6
|
-
* Note: "on" property is always available (standard)
|
|
7
|
-
*/
|
|
1
|
+
import { Sensor, SensorType, SensorCategory } from './base.js';
|
|
2
|
+
/** Optional capabilities for light controls */
|
|
8
3
|
export var LightCapability;
|
|
9
4
|
(function (LightCapability) {
|
|
10
|
-
/**
|
|
5
|
+
/** Light supports brightness adjustment (0–100) */
|
|
11
6
|
LightCapability["Brightness"] = "brightness";
|
|
12
7
|
})(LightCapability || (LightCapability = {}));
|
|
13
8
|
/**
|
|
14
|
-
*
|
|
9
|
+
* Properties for light controls
|
|
10
|
+
*
|
|
11
|
+
* @internal
|
|
15
12
|
*/
|
|
16
13
|
export var LightProperty;
|
|
17
14
|
(function (LightProperty) {
|
|
15
|
+
/** Whether the light is on */
|
|
18
16
|
LightProperty["On"] = "on";
|
|
17
|
+
/** Brightness level (0–100) */
|
|
19
18
|
LightProperty["Brightness"] = "brightness";
|
|
20
19
|
})(LightProperty || (LightProperty = {}));
|
|
21
20
|
/**
|
|
22
|
-
* Light
|
|
21
|
+
* Light control sensor. Override `setOn()`/`setOff()` to drive your hardware,
|
|
22
|
+
* then `await super.setOn()` / `await super.setOff()` to sync the SDK state.
|
|
23
23
|
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
24
|
+
* Plugins that have no hardware-action use case can leave the methods unoverridden —
|
|
25
|
+
* the base implementation just updates the state.
|
|
26
|
+
*
|
|
27
|
+
* For hardware-pushed updates (someone manually flipped the switch), call
|
|
28
|
+
* `super.setOn()` / `super.setOff()` from your event handler — that bypasses
|
|
29
|
+
* any plugin override and only syncs state.
|
|
26
30
|
*/
|
|
27
31
|
export class LightControl extends Sensor {
|
|
28
32
|
type = SensorType.Light;
|
|
29
33
|
category = SensorCategory.Control;
|
|
30
|
-
name;
|
|
31
34
|
constructor(name = 'Light') {
|
|
32
|
-
super();
|
|
33
|
-
this.
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
super(name);
|
|
36
|
+
this._writeState({
|
|
37
|
+
[LightProperty.On]: false,
|
|
38
|
+
[LightProperty.Brightness]: 100,
|
|
39
|
+
});
|
|
37
40
|
}
|
|
38
|
-
/** Whether light is on */
|
|
39
41
|
get on() {
|
|
40
|
-
return this.
|
|
41
|
-
}
|
|
42
|
-
/** Turn light on/off */
|
|
43
|
-
set on(value) {
|
|
44
|
-
this.props.on = value;
|
|
42
|
+
return this.props.on;
|
|
45
43
|
}
|
|
46
|
-
/** Brightness level (0-100) */
|
|
47
44
|
get brightness() {
|
|
48
|
-
return this.
|
|
45
|
+
return this.props.brightness;
|
|
49
46
|
}
|
|
50
|
-
/**
|
|
51
|
-
|
|
52
|
-
|
|
47
|
+
/**
|
|
48
|
+
* Turn the light on. Override to drive hardware and call `await super.setOn()`
|
|
49
|
+
* after the hardware call succeeds to sync the SDK state.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```ts
|
|
53
|
+
* await light.setOn();
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
async setOn() {
|
|
57
|
+
this._writeState({ [LightProperty.On]: true });
|
|
53
58
|
}
|
|
54
|
-
/**
|
|
55
|
-
|
|
56
|
-
|
|
59
|
+
/**
|
|
60
|
+
* Turn the light off. Override to drive hardware and call `await super.setOff()`
|
|
61
|
+
* after the hardware call succeeds to sync the SDK state.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```ts
|
|
65
|
+
* await light.setOff();
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
async setOff() {
|
|
69
|
+
this._writeState({ [LightProperty.On]: false });
|
|
57
70
|
}
|
|
58
|
-
/**
|
|
59
|
-
|
|
60
|
-
|
|
71
|
+
/**
|
|
72
|
+
* Set brightness. Override to drive hardware and call `await super.setBrightness(value)`
|
|
73
|
+
* after the hardware call succeeds. The default implementation clamps the value to [0, 100].
|
|
74
|
+
*
|
|
75
|
+
* @param value - Brightness level in the range 0–100.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```ts
|
|
79
|
+
* await light.setBrightness(75);
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
async setBrightness(value) {
|
|
83
|
+
this._writeState({ [LightProperty.Brightness]: Math.max(0, Math.min(100, value)) });
|
|
61
84
|
}
|
|
62
|
-
/**
|
|
63
|
-
|
|
64
|
-
|
|
85
|
+
/**
|
|
86
|
+
* Cross-process consumer entry point. Dispatches writable properties
|
|
87
|
+
* to semantic methods so plugin overrides (hardware actions) are honored.
|
|
88
|
+
* Unknown properties are ignored — only `On` and `Brightness` are externally writable.
|
|
89
|
+
*
|
|
90
|
+
* @param property - Property name to write.
|
|
91
|
+
*
|
|
92
|
+
* @param value - New value for the property.
|
|
93
|
+
*
|
|
94
|
+
* @internal
|
|
95
|
+
*/
|
|
96
|
+
async updateValue(property, value) {
|
|
97
|
+
switch (property) {
|
|
98
|
+
case LightProperty.On:
|
|
99
|
+
if (value)
|
|
100
|
+
await this.setOn();
|
|
101
|
+
else
|
|
102
|
+
await this.setOff();
|
|
103
|
+
return;
|
|
104
|
+
case LightProperty.Brightness:
|
|
105
|
+
await this.setBrightness(value);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
// Unknown / non-writable property — ignored.
|
|
65
109
|
}
|
|
66
110
|
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { Sensor, SensorType, SensorCategory } from './base.js';
|
|
2
|
+
/** Lock states (HomeKit-compatible values) */
|
|
3
|
+
export var LockState;
|
|
4
|
+
(function (LockState) {
|
|
5
|
+
LockState[LockState["Secured"] = 0] = "Secured";
|
|
6
|
+
LockState[LockState["Unsecured"] = 1] = "Unsecured";
|
|
7
|
+
LockState[LockState["Unknown"] = 2] = "Unknown";
|
|
8
|
+
})(LockState || (LockState = {}));
|
|
9
|
+
/**
|
|
10
|
+
* Properties for lock controls
|
|
11
|
+
*
|
|
12
|
+
* @internal
|
|
13
|
+
*/
|
|
14
|
+
export var LockProperty;
|
|
15
|
+
(function (LockProperty) {
|
|
16
|
+
/** The actual current state of the lock */
|
|
17
|
+
LockProperty["CurrentState"] = "currentState";
|
|
18
|
+
/** The desired target state (set by user, transitions to currentState) */
|
|
19
|
+
LockProperty["TargetState"] = "targetState";
|
|
20
|
+
})(LockProperty || (LockProperty = {}));
|
|
21
|
+
/**
|
|
22
|
+
* Lock control. Override `setTargetState()` to drive hardware and call
|
|
23
|
+
* `await super.setTargetState(value)` once the hardware confirms — the base
|
|
24
|
+
* implementation updates both `targetState` and `currentState` to the new value.
|
|
25
|
+
*
|
|
26
|
+
* For asymmetric flows (long-running unlock with intermediate state) override
|
|
27
|
+
* `setTargetState` and write `currentState` separately when transitions complete.
|
|
28
|
+
*/
|
|
29
|
+
export class LockControl extends Sensor {
|
|
30
|
+
type = SensorType.Lock;
|
|
31
|
+
category = SensorCategory.Control;
|
|
32
|
+
constructor(name = 'Lock') {
|
|
33
|
+
super(name);
|
|
34
|
+
this._writeState({
|
|
35
|
+
[LockProperty.CurrentState]: LockState.Secured,
|
|
36
|
+
[LockProperty.TargetState]: LockState.Secured,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
get currentState() {
|
|
40
|
+
return this.props.currentState;
|
|
41
|
+
}
|
|
42
|
+
get targetState() {
|
|
43
|
+
return this.props.targetState;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Set the target state. Override to drive hardware and call
|
|
47
|
+
* `await super.setTargetState(value)` after success — the base implementation
|
|
48
|
+
* syncs both `targetState` and `currentState` to the new value.
|
|
49
|
+
*
|
|
50
|
+
* @param value - Desired lock state from the {@link LockState} enum.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```ts
|
|
54
|
+
* import { LockState } from '@camera.ui/sdk';
|
|
55
|
+
* await lock.setTargetState(LockState.Secured);
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
async setTargetState(value) {
|
|
59
|
+
this._writeState({
|
|
60
|
+
[LockProperty.TargetState]: value,
|
|
61
|
+
[LockProperty.CurrentState]: value,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Publish the actual lock state. Use this to drive transitions where the
|
|
66
|
+
* physical state diverges from the user-requested target — e.g. motorized
|
|
67
|
+
* smart locks that take time to rotate (publish `Unknown` while moving),
|
|
68
|
+
* or hardware reporting an out-of-band state change. Read-only from
|
|
69
|
+
* cross-process consumers (`updateValue` ignores it).
|
|
70
|
+
*
|
|
71
|
+
* @param value - Current physical lock state from the {@link LockState} enum.
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```ts
|
|
75
|
+
* import { LockState } from '@camera.ui/sdk';
|
|
76
|
+
* lock.setCurrentState(LockState.Unknown);
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
setCurrentState(value) {
|
|
80
|
+
this._writeState({ [LockProperty.CurrentState]: value });
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Cross-process consumer entry point. Dispatches writable properties
|
|
84
|
+
* to semantic methods so plugin overrides (hardware actions) are honored.
|
|
85
|
+
* `currentState` is observed-only and not externally writable; only `targetState` may be set.
|
|
86
|
+
*
|
|
87
|
+
* @param property - Property name to write.
|
|
88
|
+
*
|
|
89
|
+
* @param value - New value for the property.
|
|
90
|
+
*
|
|
91
|
+
* @internal
|
|
92
|
+
*/
|
|
93
|
+
async updateValue(property, value) {
|
|
94
|
+
if (property === LockProperty.TargetState) {
|
|
95
|
+
await this.setTargetState(value);
|
|
96
|
+
}
|
|
97
|
+
// Unknown / non-writable property (incl. currentState) — ignored.
|
|
98
|
+
}
|
|
99
|
+
}
|
package/dist/sensor/motion.js
CHANGED
|
@@ -1,103 +1,118 @@
|
|
|
1
|
-
import { Sensor } from './base.js';
|
|
2
|
-
import { SensorCategory, SensorType } from './types.js';
|
|
1
|
+
import { Sensor, SensorType, SensorCategory } from './base.js';
|
|
3
2
|
/**
|
|
4
|
-
*
|
|
3
|
+
* Property names of a motion sensor.
|
|
4
|
+
*
|
|
5
|
+
* @internal
|
|
5
6
|
*/
|
|
6
7
|
export var MotionProperty;
|
|
7
8
|
(function (MotionProperty) {
|
|
9
|
+
/** Whether motion is currently detected. */
|
|
8
10
|
MotionProperty["Detected"] = "detected";
|
|
11
|
+
/** List of detection results with bounding boxes. */
|
|
9
12
|
MotionProperty["Detections"] = "detections";
|
|
13
|
+
/** When true, detection updates are suppressed (set by the backend dwell logic). */
|
|
14
|
+
MotionProperty["Blocked"] = "blocked";
|
|
15
|
+
/** Timestamp in milliseconds of the last detection trigger, set by the backend. */
|
|
16
|
+
MotionProperty["LastTriggered"] = "lastTriggered";
|
|
10
17
|
})(MotionProperty || (MotionProperty = {}));
|
|
11
18
|
/**
|
|
12
|
-
* Motion
|
|
13
|
-
*
|
|
14
|
-
* Base class for external motion detection (Ring, ONVIF events, SMTP, etc.)
|
|
15
|
-
* Properties can be set directly: `sensor.detected = true`
|
|
19
|
+
* Motion sensor that reports motion state and detection results.
|
|
16
20
|
*
|
|
17
|
-
*
|
|
21
|
+
* Plugin authors call `reportDetections(list)` to push detection results.
|
|
22
|
+
* `detected` is auto-derived from the detection list. `blocked` is read-only
|
|
23
|
+
* and is set by the backend (dwell logic) — `reportDetections()` becomes a
|
|
24
|
+
* no-op while the sensor is blocked.
|
|
18
25
|
*/
|
|
19
26
|
export class MotionSensor extends Sensor {
|
|
20
27
|
type = SensorType.Motion;
|
|
21
28
|
category = SensorCategory.Sensor;
|
|
22
|
-
name;
|
|
23
|
-
/**
|
|
24
|
-
* External motion sensors don't require video frames.
|
|
25
|
-
* They receive motion events from external sources (SMTP, ONVIF, Ring API, etc.)
|
|
26
|
-
*/
|
|
27
29
|
_requiresFrames = false;
|
|
28
30
|
constructor(name = 'Motion Sensor') {
|
|
29
|
-
super();
|
|
30
|
-
this.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
super(name);
|
|
32
|
+
this._writeState({
|
|
33
|
+
[MotionProperty.Detected]: false,
|
|
34
|
+
[MotionProperty.Detections]: [],
|
|
35
|
+
[MotionProperty.Blocked]: false,
|
|
36
|
+
});
|
|
34
37
|
}
|
|
35
|
-
/** Whether motion is currently detected */
|
|
38
|
+
/** Whether motion is currently detected. */
|
|
36
39
|
get detected() {
|
|
37
|
-
return this.
|
|
38
|
-
}
|
|
39
|
-
/** Set motion detected state */
|
|
40
|
-
set detected(value) {
|
|
41
|
-
this.props.detected = value;
|
|
40
|
+
return this.props.detected;
|
|
42
41
|
}
|
|
43
|
-
/** Current
|
|
42
|
+
/** Current detection list. */
|
|
44
43
|
get detections() {
|
|
45
|
-
return this.
|
|
44
|
+
return this.props.detections;
|
|
46
45
|
}
|
|
47
|
-
/**
|
|
48
|
-
|
|
49
|
-
this.props.
|
|
46
|
+
/** Whether the sensor is currently blocked. Read-only — set by the backend dwell logic, not by plugin code. */
|
|
47
|
+
get blocked() {
|
|
48
|
+
return this.props.blocked;
|
|
50
49
|
}
|
|
51
50
|
/**
|
|
52
|
-
*
|
|
51
|
+
* Report a motion detection result.
|
|
52
|
+
*
|
|
53
|
+
* - `reportDetections(true)` — motion detected without bbox (e.g. Ring camera).
|
|
54
|
+
* The SDK synthesizes a single full-frame `'motion'` detection.
|
|
55
|
+
* - `reportDetections(true, [...])` — motion detected with explicit detections.
|
|
56
|
+
* - `reportDetections(false)` — no motion (clears detections).
|
|
53
57
|
*
|
|
54
|
-
*
|
|
58
|
+
* No-op while the sensor is blocked by backend dwell logic.
|
|
59
|
+
*
|
|
60
|
+
* @param detected - Whether motion is currently detected.
|
|
61
|
+
*
|
|
62
|
+
* @param detections - Optional explicit detections produced for this frame.
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```ts
|
|
66
|
+
* import type { Detection } from '@camera.ui/sdk';
|
|
67
|
+
* sensor.reportDetections(true, [
|
|
68
|
+
* { label: 'motion', confidence: 0.85, box: { x: 0.1, y: 0.2, width: 0.3, height: 0.4 } } satisfies Detection,
|
|
69
|
+
* ]);
|
|
70
|
+
* sensor.reportDetections(false);
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
reportDetections(detected, detections) {
|
|
74
|
+
if (this.blocked)
|
|
75
|
+
return;
|
|
76
|
+
const list = this._normalizeReportedDetections(detected, detections, 'motion');
|
|
77
|
+
this._writeState({
|
|
78
|
+
[MotionProperty.Detected]: detected,
|
|
79
|
+
[MotionProperty.Detections]: list,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Explicitly clear motion state (detected = false, detections = []).
|
|
55
84
|
*
|
|
56
|
-
* @
|
|
85
|
+
* @example
|
|
86
|
+
* ```ts
|
|
87
|
+
* sensor.clearDetections();
|
|
88
|
+
* ```
|
|
57
89
|
*/
|
|
58
|
-
|
|
59
|
-
this.
|
|
60
|
-
this.props.detections = detections;
|
|
90
|
+
clearDetections() {
|
|
91
|
+
this.reportDetections(false);
|
|
61
92
|
}
|
|
62
|
-
/**
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
93
|
+
/**
|
|
94
|
+
* Read-only sensor: external writes are ignored. State is reported via `reportDetections`.
|
|
95
|
+
*
|
|
96
|
+
* Called by the cross-process plugin host when a generic property write is received.
|
|
97
|
+
* Motion sensors have no externally writable properties, so the parameters are
|
|
98
|
+
* unused (underscore-prefixed) and the call is a no-op.
|
|
99
|
+
*
|
|
100
|
+
* @param _property - Unused — motion sensors expose no writable properties.
|
|
101
|
+
*
|
|
102
|
+
* @param _value - Unused — motion sensors expose no writable properties.
|
|
103
|
+
*
|
|
104
|
+
* @internal
|
|
105
|
+
*/
|
|
106
|
+
updateValue(_property, _value) {
|
|
107
|
+
// No-op — motion state is reported by the plugin, not set externally.
|
|
66
108
|
}
|
|
67
109
|
}
|
|
68
110
|
/**
|
|
69
|
-
* Motion
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
* For external motion events (Ring, ONVIF, SMTP), use the base `MotionSensor` class instead.
|
|
75
|
-
*
|
|
76
|
-
* @example
|
|
77
|
-
* ```typescript
|
|
78
|
-
* class RustMotionDetector extends MotionDetectorSensor {
|
|
79
|
-
* get inputProperties(): VideoInputProperties {
|
|
80
|
-
* return { width: 320, height: 240, format: 'gray' };
|
|
81
|
-
* }
|
|
82
|
-
*
|
|
83
|
-
* async detectMotion(frame: VideoFrameData): Promise<MotionResult> {
|
|
84
|
-
* const result = await this.rustDetector.process(frame.data);
|
|
85
|
-
* return {
|
|
86
|
-
* detected: result.motionDetected,
|
|
87
|
-
* detections: result.regions.map(r => ({
|
|
88
|
-
* label: 'motion',
|
|
89
|
-
* confidence: r.intensity,
|
|
90
|
-
* box: r.boundingBox,
|
|
91
|
-
* })),
|
|
92
|
-
* };
|
|
93
|
-
* }
|
|
94
|
-
* }
|
|
95
|
-
* ```
|
|
111
|
+
* Motion detector that receives video frames from the backend pipeline.
|
|
112
|
+
* Extend this class and implement {@link detectMotion} to analyze frames
|
|
113
|
+
* for motion. The backend calls `detectMotion()` at the configured frame
|
|
114
|
+
* interval and applies the returned result to the sensor.
|
|
96
115
|
*/
|
|
97
116
|
export class MotionDetectorSensor extends MotionSensor {
|
|
98
|
-
/**
|
|
99
|
-
* Indicates this sensor requires video frames for detection.
|
|
100
|
-
* Used by the backend to determine streaming requirements.
|
|
101
|
-
*/
|
|
102
117
|
_requiresFrames = true;
|
|
103
118
|
}
|
package/dist/sensor/object.js
CHANGED
|
@@ -1,137 +1,116 @@
|
|
|
1
|
-
import { Sensor } from './base.js';
|
|
2
|
-
import { SensorCategory, SensorType } from './types.js';
|
|
1
|
+
import { Sensor, SensorType, SensorCategory } from './base.js';
|
|
3
2
|
/**
|
|
4
|
-
*
|
|
3
|
+
* Property names of an object detection sensor.
|
|
4
|
+
*
|
|
5
|
+
* @internal
|
|
5
6
|
*/
|
|
6
7
|
export var ObjectProperty;
|
|
7
8
|
(function (ObjectProperty) {
|
|
9
|
+
/** Whether any object is currently detected. */
|
|
8
10
|
ObjectProperty["Detected"] = "detected";
|
|
11
|
+
/** List of detected objects with labels and bounding boxes. */
|
|
9
12
|
ObjectProperty["Detections"] = "detections";
|
|
13
|
+
/** Unique labels of the current detections (auto-derived when reporting detections). */
|
|
10
14
|
ObjectProperty["Labels"] = "labels";
|
|
11
15
|
})(ObjectProperty || (ObjectProperty = {}));
|
|
12
16
|
/**
|
|
13
|
-
* Object
|
|
14
|
-
*
|
|
15
|
-
* Base class for external object detection (Ring, ONVIF events, Eufy, etc.)
|
|
16
|
-
* Properties can be set directly: `sensor.detected = true`
|
|
17
|
+
* Object detection sensor that reports detected objects (person, vehicle, animal, etc.).
|
|
17
18
|
*
|
|
18
|
-
*
|
|
19
|
+
* Plugin authors call `reportDetections(list)` to push detection results.
|
|
20
|
+
* `detected` and `labels` are auto-derived from the detection list.
|
|
19
21
|
*/
|
|
20
22
|
export class ObjectSensor extends Sensor {
|
|
21
23
|
type = SensorType.Object;
|
|
22
24
|
category = SensorCategory.Sensor;
|
|
23
|
-
name;
|
|
24
|
-
/**
|
|
25
|
-
* External object sensors don't require video frames.
|
|
26
|
-
* They receive detection events from external sources (APIs, ONVIF, etc.)
|
|
27
|
-
*/
|
|
28
25
|
_requiresFrames = false;
|
|
29
26
|
constructor(name = 'Object Sensor') {
|
|
30
|
-
super();
|
|
31
|
-
this.
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
27
|
+
super(name);
|
|
28
|
+
this._writeState({
|
|
29
|
+
[ObjectProperty.Detected]: false,
|
|
30
|
+
[ObjectProperty.Detections]: [],
|
|
31
|
+
[ObjectProperty.Labels]: [],
|
|
32
|
+
});
|
|
36
33
|
}
|
|
37
|
-
/** Whether
|
|
34
|
+
/** Whether any object is currently detected. */
|
|
38
35
|
get detected() {
|
|
39
|
-
return this.
|
|
40
|
-
}
|
|
41
|
-
/** Set object detected state */
|
|
42
|
-
set detected(value) {
|
|
43
|
-
this.props.detected = value;
|
|
36
|
+
return this.props.detected;
|
|
44
37
|
}
|
|
45
|
-
/** Current
|
|
38
|
+
/** Current detection list. */
|
|
46
39
|
get detections() {
|
|
47
|
-
return this.
|
|
40
|
+
return this.props.detections;
|
|
48
41
|
}
|
|
49
|
-
/**
|
|
50
|
-
set detections(value) {
|
|
51
|
-
this.props.detections = value;
|
|
52
|
-
}
|
|
53
|
-
/** Labels currently being detected */
|
|
42
|
+
/** Unique labels of the current detections. */
|
|
54
43
|
get labels() {
|
|
55
|
-
return this.
|
|
56
|
-
}
|
|
57
|
-
/** Set detected labels */
|
|
58
|
-
set labels(value) {
|
|
59
|
-
this.props.labels = value;
|
|
44
|
+
return this.props.labels;
|
|
60
45
|
}
|
|
61
46
|
/**
|
|
62
|
-
*
|
|
47
|
+
* Report detected objects. Auto-derives `detected` and `labels` from the list.
|
|
48
|
+
*
|
|
49
|
+
* - `reportDetections(true)` — something detected without specific data. The SDK
|
|
50
|
+
* synthesizes a single full-frame `'motion'` detection as a generic fallback.
|
|
51
|
+
* - `reportDetections(true, [...])` — explicit detections (typical case).
|
|
52
|
+
* - `reportDetections(false)` — clear.
|
|
63
53
|
*
|
|
64
|
-
* @param detected - Whether
|
|
54
|
+
* @param detected - Whether any object is currently detected.
|
|
65
55
|
*
|
|
66
|
-
* @param detections -
|
|
56
|
+
* @param detections - Optional explicit object detections (with optional tracking metadata).
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```ts
|
|
60
|
+
* import type { TrackedDetection } from '@camera.ui/sdk';
|
|
61
|
+
* sensor.reportDetections(true, [
|
|
62
|
+
* {
|
|
63
|
+
* label: 'person',
|
|
64
|
+
* confidence: 0.92,
|
|
65
|
+
* box: { x: 0.1, y: 0.2, width: 0.3, height: 0.4 },
|
|
66
|
+
* } satisfies TrackedDetection,
|
|
67
|
+
* ]);
|
|
68
|
+
* sensor.reportDetections(false);
|
|
69
|
+
* ```
|
|
67
70
|
*/
|
|
68
|
-
|
|
69
|
-
this.
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
clearObjects() {
|
|
77
|
-
this.props.detected = false;
|
|
78
|
-
this.props.detections = [];
|
|
79
|
-
this.props.labels = [];
|
|
71
|
+
reportDetections(detected, detections) {
|
|
72
|
+
const list = this._normalizeReportedDetections(detected, detections, 'motion');
|
|
73
|
+
const labels = Array.from(new Set(list.map((d) => d.label)));
|
|
74
|
+
this._writeState({
|
|
75
|
+
[ObjectProperty.Detected]: detected,
|
|
76
|
+
[ObjectProperty.Detections]: list,
|
|
77
|
+
[ObjectProperty.Labels]: labels,
|
|
78
|
+
});
|
|
80
79
|
}
|
|
81
80
|
/**
|
|
82
|
-
*
|
|
81
|
+
* Explicitly clear detection state (detected = false, detections = [], labels = []).
|
|
83
82
|
*
|
|
84
|
-
* @
|
|
85
|
-
*
|
|
86
|
-
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```ts
|
|
85
|
+
* sensor.clearDetections();
|
|
86
|
+
* ```
|
|
87
87
|
*/
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
clearDetections() {
|
|
89
|
+
this.reportDetections(false);
|
|
90
90
|
}
|
|
91
91
|
/**
|
|
92
|
-
*
|
|
92
|
+
* Read-only sensor: external writes are ignored. State is reported via `reportDetections`.
|
|
93
|
+
*
|
|
94
|
+
* Called by the cross-process plugin host when a generic property write is received.
|
|
95
|
+
* Object detection sensors have no externally writable properties, so the parameters are
|
|
96
|
+
* unused (underscore-prefixed) and the call is a no-op.
|
|
97
|
+
*
|
|
98
|
+
* @param _property - Unused — object detection sensors expose no writable properties.
|
|
93
99
|
*
|
|
94
|
-
* @param
|
|
100
|
+
* @param _value - Unused — object detection sensors expose no writable properties.
|
|
95
101
|
*
|
|
96
|
-
* @
|
|
102
|
+
* @internal
|
|
97
103
|
*/
|
|
98
|
-
|
|
99
|
-
|
|
104
|
+
updateValue(_property, _value) {
|
|
105
|
+
// No-op — object detection state is reported by the plugin, not set externally.
|
|
100
106
|
}
|
|
101
107
|
}
|
|
102
108
|
/**
|
|
103
|
-
* Object
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
* For external object events, use the base `ObjectSensor` class instead.
|
|
109
|
-
*
|
|
110
|
-
* @example
|
|
111
|
-
* ```typescript
|
|
112
|
-
* class TensorFlowObjectDetector extends ObjectDetectorSensor {
|
|
113
|
-
* get inputProperties(): VideoInputProperties {
|
|
114
|
-
* return { width: 640, height: 640, format: 'rgb' };
|
|
115
|
-
* }
|
|
116
|
-
*
|
|
117
|
-
* async detectObjects(frame: VideoFrameData): Promise<ObjectResult> {
|
|
118
|
-
* const predictions = await this.model.detect(frame.data);
|
|
119
|
-
* return {
|
|
120
|
-
* detected: predictions.length > 0,
|
|
121
|
-
* detections: predictions.map(p => ({
|
|
122
|
-
* label: p.class,
|
|
123
|
-
* confidence: p.score,
|
|
124
|
-
* box: p.bbox,
|
|
125
|
-
* })),
|
|
126
|
-
* };
|
|
127
|
-
* }
|
|
128
|
-
* }
|
|
129
|
-
* ```
|
|
109
|
+
* Object detector that receives video frames from the backend pipeline.
|
|
110
|
+
* Extend this class and implement {@link detectObjects} and {@link modelSpec}.
|
|
111
|
+
* The backend scales frames to match `modelSpec.input` dimensions before
|
|
112
|
+
* each call.
|
|
130
113
|
*/
|
|
131
114
|
export class ObjectDetectorSensor extends ObjectSensor {
|
|
132
|
-
/**
|
|
133
|
-
* Indicates this sensor requires video frames for detection.
|
|
134
|
-
* Used by the backend to determine streaming requirements.
|
|
135
|
-
*/
|
|
136
115
|
_requiresFrames = true;
|
|
137
116
|
}
|