@camera.ui/sdk 0.0.2 → 0.0.4

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.
Files changed (76) hide show
  1. package/LICENSE.md +1 -1
  2. package/README.md +3 -3
  3. package/dist/camera/events.js +2 -0
  4. package/dist/camera/index.js +3 -1
  5. package/dist/external.js +7 -0
  6. package/dist/index.d.ts +7132 -4248
  7. package/dist/index.js +3 -11
  8. package/dist/internal/contract-validators.js +21 -0
  9. package/dist/internal/index.d.ts +915 -0
  10. package/dist/internal/index.js +9 -0
  11. package/dist/internal/sensor-triggers.js +2 -0
  12. package/dist/internal/shared-utils.js +86 -0
  13. package/dist/internal/streaming-internal.js +1 -0
  14. package/dist/manager/index.js +1 -1
  15. package/dist/observable/index.js +419 -0
  16. package/dist/plugin/api.js +21 -0
  17. package/dist/plugin/contract.js +101 -114
  18. package/dist/plugin/helper.js +277 -0
  19. package/dist/plugin/index.js +4 -1
  20. package/dist/plugin/interfaces.js +51 -1
  21. package/dist/plugin/notifier.js +23 -0
  22. package/dist/plugin/oauth.js +1 -0
  23. package/dist/sensor/audio.js +103 -81
  24. package/dist/sensor/base.js +350 -318
  25. package/dist/sensor/battery.js +73 -59
  26. package/dist/sensor/classifier.js +117 -0
  27. package/dist/sensor/clip.js +30 -0
  28. package/dist/sensor/contact.js +37 -18
  29. package/dist/sensor/detection.js +4 -0
  30. package/dist/sensor/doorbell.js +52 -38
  31. package/dist/sensor/face.js +71 -86
  32. package/dist/sensor/garage.js +121 -0
  33. package/dist/sensor/humidity.js +52 -0
  34. package/dist/sensor/index.js +17 -11
  35. package/dist/sensor/leak.js +52 -0
  36. package/dist/sensor/licensePlate.js +70 -79
  37. package/dist/sensor/light.js +82 -38
  38. package/dist/sensor/lock.js +99 -0
  39. package/dist/sensor/motion.js +85 -70
  40. package/dist/sensor/object.js +73 -94
  41. package/dist/sensor/occupancy.js +52 -0
  42. package/dist/sensor/ptz.js +114 -100
  43. package/dist/sensor/securitySystem.js +98 -0
  44. package/dist/sensor/siren.js +75 -43
  45. package/dist/sensor/smoke.js +52 -0
  46. package/dist/sensor/spec.js +1 -0
  47. package/dist/sensor/switch.js +72 -0
  48. package/dist/sensor/temperature.js +52 -0
  49. package/dist/storage/index.js +1 -2
  50. package/dist/types.js +1 -0
  51. package/docs/.vitepress/config.ts +77 -0
  52. package/docs/.vitepress/theme/index.ts +5 -0
  53. package/docs/.vitepress/theme/style.css +117 -0
  54. package/docs/index.md +16 -0
  55. package/docs/logo.png +0 -0
  56. package/docs/public/apple-touch-icon.png +0 -0
  57. package/docs/public/favicon-16.ico +0 -0
  58. package/docs/public/favicon.ico +0 -0
  59. package/docs/public/logo.svg +1 -0
  60. package/examples/README.md +7 -0
  61. package/examples/getting-started.md +535 -0
  62. package/package.json +36 -23
  63. package/scripts/build-example-docs.mjs +62 -0
  64. package/tsconfig.node.json +3 -2
  65. package/typedoc.json +42 -0
  66. package/dist/sensor/guards.js +0 -133
  67. package/dist/sensor/types.js +0 -46
  68. package/dist/service/base.js +0 -96
  69. package/dist/service/index.js +0 -3
  70. /package/dist/camera/{types.js → enums.js} +0 -0
  71. /package/dist/{manager/types.js → camera/frames.js} +0 -0
  72. /package/dist/{plugin/types.js → internal/camera-config-internal.js} +0 -0
  73. /package/dist/{service/services.js → internal/camera-enums.js} +0 -0
  74. /package/dist/{service/types.js → internal/camera-wire.js} +0 -0
  75. /package/dist/{storage/schema.js → internal/manager-rpc.js} +0 -0
  76. /package/dist/{storage/storages.js → internal/sensor-rpc.js} +0 -0
