@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,561 @@
1
+ /**
2
+ * Capability-module barrel — collects every `capabilities/<cap>.ts` module and exposes the
3
+ * fleet-wide helpers (`getCapabilityModule`, `mergeProperties`, `detectCapabilities`,
4
+ * `decodeFrame`, `buildCommand`). Adding a capability = a new file + one import line here.
5
+ *
6
+ * @module model/capabilities
7
+ */
8
+ import type { Capability, CloudRecord, Codec, PropertyChange, PropertySpec } from "../types.js";
9
+ import { type MemberDeps } from "./members.js";
10
+ import { type CapabilityDescriptor } from "./manifest.js";
11
+ import type { CapabilityModule, EventMapping, CapabilityEvent, DecodedState, InboundSignal, CommandContext, AvailabilityContext } from "./types.js";
12
+ import type { Command } from "../../core/contracts.js";
13
+ export { RtspRecordingMode, type RtspRecordingModeValue, type RtspAuthScheme } from "./rtsp.js";
14
+ export { EntryAlarmTone, type EntryAlarmToneValue } from "./contact.js";
15
+ export { SirenVolume, type SirenVolumeValue, SirenAlarmDuration, type SirenAlarmDurationValue } from "./siren.js";
16
+ /**
17
+ * Ask what a bound capability can be told to change but can never report back, and what it reports without
18
+ * that value reflecting its own setter.
19
+ */
20
+ export { unobservableMembers, unreflectedMembers } from "./members.js";
21
+ export { Watermark, type WatermarkValue, NightVision, type NightVisionValue, RecordingQuality, type RecordingQualityName, RECORDING_QUALITY_TIERS, StreamingQuality, type StreamingQualityName, STREAMING_QUALITY_TIERS, resolveStreamingQuality, resolveStreamingQualityTier, resolveRecordingQuality, resolveRecordingQualityValue, resolveRecordingQualityTier, } from "./camera.js";
22
+ export { WorkingMode, PowerSource, resolveWorkingMode, resolveWorkingModeValue, WORKING_MODE_MAPS, type WorkingModeName, type PowerSourceName, } from "./battery.js";
23
+ export { type DpCatalog, EMPTY_DP_CATALOG } from "./dp-catalog.js";
24
+ import type { PtzActions } from "./ptz.js";
25
+ import type { LightActions } from "./light.js";
26
+ import type { RgbColor, SmartLightActions } from "./smart-light.js";
27
+ import type { CameraActions } from "./camera.js";
28
+ import type { AudioActions } from "./audio.js";
29
+ import type { BatteryActions } from "./battery.js";
30
+ import type { LockActions } from "./lock.js";
31
+ import type { SirenActions } from "./siren.js";
32
+ import type { ArmingActions } from "./arming.js";
33
+ import type { DoorbellActions } from "./doorbell.js";
34
+ import type { MotionActions } from "./motion.js";
35
+ import type { ContactActions } from "./contact.js";
36
+ import type { LeakActions } from "./leak.js";
37
+ import type { SmokeActions } from "./smoke.js";
38
+ import type { CoActions } from "./co.js";
39
+ import type { KeypadActions } from "./keypad.js";
40
+ import type { RtspActions } from "./rtsp.js";
41
+ import type { VacuumCleanActions } from "./vacuum-clean.js";
42
+ import type { VacuumDockActions } from "./vacuum-dock.js";
43
+ import type { SuctionActions } from "./suction.js";
44
+ import type { LocateActions } from "./locate.js";
45
+ import type { DeviceInfo } from "./info.js";
46
+ /**
47
+ * Look up the {@link CapabilityModule} for a capability, or `undefined` if none is registered.
48
+ * @internal
49
+ */
50
+ export declare function getCapabilityModule(cap: Capability): CapabilityModule | undefined;
51
+ /**
52
+ * The complete capability → module map. Every member of the {@link Capability} union has an entry.
53
+ * @internal
54
+ */
55
+ export declare const CAPABILITY_MODULES: Record<Capability, CapabilityModule>;
56
+ /**
57
+ * Merge the property schemas of several capabilities into one flat, de-duplicated list.
58
+ *
59
+ * Properties are de-duplicated by `PropertySpec.name` with **first-wins** semantics, so the
60
+ * caller controls precedence through the order of `caps`. Capabilities with no registered module
61
+ * are skipped.
62
+ *
63
+ * @param caps - capabilities to combine (order = precedence).
64
+ * @returns the union of all contributed `PropertySpec`s, unique by `name`.
65
+ * @internal
66
+ */
67
+ export declare function mergeProperties(caps: Capability[], ctx?: AvailabilityContext): PropertySpec[];
68
+ /**
69
+ * Detect the capabilities a device exposes from its cloud record and codec. A capability is added
70
+ * if its product line matches the codec's ({@link lineAllows}, checked first) AND ANY of its
71
+ * {@link import("./types").DetectionSpec} fields match:
72
+ * - an `evidenceParams` id is present in `rec.params` keys,
73
+ * - `deviceTypes` includes `rec.deviceType`,
74
+ * - a `modelHints` regex matches the model/category/name haystack,
75
+ * - `codecs` includes `codec`,
76
+ * - `detect(rec, codec)` returns true.
77
+ * Never throws. Returns a de-duplicated array.
78
+ * @internal
79
+ */
80
+ export declare function detectCapabilities(rec: CloudRecord, codec: Codec): Capability[];
81
+ /**
82
+ * The baseline capabilities a codec grants every device of that family — derived from the modules
83
+ * that declare the codec in their {@link import("./types").DetectionSpec} `codecs`. Each capability
84
+ * file owns "I am part of codec X's baseline", so the codec→caps table is a projection of the modules,
85
+ * not a second source of truth.
86
+ *
87
+ * @param codec the resolved codec.
88
+ * @returns a fresh array of baseline capabilities for that codec (possibly empty).
89
+ * @internal
90
+ */
91
+ export declare function codecBaseline(codec: Codec): Capability[];
92
+ /**
93
+ * The capabilities only the device that OWNS a group may expose, folded from every module's
94
+ * {@link CapabilityModule.ownedByStation}.
95
+ *
96
+ * A barrel projection like {@link codecBaseline}: it lets `resolveDevice` withhold a group-owned
97
+ * control from an attached device without naming a capability, so the next one that turns out to live
98
+ * on the hub is a flag on its own module rather than another branch in the resolver.
99
+ *
100
+ * @internal
101
+ */
102
+ export declare const STATION_OWNED_CAPABILITIES: ReadonlySet<Capability>;
103
+ /** @internal */
104
+ interface ResolvedEventRefresh {
105
+ param: number;
106
+ property: string;
107
+ timeoutMs: number;
108
+ }
109
+ /**
110
+ * An index hit: the semantic event name, the capability that claims the id, and any static payload
111
+ * the mapping attached. The capability is what disambiguates a shared id.
112
+ * @internal
113
+ */
114
+ export type EventHit = Pick<EventMapping, "payload" | "derive"> & {
115
+ emit: string;
116
+ capability: Capability;
117
+ refresh?: ResolvedEventRefresh;
118
+ };
119
+ type EventIndex = {
120
+ exact: Map<number, EventHit[]>;
121
+ ranges: Array<{
122
+ lo: number;
123
+ hi: number;
124
+ } & EventHit>;
125
+ };
126
+ /**
127
+ * Build the inbound-event index from a module list: keyed by source ("push" | "poll"), then exact id →
128
+ * the candidate hits, plus a small list of `[lo,hi]` ranges. Dispatch is a direct lookup — no loop over
129
+ * modules, no per-module decode code for the common case.
130
+ *
131
+ * Each id maps to a LIST because push ids are namespaced **per device family**, not globally: the same
132
+ * integer means different things on different hardware (`SmartDropPushEvent.TAMPERED_WARNING` and
133
+ * `CusPushEvent.ALARM` are both 10; SmartDrop's battery ids 6/7/11 are `CusPushEvent`'s
134
+ * BATTERY_LOW/HOT/FULL). With one entry per id, whichever module happens to be registered last wins for
135
+ * every device — turning a tamper alert into a battery alert. Candidates are resolved against the target
136
+ * device's capabilities at dispatch time ({@link CapabilityModule.decodeEvent}).
137
+ *
138
+ * Parameterised over the modules rather than closing over the registry; the real index is built once
139
+ * from every registered capability module.
140
+ * @internal
141
+ */
142
+ export declare function buildEventIndex(modules: readonly CapabilityModule[]): Record<"push" | "poll", EventIndex>;
143
+ /**
144
+ * Semantic event name → the payload field carrying its state, folded from every module's
145
+ * {@link CapabilityModule.stateEvents}.
146
+ *
147
+ * A barrel projection like the action/event maps: it lets the facade be edge-triggered on state
148
+ * without naming a capability. An event ABSENT here is a pulse and is always announced.
149
+ */
150
+ export declare const STATE_EVENT_FIELDS: Readonly<Record<string, string>>;
151
+ /**
152
+ * Pick the mapping that belongs to THIS device when several families claim the same id.
153
+ *
154
+ * With one candidate there is nothing to resolve — emit it, so a device whose capabilities can't be
155
+ * resolved still gets the event. With several, the device's own capability set decides; if
156
+ * that isn't known, the SDK emits NOTHING rather than guessing, because naming the wrong event (a
157
+ * tamper reported as a battery alert) is worse than staying silent about it.
158
+ */
159
+ export declare function resolveHits(hits: EventHit[], capabilities?: ReadonlySet<Capability>): EventHit[];
160
+ type DecodedCapabilityEvent = CapabilityEvent & {
161
+ refresh?: ResolvedEventRefresh;
162
+ };
163
+ /**
164
+ * Normalize an inbound {@link InboundSignal} (push / P2P frame / poll) into the semantic
165
+ * {@link CapabilityEvent}s to emit. Push/poll resolve via the declarative index (pure data);
166
+ * P2P frames run the modules' {@link CapabilityModule.decodeEvent} escape hatch (binary parsing).
167
+ * A `deviceSn`/`stationSn` from the signal is folded into each payload.
168
+ *
169
+ * `capabilities`, when supplied, has a different job per source:
170
+ *
171
+ * - **p2p-frame / mqtt** — an allow-list over the escape-hatch decoders, mirroring `buildCommand`'s
172
+ * gate on the outbound side. A frame reusing a shared command id (e.g. 1700
173
+ * `CMD_DOORBELL_SET_PAYLOAD`) would otherwise be fed to every module's binary parser and could
174
+ * fabricate a semantic event on hardware lacking the capability that owns that parser.
175
+ * - **push / poll** — a tie-breaker only, between families claiming the SAME id (see
176
+ * the shared event index). An id with one claimant emits regardless of capabilities: detection is
177
+ * evidence-based and can under-report, so gating every push on it would silently drop real events.
178
+ * A contested id with no capability context emits nothing rather than a guess.
179
+ *
180
+ * A mapping's static payload is spread LAST, so the raw push body cannot overwrite it. Push payloads
181
+ * carry short, generic keys straight off the wire, and a discriminator like `phase` is the only thing
182
+ * separating a fired alarm from a countdown — letting the wire win there would silently change an
183
+ * event's meaning.
184
+ *
185
+ * Omitted (undefined) = run all escape-hatch modules and accept any single-claimant id.
186
+ * @internal
187
+ */
188
+ export declare function decodeEvent(signal: InboundSignal, capabilities?: ReadonlySet<Capability>): DecodedCapabilityEvent[];
189
+ /** Whether any of these capabilities has realtime-init commands to send — checked before the caller
190
+ * pays for a {@link CommandContext}, which costs a device-param fetch. */
191
+ export declare function needsRealtimeInit(capabilities: ReadonlySet<Capability>): boolean;
192
+ /**
193
+ * The commands to send once a device's realtime channel is up, from every capability it has that asks
194
+ * for one. Empty for a device whose state arrives without being asked.
195
+ */
196
+ export declare function buildRealtimeInit(capabilities: ReadonlySet<Capability>, ctx: CommandContext): Command[];
197
+ /**
198
+ * Whether any of these capabilities feeds its readable state from realtime rather than from a pollable
199
+ * cloud param — i.e. whether a device is worth waiting on before its reads are meaningful.
200
+ */
201
+ export declare function hasRealtimeReads(capabilities: ReadonlySet<Capability>): boolean;
202
+ /**
203
+ * Recover device state from an inbound signal — the state-side dual of {@link CapabilityModule.decodeEvent}. Gated by
204
+ * the reporting device's capabilities exactly as events are, so one product line's decoder never runs
205
+ * against another line's traffic. One entry per module that recognised the signal; a module that
206
+ * decoded no fields is dropped.
207
+ */
208
+ export declare function decodeState(signal: InboundSignal, capabilities?: ReadonlySet<Capability>): DecodedState[];
209
+ /**
210
+ * Resolve a semantic `action` into a transport-neutral {@link Command} for a device, using
211
+ * {@link CommandContext} to pick the right variant. The first module that handles the action wins
212
+ * (module order = precedence). `undefined` if no module has a recipe.
213
+ * @internal
214
+ */
215
+ export declare function buildCommand(action: string, value: boolean | number | string, ctx: CommandContext): Command | undefined;
216
+ /**
217
+ * Fields every semantic event carries — which device/station it came from. `decodeEvent` always
218
+ * folds these in from the signal.
219
+ */
220
+ export interface SemanticEventBase {
221
+ /** Serial of the device the event is about (present for push/poll signals). */
222
+ deviceSn?: string;
223
+ /** Serial of the station that delivered it (present for P2P / HomeBase-relayed signals). */
224
+ stationSn?: string;
225
+ }
226
+ /** A push-delivered semantic event (motion, doorbell, person, package, lock). */
227
+ export interface PushSemanticEvent extends SemanticEventBase {
228
+ /** The raw FCM event-type code that produced this event. */
229
+ eventType?: number;
230
+ /** A thumbnail URL when the push carried one. */
231
+ thumbnailUrl?: string;
232
+ }
233
+ /** A poll-delivered semantic event — a cloud param that changed between polls. */
234
+ export interface PollSemanticEvent extends SemanticEventBase {
235
+ /** The param id that changed. */
236
+ paramType?: number;
237
+ /** Previous raw value. */
238
+ from?: string;
239
+ /** New raw value. */
240
+ to?: string;
241
+ }
242
+ /**
243
+ * The typed **event** surface, keyed by semantic event name → payload type. THE projection point
244
+ * for events (the sibling of {@link DeviceActionMap}): a capability that emits a new event name adds
245
+ * one line here. `EufyMega`'s typed `on`/`once`/`off`/`emit` overloads are derived from this map, so
246
+ * `eufy.on("motion", e => e.deviceSn)` autocompletes the name and types the payload. Names MUST
247
+ * match the module `emit:` / `decodeEvent` `event:` strings.
248
+ */
249
+ export interface DeviceEventMap {
250
+ /** Motion detected (camera / PIR sensor). */
251
+ motion: PushSemanticEvent;
252
+ /** A recognized/known or stranger person detected. */
253
+ personDetected: PushSemanticEvent;
254
+ /** Doorbell button pressed. */
255
+ doorbellPress: PushSemanticEvent;
256
+ /** Pet detected. */
257
+ petDetection: PushSemanticEvent;
258
+ /** A package was delivered (drop/porch). */
259
+ packageDelivered: PushSemanticEvent;
260
+ /** A previously-delivered package was taken. */
261
+ packageTaken: PushSemanticEvent;
262
+ /** A delivered package has been left unattended too long. */
263
+ packageStranded: PushSemanticEvent;
264
+ /** A person the device does NOT recognise (distinct from {@link personDetected}). */
265
+ strangerDetected: PushSemanticEvent;
266
+ /** Sound above the configured threshold. */
267
+ soundDetected: PushSemanticEvent;
268
+ /** Crying detected (indoor/baby-monitor families). */
269
+ cryingDetected: PushSemanticEvent;
270
+ /** A vehicle was detected. */
271
+ vehicleDetected: PushSemanticEvent;
272
+ /** A dog was detected; `kind` distinguishes the licking/fouling sub-events when the device reports one. */
273
+ dogDetected: PushSemanticEvent & {
274
+ kind?: "lick" | "poop";
275
+ };
276
+ /** The guard mode changed. Carries no mode value — re-read the current mode. */
277
+ armingModeChanged: PushSemanticEvent;
278
+ /**
279
+ * A camera's own enablement was confirmed changed, after a write this SDK issued was read back off the
280
+ * device. Carries no value — re-read `enabled`, which has converged by the time this fires.
281
+ *
282
+ * Distinct from {@link propertyChanged}, which reports `enabled` moving for any reason on whichever
283
+ * inbound path saw it. This one says a write LANDED, which is a different fact and the only thing that
284
+ * can be known about a value nothing pushes.
285
+ */
286
+ cameraEnabledChanged: PushSemanticEvent;
287
+ /** Station alarm lifecycle; `phase` says whether it fired or is counting down. */
288
+ alarm: PushSemanticEvent & {
289
+ phase?: "triggered" | "delayed";
290
+ };
291
+ /** Lock (un)locked or a lock alarm fired. */
292
+ lockState: PushSemanticEvent;
293
+ /**
294
+ * Entry sensor opened/closed. Arrives via push (seconds) or cloud poll (minutes), which carry the
295
+ * state under different raw keys — read `open`, which both normalise to. Absent when the signal
296
+ * carried no contact value, so `undefined` means "not reported here", not "closed".
297
+ */
298
+ contactState: PushSemanticEvent & PollSemanticEvent & {
299
+ open?: boolean;
300
+ };
301
+ /**
302
+ * A property this device reports changed value — the generic announcement, derived from the same
303
+ * `members` table the getters are, for every readable property of every capability.
304
+ *
305
+ * `property` is the name `Device.getProperty` takes and the one a capability getter answers, so a
306
+ * caller can re-read immediately; `Device.describe()` publishes the `{ accessor, property }` pair,
307
+ * which maps the name back to the fluent accessor behind it. `value` is what `getProperty` now serves,
308
+ * narrowed the way the capability getter narrows it and read from the same live state rather than
309
+ * re-converted from the wire. It is absent where no scalar can honestly be given — a property whose
310
+ * stored form is a payload, or one whose stored value does not match its declared type — which means
311
+ * "this moved, re-read it". No wire id travels with it: several ids resolve to one property, which is
312
+ * the point.
313
+ *
314
+ * Announced from the cloud poll, from a realtime report, and from the read-through cache's own
315
+ * background re-read, for a change with any cause — the SDK cannot tell its own write's echo from a
316
+ * change made in the vendor app, and suppressing on a guess would lose a real external change in
317
+ * exchange for one redundant re-read. Not announced on first sight of a device (that is discovery, not
318
+ * a transition), nor inside a write's own confirmation (already reported through that command's
319
+ * outcome).
320
+ *
321
+ * Announced against a `Device` the caller is holding, since the value is read out of that device's own
322
+ * live state and the SDK holds the devices it hands out weakly.
323
+ *
324
+ * Every readable property of every capability, with nothing filtered for being uninteresting. So a
325
+ * sensor's own check-in timestamp is announced too, even though the `deviceState` event already
326
+ * carries that fact.
327
+ *
328
+ * Latency is the inbound path's: seconds for a property a device reports over realtime. For one that
329
+ * only ever arrives as a cloud param — which is most of them — it is whichever comes first of the poll
330
+ * (`EufyMegaOptions.pollMs`, `EufyMega.setPollInterval`) and the cache's re-read
331
+ * (`EufyMegaOptions.cacheTtlMs`), both the caller's to choose.
332
+ */
333
+ propertyChanged: SemanticEventBase & PropertyChange & {
334
+ deviceSn: string;
335
+ };
336
+ /** Battery alert — `state` discriminates low / hot / full. */
337
+ batteryAlert: PushSemanticEvent & {
338
+ state?: "low" | "hot" | "full";
339
+ };
340
+ /** Pan/tilt status streamed while the camera moves. */
341
+ ptzNotify: SemanticEventBase & {
342
+ kind: "rotate" | "zoom" | "position";
343
+ payload?: unknown;
344
+ coords?: Array<[number, number]>;
345
+ };
346
+ /**
347
+ * A eufy_life smart light reported its state (secure-MQTT DP status report). Every field is
348
+ * optional: a report carries only the fields the device sent, and an absent one is silence about
349
+ * that field rather than a change to it.
350
+ */
351
+ smartLightState: SemanticEventBase & {
352
+ power?: boolean;
353
+ brightness?: number;
354
+ lightLength?: number;
355
+ effectId?: number;
356
+ colorGradient?: boolean;
357
+ cloudEffectId?: number;
358
+ };
359
+ }
360
+ /**
361
+ * The typed action surface, keyed by the **camelCased capability id** (the fluent accessor name).
362
+ *
363
+ * THE projection point for actions: adding a capability with an `actions()` factory = add its
364
+ * typed-actions import above + one line here. `device.ts` and the client stay capability-agnostic —
365
+ * the fluent `dev.ptz()` accessors are derived from this map ({@link CapabilityAccessors}), so
366
+ * nothing outside a capability file names a capability.
367
+ *
368
+ * A key here MUST match `camelCase(module.capability)` for the runtime accessor install to line up
369
+ * with the type. (Only capabilities whose module defines `actions()` appear.)
370
+ */
371
+ export interface DeviceActionMap {
372
+ /** Pan/tilt/zoom control: `rotate(dir, step)` + `left`/`right`/`up`/`down`, `zoom`, preset() namespace (goto/preview/save/setDefault/delete/list/image). */
373
+ ptz: PtzActions;
374
+ /** Floodlight/spotlight: `on`/`off`/`set`, `setBrightness`/`setColorTemp`/`setEnabled`, `setAutoSpotlight`. */
375
+ light: LightActions;
376
+ /** eufy_life smart light (T8L0x): `on`/`off`, `setBrightness`, T8L02 `setColor`, `setEffect(lightId)`. */
377
+ smartLight: SmartLightActions;
378
+ /** Camera: `on`/`off`, privacy, status LED; `snapshot`/`live`/`record` when bound to a live client. */
379
+ camera: CameraActions;
380
+ /** Audio/volume (family-gated): mic, speaker + volume, in-video recording, doorbell ringtone, HomeBase alarm/prompt. */
381
+ audio: AudioActions;
382
+ /** Battery/power: power source, working mode, and the custom-mode clip/interval/auto-stop settings. */
383
+ battery: BatteryActions;
384
+ /** Smart lock: `lock()`/`unlock()` + verified `setRainMode`/`setAutoLock`. The 6 source-confirmed-but-uncaptured setting toggles are ABSENT until captured (present method ⇒ wire verified). */
385
+ lock: LockActions;
386
+ /** Siren: reads `active`, `volume`, `alarmDuration`, `doNotDisturb`; writes `setVolume`, `setAlarmDuration`, `test`, `stop` (config setters present when the param is reported). No direct "sound the alarm" wire — a real alarm is driven by the `arming` system; `test` is the on-demand trigger. */
387
+ siren: SirenActions;
388
+ /** Guard mode: `setMode(ArmingMode)` + `setAlarmDelayConfig(mode, config)`. Of the 8 `ArmingMode` values only `away`/`home`/`disarmed` are confirmed on-device. */
389
+ arming: ArmingActions;
390
+ /** Doorbell: `playQuickResponse(voiceId)` (the canned voice replies). */
391
+ doorbell: DoorbellActions;
392
+ /** Motion/PIR: `setDetection(on)` (sensitivity is read-only until its write wire is captured). */
393
+ motion: MotionActions;
394
+ /** Entry (door/window) sensor: reads `open`, `lastSeen`, `rssi`, `alarmSoundType`, `alarmVolume`; writes `setAlarmSoundType`, `setAlarmVolume` (present when the sensor reports the alarm params). */
395
+ contact: ContactActions;
396
+ /** Water-leak / freeze sensor reads (read-only): `leakDetected`, `lastSeen`. */
397
+ leak: LeakActions;
398
+ /** Smoke-detector reads (read-only): `smokeDetected`, `lastSeen`. */
399
+ smoke: SmokeActions;
400
+ /** CO-detector reads (read-only): `coDetected`, `lastSeen`. */
401
+ co: CoActions;
402
+ /** Security-keypad reads (read-only): `rssi`. */
403
+ keypad: KeypadActions;
404
+ /** RTSP publish for a NAS/NVR: `publish`/`withdraw` + `published`, `requireAuth`/`allowAnonymous`, `recordingMode`/`setRecordingMode`. One camera at a time per station. */
405
+ rtsp: RtspActions;
406
+ /** RoboVac core state and controls: `power`, `activity` (WorkStatus), `volume`, `battery`, `cleanType`; `setPower`, `startCleaning`, `returnToDock`, `pauseCleaning`. */
407
+ vacuumClean: VacuumCleanActions;
408
+ /** RoboVac Omni dock controls: `emptyDust`, `washMops`, `dryMops`; raw `dockState` unexposed until wire confirmed. */
409
+ vacuumDock: VacuumDockActions;
410
+ /** RoboVac suction: `level`, `boostIq`, `supportedLevels`; `setSuctionLevel`, `setBoostIq`. */
411
+ suction: SuctionActions;
412
+ /** RoboVac locate (find-robot beep): `locating`; `locate(on?)`. */
413
+ locate: LocateActions;
414
+ /** Identity metadata (read-only): `{ manufacturer, model, serialNumber, name, deviceType?, firmwareVersion?, hardwareVersion? }`. */
415
+ info: DeviceInfo;
416
+ }
417
+ /**
418
+ * The fluent capability accessors merged onto `Device`: `dev.ptz?.()?.rotate(PtzDirection.left)`.
419
+ *
420
+ * **Each accessor is optional**, because a device carries only the accessors for capabilities it
421
+ * actually has — a smart light has no `camera` at all. Calling one that exists still yields `undefined`
422
+ * until the device is bound to a live transport, so a call site needs `?.` twice: `dev.ptz?.()?.…`,
423
+ * the first for "does this device have it", the second for "is it bound yet".
424
+ */
425
+ export type CapabilityAccessors = {
426
+ [K in keyof DeviceActionMap]?: () => DeviceActionMap[K] | undefined;
427
+ };
428
+ /**
429
+ * Every fluent-accessor name the SDK knows — the camelCased id of every module with a `members` table
430
+ * or an `actions()` factory. A module needs only ONE of the two: `battery` is all members and `ptz` all
431
+ * hand-written actions. The runtime twin of {@link DeviceActionMap}'s keys (types erase at
432
+ * build). A projection of `MODULES`, so `device.ts` stays capability-agnostic. A device installs the
433
+ * subset it has: see {@link accessorNamesFor}.
434
+ * @internal
435
+ */
436
+ export declare const ACTION_ACCESSOR_NAMES: readonly (keyof DeviceActionMap)[];
437
+ /**
438
+ * The fluent-accessor names a device with THESE capabilities should carry — the subset of
439
+ * {@link ACTION_ACCESSOR_NAMES} it can actually answer for.
440
+ *
441
+ * A device only advertises what it can do: a smart light has no `camera` accessor at all, rather than
442
+ * one that answers `undefined` forever. That makes the object's own shape a truthful description of the
443
+ * device, and it makes `"camera" in dev` mean what a reader expects it to.
444
+ * @internal
445
+ */
446
+ export declare function accessorNamesFor(capabilities: ReadonlySet<Capability>): (keyof DeviceActionMap)[];
447
+ /** Whether this resolved set owns a provider-backed member with the given action name. */
448
+ export declare function hasProvidedAction(capabilities: ReadonlySet<Capability>, action: string): boolean;
449
+ /**
450
+ * Build the map of action-objects for the capabilities a device HAS, e.g.
451
+ * `{ light: {on, off, ...}, ptz: {rotate, ...}, camera: {on, snapshot, ...} }`. Keys are
452
+ * camelCased {@link Capability} ids. Only capabilities in `caps` with an `actions` factory appear.
453
+ * Consumed by `Device` to install the fluent `dev.<cap>()` accessors. `media`/`ff09Settings`/`rawDp`
454
+ * are the optional transport-supplied providers — media actions (snapshot/live/record) only appear when
455
+ * a provider is supplied, likewise `dev.lock()?.getAutoLockState()`, and a member declaring a
456
+ * `decode` returns `undefined` without a codec. Each names a technical job — a media session,
457
+ * an `ff09` settings query, a payload shape — never the capability that calls it first; see
458
+ * {@link CapabilityModule.actions}'s doc before adding another.
459
+ * @internal
460
+ */
461
+ export declare function buildActions(caps: readonly Capability[], deps: MemberDeps): Partial<DeviceActionMap>;
462
+ /**
463
+ * Describe the capability objects a device has bound — the capability half of `Device.describe()`.
464
+ *
465
+ * The projection point for discovery, the way {@link buildActions} is for control: `device.ts` hands
466
+ * over the bound objects it holds and gets back what each exposes, without naming a capability.
467
+ * @internal
468
+ */
469
+ export declare function describeCapabilities(bound: Partial<DeviceActionMap>, ctx?: AvailabilityContext): CapabilityDescriptor[];
470
+ export type { CommandContext, CapabilityActions, CapabilityStateReader, CapabilityModule, DetectionSpec, CapabilityFrame, CapabilityEvent, InboundSignal, EventMapping, ProductLine, ActionArgSpec, DecodedState, } from "./types.js";
471
+ /**
472
+ * The value-kind vocabulary a read is annotated with, re-exported from the barrel that publishes the
473
+ * read itself, so the union a member's `kind` is drawn from is reachable from the same import.
474
+ */
475
+ export type { ValueKind, KnownValueKind } from "../types.js";
476
+ export { KNOWN_VALUE_KINDS, isKnownValueKind } from "../types.js";
477
+ /**
478
+ * The member-table vocabulary a capability's surface is declared in — published because
479
+ * `CapabilityModule.members` is.
480
+ */
481
+ export type { Members, Member, ValueMember, ActionMember, MethodMember, ProvidedMember, AnyProvidedMember, MemberDeps, Providers, Surface, } from "./members.js";
482
+ /**
483
+ * The type-level parts `Surface` is assembled from — published because `Surface` NAMES them.
484
+ * `ValueKeys` and its
485
+ * siblings select which members each branch of the projection covers; `ReadValue`/`WriteValue` say what
486
+ * a getter answers and a setter takes; `SetterName` gives the setter its name.
487
+ */
488
+ export type { ValueKeys, WritableKeys, ActionKeys, MethodKeys, ProvidedKeys, UnverifiedKeys, ConditionalKeys, ValueOf, ReadValue, WriteValue, SetterName, } from "./members.js";
489
+ export { CapabilityNotSupportedError } from "./types.js";
490
+ /**
491
+ * The shape `Device.describe()` answers with — published from the barrel that publishes the surface it
492
+ * describes.
493
+ */
494
+ export type { DeviceManifest, CapabilityDescriptor, ReadDescriptor, ActionDescriptor } from "./manifest.js";
495
+ export type { ActionSpec } from "./types.js";
496
+ /**
497
+ * Ask ONE method what it accepts, without walking a whole manifest.
498
+ *
499
+ * `Device.describe()` is the discovery entry point; this is the same answer for a method already in
500
+ * hand, read off the function itself rather than carried beside it. Every member
501
+ * kind is wrapped, so it answers for a derived setter, a momentary action and a method alike, and
502
+ * `undefined` for an action nothing describes.
503
+ */
504
+ export { actionSpecOf } from "./access.js";
505
+ export type { PtzActions, LightActions, SmartLightActions, RgbColor, CameraActions, LockActions, SirenActions, ArmingActions, BatteryActions, MotionActions, ContactActions, LeakActions, SmokeActions, CoActions, KeypadActions, RtspActions, VacuumCleanActions, SuctionActions, LocateActions, };
506
+ /**
507
+ * The member table each `*Actions` type is DERIVED from (`LockActions = Surface<typeof LOCK_MEMBERS>`),
508
+ * so the type names the table and the table is part of the published surface.
509
+ *
510
+ * It is also the one declaration of what a capability exposes: per feature its wire id, value type,
511
+ * `kind`, domain (`min`/`max`/`enumValues`), presence gate and the description published for it.
512
+ * `Surface` and the runtime install from the same entry, so there is no second table to disagree with it.
513
+ */
514
+ export { ARMING_MEMBERS } from "./arming.js";
515
+ export { AUDIO_MEMBERS } from "./audio.js";
516
+ export { BATTERY_MEMBERS } from "./battery.js";
517
+ export { CAMERA_MEMBERS } from "./camera.js";
518
+ export { CO_MEMBERS } from "./co.js";
519
+ export { CONTACT_MEMBERS } from "./contact.js";
520
+ export { DOORBELL_MEMBERS } from "./doorbell.js";
521
+ export { KEYPAD_MEMBERS } from "./keypad.js";
522
+ export { LEAK_MEMBERS } from "./leak.js";
523
+ export { LIGHT_MEMBERS } from "./light.js";
524
+ export { LOCATE_MEMBERS } from "./locate.js";
525
+ export { LOCK_MEMBERS } from "./lock.js";
526
+ export { MOTION_MEMBERS } from "./motion.js";
527
+ export { PTZ_MEMBERS } from "./ptz.js";
528
+ export { RTSP_MEMBERS } from "./rtsp.js";
529
+ export { SIREN_MEMBERS } from "./siren.js";
530
+ export { SMART_LIGHT_MEMBERS } from "./smart-light.js";
531
+ export { SMOKE_MEMBERS } from "./smoke.js";
532
+ export { SUCTION_MEMBERS } from "./suction.js";
533
+ export { VACUUM_CLEAN_MEMBERS } from "./vacuum-clean.js";
534
+ export type { DeviceInfo } from "./info.js";
535
+ export type { AutoSpotlightOptions } from "./light.js";
536
+ export type { DoorbellActions, QuickResponse } from "./doorbell.js";
537
+ export { parseQuickResponses } from "./doorbell.js";
538
+ export { DoorbellRingtone, type DoorbellRingtoneValue } from "./doorbell.js";
539
+ export type { AudioActions } from "./audio.js";
540
+ export { VACUUM_DOCK_MEMBERS } from "./vacuum-dock.js";
541
+ export type { VacuumDockActions } from "./vacuum-dock.js";
542
+ /**
543
+ * The dock's activity is the declared return of the public `dev.vacuumDock()?.dockState` getter, so the
544
+ * union is published — and the list it is taken from, since it names its own.
545
+ */
546
+ export type { DockActivity } from "./vacuum-dock.js";
547
+ export { DOCK_ACTIVITIES } from "./vacuum-dock.js";
548
+ export { HubAlarmTone, type HubAlarmToneValue } from "./siren.js";
549
+ /**
550
+ * RoboVac activity and clean type are the declared returns of the public `dev.vacuumClean()` getters,
551
+ * so both unions are published.
552
+ */
553
+ export type { VacuumActivity, VacuumCleanType, CarpetStrategy, CleanExtent } from "./vacuum-clean.js";
554
+ /** The lists those unions are taken from — published because each union names its own. */
555
+ export { VACUUM_ACTIVITIES, VACUUM_CLEAN_TYPES, CARPET_STRATEGIES, CLEAN_EXTENTS, MOP_LEVELS } from "./vacuum-clean.js";
556
+ export { SuctionLevel, suctionLevelName, type SuctionLevelValue } from "./suction.js";
557
+ export type { PtzPresetActions, ZoomRegion, PtzPreset, PtzPresetImage } from "./ptz.js";
558
+ export { ArmingMode } from "./arming.js";
559
+ export type { AlarmDelayConfig, AlarmDelayCountdown, AlarmDelayDeviceAction, AlarmDelaySeconds } from "./arming.js";
560
+ export { PtzDirection } from "./ptz.js";
561
+ export { AiDetectType, encodeAiDetectType, decodeAiDetectType, type AiDetectFlags } from "./motion.js";
@@ -0,0 +1,28 @@
1
+ import type { CapabilityModule } from "./types.js";
2
+ /**
3
+ * Per-device identity metadata — the object returned by `dev.info()`. The standard identity fields
4
+ * (manufacturer / model / serial / name / firmware / hardware version); `deviceType` is diagnostic.
5
+ */
6
+ export interface DeviceInfo {
7
+ /** Always "eufy" (Anker AIoT) — no per-device manufacturer on the wire. */
8
+ manufacturer: string;
9
+ /** Model / T-code (e.g. "T8410"), when known. */
10
+ model?: string;
11
+ /** Full device serial number, when known. */
12
+ serialNumber?: string;
13
+ /** Display name, when known. */
14
+ name?: string;
15
+ /** eufy numeric DeviceType, when known (diagnostic). */
16
+ deviceType?: number;
17
+ /** Firmware (main software) version (`main_sw_version`), when the device record carries it. */
18
+ firmwareVersion?: string;
19
+ /** Hardware version (`main_hw_version`), when the device record carries it. */
20
+ hardwareVersion?: string;
21
+ /** Secondary/sub firmware version (`sec_sw_version`, app label `firmware_sub_version`), when present. */
22
+ firmwareSubVersion?: string;
23
+ /** Wi-Fi MAC address (`wifi_mac`, app label `mac_address`), when present. */
24
+ macAddress?: string;
25
+ /** Whether the device reports a firmware update is available (`needUpdate`). */
26
+ updateAvailable?: boolean;
27
+ }
28
+ export declare const INFO: CapabilityModule;
@@ -0,0 +1,61 @@
1
+ import { type Surface } from "./members.js";
2
+ import type { CapabilityModule } from "./types.js";
3
+ /**
4
+ * Every `keypad` feature, declared once. Only `rssi` is a verified read.
5
+ *
6
+ * The battery pair is `unexposed`: both ids are placeholders, and the keypad's real battery state is
7
+ * reported under model-specific params (`keypadBatteryCapState` / `keypadBatteryChargerState`, seen
8
+ * live) whose low/charging semantics are not confirmed. They stay in the schema so a diagnosis can
9
+ * reach them through `getProperty`, with no typed getter asserting a meaning this SDK cannot back.
10
+ * A live probe of the fleet's T8960 confirms neither is reported at all today.
11
+ *
12
+ * Exported but NOT published: each entry states its wire id and the evidence it was confirmed on,
13
+ * which the reference site does not carry.
14
+ * @internal
15
+ */
16
+ export declare const KEYPAD_MEMBERS: {
17
+ /**
18
+ * `unexposed`, so it reaches a diagnosis through `getProperty` but gets no typed getter. 1103 is a
19
+ * placeholder AND a likely collision — the app's own param table names 1103 GET_CAMERA_INFO — so a
20
+ * getter here would be asserting a meaning nothing backs. The keypad's real battery state arrives
21
+ * under `keypadBatteryCapState`, whose low/charging semantics are not confirmed.
22
+ */
23
+ readonly batteryLow: {
24
+ readonly param: 1103;
25
+ readonly type: "bool";
26
+ readonly kind: "boolean";
27
+ readonly provenance: "guessed";
28
+ readonly unexposed: true;
29
+ readonly description: string;
30
+ };
31
+ /**
32
+ * The charging half of the battery pair, `unexposed` for the same reason as `batteryLow`: 1102 is a
33
+ * placeholder id, and the state the keypad actually reports (`keypadBatteryChargerState`) has no
34
+ * confirmed value space. In the schema for `getProperty`, absent from the typed surface.
35
+ */
36
+ readonly charging: {
37
+ readonly param: 1102;
38
+ readonly type: "bool";
39
+ readonly kind: "boolean";
40
+ readonly provenance: "guessed";
41
+ readonly unexposed: true;
42
+ readonly description: "Keypad charging flag. UNVERIFIED: placeholder id pending verification.";
43
+ };
44
+ /**
45
+ * The keypad's link quality in dBm — the one verified read in this table, on the same param 1141 the
46
+ * other sub-1G sensors report signal strength on. Reported as the device measures it: raw dBm, never
47
+ * normalised to a bar count.
48
+ */
49
+ readonly rssi: {
50
+ readonly param: 1141;
51
+ readonly type: "number";
52
+ readonly unit: "dBm";
53
+ readonly kind: "dbm";
54
+ readonly provenance: "verified";
55
+ readonly description: "Keypad signal strength (verified: param 1141 = RSSI).";
56
+ };
57
+ };
58
+ /** Bound keypad reads — the object returned by `dev.keypad()`. Read-only. */
59
+ export type KeypadActions = Surface<typeof KEYPAD_MEMBERS>;
60
+ /** `keypad` — security keypad. Battery low/charging and signal. Param ids here are placeholders apart from RSSI. */
61
+ export declare const KEYPAD: CapabilityModule;