@mega-yfue/eufy-sdk 0.5.0-beta.7 → 0.5.0-beta.71

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 (60) hide show
  1. package/dist/client/device-registry.d.ts +24 -2
  2. package/dist/client/eufy-mega.d.ts +83 -10
  3. package/dist/client/types.d.ts +1 -1
  4. package/dist/core/contracts.d.ts +71 -30
  5. package/dist/core/store.d.ts +4 -0
  6. package/dist/core/types.d.ts +2 -0
  7. package/dist/index.js +3611 -603
  8. package/dist/index.js.map +4 -4
  9. package/dist/model/capabilities/arming.d.ts +39 -4
  10. package/dist/model/capabilities/camera.d.ts +24 -10
  11. package/dist/model/capabilities/dp-catalog.d.ts +4 -3
  12. package/dist/model/capabilities/index.d.ts +16 -3
  13. package/dist/model/capabilities/light.d.ts +3 -0
  14. package/dist/model/capabilities/lock.d.ts +21 -7
  15. package/dist/model/capabilities/motion.d.ts +5 -0
  16. package/dist/model/capabilities/mower.d.ts +230 -0
  17. package/dist/model/capabilities/rtsp.d.ts +16 -3
  18. package/dist/model/capabilities/smart-drop.d.ts +20 -0
  19. package/dist/model/capabilities/suction.d.ts +5 -5
  20. package/dist/model/capabilities/types.d.ts +10 -0
  21. package/dist/model/capabilities/vacuum-clean.d.ts +19 -13
  22. package/dist/model/classify.d.ts +1 -2
  23. package/dist/model/device-family.d.ts +8 -0
  24. package/dist/model/param-dictionary.d.ts +6 -0
  25. package/dist/model/param-namespace.d.ts +1 -1
  26. package/dist/model/registry.d.ts +3 -2
  27. package/dist/model/types.d.ts +26 -12
  28. package/dist/transport/abortable.d.ts +8 -0
  29. package/dist/transport/http/mega-client.d.ts +34 -2
  30. package/dist/transport/mqtt/broker-discovery.d.ts +2 -1
  31. package/dist/transport/mqtt/command-router.d.ts +3 -2
  32. package/dist/transport/p2p/codec.d.ts +16 -0
  33. package/dist/transport/p2p/command-router.d.ts +27 -35
  34. package/dist/transport/p2p/fmp4.d.ts +12 -2
  35. package/dist/transport/p2p/live-trace.d.ts +11 -2
  36. package/dist/transport/p2p/p2p-session.d.ts +59 -12
  37. package/dist/transport/p2p/readable-egress.d.ts +4 -0
  38. package/dist/transport/p2p/recording-download.d.ts +4 -3
  39. package/dist/transport/p2p/shared-live-source.d.ts +27 -13
  40. package/dist/transport/p2p/talkback.d.ts +21 -10
  41. package/dist/transport/p2p/video.d.ts +2 -0
  42. package/dist/transport/rtc/call-live.d.ts +41 -0
  43. package/dist/transport/rtc/command-router.d.ts +141 -0
  44. package/dist/transport/rtc/live.d.ts +69 -0
  45. package/dist/transport/rtc/peer.d.ts +122 -0
  46. package/dist/transport/rtc/portal-keepalive.d.ts +11 -0
  47. package/dist/transport/rtc/portal-packet.d.ts +72 -0
  48. package/dist/transport/rtc/ptcs-framer.d.ts +86 -0
  49. package/dist/transport/rtc/scall-sdp.d.ts +50 -0
  50. package/dist/transport/rtc/session.d.ts +95 -0
  51. package/dist/transport/rtc/signaling.d.ts +139 -0
  52. package/dist/transport/token-echo.d.ts +8 -0
  53. package/dist/transport/tuya/account.d.ts +8 -5
  54. package/dist/transport/tuya/client.d.ts +19 -5
  55. package/dist/transport/tuya/command-router.d.ts +10 -14
  56. package/dist/transport/tuya/dp-codec.d.ts +2 -23
  57. package/dist/transport/tuya/et3.d.ts +22 -0
  58. package/dist/transport/tuya/request.d.ts +18 -8
  59. package/dist/transport/tuya/sign.d.ts +7 -0
  60. package/package.json +2 -1
