@mega-yfue/eufy-sdk 0.0.4 → 0.1.0-beta.0

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 (143) hide show
  1. package/README.md +31 -12
  2. package/dist/client/device-registry.d.ts +343 -0
  3. package/dist/client/eufy-mega.d.ts +872 -0
  4. package/dist/client/index.d.ts +1 -6
  5. package/dist/client/map-channels.d.ts +22 -0
  6. package/dist/client/types.d.ts +383 -0
  7. package/dist/core/contracts.d.ts +898 -0
  8. package/dist/core/crypto.d.ts +98 -0
  9. package/dist/core/index.d.ts +9 -7
  10. package/dist/core/logger.d.ts +53 -0
  11. package/dist/core/lz4-block.d.ts +35 -0
  12. package/dist/core/raw-dp-hex.d.ts +32 -0
  13. package/dist/core/raw-dp-writer.d.ts +83 -0
  14. package/dist/core/store.d.ts +43 -0
  15. package/dist/core/types.d.ts +169 -0
  16. package/dist/core/util.d.ts +78 -0
  17. package/dist/index.d.ts +4 -7
  18. package/dist/index.js +25526 -14
  19. package/dist/index.js.map +7 -1
  20. package/dist/model/capabilities/access.d.ts +127 -0
  21. package/dist/model/capabilities/arming.d.ts +201 -0
  22. package/dist/model/capabilities/audio.d.ts +154 -0
  23. package/dist/model/capabilities/battery.d.ts +363 -0
  24. package/dist/model/capabilities/camera.d.ts +564 -0
  25. package/dist/model/capabilities/co.d.ts +40 -0
  26. package/dist/model/capabilities/contact.d.ts +133 -0
  27. package/dist/model/capabilities/doorbell.d.ts +345 -0
  28. package/dist/model/capabilities/dp-catalog.d.ts +38 -0
  29. package/dist/model/capabilities/index.d.ts +561 -0
  30. package/dist/model/capabilities/info.d.ts +28 -0
  31. package/dist/model/capabilities/keypad.d.ts +61 -0
  32. package/dist/model/capabilities/leak.d.ts +43 -0
  33. package/dist/model/capabilities/light.d.ts +174 -0
  34. package/dist/model/capabilities/locate.d.ts +63 -0
  35. package/dist/model/capabilities/lock.d.ts +242 -0
  36. package/dist/model/capabilities/manifest.d.ts +107 -0
  37. package/dist/model/capabilities/members.d.ts +647 -0
  38. package/dist/model/capabilities/motion.d.ts +377 -0
  39. package/dist/model/capabilities/person-detection.d.ts +8 -0
  40. package/dist/model/capabilities/ptz.d.ts +289 -0
  41. package/dist/model/capabilities/rtsp.d.ts +221 -0
  42. package/dist/model/capabilities/siren.d.ts +218 -0
  43. package/dist/model/capabilities/smart-light.d.ts +172 -0
  44. package/dist/model/capabilities/smoke.d.ts +40 -0
  45. package/dist/model/capabilities/snapshot.d.ts +6 -0
  46. package/dist/model/capabilities/storage.d.ts +11 -0
  47. package/dist/model/capabilities/suction.d.ts +104 -0
  48. package/dist/model/capabilities/types.d.ts +484 -0
  49. package/dist/model/capabilities/vacuum-clean.d.ts +1946 -0
  50. package/dist/model/capabilities/vacuum-dock.d.ts +208 -0
  51. package/dist/model/capabilities/video.d.ts +6 -0
  52. package/dist/model/classify.d.ts +78 -0
  53. package/dist/model/clean-record-detail.d.ts +65 -0
  54. package/dist/model/clean-records.d.ts +69 -0
  55. package/dist/model/device-family.d.ts +73 -0
  56. package/dist/model/device-types.d.ts +123 -0
  57. package/dist/model/device.d.ts +265 -0
  58. package/dist/model/index.d.ts +29 -4
  59. package/dist/model/infer.d.ts +23 -0
  60. package/dist/model/inspect.d.ts +61 -0
  61. package/dist/model/life-params.d.ts +21 -0
  62. package/dist/model/map-pixels.d.ts +70 -0
  63. package/dist/model/param-dictionary.d.ts +28 -0
  64. package/dist/model/param-namespace.d.ts +21 -0
  65. package/dist/model/proto-read.d.ts +53 -0
  66. package/dist/model/push-events.d.ts +147 -0
  67. package/dist/model/registry.d.ts +54 -0
  68. package/dist/model/types.d.ts +301 -0
  69. package/dist/model/vacuum-map-store.d.ts +92 -0
  70. package/dist/model/vacuum-map.d.ts +286 -0
  71. package/dist/model/vacuum-scenes.d.ts +76 -0
  72. package/dist/model/vacuum-schedules.d.ts +85 -0
  73. package/dist/transport/dp-preset.d.ts +102 -0
  74. package/dist/transport/ff09.d.ts +444 -0
  75. package/dist/transport/ffmpeg.d.ts +86 -0
  76. package/dist/transport/http/decodeImageV1.d.ts +20 -0
  77. package/dist/transport/http/decodeImageV2.d.ts +19 -0
  78. package/dist/transport/http/index.d.ts +5 -0
  79. package/dist/transport/http/light-catalog.d.ts +62 -0
  80. package/dist/transport/http/media-download.d.ts +14 -0
  81. package/dist/transport/http/mega-client.d.ts +514 -0
  82. package/dist/transport/http/phone-model.d.ts +21 -0
  83. package/dist/transport/index.d.ts +10 -7
  84. package/dist/transport/mqtt/app-client-id.d.ts +16 -0
  85. package/dist/transport/mqtt/availability.d.ts +14 -0
  86. package/dist/transport/mqtt/bare-ip-tls.d.ts +46 -0
  87. package/dist/transport/mqtt/biz-stream.d.ts +98 -0
  88. package/dist/transport/mqtt/broker-discovery.d.ts +55 -0
  89. package/dist/transport/mqtt/clean-codec.d.ts +14 -0
  90. package/dist/transport/mqtt/command-router.d.ts +285 -0
  91. package/dist/transport/mqtt/dp-codec.d.ts +58 -0
  92. package/dist/transport/mqtt/dp-color.d.ts +14 -0
  93. package/dist/transport/mqtt/engine.d.ts +16 -0
  94. package/dist/transport/mqtt/index.d.ts +5 -0
  95. package/dist/transport/mqtt/secure-mqtt.d.ts +107 -0
  96. package/dist/transport/mqtt/topics.d.ts +80 -0
  97. package/dist/transport/p2p/adts.d.ts +91 -0
  98. package/dist/transport/p2p/annexb.d.ts +124 -0
  99. package/dist/transport/p2p/codec.d.ts +166 -0
  100. package/dist/transport/p2p/command-router.d.ts +655 -0
  101. package/dist/transport/p2p/commands.d.ts +550 -0
  102. package/dist/transport/p2p/envelope.d.ts +46 -0
  103. package/dist/transport/p2p/fmp4.d.ts +89 -0
  104. package/dist/transport/p2p/fragment-recording.d.ts +33 -0
  105. package/dist/transport/p2p/index.d.ts +13 -0
  106. package/dist/transport/p2p/lan-ip.d.ts +25 -0
  107. package/dist/transport/p2p/live-stream.d.ts +223 -0
  108. package/dist/transport/p2p/live-trace.d.ts +123 -0
  109. package/dist/transport/p2p/media.d.ts +105 -0
  110. package/dist/transport/p2p/p2p-session.d.ts +620 -0
  111. package/dist/transport/p2p/readable-egress.d.ts +27 -0
  112. package/dist/transport/p2p/session-manager.d.ts +154 -0
  113. package/dist/transport/p2p/shared-live-source.d.ts +431 -0
  114. package/dist/transport/p2p/talkback.d.ts +187 -0
  115. package/dist/transport/p2p/video.d.ts +150 -0
  116. package/dist/transport/p2p/write-commands.d.ts +21 -0
  117. package/dist/transport/protobuf.d.ts +5 -0
  118. package/dist/transport/push/fcm.d.ts +23 -0
  119. package/dist/transport/push/index.d.ts +6 -0
  120. package/dist/transport/push/message-tags.d.ts +26 -0
  121. package/dist/transport/push/parser.d.ts +27 -0
  122. package/dist/transport/push/proto.d.ts +11 -0
  123. package/dist/transport/push/push-client.d.ts +64 -0
  124. package/dist/transport/push/store.d.ts +23 -0
  125. package/dist/transport/push/types.d.ts +180 -0
  126. package/dist/transport/raw-dp.d.ts +6 -0
  127. package/dist/transport/stored-image-cache.d.ts +23 -0
  128. package/dist/transport/tuya/account.d.ts +44 -0
  129. package/dist/transport/tuya/client.d.ts +89 -0
  130. package/dist/transport/tuya/command-router.d.ts +79 -0
  131. package/dist/transport/tuya/dp-codec.d.ts +56 -0
  132. package/dist/transport/tuya/index.d.ts +28 -0
  133. package/dist/transport/tuya/request.d.ts +157 -0
  134. package/dist/transport/tuya/sign.d.ts +64 -0
  135. package/package.json +12 -13
  136. package/dist/client/index.js +0 -2
  137. package/dist/client/index.js.map +0 -1
  138. package/dist/core/index.js +0 -2
  139. package/dist/core/index.js.map +0 -1
  140. package/dist/model/index.js +0 -2
  141. package/dist/model/index.js.map +0 -1
  142. package/dist/transport/index.js +0 -2
  143. package/dist/transport/index.js.map +0 -1