@@ -1,101 +1,115 @@
1
- import { Sensor } from './base.js';
2
- import { ChargingState, SensorCategory, SensorType } from './types.js';
3
- /**
4
- * Battery Capability enum
5
- * Describes what Battery features this sensor supports
6
- * Note: "level" property is always available (standard)
7
- */
1
+ import { Sensor, SensorType, SensorCategory } from './base.js';
2
+ /** Optional capabilities for battery info sensors */
8
3
  export var BatteryCapability;
9
4
  (function (BatteryCapability) {
10
- /** Supports low battery detection */
5
+ /** Sensor reports low-battery alerts */
11
6
  BatteryCapability["LowBattery"] = "lowBattery";
12
- /** Supports charging state detection */
7
+ /** Sensor reports charging state */
13
8
  BatteryCapability["Charging"] = "charging";
14
9
  })(BatteryCapability || (BatteryCapability = {}));
15
10
  /**
16
- * Battery info property keys
11
+ * Properties for battery info sensors
12
+ *
13
+ * @internal
17
14
  */
18
15
  export var BatteryProperty;
19
16
  (function (BatteryProperty) {
17
+ /** Battery level percentage (0–100) */
20
18
  BatteryProperty["Level"] = "level";
19
+ /** Current charging state */
21
20
  BatteryProperty["Charging"] = "charging";
21
+ /** Whether battery is critically low */
22
22
  BatteryProperty["Low"] = "low";
23
23
  })(BatteryProperty || (BatteryProperty = {}));
24
+ /** Battery charging state */
25
+ export var ChargingState;
26
+ (function (ChargingState) {
27
+ ChargingState["NotChargeable"] = "NOT_CHARGEABLE";
28
+ ChargingState["NotCharging"] = "NOT_CHARGING";
29
+ ChargingState["Charging"] = "CHARGING";
30
+ ChargingState["Full"] = "FULL";
31
+ })(ChargingState || (ChargingState = {}));
24
32
  /**
25
- * Battery Info
33
+ * Battery info sensor. Reports battery level, charging state, and low-battery alerts.
26
34
  *
27
- * Read-only hardware status for battery-powered cameras.
35
+ * Plugin authors call `setLevel(value)`, `setCharging(state)`, and `setLow(value)`
36
+ * to push updates from the device.
28
37
  */