@@ -76,10 +76,13 @@ export declare const ARMING_CMD: {
76
76
  * The ENCRYPTION LEVEL is the session's to pick (`"auto"`), not this command's: the T8030 the envelope
77
77
  * was captured on holds a level-2 key and seals it level-2, while an own-session camera that never
78
78
  * negotiates one carries the same envelope level-1. See `armingCommand`.
79
+ *
80
+ * A T8410C takes the mode as a direct frame instead of this envelope; see {@link DIRECT_ARMING_MODELS}.
79
81
  */
80
82
  readonly SET_ARMING: 1224;
81
83
  /**
82
- * The per-mode alarm/arm-delay configuration write. ✅ WIRE CAPTURED live on a T8030 (
84
+ * One guard mode's per-device action table (app `CMD_SET_ALL_ACTION`), which carries the alarm delays
85
+ * and each device's actions in that mode. ✅ WIRE CAPTURED live on a T8030 (
83
86
  * 2026-07-23, both directions): a **bare
84
87
  * JSON frame, no `1350`/`1700` envelope** — outer P2P cmd IS `1255` itself, station channel 255,
85
88
  * plaintext `{account_id, count_down_alarm:{channel_list,delay_time},
@@ -96,15 +99,26 @@ export declare const ARMING_CMD: {
96
99
  * corresponding GET command (`1310`/inner cmd `40003`, sent by the app right before editing) always
97
100
  * replied `{count:0,data:null}` in every capture — genuinely empty, not a decrypt failure (confirmed
98
101
  * via the same bidirectional decrypt this finding used) — so the app does NOT read the current
99
- * config this way; how it does is still unknown. Without a working GET, safely PATCHING just one
100
- * channel in or out of an existing list isn't possible without risking clobbering the rest — so
102
+ * config this way; a T8010 reports it on its own params instead, see below. Without a working GET,
103
+ * safely PATCHING just one channel in or out of an existing list isn't possible without risking
104
+ * clobbering the rest — so
101
105
  * this ships as a caller-supplies-everything write instead of guessing a merge.
102
106
  * `devices`/`siren_sensor_action` are even less understood (raw per-device action codes, meaning
103
107
  * unconfirmed) and MUST come from a value independently read/captured for the target mode —
104
108
  * see `AlarmDelayConfig`'s field docs.
109
+ *
110
+ * ✅ On a T8010 the app writes the same command for the Device Control screen: header channel 0, the
111
+ * whole table of the mode `{mode_id, devices, count_down_alarm, count_down_arm}`, acked by an all-zero
112
+ * 1255 reply. The T8010 reports each table on its own params, Home on 1157 and Away on 1158, and the
113
+ * reported table follows a write within 15 s. See {@link DEVICE_NOTIFY_FLAG}.
105
114
  */
106
- readonly ALARM_DELAY_CONFIG: 1255;
115
+ readonly SET_ALL_ACTION: 1255;
107
116
  };
117
+ /**
118
+ * The guard modes whose device notification is read and written. Home and away are replayed on a T8010;
119
+ * `custom1` (wire 3) is captured on a T8170, whose own params report it on 1148.
120
+ */
121
+ export type DeviceNotificationMode = Extract<ArmingMode, "home" | "away" | "custom1">;
108
122
  /**
109
123
  * Alarm-delay durations the app's OWN picker UI offers — `AlarmDelaySeconds` is both the const
110
124
  * value-object (`AlarmDelaySeconds.sec45`) and the union type of its values, so callers pass the
@@ -225,6 +239,27 @@ export declare const ARMING_MEMBERS: {
225
239
  * would be the same unverified guess `setMode` refuses.
226
240
  */
227
241
  readonly setAlarmDelayConfig: import("./members.js").MethodMember<(mode: AlarmDelayMode, config: AlarmDelayConfig) => Promise<void>>;
242
+ /**
243
+ * Whether the device on `channel` sends a push notification in `mode`: its {@link DEVICE_NOTIFY_FLAG}
244
+ * in the action table the station reports for that mode. `undefined` where the station reports no table
245
+ * or the table does not list `channel`. A standalone camera answers from its own 1225/1239/1148 flags,
246
+ * for its own channel only. A device's channel is `EufyDevice.channel`.
247
+ */
248
+ readonly deviceNotification: import("./members.js").MethodMember<(mode: DeviceNotificationMode, channel: number) => boolean | undefined> & {
249
+ available: (ctx: CommandContext) => boolean;
250
+ };
251
+ /**
252
+ * Turn the push notification of the device on `channel` on or off in `mode` (cmd
253
+ * {@link ARMING_CMD.SET_ALL_ACTION}): the station's reported table written back with that one flag
254
+ * changed. A standalone camera is sent a one-entry `{mode_id, devices}` table built from its own flags,
255
+ * for its own channel only. Rejects, sending nothing, where the table does not list `channel`. A write
256
+ * builds on the last one sent for that mode until the device reports a table (`${mode}Action` on a
257
+ * standalone camera) observed 15 s after it, so a second write does not revert it; a write whose dispatch
258
+ * rejects is not built on.
259
+ */
260
+ readonly setDeviceNotification: import("./members.js").MethodMember<(mode: DeviceNotificationMode, channel: number, on: boolean) => Promise<void>> & {
261
+ available: (ctx: CommandContext) => boolean;
262
+ };
228
263
  };
229
264
  /**
230
265
  * `arming` — guard/arming mode. `armingMode` (see {@link ARMING_CMD.SET_ARMING}) has a verified read/write
@@ -8,6 +8,8 @@ import { type Command, type MediaProvider } from "../../core/contracts.js";
8
8
  * `transport/p2p/commands.ts`). Each entry notes its app `CommandType` name.
9
9
  */