@@ -0,0 +1,218 @@
1
+ import { isHomeBase } from "../device-family.js";
2
+ import { type Surface } from "./members.js";
3
+ import type { AvailabilityContext, CapabilityModule, CommandContext } from "./types.js";
4
+ import type { Command } from "../../core/contracts.js";
5
+ /**
6
+ * The siren's **state-backed param ids** — each is a param the device reports (and some are also
7
+ * writable). Named `SIREN_PARAM` vs `SIREN_CMD` below (momentary triggers with no reported state) so
8
+ * the split the code implements is explicit. Surveyed + write-captured on a real T90R0
9
+ * (`SIREN_SENSOR_E20`, 2026-08-03).
10
+ */
11
+ export declare const SIREN_PARAM: {
12
+ /** Whether the siren is sounding (app `APP_CMD_DEV_RING_STATUS`). 1 = sounding, 0 = silent. */
13
+ readonly RING_STATUS: 61008;
14
+ /** Alarm volume as a device level (app `APP_CMD_SIREN_SENSOR_SET_ALARM_VOL`). See {@link SirenVolume}. */
15
+ readonly ALARM_VOLUME: 1825;
16
+ /** Seconds an alarm sounds before stopping itself (app `APP_CMD_DEV_ALARM_TIMEOUT`). */
17
+ readonly ALARM_TIMEOUT: 61006;
18
+ /** Do-not-disturb (app `APP_CMD_SENSOR_NOT_DISTURB`). */
19
+ readonly NOT_DISTURB: 1828;
20
+ };
21
+ /**
22
+ * The siren's **write-only command ids**. Momentary actions install only when their family-specific
23
+ * reported evidence and topology gates hold.
24
+ */
25
+ export declare const SIREN_CMD: {
26
+ /** Sound the siren briefly as a test (app `APP_CMD_SIREN_SENSOR_ALARM_TEST`). */
27
+ readonly ALARM_TEST: 1826;
28
+ /** Manually stop a sounding alarm (app `APP_CMD_SIREN_SENSOR_MANUAL_STOP_ALARM`). */
29
+ readonly MANUAL_STOP: 1871;
30
+ /** Station-family HomeBase duration alarm, verified live on T8010 (app `SET_TONE_FILE`). */
31
+ readonly HOMEBASE_TONE: 1201;
32
+ /** HomeBase alarm volume percentage (app `CMD_SET_HUB_SPK_VOLUME`). */
33
+ readonly HUB_SPK_VOLUME: 1235;
34
+ /** HomeBase alarm-tone selection (app `APP_CMD_HUB_ALARM_TONE`). */
35
+ readonly HUB_ALARM_TONE: 1281;
36
+ /** Attached-camera duration alarm, verified live on T8114 and T8210 (app `SET_DEVS_TONE_FILE`). */
37
+ readonly CAMERA_TONE: 1202;
38
+ };
39
+ /**
40
+ * Siren alarm volume — a small device level 1-3 (Low/Mid/High), NOT a percentage. Pass a value to
41
+ * `setVolume`.
42
+ */
43
+ export declare const SirenVolume: {
44
+ readonly Low: 1;
45
+ readonly Mid: 2;
46
+ readonly High: 3;
47
+ };
48
+ /** A siren volume level — the value side of {@link SirenVolume}. */
49
+ export type SirenVolumeValue = (typeof SirenVolume)[keyof typeof SirenVolume];
50
+ /**
51
+ * The alarm-duration presets the app offers, in seconds (1/5/10/15 minutes). These are the only
52
+ * values captured, so `setAlarmDuration` accepts exactly these (rejecting others),
53
+ * the same way the arming capability makes its delay presets the parameter type.
54
+ */
55
+ export declare const SirenAlarmDuration: {
56
+ readonly Min1: 60;
57
+ readonly Min5: 300;
58
+ readonly Min10: 600;
59
+ readonly Min15: 900;
60
+ };
61
+ /** A siren alarm duration in seconds — the value side of {@link SirenAlarmDuration}. */
62
+ export type SirenAlarmDurationValue = (typeof SirenAlarmDuration)[keyof typeof SirenAlarmDuration];
63
+ /** HomeBase alarm tone options, 1-indexed; both options were confirmed on a T8030. */
64
+ export declare const HubAlarmTone: {
65
+ readonly Tone1: 1;
66
+ readonly Tone2: 2;
67
+ };
68
+ /** A HomeBase alarm tone option. */
69
+ export type HubAlarmToneValue = (typeof HubAlarmTone)[keyof typeof HubAlarmTone];
70
+ /**
71
+ * Bound siren controls — the object returned by `dev.siren()`.
72
+ *
73
+ * Everything is derived from `SIREN_MEMBERS`. Each optional member is installed only for the exact
74
+ * standalone-siren, HomeBase, or camera evidence that proves its wire contract.
75
+ */
76
+ export type SirenActions = Surface<typeof SIREN_MEMBERS>;
77
+ /** Whether this context belongs to the sensor codec used by standalone sirens. */
78
+ declare function isSensorCodec(ctx: AvailabilityContext): boolean;
79
+ /** Whether a sensor-codec device reports the combined standalone siren evidence. */
80
+ declare function isEvidencedStandaloneSiren(ctx: CommandContext): boolean;
81
+ /**
82
+ * Every audible alarm-output feature, declared once. Standalone sirens expose observed state,
83
+ * configuration, test, and stop; evidenced HomeBases expose alarm configuration plus trigger/stop;
84
+ * verified attached cameras expose trigger/stop only.
85
+ *
86
+ * Exported but NOT published: each entry states its wire id and the evidence it was confirmed on,
87
+ * which the reference site does not carry.
88
+ * @internal
89
+ */
90
+ export declare const SIREN_MEMBERS: {
91
+ /**
92
+ * Authoritative sounding state reported by a standalone siren. HomeBase and camera command
93
+ * acknowledgements do not install or update this read.
94
+ */
95
+ readonly active: {
96
+ readonly param: 61008;
97
+ readonly property: "siren";
98
+ readonly type: "bool";
99
+ readonly kind: "boolean";
100
+ readonly provenance: "verified";
101
+ readonly available: typeof isSensorCodec;
102
+ readonly description: string;
103
+ };
104
+ /**
105
+ * Rejected, not clamped, outside the 1-3 set: the write is fire-and-forget, so an out-of-range level
106
+ * would look like it worked.
107
+ */
108
+ readonly volume: {
109
+ readonly param: 1825;
110
+ readonly property: "sirenVolume";
111
+ readonly type: "number";
112
+ readonly kind: "scalar";
113
+ readonly provenance: "verified";
114
+ readonly available: typeof isSensorCodec;
115
+ readonly requires: readonly [1825];
116
+ readonly enumValues: Record<number, string>;
117
+ readonly args: readonly [{
118
+ readonly name: "level";
119
+ readonly kind: "scalar";
120
+ readonly description: "A device level 1-3 (Low/Mid/High), not a percentage.";
121
+ }];
122
+ readonly description: string;
123
+ readonly write: (v: string | number | boolean, ctx: CommandContext) => Command | undefined;
124
+ };
125
+ /** Only the four captured presets are accepted: no capture supports an arbitrary duration. */
126
+ readonly alarmDuration: {
127
+ readonly param: 61006;
128
+ readonly type: "number";
129
+ readonly unit: "s";
130
+ readonly kind: "seconds";
131
+ readonly provenance: "verified";
132
+ readonly available: typeof isSensorCodec;
133
+ readonly requires: readonly [61006];
134
+ readonly enumValues: Record<number, string>;
135
+ readonly args: readonly [{
136
+ readonly name: "seconds";
137
+ readonly kind: "seconds";
138
+ readonly description: "One of the app's presets: 60/300/600/900.";
139
+ }];
140
+ readonly description: string;
141
+ readonly write: (v: string | number | boolean, ctx: CommandContext) => Command | undefined;
142
+ };
143
+ /**
144
+ * Read-only: `apk` provenance means the id comes from the disassembled app and the only live evidence
145
+ * is a T90R0 reporting 0, which fixes neither the polarity's other value nor a write frame. Typed
146
+ * `bool` on the app's own naming; do not add a setter until a toggle is captured.
147
+ */
148
+ readonly doNotDisturb: {
149
+ readonly param: 1828;
150
+ readonly type: "bool";
151
+ readonly kind: "boolean";
152
+ readonly provenance: "apk";
153
+ readonly available: typeof isSensorCodec;
154
+ readonly description: "Do-not-disturb (1828 APP_CMD_SENSOR_NOT_DISTURB). Observed 0 on a T90R0.";
155
+ };
156
+ /** HomeBase alarm volume is a percentage on a station-scalar wire, unlike standalone level 1-3. */
157
+ readonly alarmVolume: {
158
+ readonly param: 1235;
159
+ readonly type: "number";
160
+ readonly unit: "%";
161
+ readonly kind: "percent";
162
+ readonly writeOnly: true;
163
+ readonly provenance: "verified";
164
+ readonly available: typeof isHomeBase;
165
+ readonly requires: readonly [1281, 1282];
166
+ readonly min: 0;
167
+ readonly max: 100;
168
+ readonly description: "HomeBase alarm volume 0..100 (1235 CMD_SET_HUB_SPK_VOLUME). Verified audible on a T8030.";
169
+ readonly write: (v: string | number | boolean) => Command;
170
+ };
171
+ /** HomeBase alarm tone keeps its independently verified two-option domain. */
172
+ readonly alarmTone: {
173
+ readonly param: 1281;
174
+ readonly property: "hubAlarmTone";
175
+ readonly type: "number";
176
+ readonly kind: "enum";
177
+ readonly enumValues: Record<number, string>;
178
+ readonly provenance: "verified";
179
+ readonly available: typeof isHomeBase;
180
+ readonly requires: readonly [1281, 1282];
181
+ readonly args: readonly [{
182
+ readonly name: "tone";
183
+ readonly kind: "enum";
184
+ readonly description: "One of the app's alarm tones (1-indexed).";
185
+ }];
186
+ readonly description: string;
187
+ readonly write: (v: string | number | boolean, ctx: CommandContext) => Command | undefined;
188
+ };
189
+ /** Sound a standalone siren briefly using its dedicated installation-test wire. */
190
+ readonly test: {
191
+ readonly action: (ctx: CommandContext) => Command;
192
+ readonly available: typeof isEvidencedStandaloneSiren;
193
+ readonly description: "Sound the siren briefly as a test.";
194
+ };
195
+ /** Trigger a verified station-family HomeBase or evidenced attached-camera alarm for a bounded duration. */
196
+ readonly trigger: {
197
+ readonly method: (deps: import("./members.js").MemberDeps) => (seconds: number) => Promise<void>;
198
+ readonly description: string;
199
+ readonly available: ((ctx: CommandContext) => boolean) & ((ctx: CommandContext) => boolean);
200
+ readonly answers?: true;
201
+ readonly args: readonly [{
202
+ readonly name: "seconds";
203
+ readonly kind: "seconds";
204
+ readonly min: 1;
205
+ readonly description: "A positive whole-number duration.";
206
+ }];
207
+ };
208
+ /** Stop a verified alarm-output family through its own wire contract. */
209
+ readonly stop: import("./members.js").MethodMember<() => Promise<void>> & {
210
+ available: (ctx: CommandContext) => boolean;
211
+ };
212
+ };
213
+ /**
214
+ * `siren` — audible alarm output across independently verified standalone siren, HomeBase, and camera
215
+ * families. Member installation preserves each family's state evidence, units, and wire contract.
216
+ */
217
+ export declare const SIREN: CapabilityModule;
218
+ export {};
@@ -0,0 +1,172 @@
1
+ import type { CapabilityModule } from "./types.js";
2
+ import type { Command } from "../../core/contracts.js";
3
+ import { type Surface } from "./members.js";
4
+ /** Integer RGB input for `SmartLightActions.setColor`; each channel must be in 0..255. */
5
+ export interface RgbColor {
6
+ red: number;
7
+ green: number;
8
+ blue: number;
9
+ }
10
+ /**
11
+ * Bound `smart_light` controls — the object returned by `dev.smartLight()`.
12
+ *
13
+ * The reads, their setters, the state request and the effect write are DERIVED from
14
+ * `SMART_LIGHT_MEMBERS`: one declaration per feature gives the getter, the setter, its argument
15
+ * type and its description. Only the no-argument power verbs are written out below.
16
+ */
17
+ export type SmartLightActions = Surface<typeof SMART_LIGHT_MEMBERS> & {
18
+ /** Turn the light on. */
19
+ on(): Promise<void>;
20
+ /** Turn the light off. */
21
+ off(): Promise<void>;
22
+ };
23
+ /**
24
+ * Every `smart_light` feature, declared once. The property schema, the typed getters, the derived
25
+ * setters, the intent routes and the descriptions all come out of this table.
26
+ *
27
+ * Every read is `realtime`: this line has no pollable cloud param to gate a getter on — state arrives
28
+ * only over the light's own MQTT wire — so the capability's own detection is the evidence, and each
29
+ * getter reads `undefined` until the first report lands.
30
+ *
31
+ * Exported but NOT published: each entry states its wire id and the evidence it was confirmed on,
32
+ * which the reference site does not carry.
33
+ * @internal
34
+ */
35
+ export declare const SMART_LIGHT_MEMBERS: {
36
+ /**
37
+ * On/off for the whole run of lights. `writeAs` names the setter `set` rather than `setPower`, and the
38
+ * `on`/`off` verbs beside it in `actions()` reach the same frame. `realtime` like every read here:
39
+ * there is no pollable cloud param, so the getter answers `undefined` until the first MQTT report —
40
+ * `refreshState` is how a caller populates it on demand. Note the READ tag (0xa1) and the WRITE tag
41
+ * (0xa3) differ; the two legs' tag maps are unrelated.
42
+ */
43
+ readonly power: {
44
+ readonly param: 161;
45
+ readonly property: "lightPower";
46
+ readonly type: "bool";
47
+ readonly kind: "boolean";
48
+ readonly provenance: "verified";
49
+ readonly realtime: true;
50
+ readonly description: "Power state, DP tag 0xa1. ✅ Source-confirmed in the app's own report parser, then live-decoded off a T8L02 status report.";
51
+ readonly write: (v: string | number | boolean) => Command;
52
+ readonly writeAs: "set";
53
+ readonly aliases: {
54
+ readonly on: true;
55
+ readonly off: false;
56
+ };
57
+ };
58
+ /**
59
+ * The CONFIGURED level, not the live output: it persists across an off, so reading a non-zero
60
+ * brightness says nothing about whether the lights are lit — pair it with `power`. 0 is a legal level
61
+ * here (unlike the camera spotlight's 1-100), and the write clamps into 0-100 rather than refusing.
62
+ * `realtime`, so `undefined` until the first report.
63
+ */
64
+ readonly brightness: {
65
+ readonly param: 162;
66
+ readonly property: "lightBrightness";
67
+ readonly type: "number";
68
+ readonly unit: "%";
69
+ readonly kind: "percent";
70
+ readonly provenance: "verified";
71
+ readonly realtime: true;
72
+ readonly min: 0;
73
+ readonly max: 100;
74
+ readonly description: string;
75
+ readonly write: (v: string | number | boolean) => Command;
76
+ };
77
+ /**
78
+ * How many individually addressable segments the installed run has — a physical fact of the strip,
79
+ * which is why it is read-only. A bare `scalar` with no unit: the wire says how many, not how long.
80
+ * `realtime`, so `undefined` until the first report.
81
+ */
82
+ readonly lightLength: {
83
+ readonly param: 163;
84
+ readonly type: "number";
85
+ readonly kind: "scalar";
86
+ readonly provenance: "verified";
87
+ readonly realtime: true;
88
+ readonly description: "Addressable segment count, DP tag 0xa3.";
89
+ };
90
+ /**
91
+ * The gallery effect SELECTED — an `identifier`, not an enum, because it names an entry in a catalog
92
+ * that only exists at runtime, so there is no option set to publish. Distinct from `cloudEffectId`,
93
+ * which is the one actually running. Written by `setEffect`, whose gate is the model rather than a
94
+ * value. `realtime`, so `undefined` until the first report.
95
+ */
96
+ readonly effectId: {
97
+ readonly param: 164;
98
+ readonly property: "lightEffectId";
99
+ readonly type: "number";
100
+ readonly kind: "identifier";
101
+ readonly provenance: "verified";
102
+ readonly realtime: true;
103
+ readonly description: "Selected gallery effect id, DP tag 0xa4.";
104
+ };
105
+ /**
106
+ * Whether the run blends between an effect's colours rather than stepping between them. Read-only:
107
+ * the report parser establishes the flag, but no write frame for it has been reversed, so no setter
108
+ * is offered. One of the two params surfaced as `"1"`/`"0"` so the `bool` narrowing reads it.
109
+ * `realtime`, so `undefined` until the first report.
110
+ */
111
+ readonly colorGradient: {
112
+ readonly param: 165;
113
+ readonly property: "lightColorGradient";
114
+ readonly type: "bool";
115
+ readonly kind: "boolean";
116
+ readonly provenance: "verified";
117
+ readonly realtime: true;
118
+ readonly description: "Colour-gradient switch, DP tag 0xa5.";
119
+ };
120
+ /**
121
+ * The effect actually RUNNING, `0` when none is — so this, not `effectId`, is the read that answers
122
+ * "is an effect playing". An `identifier` for the same reason as its sibling: the catalog it indexes
123
+ * is fetched at runtime. Read-only; `setEffect` drives the selection. `realtime`, so `undefined`
124
+ * until the first report.
125
+ */
126
+ readonly cloudEffectId: {
127
+ readonly param: 166;
128
+ readonly property: "lightCloudEffectId";
129
+ readonly type: "number";
130
+ readonly kind: "identifier";
131
+ readonly provenance: "verified";
132
+ readonly realtime: true;
133
+ readonly description: "Running gallery effect id (0 when off), DP tag 0xa6.";
134
+ };
135
+ /**
136
+ * Reported in every status frame, so it belongs in the schema and answers through `getProperty` — but
137
+ * given no typed getter: the app's own parser reads 0xa7 differently on the notify and on the
138
+ * get-reply, and no capture settles which value means what.
139
+ */
140
+ readonly lightEffectMode: {
141
+ readonly param: 167;
142
+ readonly type: "number";
143
+ readonly kind: "scalar";
144
+ readonly provenance: "apk";
145
+ readonly unexposed: true;
146
+ readonly description: string;
147
+ };
148
+ /**
149
+ * A request, not a state: reports are pushed on change with no periodic heartbeat, so this is how a
150
+ * caller populates the getters on demand. The reply arrives asynchronously and does not resolve here.
151
+ */
152
+ readonly refreshState: {
153
+ readonly action: () => Command;
154
+ readonly description: "Ask the device to report its current state; the reply refreshes the reads.";
155
+ };
156
+ /**
157
+ * Gated on the MODEL, not on a value, and carrying no description: it refuses off the confirmed list
158
+ * for a reason a generated message cannot give, and its id names an entry in a catalog that only
159
+ * exists at runtime, so a generated control would have no domain to offer. Neither is a property
160
+ * write, so it keeps its own signature.
161
+ */
162
+ readonly setEffect: import("./members.js").MethodMember<(lightId: number) => Promise<void>>;
163
+ /**
164
+ * Plain custom colour, distinct from the gallery-effect wire. The frame addresses every reported
165
+ * segment, so a current positive segment count is mandatory and no family-wide length is guessed.
166
+ * Completion acknowledges transport publication only; the device reports no authoritative RGB.
167
+ */
168
+ readonly setColor: import("./members.js").MethodMember<(color: RgbColor) => Promise<void>> & {
169
+ available: (ctx: import("./types.js").CommandContext) => boolean;
170
+ };
171
+ };
172
+ export declare const SMART_LIGHT: CapabilityModule;
@@ -0,0 +1,40 @@
1
+ import { type Surface } from "./members.js";
2
+ import type { CapabilityModule } from "./types.js";
3
+ /**
4
+ * Every `smoke` feature, declared once — the property schema and the evidence-gated getters derive from here.
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 SMOKE_MEMBERS: {
11
+ /**
12
+ * The alarm flag itself — and the reason this capability is detected by model name rather than by a
13
+ * reported param. 1561 is a `guessed` placeholder: nothing captured from a smoke detector confirms the
14
+ * id or which value means alarming, so the evidence gate installs this getter only on a device that
15
+ * happens to report 1561. Promote it once a capture pins the id, not before.
16
+ */
17
+ readonly smokeDetected: {
18
+ readonly param: 1561;
19
+ readonly type: "bool";
20
+ readonly kind: "boolean";
21
+ readonly provenance: "guessed";
22
+ readonly description: "Smoke detected. UNVERIFIED: placeholder id pending capture verification.";
23
+ };
24
+ /**
25
+ * Unix seconds at which the detector last checked in — param 1551, the same last-seen id the other
26
+ * sensor capabilities read. A `timestamp` kind takes no `unit`: the number is an instant, not a
27
+ * duration, and declaring `unit: "s"` beside it fails the value-kind spec.
28
+ */
29
+ readonly lastSeen: {
30
+ readonly param: 1551;
31
+ readonly type: "number";
32
+ readonly kind: "timestamp";
33
+ readonly provenance: "verified";
34
+ readonly description: "Last-seen unix timestamp, seconds (verified: param 1551).";
35
+ };
36
+ };
37
+ /** Bound smoke-detector reads — the object returned by `dev.smoke()`. Read-only. */
38
+ export type SmokeActions = Surface<typeof SMOKE_MEMBERS>;
39
+ /** `smoke` — smoke detector. Alarm flag is a placeholder pending verification. */
40
+ export declare const SMOKE: CapabilityModule;
@@ -0,0 +1,6 @@
1
+ import type { CapabilityModule } from "./types.js";
2
+ /**
3
+ * `snapshot` — still-image capture / thumbnail. Behaviour-only (a capture command);
4
+ * the resulting image is delivered out-of-band, not as a state param.
5
+ */
6
+ export declare const SNAPSHOT: CapabilityModule;
@@ -0,0 +1,11 @@
1
+ import type { CapabilityModule } from "./types.js";
2
+ /**
3
+ * `storage` — on-device storage (SD card / eMMC / HDD).
4
+ *
5
+ * A station-codec baseline capability, since hubs own recordings. It contributes no state properties:
6
+ * no owned station reports a capacity or SD-card parameter, and the one id a table here could point at
7
+ * (1131) is `deviceStatus` in the param dictionary — reported by ten devices with an unrelated meaning,
8
+ * so a capacity getter over it would install widely and answer a device-status code as megabytes.
9
+ * Capacity earns a member when a station is captured reporting one.
10
+ */
11
+ export declare const STORAGE: CapabilityModule;
@@ -0,0 +1,104 @@
1
+ import type { AvailabilityContext, CapabilityModule } from "./types.js";
2
+ import { type Surface } from "./members.js";
3
+ /**
4
+ * RoboVac suction Tuya **DP ids** — this capability's own wire vocabulary (clean namespace, from the
5
+ * cloud `get_product_data_point` schema). Named like the P2P feature-command consts so a DP is
6
+ * referenced by meaning rather than a magic number.
7
+ */
8
+ export declare const SUCTION_DP: {
9
+ /** Suction level (DP 158, Enum). */
10
+ readonly SUCTION: 158;
11
+ /** BoostIQ auto-suction on/off (DP 159, Bool). */
12
+ readonly BOOST_IQ: 159;
13
+ };
14
+ /**
15
+ * Suction levels — the app's `SuctionEnum` (`getSuctionEnumByValue`). This is a **fixed** value→label
16
+ * map with **no model argument**: a given int means the same thing on every RoboVac. What varies per
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
19
+ * constrained per device, and {@link suctionLevelName} names a reported level.
20
+ *
21
+ * `BoostIQ` (4) is a real suction level in this scale. The separate `boostIq`
22
+ * boolean (DP 159) is the independent auto-suction toggle — a device may report both, and they don't
23
+ * contradict.
24
+ */
25
+ export declare const SuctionLevel: {
26
+ readonly Quiet: 0;
27
+ readonly Standard: 1;
28
+ readonly Turbo: 2;
29
+ readonly Max: 3;
30
+ readonly BoostIQ: 4;
31
+ readonly MaxPro: 5;
32
+ };
33
+ export type SuctionLevelValue = (typeof SuctionLevel)[keyof typeof SuctionLevel];
34
+ /**
35
+ * The label for a raw suction int, per the app's `SuctionEnum`, or `undefined` for a value outside the
36
+ * known scale. The mapping is global (not per-model) — see {@link SuctionLevel}.
37
+ */
38
+ export declare function suctionLevelName(value: number): string | undefined;
39
+ /**
40
+ * Bound suction reads and controls — the object returned by `dev.suction()`.
41
+ *
42
+ * `setSuctionLevel` is DERIVED from the `level` member entry; `supportedLevels` is the only addition
43
+ * from `actions()` — it names the per-SKU DP 158 range but is not itself a device param.
44
+ */
45
+ export type SuctionActions = Surface<typeof SUCTION_MEMBERS> & {
46
+ /**
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]`.
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).
53
+ */
54
+ readonly supportedLevels?: readonly SuctionLevelValue[];
55
+ };
56
+ /**
57
+ * Every `suction` read and write — `setSuctionLevel` (DP 158, via `writeAs`) and `setBoostIq`
58
+ * (DP 159) are both derived from this table.
59
+ *
60
+ * Exported but NOT published: each entry states its wire id and the evidence it was confirmed on,
61
+ * which the reference site does not carry.
62
+ * @internal
63
+ */
64
+ export declare const SUCTION_MEMBERS: {
65
+ /**
66
+ * Narrowed to the known scale, which is NARROWER THAN THE WIRE: the level
67
+ * arrives as a plain integer and a firmware reporting a value outside {@link SuctionLevel} would be
68
+ * typed as one of these regardless. {@link suctionLevelName} stays total for that reason — it answers
69
+ * `undefined` for an int it does not recognise, so an unexpected level surfaces as unnamed rather than
70
+ * mislabelled.
71
+ */
72
+ readonly level: {
73
+ readonly param: 158;
74
+ readonly property: "suction";
75
+ readonly type: "number";
76
+ readonly kind: "enum";
77
+ readonly enumValues: Record<number, string>;
78
+ readonly provenance: "mega";
79
+ readonly decode: (raw: unknown) => SuctionLevelValue | undefined;
80
+ readonly decodedKind: "enum";
81
+ readonly decodedValues: readonly SuctionLevelValue[];
82
+ readonly write: (v: string | number | boolean) => import("../../index.js").Command;
83
+ readonly writeAs: "setSuctionLevel";
84
+ readonly available: (ctx: AvailabilityContext) => boolean;
85
+ readonly description: string;
86
+ };
87
+ /**
88
+ * The auto-suction toggle — an independent boolean, NOT the `BoostIQ` entry in the suction scale. A
89
+ * robot may report both at once without contradicting itself: `level` says which power the robot is
90
+ * fixed at, this says whether it may raise it by itself on carpet. Writable straight from the table
91
+ * because DP 159 is a plain bool with no per-model range to validate against, unlike `level`.
92
+ */
93
+ readonly boostIq: {
94
+ readonly param: 159;
95
+ readonly type: "bool";
96
+ readonly kind: "boolean";
97
+ readonly provenance: "mega";
98
+ readonly description: "BoostIQ auto-suction (DP 159, Bool).";
99
+ readonly write: (v: string | number | boolean) => import("../../index.js").Command;
100
+ readonly available: (ctx: AvailabilityContext) => boolean;
101
+ };
102
+ };
103
+ /** `suction` — vacuum suction power level (RoboVac). */
104
+ export declare const SUCTION: CapabilityModule;