@camstack/addon-notifiers 1.2.74 → 1.2.76

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 CHANGED
@@ -5436,6 +5436,12 @@ Object.fromEntries([
5436
5436
  icon: "move",
5437
5437
  order: 40
5438
5438
  },
5439
+ {
5440
+ id: "navigation",
5441
+ label: "Navigation",
5442
+ icon: "compass",
5443
+ order: 41
5444
+ },
5439
5445
  {
5440
5446
  id: "consumables",
5441
5447
  label: "Consumables",
@@ -27003,6 +27009,203 @@ DeviceType.Camera, method(object({ deviceId: number() }), PtzAutotrackStatusSche
27003
27009
  deviceId: number(),
27004
27010
  status: PtzAutotrackStatusSchema
27005
27011
  });
27012
+ /**
27013
+ * `navigation` — a device-scoped capability that natively expresses the FULL
27014
+ * navigation / action surface of a robot that DRIVES ITSELF and carries an
27015
+ * on-board camera (the Dreame robot-vacuum camera is the first provider).
27016
+ *
27017
+ * Why a NEW cap rather than overloading `ptz`:
27018
+ * - `ptz` moves a *gimbal* on a fixed camera (pan/tilt/zoom of the lens). A
27019
+ * robot vacuum has no gimbal — the whole chassis drives, turns and spins.
27020
+ * The two are different physical models: PTZ is absolute-position + presets,
27021
+ * navigation is momentary drive nudges + discrete robot ACTIONS
27022
+ * (dock / spot-clean / follow-pet / go-to-point / …).
27023
+ * - This cap is the SOURCE OF TRUTH. Two consumers adapt from it rather than
27024
+ * the reverse:
27025
+ * 1. a native CamStack navigation panel (data-driven from `listActions`
27026
+ * / `getOptions`), and
27027
+ * 2. the PTZ surface — a thin adapter mimics `ptz` from `navigation` so a
27028
+ * robot camera shows up in the existing PTZ control path without every
27029
+ * PTZ provider learning about robots. The mapping lives in the adapter,
27030
+ * not here (see the addon design note):
27031
+ * ptz.continuousMove({pan,tilt}) → navigation.move({pan,tilt})
27032
+ * ptz.stop() → navigation.stop()
27033
+ * ptz.goHome() → navigation.runAction('goHome')
27034
+ * ptz.getPresets() → navigation.listActions() (id→preset)
27035
+ * ptz.goToPreset(id) → navigation.runAction(id)
27036
+ *
27037
+ * ## Continuous drive
27038
+ *
27039
+ * `move` is MOMENTARY. Fluid navigation comes from the UI (or the PTZ adapter)
27040
+ * sending `move({pan,tilt})` REPEATEDLY at ~1 Hz while a direction is held, and
27041
+ * one `stop()` on release — exactly like the robot app's remote-drive joystick.
27042
+ * The provider forwards EACH `move` to one drive write; it must NOT debounce or
27043
+ * coalesce them. The UI owns the cadence.
27044
+ *
27045
+ * ## The action dictionary
27046
+ *
27047
+ * The discrete controls (dock / locate / spot-clean / follow / flash / sounds)
27048
+ * are a DATA-DRIVEN dictionary the cap exposes via `listActions()`. Each entry
27049
+ * carries `{ id, kind, label, icon }` (plus `soundId` for sound entries) so the
27050
+ * native panel AND the PTZ mimic render buttons WITHOUT hardcoding a
27051
+ * vendor-specific list. `kind: 'action'` entries are triggered with
27052
+ * `runAction({ actionId })`; `kind: 'sound'` entries with `playSound({ soundId })`
27053
+ * (the entry carries the `soundId` to pass). The general primitives — `move`,
27054
+ * `stop`, `goToPoint` — stay as first-class methods, not dictionary entries.
27055
+ *
27056
+ * NOTE (provider wiring): the first provider (Dreame) drives this with the RAW
27057
+ * `callAction(siid,aiid,in)` / `setProperty({siid,piid,value})` MIoT primitives
27058
+ * that the currently-published `@apocaliss92/nodedreame` already exposes on
27059
+ * every device handle. A future nodedreame publish adds a typed
27060
+ * `DreameCameraController` (drive / playPetSound / spotClean / findPet / …); the
27061
+ * provider can then swap the raw calls for the typed methods with no change to
27062
+ * THIS contract.
27063
+ */
27064
+ /**
27065
+ * A momentary drive nudge. The robot MOVES (no gimbal) for as long as the caller
27066
+ * keeps sending nudges (~1 Hz); an explicit `stop` (or letting the nudges lapse)
27067
+ * halts it.
27068
+ *
27069
+ * - `pan` — turn: negative = left, positive = right, 0 = straight.
27070
+ * - `tilt` — throttle: positive = forward, negative = spin / turn-around.
27071
+ * - `speed` — optional intensity hint [0, 1]; the provider may scale the drive
27072
+ * vector by it (drivers without proportional drive ignore it).
27073
+ *
27074
+ * `pan` / `tilt` are normalized [-1, 1]. Both optional so a caller can nudge one
27075
+ * axis alone; an all-undefined nudge is a no-op.
27076
+ */
27077
+ var NavigationMoveCommandSchema = object({
27078
+ pan: number().min(-1).max(1).optional(),
27079
+ tilt: number().min(-1).max(1).optional(),
27080
+ speed: number().min(0).max(1).optional()
27081
+ });
27082
+ /**
27083
+ * The enumerated discrete actions a navigation-capable robot can perform via
27084
+ * `runAction`. This is the CLOSED vocabulary; a given device advertises the
27085
+ * subset it supports through `listActions`. Sounds are NOT here — they go through
27086
+ * `playSound` (see the `sound` dictionary entries).
27087
+ */
27088
+ var NavigationActionIdSchema = _enum([
27089
+ "goHome",
27090
+ "locate",
27091
+ "spotClean",
27092
+ "findPet",
27093
+ "personFollow",
27094
+ "stop",
27095
+ "startClean",
27096
+ "pauseClean",
27097
+ "dockWash",
27098
+ "autoEmpty",
27099
+ "flashOn",
27100
+ "flashOff"
27101
+ ]);
27102
+ /** Whether a dictionary entry is a `runAction` action or a `playSound` sound. */
27103
+ var NavigationEntryKindSchema = _enum(["action", "sound"]);
27104
+ /**
27105
+ * One entry in the navigation action dictionary — the DATA-DRIVEN unit both the
27106
+ * native panel and the PTZ mimic render as a button.
27107
+ *
27108
+ * - `id` — stable id. For `kind:'action'` it is a {@link NavigationActionId}
27109
+ * (pass to `runAction`); for `kind:'sound'` it is a namespaced id
27110
+ * (`sound:meow`) whose `soundId` is passed to `playSound`.
27111
+ * - `icon` — icon HINT (lucide-style name; the UI maps it to its own set).
27112
+ * - `label` — operator-facing English label.
27113
+ * - `soundId` — wire sound id, present only on `kind:'sound'` entries.
27114
+ * - `enabled` — per-device FEATURE FLAG. `listActions` reports it so the UI /
27115
+ * PTZ render ONLY enabled entries. Data-driven: the provider
27116
+ * flips it from config, never by editing code.
27117
+ */
27118
+ var NavigationActionEntrySchema = object({
27119
+ id: string(),
27120
+ kind: NavigationEntryKindSchema,
27121
+ label: string(),
27122
+ icon: string(),
27123
+ /** Present only on `kind:'sound'` entries — the id to pass to `playSound`. */
27124
+ soundId: number().int().optional(),
27125
+ /** Per-device feature flag — render this entry only when true. */
27126
+ enabled: boolean()
27127
+ });
27128
+ /** Coordinates for `goToPoint` — a point on the robot's live map. */
27129
+ var NavigationPointSchema = object({
27130
+ x: number(),
27131
+ y: number()
27132
+ });
27133
+ /**
27134
+ * Per-device FEATURE-FLAG report for the general (non-dictionary) primitives.
27135
+ * The cap reports which are enabled so the UI / PTZ render only the controls
27136
+ * that are turned on for THIS device. Data-driven: the provider derives these
27137
+ * from config + probe, never hardcoded in the UI. The per-DICTIONARY-entry flags
27138
+ * live on {@link NavigationActionEntrySchema.enabled}; these gate the primitives
27139
+ * that are not dictionary entries.
27140
+ *
27141
+ * - `move` / `stop` — the momentary drive joystick.
27142
+ * - `goToPoint` — send-to-map-coordinate. Ships OFF on Dreame until the
27143
+ * map-coordinate plumbing is wired.
27144
+ * - `runAction` — the discrete action buttons (dictionary `kind:'action'`).
27145
+ * - `playSound` — the sound buttons (dictionary `kind:'sound'`).
27146
+ * - `light` — the on/off fill-light toggle (works anytime).
27147
+ * - `lightMode` — the auto/manual selector + manual level slider (a
27148
+ * camera-service control; needs an active stream).
27149
+ */
27150
+ var NavigationFeaturesSchema = object({
27151
+ move: boolean(),
27152
+ stop: boolean(),
27153
+ goToPoint: boolean(),
27154
+ runAction: boolean(),
27155
+ playSound: boolean(),
27156
+ light: boolean(),
27157
+ lightMode: boolean()
27158
+ });
27159
+ /** Light mode: `auto` lets the camera choose brightness; `manual` uses `level`. */
27160
+ var NavigationLightModeSchema = _enum(["auto", "manual"]);
27161
+ /**
27162
+ * Live navigation state so the UI can reflect what the robot is doing:
27163
+ * - `mode` — coarse activity (idle / cleaning / following / …).
27164
+ * - `following` — person/pet follow is currently armed.
27165
+ * - `flash` — the on-camera fill light is on.
27166
+ * - `lightMode` — auto vs manual fill-light mode.
27167
+ * - `lightLevel` — manual fill-light level (40..100); meaningful when
27168
+ * `lightMode === 'manual'`.
27169
+ */
27170
+ var NavigationStatusSchema = object({
27171
+ mode: _enum([
27172
+ "idle",
27173
+ "cleaning",
27174
+ "spot",
27175
+ "following",
27176
+ "goto",
27177
+ "returning",
27178
+ "paused",
27179
+ "unknown"
27180
+ ]),
27181
+ following: boolean(),
27182
+ flash: boolean(),
27183
+ lightMode: NavigationLightModeSchema,
27184
+ lightLevel: number().min(40).max(100),
27185
+ /** Ms epoch when the slice was last updated. */
27186
+ lastChangedAt: number()
27187
+ });
27188
+ NavigationStatusSchema.extend({ lastFetchedAt: number() });
27189
+ DeviceType.Camera, method(NavigationMoveCommandSchema.extend({ deviceId: number() }), _void(), { kind: "mutation" }), method(object({ deviceId: number() }), _void(), { kind: "mutation" }), method(NavigationPointSchema.extend({ deviceId: number() }), _void(), { kind: "mutation" }), method(object({ deviceId: number() }), array(NavigationActionEntrySchema)), method(object({
27190
+ deviceId: number(),
27191
+ actionId: NavigationActionIdSchema
27192
+ }), _void(), { kind: "mutation" }), method(object({
27193
+ deviceId: number(),
27194
+ soundId: number().int()
27195
+ }), _void(), { kind: "mutation" }), method(object({
27196
+ deviceId: number(),
27197
+ on: boolean()
27198
+ }), _void(), { kind: "mutation" }), method(object({
27199
+ deviceId: number(),
27200
+ mode: NavigationLightModeSchema,
27201
+ level: number().min(40).max(100).optional()
27202
+ }), _void(), { kind: "mutation" }), method(object({
27203
+ deviceId: number(),
27204
+ level: number().min(40).max(100)
27205
+ }), _void(), { kind: "mutation" }), method(object({ deviceId: number() }), NavigationFeaturesSchema), object({
27206
+ deviceId: number(),
27207
+ status: NavigationStatusSchema
27208
+ });
27006
27209
  DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, method(object({ deviceId: number().int().nonnegative() }), object({ success: literal(true) }), {
27007
27210
  kind: "mutation",
27008
27211
  auth: "admin"
@@ -32067,6 +32270,66 @@ Object.freeze({
32067
32270
  addonId: null,
32068
32271
  access: "create"
32069
32272
  },
32273
+ "navigation.getFeatures": {
32274
+ capName: "navigation",
32275
+ capScope: "device",
32276
+ addonId: null,
32277
+ access: "view"
32278
+ },
32279
+ "navigation.goToPoint": {
32280
+ capName: "navigation",
32281
+ capScope: "device",
32282
+ addonId: null,
32283
+ access: "create"
32284
+ },
32285
+ "navigation.listActions": {
32286
+ capName: "navigation",
32287
+ capScope: "device",
32288
+ addonId: null,
32289
+ access: "view"
32290
+ },
32291
+ "navigation.move": {
32292
+ capName: "navigation",
32293
+ capScope: "device",
32294
+ addonId: null,
32295
+ access: "create"
32296
+ },
32297
+ "navigation.playSound": {
32298
+ capName: "navigation",
32299
+ capScope: "device",
32300
+ addonId: null,
32301
+ access: "create"
32302
+ },
32303
+ "navigation.runAction": {
32304
+ capName: "navigation",
32305
+ capScope: "device",
32306
+ addonId: null,
32307
+ access: "create"
32308
+ },
32309
+ "navigation.setLightLevel": {
32310
+ capName: "navigation",
32311
+ capScope: "device",
32312
+ addonId: null,
32313
+ access: "create"
32314
+ },
32315
+ "navigation.setLightMode": {
32316
+ capName: "navigation",
32317
+ capScope: "device",
32318
+ addonId: null,
32319
+ access: "create"
32320
+ },
32321
+ "navigation.setLightOn": {
32322
+ capName: "navigation",
32323
+ capScope: "device",
32324
+ addonId: null,
32325
+ access: "create"
32326
+ },
32327
+ "navigation.stop": {
32328
+ capName: "navigation",
32329
+ capScope: "device",
32330
+ addonId: null,
32331
+ access: "create"
32332
+ },
32070
32333
  "networkAccess.getEndpoint": {
32071
32334
  capName: "network-access",
32072
32335
  capScope: "system",
@@ -36162,6 +36425,56 @@ Object.freeze({
36162
36425
  form: "single",
36163
36426
  optional: false
36164
36427
  }],
36428
+ "navigation.getFeatures": [{
36429
+ name: "deviceId",
36430
+ form: "single",
36431
+ optional: false
36432
+ }],
36433
+ "navigation.goToPoint": [{
36434
+ name: "deviceId",
36435
+ form: "single",
36436
+ optional: false
36437
+ }],
36438
+ "navigation.listActions": [{
36439
+ name: "deviceId",
36440
+ form: "single",
36441
+ optional: false
36442
+ }],
36443
+ "navigation.move": [{
36444
+ name: "deviceId",
36445
+ form: "single",
36446
+ optional: false
36447
+ }],
36448
+ "navigation.playSound": [{
36449
+ name: "deviceId",
36450
+ form: "single",
36451
+ optional: false
36452
+ }],
36453
+ "navigation.runAction": [{
36454
+ name: "deviceId",
36455
+ form: "single",
36456
+ optional: false
36457
+ }],
36458
+ "navigation.setLightLevel": [{
36459
+ name: "deviceId",
36460
+ form: "single",
36461
+ optional: false
36462
+ }],
36463
+ "navigation.setLightMode": [{
36464
+ name: "deviceId",
36465
+ form: "single",
36466
+ optional: false
36467
+ }],
36468
+ "navigation.setLightOn": [{
36469
+ name: "deviceId",
36470
+ form: "single",
36471
+ optional: false
36472
+ }],
36473
+ "navigation.stop": [{
36474
+ name: "deviceId",
36475
+ form: "single",
36476
+ optional: false
36477
+ }],
36165
36478
  "networkQuality.getDeviceStats": [{
36166
36479
  name: "deviceId",
36167
36480
  form: "single",
package/dist/addon.mjs CHANGED
@@ -5409,6 +5409,12 @@ Object.fromEntries([
5409
5409
  icon: "move",
5410
5410
  order: 40
5411
5411
  },
5412
+ {
5413
+ id: "navigation",
5414
+ label: "Navigation",
5415
+ icon: "compass",
5416
+ order: 41
5417
+ },
5412
5418
  {
5413
5419
  id: "consumables",
5414
5420
  label: "Consumables",
@@ -26976,6 +26982,203 @@ DeviceType.Camera, method(object({ deviceId: number() }), PtzAutotrackStatusSche
26976
26982
  deviceId: number(),
26977
26983
  status: PtzAutotrackStatusSchema
26978
26984
  });
26985
+ /**
26986
+ * `navigation` — a device-scoped capability that natively expresses the FULL
26987
+ * navigation / action surface of a robot that DRIVES ITSELF and carries an
26988
+ * on-board camera (the Dreame robot-vacuum camera is the first provider).
26989
+ *
26990
+ * Why a NEW cap rather than overloading `ptz`:
26991
+ * - `ptz` moves a *gimbal* on a fixed camera (pan/tilt/zoom of the lens). A
26992
+ * robot vacuum has no gimbal — the whole chassis drives, turns and spins.
26993
+ * The two are different physical models: PTZ is absolute-position + presets,
26994
+ * navigation is momentary drive nudges + discrete robot ACTIONS
26995
+ * (dock / spot-clean / follow-pet / go-to-point / …).
26996
+ * - This cap is the SOURCE OF TRUTH. Two consumers adapt from it rather than
26997
+ * the reverse:
26998
+ * 1. a native CamStack navigation panel (data-driven from `listActions`
26999
+ * / `getOptions`), and
27000
+ * 2. the PTZ surface — a thin adapter mimics `ptz` from `navigation` so a
27001
+ * robot camera shows up in the existing PTZ control path without every
27002
+ * PTZ provider learning about robots. The mapping lives in the adapter,
27003
+ * not here (see the addon design note):
27004
+ * ptz.continuousMove({pan,tilt}) → navigation.move({pan,tilt})
27005
+ * ptz.stop() → navigation.stop()
27006
+ * ptz.goHome() → navigation.runAction('goHome')
27007
+ * ptz.getPresets() → navigation.listActions() (id→preset)
27008
+ * ptz.goToPreset(id) → navigation.runAction(id)
27009
+ *
27010
+ * ## Continuous drive
27011
+ *
27012
+ * `move` is MOMENTARY. Fluid navigation comes from the UI (or the PTZ adapter)
27013
+ * sending `move({pan,tilt})` REPEATEDLY at ~1 Hz while a direction is held, and
27014
+ * one `stop()` on release — exactly like the robot app's remote-drive joystick.
27015
+ * The provider forwards EACH `move` to one drive write; it must NOT debounce or
27016
+ * coalesce them. The UI owns the cadence.
27017
+ *
27018
+ * ## The action dictionary
27019
+ *
27020
+ * The discrete controls (dock / locate / spot-clean / follow / flash / sounds)
27021
+ * are a DATA-DRIVEN dictionary the cap exposes via `listActions()`. Each entry
27022
+ * carries `{ id, kind, label, icon }` (plus `soundId` for sound entries) so the
27023
+ * native panel AND the PTZ mimic render buttons WITHOUT hardcoding a
27024
+ * vendor-specific list. `kind: 'action'` entries are triggered with
27025
+ * `runAction({ actionId })`; `kind: 'sound'` entries with `playSound({ soundId })`
27026
+ * (the entry carries the `soundId` to pass). The general primitives — `move`,
27027
+ * `stop`, `goToPoint` — stay as first-class methods, not dictionary entries.
27028
+ *
27029
+ * NOTE (provider wiring): the first provider (Dreame) drives this with the RAW
27030
+ * `callAction(siid,aiid,in)` / `setProperty({siid,piid,value})` MIoT primitives
27031
+ * that the currently-published `@apocaliss92/nodedreame` already exposes on
27032
+ * every device handle. A future nodedreame publish adds a typed
27033
+ * `DreameCameraController` (drive / playPetSound / spotClean / findPet / …); the
27034
+ * provider can then swap the raw calls for the typed methods with no change to
27035
+ * THIS contract.
27036
+ */
27037
+ /**
27038
+ * A momentary drive nudge. The robot MOVES (no gimbal) for as long as the caller
27039
+ * keeps sending nudges (~1 Hz); an explicit `stop` (or letting the nudges lapse)
27040
+ * halts it.
27041
+ *
27042
+ * - `pan` — turn: negative = left, positive = right, 0 = straight.
27043
+ * - `tilt` — throttle: positive = forward, negative = spin / turn-around.
27044
+ * - `speed` — optional intensity hint [0, 1]; the provider may scale the drive
27045
+ * vector by it (drivers without proportional drive ignore it).
27046
+ *
27047
+ * `pan` / `tilt` are normalized [-1, 1]. Both optional so a caller can nudge one
27048
+ * axis alone; an all-undefined nudge is a no-op.
27049
+ */
27050
+ var NavigationMoveCommandSchema = object({
27051
+ pan: number().min(-1).max(1).optional(),
27052
+ tilt: number().min(-1).max(1).optional(),
27053
+ speed: number().min(0).max(1).optional()
27054
+ });
27055
+ /**
27056
+ * The enumerated discrete actions a navigation-capable robot can perform via
27057
+ * `runAction`. This is the CLOSED vocabulary; a given device advertises the
27058
+ * subset it supports through `listActions`. Sounds are NOT here — they go through
27059
+ * `playSound` (see the `sound` dictionary entries).
27060
+ */
27061
+ var NavigationActionIdSchema = _enum([
27062
+ "goHome",
27063
+ "locate",
27064
+ "spotClean",
27065
+ "findPet",
27066
+ "personFollow",
27067
+ "stop",
27068
+ "startClean",
27069
+ "pauseClean",
27070
+ "dockWash",
27071
+ "autoEmpty",
27072
+ "flashOn",
27073
+ "flashOff"
27074
+ ]);
27075
+ /** Whether a dictionary entry is a `runAction` action or a `playSound` sound. */
27076
+ var NavigationEntryKindSchema = _enum(["action", "sound"]);
27077
+ /**
27078
+ * One entry in the navigation action dictionary — the DATA-DRIVEN unit both the
27079
+ * native panel and the PTZ mimic render as a button.
27080
+ *
27081
+ * - `id` — stable id. For `kind:'action'` it is a {@link NavigationActionId}
27082
+ * (pass to `runAction`); for `kind:'sound'` it is a namespaced id
27083
+ * (`sound:meow`) whose `soundId` is passed to `playSound`.
27084
+ * - `icon` — icon HINT (lucide-style name; the UI maps it to its own set).
27085
+ * - `label` — operator-facing English label.
27086
+ * - `soundId` — wire sound id, present only on `kind:'sound'` entries.
27087
+ * - `enabled` — per-device FEATURE FLAG. `listActions` reports it so the UI /
27088
+ * PTZ render ONLY enabled entries. Data-driven: the provider
27089
+ * flips it from config, never by editing code.
27090
+ */
27091
+ var NavigationActionEntrySchema = object({
27092
+ id: string(),
27093
+ kind: NavigationEntryKindSchema,
27094
+ label: string(),
27095
+ icon: string(),
27096
+ /** Present only on `kind:'sound'` entries — the id to pass to `playSound`. */
27097
+ soundId: number().int().optional(),
27098
+ /** Per-device feature flag — render this entry only when true. */
27099
+ enabled: boolean()
27100
+ });
27101
+ /** Coordinates for `goToPoint` — a point on the robot's live map. */
27102
+ var NavigationPointSchema = object({
27103
+ x: number(),
27104
+ y: number()
27105
+ });
27106
+ /**
27107
+ * Per-device FEATURE-FLAG report for the general (non-dictionary) primitives.
27108
+ * The cap reports which are enabled so the UI / PTZ render only the controls
27109
+ * that are turned on for THIS device. Data-driven: the provider derives these
27110
+ * from config + probe, never hardcoded in the UI. The per-DICTIONARY-entry flags
27111
+ * live on {@link NavigationActionEntrySchema.enabled}; these gate the primitives
27112
+ * that are not dictionary entries.
27113
+ *
27114
+ * - `move` / `stop` — the momentary drive joystick.
27115
+ * - `goToPoint` — send-to-map-coordinate. Ships OFF on Dreame until the
27116
+ * map-coordinate plumbing is wired.
27117
+ * - `runAction` — the discrete action buttons (dictionary `kind:'action'`).
27118
+ * - `playSound` — the sound buttons (dictionary `kind:'sound'`).
27119
+ * - `light` — the on/off fill-light toggle (works anytime).
27120
+ * - `lightMode` — the auto/manual selector + manual level slider (a
27121
+ * camera-service control; needs an active stream).
27122
+ */
27123
+ var NavigationFeaturesSchema = object({
27124
+ move: boolean(),
27125
+ stop: boolean(),
27126
+ goToPoint: boolean(),
27127
+ runAction: boolean(),
27128
+ playSound: boolean(),
27129
+ light: boolean(),
27130
+ lightMode: boolean()
27131
+ });
27132
+ /** Light mode: `auto` lets the camera choose brightness; `manual` uses `level`. */
27133
+ var NavigationLightModeSchema = _enum(["auto", "manual"]);
27134
+ /**
27135
+ * Live navigation state so the UI can reflect what the robot is doing:
27136
+ * - `mode` — coarse activity (idle / cleaning / following / …).
27137
+ * - `following` — person/pet follow is currently armed.
27138
+ * - `flash` — the on-camera fill light is on.
27139
+ * - `lightMode` — auto vs manual fill-light mode.
27140
+ * - `lightLevel` — manual fill-light level (40..100); meaningful when
27141
+ * `lightMode === 'manual'`.
27142
+ */
27143
+ var NavigationStatusSchema = object({
27144
+ mode: _enum([
27145
+ "idle",
27146
+ "cleaning",
27147
+ "spot",
27148
+ "following",
27149
+ "goto",
27150
+ "returning",
27151
+ "paused",
27152
+ "unknown"
27153
+ ]),
27154
+ following: boolean(),
27155
+ flash: boolean(),
27156
+ lightMode: NavigationLightModeSchema,
27157
+ lightLevel: number().min(40).max(100),
27158
+ /** Ms epoch when the slice was last updated. */
27159
+ lastChangedAt: number()
27160
+ });
27161
+ NavigationStatusSchema.extend({ lastFetchedAt: number() });
27162
+ DeviceType.Camera, method(NavigationMoveCommandSchema.extend({ deviceId: number() }), _void(), { kind: "mutation" }), method(object({ deviceId: number() }), _void(), { kind: "mutation" }), method(NavigationPointSchema.extend({ deviceId: number() }), _void(), { kind: "mutation" }), method(object({ deviceId: number() }), array(NavigationActionEntrySchema)), method(object({
27163
+ deviceId: number(),
27164
+ actionId: NavigationActionIdSchema
27165
+ }), _void(), { kind: "mutation" }), method(object({
27166
+ deviceId: number(),
27167
+ soundId: number().int()
27168
+ }), _void(), { kind: "mutation" }), method(object({
27169
+ deviceId: number(),
27170
+ on: boolean()
27171
+ }), _void(), { kind: "mutation" }), method(object({
27172
+ deviceId: number(),
27173
+ mode: NavigationLightModeSchema,
27174
+ level: number().min(40).max(100).optional()
27175
+ }), _void(), { kind: "mutation" }), method(object({
27176
+ deviceId: number(),
27177
+ level: number().min(40).max(100)
27178
+ }), _void(), { kind: "mutation" }), method(object({ deviceId: number() }), NavigationFeaturesSchema), object({
27179
+ deviceId: number(),
27180
+ status: NavigationStatusSchema
27181
+ });
26979
27182
  DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, method(object({ deviceId: number().int().nonnegative() }), object({ success: literal(true) }), {
26980
27183
  kind: "mutation",
26981
27184
  auth: "admin"
@@ -32040,6 +32243,66 @@ Object.freeze({
32040
32243
  addonId: null,
32041
32244
  access: "create"
32042
32245
  },
32246
+ "navigation.getFeatures": {
32247
+ capName: "navigation",
32248
+ capScope: "device",
32249
+ addonId: null,
32250
+ access: "view"
32251
+ },
32252
+ "navigation.goToPoint": {
32253
+ capName: "navigation",
32254
+ capScope: "device",
32255
+ addonId: null,
32256
+ access: "create"
32257
+ },
32258
+ "navigation.listActions": {
32259
+ capName: "navigation",
32260
+ capScope: "device",
32261
+ addonId: null,
32262
+ access: "view"
32263
+ },
32264
+ "navigation.move": {
32265
+ capName: "navigation",
32266
+ capScope: "device",
32267
+ addonId: null,
32268
+ access: "create"
32269
+ },
32270
+ "navigation.playSound": {
32271
+ capName: "navigation",
32272
+ capScope: "device",
32273
+ addonId: null,
32274
+ access: "create"
32275
+ },
32276
+ "navigation.runAction": {
32277
+ capName: "navigation",
32278
+ capScope: "device",
32279
+ addonId: null,
32280
+ access: "create"
32281
+ },
32282
+ "navigation.setLightLevel": {
32283
+ capName: "navigation",
32284
+ capScope: "device",
32285
+ addonId: null,
32286
+ access: "create"
32287
+ },
32288
+ "navigation.setLightMode": {
32289
+ capName: "navigation",
32290
+ capScope: "device",
32291
+ addonId: null,
32292
+ access: "create"
32293
+ },
32294
+ "navigation.setLightOn": {
32295
+ capName: "navigation",
32296
+ capScope: "device",
32297
+ addonId: null,
32298
+ access: "create"
32299
+ },
32300
+ "navigation.stop": {
32301
+ capName: "navigation",
32302
+ capScope: "device",
32303
+ addonId: null,
32304
+ access: "create"
32305
+ },
32043
32306
  "networkAccess.getEndpoint": {
32044
32307
  capName: "network-access",
32045
32308
  capScope: "system",
@@ -36135,6 +36398,56 @@ Object.freeze({
36135
36398
  form: "single",
36136
36399
  optional: false
36137
36400
  }],
36401
+ "navigation.getFeatures": [{
36402
+ name: "deviceId",
36403
+ form: "single",
36404
+ optional: false
36405
+ }],
36406
+ "navigation.goToPoint": [{
36407
+ name: "deviceId",
36408
+ form: "single",
36409
+ optional: false
36410
+ }],
36411
+ "navigation.listActions": [{
36412
+ name: "deviceId",
36413
+ form: "single",
36414
+ optional: false
36415
+ }],
36416
+ "navigation.move": [{
36417
+ name: "deviceId",
36418
+ form: "single",
36419
+ optional: false
36420
+ }],
36421
+ "navigation.playSound": [{
36422
+ name: "deviceId",
36423
+ form: "single",
36424
+ optional: false
36425
+ }],
36426
+ "navigation.runAction": [{
36427
+ name: "deviceId",
36428
+ form: "single",
36429
+ optional: false
36430
+ }],
36431
+ "navigation.setLightLevel": [{
36432
+ name: "deviceId",
36433
+ form: "single",
36434
+ optional: false
36435
+ }],
36436
+ "navigation.setLightMode": [{
36437
+ name: "deviceId",
36438
+ form: "single",
36439
+ optional: false
36440
+ }],
36441
+ "navigation.setLightOn": [{
36442
+ name: "deviceId",
36443
+ form: "single",
36444
+ optional: false
36445
+ }],
36446
+ "navigation.stop": [{
36447
+ name: "deviceId",
36448
+ form: "single",
36449
+ optional: false
36450
+ }],
36138
36451
  "networkQuality.getDeviceStats": [{
36139
36452
  name: "deviceId",
36140
36453
  form: "single",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-notifiers",
3
- "version": "1.2.74",
3
+ "version": "1.2.76",
4
4
  "description": "System notifiers addon for CamStack — a `notification-output` collection provider hosting per-kind notifier adapters (ntfy, pushover, gotify, telegram, discord, webhook, zentik).",
5
5
  "keywords": [
6
6
  "camstack",