10
10
  export declare const CAMERA_CMD: {
11
+ /** Camera-reported Wi-Fi signal (app `CMD_GET_WIFI_RSSI`). */
12
+ readonly WIFI_RSSI: 1142;
11
13
  /** Camera on/off. Read and write polarity depend on the family and topology. */
12
14
  readonly CAMERA_ENABLE: 1035;
13
15
  /** Wrapped T8410 power switch on HomeBase 3. */
@@ -271,6 +273,14 @@ export type CameraActions = Surface<typeof CAMERA_MEMBERS> & {
271
273
  * @internal
272
274
  */
273
275
  export declare const CAMERA_MEMBERS: {
276
+ /** Reads the latest cached report and exposes no setter. */
277
+ readonly wifiRssi: {
278
+ readonly param: 1142;
279
+ readonly type: "number";
280
+ readonly kind: "scalar";
281
+ readonly provenance: "apk";
282
+ readonly description: "Camera-reported Wi-Fi signal; physical units and a quality scale are unspecified.";
283
+ };
274
284
  /**
275
285
  * The default READ is the *disable*-bit convention (1035 "0" ⇒ ON, 2001 direct); the WRITE polarity is
276
286
  * family-dependent — see `powerValue` / `isEnableBitPolarity`. Battery/solo cams report the state under
@@ -435,25 +445,29 @@ export declare const CAMERA_MEMBERS: {
435
445
  * Live-view quality, the pair to {@link CAMERA_MEMBERS.recordingQuality} and a different setting on a
436
446
  * different wire: changing one leaves the other's parameter untouched.
437
447
  *
438
- * The READ is 1020, which reports the resolved tier as a plain integer. 1020 is also the name the
439
- * param dictionary already gives that id, and `Device` keys state by NAME — a member claiming 2730
440
- * under this name would collide with it on a device reporting both.
448
+ * The READ is 1020, which reports the resolved tier as a plain integer, while the WRITE rides 2730's
449
+ * `1350` payload. They are two ids for one setting because 2730 carries a per-mode config and 1020
450
+ * carries the tier in force; the tier is what this property means. 1020 is also the name the param
451
+ * dictionary already gives that id, and `Device` keys state by NAME — a member claiming 2730 under
452
+ * this name would collide with it on a device reporting both.
441
453
  *
442
- * `unverified: true` with no `write`: the app's 2730 frame is captured byte-exact, but replaying it
443
- * from this SDK produced no observable change on a standalone T8171, where the recording sibling's
444
- * 2731 write on the same envelope and the same session does land. The one difference the capture
445
- * shows is that the app's frame carries no `mChannel`/`mValue3`, which this envelope always emits.
446
- * Until a send is confirmed, the setter is absent — a control that silently does nothing is worse
447
- * than none — and the read ships ahead of it, which verification per direction allows.
454
+ * `transaction` is part of the frame that was captured, so it is sent. The recording sibling's own
455
+ * confirmed frame carries no such field; neither is inferred from the other.
448
456
  */
449
457
  readonly streamingQuality: {
458
+ readonly accepts: StreamingQualityName;
450
459
  readonly param: 1020;
451
460
  readonly type: "number";
452
461
  readonly kind: "enum";
453
462
  readonly enumValues: Readonly<Record<number, string>>;
454
463
  readonly provenance: "verified";
455
- readonly unverified: true;
464
+ readonly args: readonly [{
465
+ readonly name: "quality";
466
+ readonly kind: "enum";
467
+ readonly description: "A tier, or the name it maps to. 0 is Auto.";
468
+ }];
456
469
  readonly description: string;
470
+ readonly write: (v: string | number | boolean, ctx: CommandContext) => Command | undefined;
457
471
  };
458
472
  /**
459
473
  * `type` is how the value is STORED, and 2731 stores the whole config — the ACTIVE tier is lifted out
@@ -15,10 +15,11 @@
15
15
  /** The parsed DP capability catalog for one product SKU. */
16
16
  export interface DpCatalog {
17
17
  /**
18
- * For enum-type DPs: the valid integer values as declared in the catalog.
19
- * Absent for non-enum DPs (bool, raw, integer, string).
18
+ * For enum-type DPs: the range members exactly as the catalog lists them, as strings — value names
19
+ * (`"Quiet"`) or numeric strings (`"0"`), whichever the SKU's catalog uses. What a member means is
20
+ * the reading capability's to decide. Absent for non-enum DPs (bool, raw, integer, string).
20
21
  */
21
- readonly enumRanges: ReadonlyMap<number, readonly number[]>;
22
+ readonly enumRanges: ReadonlyMap<number, readonly string[]>;
22
23
  }
23
24
  /** Returned whenever the API call fails or the response shape is not recognised. */
24
25
  export declare const EMPTY_DP_CATALOG: DpCatalog;
@@ -42,8 +42,11 @@ import type { VacuumCleanActions } from "./vacuum-clean.js";
42
42
  import type { VacuumDockActions } from "./vacuum-dock.js";
43
43
  import type { DisplayActions } from "./display.js";
44
44
  import type { SuctionActions } from "./suction.js";
45
+ import type { MowerActions } from "./mower.js";
45
46
  import type { LocateActions } from "./locate.js";
47
+ import type { SmartDropActions } from "./smart-drop.js";
46
48
  import type { DeviceInfo } from "./info.js";
49
+ import type { CusPushAlarmType } from "../push-events.js";
47
50
  /**
48
51
  * Look up the {@link CapabilityModule} for a capability, or `undefined` if none is registered.
49
52
  * @internal
@@ -296,9 +299,13 @@ export interface DeviceEventMap {
296
299
  * can be known about a value nothing pushes.
297
300
  */
298
301
  cameraEnabledChanged: PushSemanticEvent;
299
- /** Station alarm lifecycle; `phase` says whether it fired or is counting down. */
302
+ /**
303
+ * Station alarm lifecycle; `phase` says whether it fired, is counting down, or was stopped. `type` is
304
+ * the push's alarm source or stop reason, absent when the push carried none.
305
+ */
300
306
  alarm: PushSemanticEvent & {
301
- phase?: "triggered" | "delayed";
307
+ phase?: "triggered" | "delayed" | "stopped";
308
+ type?: CusPushAlarmType;
302
309
  };
303
310
  /** Lock (un)locked or a lock alarm fired. */
304
311
  lockState: PushSemanticEvent;
@@ -421,8 +428,12 @@ export interface DeviceActionMap {
421
428
  vacuumDock: VacuumDockActions;
422
429
  /** RoboVac suction: `level`, `boostIq`, `supportedLevels`; `setSuctionLevel`, `setBoostIq`. */
423
430
  suction: SuctionActions;
431
+ /** Robot mower (read-only): `battery`, `cutHeight`, `network`, `wifiSignal`, wear timers and settings. No write is captured. */
432
+ mower: MowerActions;
424
433
  /** RoboVac locate (find-robot beep): `locating`; `locate(on?)`. */
425
434
  locate: LocateActions;
435
+ /** SmartDrop parcel box: `openLid()`. */
436
+ smartDrop: SmartDropActions;
426
437
  /** Smart Display (read-only): `battery`. No display write is captured. */
427
438
  display: DisplayActions;
428
439
  /** Identity metadata (read-only): `{ manufacturer, model, serialNumber, name, deviceType?, firmwareVersion?, hardwareVersion? }`. */
@@ -516,7 +527,7 @@ export type { ActionSpec } from "./types.js";
516
527
  * `undefined` for an action nothing describes.
517
528
  */
518
529
  export { actionSpecOf } from "./access.js";
519
- export type { PtzActions, LightActions, SmartLightActions, RgbColor, CameraActions, LockActions, SirenActions, ArmingActions, BatteryActions, MotionActions, ContactActions, LeakActions, SmokeActions, CoActions, KeypadActions, RtspActions, VacuumCleanActions, SuctionActions, LocateActions, };
530
+ export type { PtzActions, LightActions, SmartLightActions, RgbColor, CameraActions, LockActions, SirenActions, ArmingActions, BatteryActions, MotionActions, ContactActions, LeakActions, SmokeActions, CoActions, KeypadActions, RtspActions, VacuumCleanActions, SuctionActions, MowerActions, LocateActions, SmartDropActions, };
520
531
  /**
521
532
  * The member table each `*Actions` type is DERIVED from (`LockActions = Surface<typeof LOCK_MEMBERS>`),
522
533
  * so the type names the table and the table is part of the published surface.
@@ -541,10 +552,12 @@ export { MOTION_MEMBERS } from "./motion.js";
541
552
  export { PTZ_MEMBERS } from "./ptz.js";
542
553
  export { RTSP_MEMBERS } from "./rtsp.js";
543
554
  export { SIREN_MEMBERS } from "./siren.js";
555
+ export { SMART_DROP_MEMBERS } from "./smart-drop.js";
544
556
  export { SMART_LIGHT_MEMBERS } from "./smart-light.js";
545
557
  export { SMOKE_MEMBERS } from "./smoke.js";
546
558
  export { DISPLAY_MEMBERS, type DisplayActions } from "./display.js";
547
559
  export { SUCTION_MEMBERS } from "./suction.js";
560
+ export { MOWER_MEMBERS } from "./mower.js";
548
561
  export { VACUUM_CLEAN_MEMBERS } from "./vacuum-clean.js";
549
562
  export type { DeviceInfo } from "./info.js";
550
563
  export type { AutoSpotlightOptions } from "./light.js";
@@ -160,6 +160,9 @@ export declare const LIGHT_MEMBERS: {
160
160
  * This is the switch a user changes and expects to STAY changed. {@link isOn} is a different fact:
161
161
  * the lamp being lit right now, driven by whichever
162
162
  * client is streaming — the vendor app lights it for a live view and drops it on quitting.
163
+ *
164
+ * The T8423 write takes the session-chosen level; level-1 int+string was verified live on a standalone
165
+ * unit.
163
166
  */
164
167
  readonly spotlightEnabled: {
165
168
  readonly param: 1403;
@@ -1,6 +1,6 @@
1
1
  import { type Surface } from "./members.js";
2
2
  import type { AvailabilityContext, CapabilityModule, CommandContext } from "./types.js";
3
- import type { Command, AutoLockSnapshot } from "../../core/contracts.js";
3
+ import type { Command, AutoLockSnapshot, MediaProvider } from "../../core/contracts.js";
4
4
  /**
5
5
  * Setting-id selectors for the compact `ff09-setting-toggle` write — this capability's OWN wire
6
6
  * vocabulary, named not inlined per the capability wire-id convention, so `setRainMode`
@@ -107,10 +107,14 @@ export declare const LOCK_MEMBERS: {
107
107
  readonly provenance: "verified";
108
108
  readonly description: "Lock signal strength (verified: param 1141 = RSSI).";
109
109
  };
110
- /** Lock the deadbolt/door. Fire-and-forget — rejects only on missing member identity, never on a device timeout. */
111
- readonly lock: import("./members.js").MethodMember<() => Promise<void>>;
112
- /** Unlock the deadbolt/door. Fire-and-forget — rejects only on missing member identity. */
113
- readonly unlock: import("./members.js").MethodMember<() => Promise<void>>;
110
+ /** Lock the deadbolt/door. Resolves after sending; does not confirm physical state. */
111
+ readonly lock: import("./members.js").MethodMember<() => Promise<void>> & {
112
+ available: (ctx: CommandContext) => boolean;
113
+ };
114
+ /** Unlock the deadbolt/door. Resolves after sending; does not confirm physical state. */
115
+ readonly unlock: import("./members.js").MethodMember<() => Promise<void>> & {
116
+ available: (ctx: CommandContext) => boolean;
117
+ };
114
118
  /**
115
119
  * Read-modify-write the auto-lock setting: the transport GETs the device's current settings, changes
116
120
  * only `enabled` (+ `delaySeconds` if given — otherwise the current delay is preserved), and writes the
@@ -120,7 +124,9 @@ export declare const LOCK_MEMBERS: {
120
124
  * **Unlike `lock`/`unlock` this can reject on a device TIMEOUT**, not just missing identity — the GET
121
125
  * step is a genuine precondition, so this one is not fire-and-forget.
122
126
  */
123
- readonly setAutoLock: import("./members.js").MethodMember<(enabled: boolean, delaySeconds?: number) => Promise<void>>;
127
+ readonly setAutoLock: import("./members.js").MethodMember<(enabled: boolean, delaySeconds?: number) => Promise<void>> & {
128
+ available: (ctx: CommandContext) => boolean;
129
+ };
124
130
  /**
125
131
  * Toggle Rain Mode — a pure blind write, unlike `setAutoLock`: the compact frame carries only this one
126
132
  * field, so there is no GET pass and it is fire-and-forget. Confirmed on-device end-to-end in both
@@ -220,6 +226,14 @@ export declare const LOCK_MEMBERS: {
220
226
  readonly description: "One-touch rear locking (setting-id 11). Wire shape confirmed in the app's own JS, NOT captured.";
221
227
  readonly write: (v: string | number | boolean, ctx: CommandContext) => Command;
222
228
  };
229
+ /** Read the current device-reported state; undefined means no settled locked/unlocked state. */
230
+ readonly refreshStatus: {
231
+ readonly needs: "media";
232
+ readonly provided: (provider: MediaProvider, deps: import("./members.js").MemberDeps) => (() => Promise<boolean | undefined>) | undefined;
233
+ readonly description: string;
234
+ readonly requiredCapabilities?: readonly import("../types.js").Capability[];
235
+ readonly answers: true;
236
+ };
223
237
  /**
224
238
  * Read the device's current auto-lock settings via a live `GET_SETTINGS` round-trip — the SAME read
225
239
  * `setAutoLock` does internally, exposed standalone with no write attached. Works over BOTH transports.
@@ -230,7 +244,7 @@ export declare const LOCK_MEMBERS: {
230
244
  */
231
245
  readonly getAutoLockState: {
232
246
  readonly needs: "ff09Settings";
233
- readonly provided: (provider: import("../../core/contracts.js").Ff09SettingsReader, deps: import("./members.js").MemberDeps) => () => Promise<AutoLockSnapshot>;
247
+ readonly provided: (provider: import("../../core/contracts.js").Ff09SettingsReader, deps: import("./members.js").MemberDeps) => (() => Promise<AutoLockSnapshot>) | undefined;
234
248
  readonly description: string;
235
249
  readonly requiredCapabilities?: readonly import("../types.js").Capability[];
236
250
  readonly answers: true;
@@ -271,6 +271,10 @@ export declare const MOTION_MEMBERS: {
271
271
  * The raw sensitivity an indoor camera reports, on the one id whose write takes a `1700` control
272
272
  * payload carrying an index rather than the `1350` envelope its siblings use — a frame-shape
273
273
  * difference `sensitivityCommand` resolves from the scale. `unexposed` like its three siblings.
274
+ *
275
+ * Some devices report 6041 as a base64 JSON list of per-sensor entries
276
+ * (`{"list":[{"sensor_id":…,"sensitivity":…}]}`) rather than a scalar. That value is stored verbatim
277
+ * and this getter answers `undefined` for it: only the scalar form is confirmed to be this step.
274
278
  */
275
279
  readonly indoorSensitivity: {
276
280
  readonly param: 6041;
@@ -279,6 +283,7 @@ export declare const MOTION_MEMBERS: {
279
283
  readonly provenance: "verified";
280
284
  readonly unexposed: true;
281
285
  readonly description: "Raw sensitivity an indoor camera reports (verified: param 6041).";
286
+ readonly decode: (raw: unknown) => number | undefined;
282
287
  };
283
288
  /**
284
289
  * The raw sensitivity on the INVERTED seven-step camera scale — a HIGHER number is LESS sensitive, so
@@ -0,0 +1,230 @@
1
+ import { type Surface } from "./members.js";
2
+ import type { CapabilityModule } from "./types.js";
3
+ /**
4
+ * Robot-mower Tuya **DP ids** — the E15's Tuya product schema (`thing.m.device.ref.info.list` v5.4,
5
+ * `schemaInfo.schema`, product `bvxrcjxom787vnit`), each id also reported by a live E15. The product
6
+ * is built on Tuya's robot-vacuum template, so ids below 101 carry that template's codes; the mower's
7
+ * own data points are 101-146.
8
+ *
9
+ * Only scalar data points are named here. The Raw ones (`robot_status` 107, `battery_status` 108,
10
+ * `map_info` 113, the `*_control` commands 103-106, …) are protobuf messages whose field layout no
11
+ * source in hand states, and 102 (`device_infomation`) and 142 (`gps_info`) carry the device's network
12
+ * identity and position.
13
+ * @internal
14
+ */
15
+ export declare const MOWER_DP: {
16
+ readonly BATTERY: 8;
17
+ readonly VOLUME: 26;
18
+ readonly CHILD_LOCK: 47;
19
+ readonly RAIN_AUTO_RETURN: 101;
20
+ readonly WIFI_SIGNAL: 109;
21
+ readonly MOW_HEIGHT: 110;
22
+ readonly SAVE_MAP_PROGRESS: 118;
23
+ readonly STATION_USED_TIME: 125;
24
+ readonly BLADE_USED_TIME: 126;
25
+ readonly EDGE_TRIM: 128;
26
+ readonly WORK_ANGLE_ENABLED: 130;
27
+ readonly WORK_ANGLE: 131;
28
+ readonly SMART_NO_GO_ZONES: 132;
29
+ readonly BIRD_VIEW_CAPTURE: 133;
30
+ readonly NETWORK: 134;
31
+ readonly CELLULAR_ENABLED: 137;
32
+ readonly EDGE_DISTANCE: 139;
33
+ readonly GPS_ANTI_THEFT: 140;
34
+ readonly SPARSE_LAWN_OPTIMIZATION: 141;
35
+ };
36
+ /** The `net_media_type` (DP 134) range, as the schema lists it. */
37
+ export declare const MOWER_NETWORKS: readonly ["None", "Wifi", "Cellular"];
38
+ /** The mower's network link (DP 134). */
39
+ export type MowerNetwork = (typeof MOWER_NETWORKS)[number];
40
+ /**
41
+ * Every `mower` read, declared once.
42
+ *
43
+ * All read-only. Several of these data points are `rw` in the schema, but no write has been captured
44
+ * against a mower, and the vendor app drives the mower through named pass-through commands rather than
45
+ * by publishing these DPs, so no setter is installed.
46
+ *
47
+ * Exported but NOT published: each entry states its wire id, which the reference site does not carry.
48
+ * @internal
49
+ */
50
+ export declare const MOWER_MEMBERS: {
51
+ /** Charge percentage (DP 8, `battery_percentage`). */
52
+ readonly battery: {
53
+ readonly param: 8;
54
+ readonly type: "number";
55
+ readonly unit: "%";
56
+ readonly kind: "percent";
57
+ readonly provenance: "mega";
58
+ readonly description: "Battery level 0-100 (DP 8, battery_percentage). Read-only.";
59
+ };
60
+ /** Speaker volume (DP 26, `volume_set`). */
61
+ readonly volume: {
62
+ readonly param: 26;
63
+ readonly type: "number";
64
+ readonly unit: "%";
65
+ readonly kind: "percent";
66
+ readonly provenance: "mega";
67
+ readonly description: "Speaker volume 0-100 (DP 26, volume_set). Read-only.";
68
+ };
69
+ /** Whether the child lock is on (DP 47, `child_lock`). */
70
+ readonly childLock: {
71
+ readonly param: 47;
72
+ readonly type: "bool";
73
+ readonly kind: "boolean";
74
+ readonly provenance: "mega";
75
+ readonly description: "Child lock on (DP 47, child_lock). Read-only.";
76
+ };
77
+ /** Whether the mower returns to its station when it detects rain (DP 101, `rain_auto_return`). */
78
+ readonly rainAutoReturn: {
79
+ readonly param: 101;
80
+ readonly type: "bool";
81
+ readonly kind: "boolean";
82
+ readonly provenance: "mega";
83
+ readonly description: "Return to the station when rain is detected (DP 101, rain_auto_return). Read-only.";
84
+ };
85
+ /** Wi-Fi signal strength as a percentage (DP 109, `wifi_signal_strength`), not a dBm reading. */
86
+ readonly wifiSignal: {
87
+ readonly param: 109;
88
+ readonly type: "number";
89
+ readonly unit: "%";
90
+ readonly kind: "percent";
91
+ readonly provenance: "mega";
92
+ readonly description: "Wi-Fi signal strength 0-100 % (DP 109, wifi_signal_strength). Read-only.";
93
+ };
94
+ /** Cutting height in millimetres (DP 110, `mow_height`), 25-75. */
95
+ readonly cutHeight: {
96
+ readonly param: 110;
97
+ readonly type: "number";
98
+ readonly unit: "mm";
99
+ readonly kind: "millimetres";
100
+ readonly min: 25;
101
+ readonly max: 75;
102
+ readonly provenance: "mega";
103
+ readonly description: "Cutting height 25-75 mm (DP 110, mow_height). Read-only.";
104
+ };
105
+ /** Progress of saving the map (DP 118, `save_map_process`). */
106
+ readonly mapSaveProgress: {
107
+ readonly param: 118;
108
+ readonly type: "number";
109
+ readonly unit: "%";
110
+ readonly kind: "percent";
111
+ readonly provenance: "mega";
112
+ readonly description: "Map-save progress 0-100 % (DP 118, save_map_process). Read-only.";
113
+ };
114
+ /** Total base-station use in minutes (DP 125, `base_station_used_time`). */
115
+ readonly stationUsedTime: {
116
+ readonly param: 125;
117
+ readonly type: "number";
118
+ readonly unit: "min";
119
+ readonly kind: "minutes";
120
+ readonly provenance: "mega";
121
+ readonly description: "Base-station use in minutes (DP 125, base_station_used_time). Read-only.";
122
+ };
123
+ /** Total cutting-blade use in minutes (DP 126, `mow_blade_used_time`). */
124
+ readonly bladeUsedTime: {
125
+ readonly param: 126;
126
+ readonly type: "number";
127
+ readonly unit: "min";
128
+ readonly kind: "minutes";
129
+ readonly provenance: "mega";
130
+ readonly description: "Cutting-blade use in minutes (DP 126, mow_blade_used_time). Read-only.";
131
+ };
132
+ /** Whether edge trimming is on (DP 128, `edge_trim`). */
133
+ readonly edgeTrim: {
134
+ readonly param: 128;
135
+ readonly type: "bool";
136
+ readonly kind: "boolean";
137
+ readonly provenance: "mega";
138
+ readonly description: "Edge trimming on (DP 128, edge_trim). Read-only.";
139
+ };
140
+ /** Whether a fixed mowing angle is in use (DP 130, `enable_work_angle`); the angle is `workAngle`. */
141
+ readonly workAngleEnabled: {
142
+ readonly param: 130;
143
+ readonly type: "bool";
144
+ readonly kind: "boolean";
145
+ readonly provenance: "mega";
146
+ readonly description: "Fixed mowing angle in use (DP 130, enable_work_angle). Read-only.";
147
+ };
148
+ /** The mowing angle in degrees, -90 to 90 (DP 131, `work_angle`). */
149
+ readonly workAngle: {
150
+ readonly param: 131;
151
+ readonly type: "number";
152
+ readonly unit: "°";
153
+ readonly kind: "degrees";
154
+ readonly min: -90;
155
+ readonly max: 90;
156
+ readonly provenance: "mega";
157
+ readonly description: "Mowing angle -90 to 90 degrees (DP 131, work_angle). Read-only.";
158
+ };
159
+ /** Whether smart no-go zones are on (DP 132, `enable_smart_forbid_zone`). */
160
+ readonly smartNoGoZones: {
161
+ readonly param: 132;
162
+ readonly type: "bool";
163
+ readonly kind: "boolean";
164
+ readonly provenance: "mega";
165
+ readonly description: "Smart no-go zones on (DP 132, enable_smart_forbid_zone). Read-only.";
166
+ };
167
+ /** Whether bird's-eye-view capture is on (DP 133, `enable_bird_view_capture`). */
168
+ readonly birdViewCapture: {
169
+ readonly param: 133;
170
+ readonly type: "bool";
171
+ readonly kind: "boolean";
172
+ readonly provenance: "mega";
173
+ readonly description: "Bird's-eye-view capture on (DP 133, enable_bird_view_capture). Read-only.";
174
+ };
175
+ /**
176
+ * The network link in use (DP 134, `net_media_type`). Answers `undefined` for a value outside the
177
+ * schema's range.
178
+ */
179
+ readonly network: {
180
+ readonly param: 134;
181
+ readonly type: "string";
182
+ readonly provenance: "mega";
183
+ readonly decode: (raw: unknown) => MowerNetwork | undefined;
184
+ readonly decodedKind: "enum";
185
+ readonly decodedValues: readonly ["None", "Wifi", "Cellular"];
186
+ readonly description: "Network link: None, Wifi or Cellular (DP 134, net_media_type). Read-only.";
187
+ };
188
+ /** Whether the cellular link is enabled (DP 137, `enable_cellular`). */
189
+ readonly cellularEnabled: {
190
+ readonly param: 137;
191
+ readonly type: "bool";
192
+ readonly kind: "boolean";
193
+ readonly provenance: "mega";
194
+ readonly description: "Cellular link enabled (DP 137, enable_cellular). Read-only.";
195
+ };
196
+ /** Edge-following distance in millimetres (DP 139, `follow_edge_distance`), signed. */
197
+ readonly edgeDistance: {
198
+ readonly param: 139;
199
+ readonly type: "number";
200
+ readonly unit: "mm";
201
+ readonly kind: "millimetres";
202
+ readonly min: -10000;
203
+ readonly max: 10000;
204
+ readonly provenance: "mega";
205
+ readonly description: "Edge-following distance in mm, signed (DP 139, follow_edge_distance). Read-only.";
206
+ };
207
+ /** Whether GPS anti-theft is on (DP 140, `gps_location_check`). */
208
+ readonly gpsAntiTheft: {
209
+ readonly param: 140;
210
+ readonly type: "bool";
211
+ readonly kind: "boolean";
212
+ readonly provenance: "mega";
213
+ readonly description: "GPS anti-theft on (DP 140, gps_location_check). Read-only.";
214
+ };
215
+ /** Whether sparse-lawn optimisation is on (DP 141, `sparse_lawn_optimization`). */
216
+ readonly sparseLawnOptimization: {
217
+ readonly param: 141;
218
+ readonly type: "bool";
219
+ readonly kind: "boolean";
220
+ readonly provenance: "mega";
221
+ readonly description: "Sparse-lawn optimisation on (DP 141, sparse_lawn_optimization). Read-only.";
222
+ };
223
+ };
224
+ /**
225
+ * Bound mower reads — the object returned by `dev.mower()`. Each getter is present only once the
226
+ * mower has reported its data point.
227
+ */
228
+ export type MowerActions = Surface<typeof MOWER_MEMBERS>;
229
+ /** `mower` — robot-mower state from its Tuya data points. */
230
+ export declare const MOWER: CapabilityModule;
@@ -1,6 +1,6 @@
1
1
  import type { Command } from "../../core/contracts.js";
2
2
  import { type Surface } from "./members.js";
3
- import type { CapabilityModule, CommandContext } from "./types.js";
3
+ import type { AvailabilityContext, CapabilityModule, CommandContext } from "./types.js";
4
4
  /** The state params this capability owns — its OWN vocabulary, used by no other capability. */
5
5
  export declare const RTSP_PARAM: {
6
6
  /**
@@ -93,6 +93,13 @@ export type RtspRecordingModeValue = (typeof RtspRecordingMode)[keyof typeof Rts
93
93
  * and the served effect on each endpoint with an RTSP `DESCRIBE`: 401 = challenged, 200 = open.
94
94
  */
95
95
  export type RtspActions = Surface<typeof RTSP_MEMBERS>;
96
+ /**
97
+ * Whether the publish switch has a wire to this camera. A HomeBase S1 Pro (`STATION_9000`) carries an
98
+ * attached camera's commands over its WebRTC control channel, which takes only the `1350` and `1700`
99
+ * envelopes; the switch is a plain scalar, and no other frame for it is captured there. Gating the
100
+ * `published` member drops its read with its setter, since one availability decision covers both.
101
+ */
102
+ declare function publishable(ctx: AvailabilityContext): boolean;
96
103
  /**
97
104
  * Every `rtsp` feature, declared once.
98
105
  *
@@ -127,6 +134,7 @@ export declare const RTSP_MEMBERS: {
127
134
  readonly publish: true;
128
135
  readonly withdraw: false;
129
136
  };
137
+ readonly available: typeof publishable;
130
138
  };
131
139
  /**
132
140
  * The device-reported RTSP URL — the full `rtsp://user:pass@host/path`, carrying the credentials the
@@ -179,9 +187,13 @@ export declare const RTSP_MEMBERS: {
179
187
  readonly description: string;
180
188
  };
181
189
  /** Persistently publish this camera's stream. The enabling caller owns withdrawing it when done. */
182
- readonly publish: import("./members.js").MethodMember<() => Promise<void>>;
190
+ readonly publish: import("./members.js").MethodMember<() => Promise<void>> & {
191
+ available: (ctx: CommandContext) => boolean;
192
+ };
183
193
  /** Withdraw this camera's persistent publication; consumer retries do not ask the SDK to republish it. */
184
- readonly withdraw: import("./members.js").MethodMember<() => Promise<void>>;
194
+ readonly withdraw: import("./members.js").MethodMember<() => Promise<void>> & {
195
+ available: (ctx: CommandContext) => boolean;
196
+ };
185
197
  /**
186
198
  * Store credentials and request authentication on this camera's stream. Served enforcement is
187
199
  * topology-dependent and must be verified with `DESCRIBE` (401 = challenged, 200 = open).
@@ -219,3 +231,4 @@ export declare const RTSP_MEMBERS: {
219
231
  * rather than a model table.
220
232
  */
221
233
  export declare const RTSP: CapabilityModule;
234
+ export {};
@@ -0,0 +1,20 @@
1
+ import { type Surface } from "./members.js";
2
+ import type { CapabilityModule } from "./types.js";
3
+ /**
4
+ * Every `smart_drop` feature, declared once.
5
+ *
6
+ * Exported but NOT published: each entry states its wire id and the evidence it was confirmed on,
7
+ * which the reference site does not carry.
8
+ * @internal
9
+ */
10
+ export declare const SMART_DROP_MEMBERS: {
11
+ /**
12
+ * Opens the lid with `SET_PAYLOAD` 2100 at level 2. Verified on a standalone T8790, whose cipher has
13
+ * only an RSA key: the frame sealed AES-128-ECB opened the lid, the same frame at level 1 did not.
14
+ */
15
+ readonly openLid: import("./members.js").MethodMember<() => Promise<void>>;
16
+ };
17
+ /** Bound SmartDrop controls — the object returned by `dev.smartDrop()`. */
18
+ export type SmartDropActions = Surface<typeof SMART_DROP_MEMBERS>;
19
+ /** `smart_drop` — a standalone SmartDrop (T8790) parcel box: open the lid. */
20
+ export declare const SMART_DROP: CapabilityModule;
@@ -15,7 +15,7 @@ export declare const SUCTION_DP: {
15
15
  * Suction levels — the app's `SuctionEnum` (`getSuctionEnumByValue`). This is a **fixed** value→label
16
16
  * map with **no model argument**: a given int means the same thing on every RoboVac. What varies per
17
17
  * model is only **availability** — a device's `get_product_data_point` range may expose a narrower
18
- * subset (the T2351 catalog lists 0-3) — so the `suction` property stays a raw int rather than being
18
+ * subset (the T2351 catalog lists `Quiet`–`Max`) — so the `suction` property stays a raw int rather than being
19
19
  * constrained per device, and {@link suctionLevelName} names a reported level.
20
20
  *
21
21
  * `BoostIQ` (4) is a real suction level in this scale. The separate `boostIq`
@@ -45,11 +45,11 @@ export declare function suctionLevelName(value: number): string | undefined;
45
45
  export type SuctionActions = Surface<typeof SUCTION_MEMBERS> & {
46
46
  /**
47
47
  * The suction levels this device supports, sourced from the per-SKU `get_product_data_point` catalog
48
- * range for DP 158. Narrower than the full six {@link SuctionLevel} values on many models — a T2351
49
- * reports `[0, 1, 2, 3]`.
48
+ * range for DP 158. Narrower than the full six {@link SuctionLevel} values on many models — a T2351's
49
+ * catalog lists `Quiet`, `Standard`, `Turbo` and `Max`, which answers `[0, 1, 2, 3]`.
50
50
  *
51
- * `undefined` when the catalog is absent or does not cover DP 158. Only meaningful on devices where
52
- * `setSuctionLevel` is installed (AIoT vacuums).
51
+ * `undefined` when the catalog is absent, does not cover DP 158, or lists only members outside the
52
+ * known scale. Only meaningful on devices where `setSuctionLevel` is installed (AIoT vacuums).
53
53
  */
54
54
  readonly supportedLevels?: readonly SuctionLevelValue[];
55
55
  };