38
+ // prettier-ignore
29
39
  export class BatteryInfo extends Sensor {
30
40
  type = SensorType.Battery;
31
41
  category = SensorCategory.Info;
32
- name;
33
- /** Threshold for low battery warning (default: 20%) */
34
- lowBatteryThreshold = 20;
35
42
  constructor(name = 'Battery') {
36
- super();
37
- this.name = name;
38
- // Initialize defaults
39
- this.props.level = 100;
40
- this.props.charging = ChargingState.NotCharging;
41
- this.props.low = false;
43
+ super(name);
44
+ this._writeState({
45
+ [BatteryProperty.Level]: 100,
46
+ [BatteryProperty.Charging]: ChargingState.NotCharging,
47
+ [BatteryProperty.Low]: false,
48
+ });
42
49
  }
43
- // ========== Properties (Getter/Setter Pairs) ==========
44
- /** Battery level (0-100) */
45
50
  get level() {
46
- return this.rawProps.level;
47
- }
48
- /** Set battery level (0-100) */
49
- set level(value) {
50
- const clampedValue = Math.max(0, Math.min(100, value));
51
- this.props.level = clampedValue;
52
- // Auto-update low battery state
53
- this.props.low = clampedValue <= this.lowBatteryThreshold;
51
+ return this.props.level;
54
52
  }
55
- /** Charging state */
56
53
  get charging() {
57
- return this.rawProps.charging;
54
+ return this.props.charging;
58
55
  }
59
- /** Set charging state */
60
- set charging(value) {
61
- this.props.charging = value;
62
- }
63
- /** Whether battery is low */
64
56
  get low() {
65
- return this.rawProps.low;
57
+ return this.props.low;
66
58
  }
67
- /** Set low battery state */
68
- set low(value) {
69
- this.props.low = value;
59
+ /**
60
+ * Report a new battery level (percentage). Clamped to [0, 100].
61
+ *
62
+ * @param value - Battery level percentage in the range 0–100.
63
+ *
64
+ * @example
65
+ * ```ts
66
+ * battery.setLevel(87);
67
+ * ```
68
+ */
69
+ setLevel(value) {
70
+ this._writeState({ [BatteryProperty.Level]: Math.max(0, Math.min(100, value)) });
70
71
  }
71
- // ========== Convenience Methods ==========
72
72
  /**
73
- * Update battery state
73
+ * Report the current charging state.
74
74
  *
75
- * @param level - Battery level (0-100)
75
+ * @param value - Current charging state from the {@link ChargingState} enum.
76
76
  *
77
- * @param charging - Charging state
77
+ * @example
78
+ * ```ts
79
+ * import { ChargingState } from '@camera.ui/sdk';
80
+ * battery.setCharging(ChargingState.Charging);
81
+ * ```
78
82
  */
79
- setBattery(level, charging) {
80
- this.level = level;
81
- if (charging !== undefined) {
82
- this.props.charging = charging;
83
- }
83
+ setCharging(value) {
84
+ this._writeState({ [BatteryProperty.Charging]: value });
84
85
  }
85
86
  /**
86
- * Check if battery is charging
87
+ * Report whether the battery is critically low.
88
+ *
89
+ * @param value - True when the battery has crossed the low-battery threshold.
87
90
  *
88
- * @returns True if battery is charging, false otherwise
91
+ * @example
92
+ * ```ts
93
+ * battery.setLow(true);
94
+ * ```
89
95
  */
90
- isCharging() {
91
- return this.charging === ChargingState.Charging;
96
+ setLow(value) {
97
+ this._writeState({ [BatteryProperty.Low]: value });
92
98
  }
93
99
  /**
94
- * Check if battery is fully charged
100
+ * Read-only sensor: external writes are ignored. State is reported via `setLevel`/`setCharging`/`setLow`.
101
+ *
102
+ * Called by the cross-process plugin host when a generic property write is received.
103
+ * Battery sensors have no externally writable properties, so the parameters are
104
+ * unused (underscore-prefixed) and the call is a no-op.
105
+ *
106
+ * @param _property - Unused — battery sensors expose no writable properties.
107
+ *
108
+ * @param _value - Unused — battery sensors expose no writable properties.
95
109
  *
96
- * @returns True if battery is fully charged, false otherwise
110
+ * @internal
97
111
  */
98
- isFullyCharged() {
99
- return this.charging === ChargingState.Full || this.level === 100;
112
+ updateValue(_property, _value) {
113
+ // No-op battery state is reported by the plugin, not set externally.
100
114
  }
101
115
  }
@@ -0,0 +1,117 @@
1
+ import { Sensor, SensorType, SensorCategory } from './base.js';
2
+ /**
3
+ * Property names of a classifier sensor.
4
+ *
5
+ * @internal
6
+ */
7
+ export var ClassifierProperty;
8
+ (function (ClassifierProperty) {
9
+ /** Whether any classification result is active. */
10
+ ClassifierProperty["Detected"] = "detected";
11
+ /** List of classification results with labels and confidence. */
12
+ ClassifierProperty["Detections"] = "detections";
13
+ /** Unique labels of the current detections (auto-derived when reporting detections). */
14
+ ClassifierProperty["Labels"] = "labels";
15
+ })(ClassifierProperty || (ClassifierProperty = {}));
16
+ /**
17
+ * General-purpose image classifier sensor.
18
+ *
19
+ * Plugin authors call `reportDetections(list)` to push classification results.
20
+ * `detected` and `labels` are auto-derived from the detection list.
21
+ */
22
+ export class ClassifierSensor extends Sensor {
23
+ type = SensorType.Classifier;
24
+ category = SensorCategory.Sensor;
25
+ _requiresFrames = false;
26
+ constructor(name = 'Classifier') {
27
+ super(name);
28
+ this._writeState({
29
+ [ClassifierProperty.Detected]: false,
30
+ [ClassifierProperty.Detections]: [],
31
+ [ClassifierProperty.Labels]: [],
32
+ });
33
+ }
34
+ /** Whether any classification result is active. */
35
+ get detected() {
36
+ return this.props.detected;
37
+ }
38
+ /** Current detection list. */
39
+ get detections() {
40
+ return this.props.detections;
41
+ }
42
+ /** Unique labels of the current detections. */
43
+ get labels() {
44
+ return this.props.labels;
45
+ }
46
+ /**
47
+ * Report classification results. Auto-derives `detected` and `labels` from the list.
48
+ *
49
+ * - `reportDetections(true)` — generic classification trigger. The SDK
50
+ * synthesizes a single full-frame detection with empty attribute/subAttribute.
51
+ * - `reportDetections(true, [...])` — explicit classifier detections.
52
+ * - `reportDetections(false)` — clear.
53
+ *
54
+ * @param detected - Whether any classification result is active.
55
+ *
56
+ * @param detections - Optional explicit classifier detections to publish.
57
+ *
58
+ * @example
59
+ * ```ts
60
+ * import type { ClassifierDetection } from '@camera.ui/sdk';
61
+ * sensor.reportDetections(true, [
62
+ * {
63
+ * label: 'animal',
64
+ * confidence: 0.88,
65
+ * box: { x: 0.1, y: 0.2, width: 0.3, height: 0.4 },
66
+ * attribute: 'bird',
67
+ * subAttribute: 'woodpecker',
68
+ * } satisfies ClassifierDetection,
69
+ * ]);
70
+ * sensor.reportDetections(false);
71
+ * ```
72
+ */
73
+ reportDetections(detected, detections) {
74
+ const list = this._normalizeReportedDetections(detected, detections, 'motion', { attribute: '', subAttribute: '' });
75
+ const labels = Array.from(new Set(list.map((d) => d.label)));
76
+ this._writeState({
77
+ [ClassifierProperty.Detected]: detected,
78
+ [ClassifierProperty.Detections]: list,
79
+ [ClassifierProperty.Labels]: labels,
80
+ });
81
+ }
82
+ /**
83
+ * Explicitly clear classifier state (detected = false, detections = [], labels = []).
84
+ *
85
+ * @example
86
+ * ```ts
87
+ * sensor.clearDetections();
88
+ * ```
89
+ */
90
+ clearDetections() {
91
+ this.reportDetections(false);
92
+ }
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
+ * Classifier 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 — classifier sensors expose no writable properties.
101
+ *
102
+ * @param _value - Unused — classifier sensors expose no writable properties.
103
+ *
104
+ * @internal
105
+ */
106
+ updateValue(_property, _value) {
107
+ // No-op — classifier state is reported by the plugin, not set externally.
108
+ }
109
+ }
110
+ /**
111
+ * Classifier detector that receives video frames from the backend pipeline.
112
+ * Extend this class and implement {@link detectClassifications} to run image
113
+ * classification models against trigger regions.
114
+ */
115
+ export class ClassifierDetectorSensor extends ClassifierSensor {
116
+ _requiresFrames = true;
117
+ }
@@ -0,0 +1,30 @@
1
+ import { Sensor, SensorType, SensorCategory } from './base.js';
2
+ /**
3
+ * CLIP detector sensor that receives video frames and generates semantic
4
+ * embeddings. Extend this class and implement {@link detectEmbeddings} to
5
+ * produce CLIP embeddings for downstream semantic search.
6
+ */
7
+ export class ClipDetectorSensor extends Sensor {
8
+ type = SensorType.Clip;
9
+ category = SensorCategory.Sensor;
10
+ _requiresFrames = true;
11
+ constructor(name = 'CLIP Sensor') {
12
+ super(name);
13
+ }
14
+ /**
15
+ * Frame-only sensor: no externally writable properties.
16
+ *
17
+ * Called by the cross-process plugin host when a generic property write is received.
18
+ * CLIP detectors have no writable properties, so the parameters are unused
19
+ * (underscore-prefixed) and the call is a no-op.
20
+ *
21
+ * @param _property - Unused — CLIP detectors expose no writable properties.
22
+ *
23
+ * @param _value - Unused — CLIP detectors expose no writable properties.
24
+ *
25
+ * @internal
26
+ */
27
+ updateValue(_property, _value) {
28
+ // No-op — clip detector has no state.
29
+ }
30
+ }
@@ -1,33 +1,52 @@
1
- import { Sensor } from './base.js';
2
- import { SensorCategory, SensorType } from './types.js';
1
+ import { Sensor, SensorType, SensorCategory } from './base.js';
3
2
  /**
4
- * Contact sensor property keys
3
+ * Properties for contact sensors
4
+ *
5
+ * @internal
5
6
  */
6
7
  export var ContactProperty;
7
8
  (function (ContactProperty) {
9
+ /** Whether the contact is open (true = open, false = closed) */
8
10
  ContactProperty["Detected"] = "detected";
9
11
  })(ContactProperty || (ContactProperty = {}));
10
- /**
11
- * Contact Sensor
12
- *
13
- * Detects contact state (open/closed) for doors, windows, etc.
14
- */
12
+ /** Contact sensor for door/window open-close state */
15
13
  export class ContactSensor extends Sensor {
16
14
  type = SensorType.Contact;
17
15
  category = SensorCategory.Sensor;
18
- name;
19
16
  constructor(name = 'Contact Sensor') {
20
- super();
21
- this.name = name;
22
- // Initialize defaults
23
- this.props.detected = false;
17
+ super(name);
18
+ this._writeState({ [ContactProperty.Detected]: false });
24
19
  }
25
- /** Whether contact is detected (closed) */
26
20
  get detected() {
27
- return this.rawProps.detected;
21
+ return this.props.detected;
22
+ }
23
+ /**
24
+ * Report contact state (true = open, false = closed).
25
+ *
26
+ * @param value - True when the contact is open, false when closed.
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * contact.setDetected(true);
31
+ * ```
32
+ */
33
+ setDetected(value) {
34
+ this._writeState({ [ContactProperty.Detected]: value });
28
35
  }
29
- /** Set contact detected state */
30
- set detected(value) {
31
- this.props.detected = value;
36
+ /**
37
+ * Read-only sensor: external writes are ignored. State is reported via `setDetected`.
38
+ *
39
+ * Called by the cross-process plugin host when a generic property write is received.
40
+ * Contact sensors have no externally writable properties, so the parameters are
41
+ * unused (underscore-prefixed) and the call is a no-op.
42
+ *
43
+ * @param _property - Unused — contact sensors expose no writable properties.
44
+ *
45
+ * @param _value - Unused — contact sensors expose no writable properties.
46
+ *
47
+ * @internal
48
+ */
49
+ updateValue(_property, _value) {
50
+ // No-op — contact state is reported by the plugin, not set externally.
32
51
  }
33
52
  }
@@ -0,0 +1,4 @@
1
+ /** Built-in detection label types recognized across the system. */
2
+ export const DETECTION_LABELS = ['motion', 'person', 'vehicle', 'animal', 'package', 'audio'];
3
+ /** Detection attribute types used to mark sub-detections (face, license plate, ...). */
4
+ export const DETECTION_ATTRIBUTES = ['face', 'license_plate'];
@@ -1,63 +1,77 @@
1
- import { Sensor } from './base.js';
2
- import { SensorCategory, SensorType } from './types.js';
1
+ import { Sensor, SensorType, SensorCategory } from './base.js';
3
2
  /**
4
- * Doorbell trigger property keys
3
+ * Properties for doorbell triggers
4
+ *
5
+ * @internal
5
6
  */
6
7
  export var DoorbellProperty;
7
8
  (function (DoorbellProperty) {
9
+ /** Whether the doorbell is currently ringing */
8
10
  DoorbellProperty["Ring"] = "ring";
9
11
  })(DoorbellProperty || (DoorbellProperty = {}));
12
+ /** Auto-reset duration after `trigger()` is called (ms). */
13
+ export const RING_AUTO_RESET_MS = 2000;
10
14
  /**
11
- * Doorbell Trigger
15
+ * Doorbell trigger sensor.
12
16
  *
13
- * Event-based trigger for doorbell rings.
14
- * Ring property auto-resets after a short delay.
17
+ * Plugin authors call `trigger()` to fire a doorbell event. The `ring` property
18
+ * is set to true and automatically reset to false after a short delay
19
+ * ({@link RING_AUTO_RESET_MS}). Calling `trigger()` again while still ringing
20
+ * resets the timer (extends the ring phase).
15
21
  */
16
22
  export class DoorbellTrigger extends Sensor {
17
23
  type = SensorType.Doorbell;
18
24
  category = SensorCategory.Trigger;
19
- name;
20
- _resetTimeout;
25
+ _ringResetTimer;
21
26
  constructor(name = 'Doorbell') {
22
- super();
23
- this.name = name;
24
- // Initialize defaults
25
- this.props.ring = false;
27
+ super(name);
28
+ this._writeState({ [DoorbellProperty.Ring]: false });
26
29
  }
27
- // ========== Properties (Getter/Setter Pairs) ==========
28
- /** Whether doorbell is currently ringing */
29
30
  get ring() {
30
- return this.rawProps.ring;
31
+ return this.props.ring;
31
32
  }
32
- /** Set ring state */
33
- set ring(value) {
34
- this.props.ring = value;
33
+ /**
34
+ * Trigger a doorbell ring. Sets `ring = true` and auto-resets after a
35
+ * short delay. Re-triggering while still ringing extends the ring phase.
36
+ *
37
+ * @example
38
+ * ```ts
39
+ * doorbell.trigger();
40
+ * ```
41
+ */
42
+ trigger() {
43
+ if (this._ringResetTimer) {
44
+ clearTimeout(this._ringResetTimer);
45
+ }
46
+ this._writeState({ [DoorbellProperty.Ring]: true });
47
+ this._ringResetTimer = setTimeout(() => {
48
+ this._ringResetTimer = undefined;
49
+ this._writeState({ [DoorbellProperty.Ring]: false });
50
+ }, RING_AUTO_RESET_MS);
35
51
  }
36
- // ========== Convenience Methods ==========
37
52
  /**
38
- * Trigger doorbell ring
39
- * Auto-resets after duration (default: 1000ms)
53
+ * Cross-process consumer entry point. Writing `ring=true` (any truthy value)
54
+ * dispatches to `trigger()` so a UI test button or external automation can
55
+ * fire the doorbell using the same flow as a real hardware ring (auto-reset
56
+ * included). Writing `ring=false` is ignored — the auto-reset timer owns
57
+ * the off transition.
58
+ *
59
+ * @param property - Property name to write.
60
+ *
61
+ * @param value - New value for the property.
40
62
  *
41
- * @param resetAfterMs - Duration in milliseconds to auto-reset ring state
63
+ * @internal
42
64
  */
43
- triggerRing(resetAfterMs = 1000) {
44
- // Clear any existing reset timeout
45
- if (this._resetTimeout) {
46
- clearTimeout(this._resetTimeout);
65
+ updateValue(property, value) {
66
+ if (property === DoorbellProperty.Ring && value) {
67
+ this.trigger();
47
68
  }
48
- this.props.ring = true;
49
- // Auto-reset after duration
50
- this._resetTimeout = setTimeout(() => {
51
- this.props.ring = false;
52
- this._resetTimeout = undefined;
53
- }, resetAfterMs);
54
69
  }
55
- /** Reset ring state immediately */
56
- resetRing() {
57
- if (this._resetTimeout) {
58
- clearTimeout(this._resetTimeout);
59
- this._resetTimeout = undefined;
70
+ _cleanup() {
71
+ if (this._ringResetTimer) {
72
+ clearTimeout(this._ringResetTimer);
73
+ this._ringResetTimer = undefined;
60
74
  }
61
- this.props.ring = false;
75
+ super._cleanup();
62
76
  }
63
77
  }