@mega-yfue/eufy-sdk 0.6.0-beta.45 → 0.6.0-beta.47

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.
@@ -128,9 +128,9 @@ export declare const CELL_PARAMS: readonly number[];
128
128
  */
129
129
  export declare function isChargingState(v: string | number | boolean): boolean;
130
130
  /**
131
- * The published `battery` table: the full camera surface, minus every member on the `sensor` codec —
132
- * a sensor's 1101 is a non-cell sentinel and it has none of the camera power reads, so it exposes no
133
- * battery entity (see {@link notOnSensor}). Every getter, setter and description derives from this.
131
+ * The published `battery` table: the full camera surface, minus every member but `batteryLow` on the
132
+ * `sensor` codec — a sensor's 1101 is a non-cell sentinel and it has none of the camera power reads, so
133
+ * it exposes its low-battery flag alone (see {@link notOnSensor}). Every getter, setter and description derives from this.
134
134
  *
135
135
  * Exported but NOT published: each entry states its wire id and the evidence it was confirmed on,
136
136
  * which the reference site does not carry.
@@ -364,6 +364,22 @@ export declare const BATTERY_MEMBERS: {
364
364
  readonly unexposed: true;
365
365
  readonly description: string;
366
366
  };
367
+ /**
368
+ * A sensor's battery is low. The app reads the entry sensor's 1552 and the motion sensor's 1601 into the
369
+ * same field (`sensor_is_low_power`, `asBoolean`), so one member reads whichever the sensor reports.
370
+ * Present on the `sensor` codec only: a camera or a lock reports a level instead.
371
+ */
372
+ readonly batteryLow: {
373
+ readonly param: 1552;
374
+ readonly readAliases: readonly [{
375
+ readonly paramType: 1601;
376
+ }];
377
+ readonly type: "bool";
378
+ readonly kind: "boolean";
379
+ readonly provenance: "verified";
380
+ readonly available: (ctx: AvailabilityContext) => boolean;
381
+ readonly description: "Sensor battery low (1552 entry sensor, 1601 motion sensor; sensor_is_low_power).";
382
+ };
367
383
  };
368
384
  export declare const BATTERY: CapabilityModule;
369
385
  /**
@@ -49,7 +49,7 @@ export declare const CAMERA_CMD: {
49
49
  * (1013). (Some models omit full colour; enum in {@link NightVision}.)
50
50
  */
51
51
  readonly NIGHT_VISION_TYPE: 1277;
52
- /** T8442 infrared night vision on/off: direct L1 int-string, hardware verified (0/1). */
52
+ /** Night vision on a device reporting 2002: direct level-1 [channel][value]. */
53
53
  readonly IC_NIGHT_VISION_TYPE: 1013;
54
54
  /**
55
55
  * Push-notification STYLE — how much a detection push carries: text alone, a thumbnail, or text
@@ -170,17 +170,19 @@ export declare const SoundDetectionType: {
170
170
  /** A sound-detection type — the value side of {@link SoundDetectionType}. */
171
171
  export type SoundDetectionTypeValue = (typeof SoundDetectionType)[keyof typeof SoundDetectionType];
172
172
  /**
173
- * Night-vision mode: 0=Off, 1=Infrared (the app shows "B&W Auto"), 2=FullColor ("Color"). Use
174
- * `NightVision.FullColor` etc. with `setNightVision` / `setProperty(sn,"nightVision",…)`. Some models
175
- * omit `FullColor`.
173
+ * Night-vision mode: 0=Off, 1=Infrared (the app shows "B&W Auto"), 2=FullColor ("Color"), 3=InfraredOn.
174
+ * Use `NightVision.FullColor` etc. with `setNightVision` / `setProperty(sn,"nightVision",…)`. Each model
175
+ * offers a subset.
176
176
  */
177
177
  export declare const NightVision: {
178
178
  /** Off — never use infrared. */
179
179
  readonly Off: 0;
180
- /** Infrared / "B&W Auto" — black-and-white night vision. */
180
+ /** Infrared / "B&W Auto" — black-and-white night vision, switched on when it gets dark. */
181
181
  readonly Infrared: 1;
182
182
  /** Full colour night vision (models with a spotlight / starlight sensor). */
183
183
  readonly FullColor: 2;
184
+ /** Infrared held on — black-and-white night vision, not switched by the light level. */
185
+ readonly InfraredOn: 3;
184
186
  };
185
187
  /** A night-vision mode — the value side of {@link NightVision}. */
186
188
  export type NightVisionValue = (typeof NightVision)[keyof typeof NightVision];
@@ -261,8 +263,8 @@ export type CameraActions = Surface<typeof CAMERA_MEMBERS> & {
261
263
  /** Power the camera off. */
262
264
  off(): Promise<void>;
263
265
  };
264
- /** T8442 has a binary night-vision wire, unlike cameras with the three-mode 1277 control. */
265
- declare function isT8442(ctx: AvailabilityContext): boolean;
266
+ /** A device that reports its night vision on 2002 and not on 1277. */
267
+ declare function readsNightVisionOn2002(ctx: AvailabilityContext): boolean;
266
268
  /** A C30/C31 has reported no 1716 and no doorbell LED write was tried on it, so it keeps 1045. */
267
269
  declare const doorbellLed: (ctx: AvailabilityContext) => boolean;
268
270
  /**
@@ -436,16 +438,7 @@ export declare const CAMERA_MEMBERS: {
436
438
  readonly description: string;
437
439
  readonly write: (v: string | number | boolean, ctx: CommandContext) => Command | undefined;
438
440
  };
439
- /**
440
- * Three modes, and `FullColor` is the conditional one: a model without a spotlight or starlight
441
- * sensor omits it, and the wire accepts the value regardless — the device's own reported set is the
442
- * only statement of which of the three it has. `coerceEnumValue` rejects a value outside
443
- * {@link NightVision} rather than coercing it. The payload key on the wire is `night_sion`.
444
- *
445
- * 1277 carries more than these three on some models: the V6 app's per-model mappings put modes on
446
- * 3, 5, 6 and 8 as well, and which model takes which mapping is not in the app bundle. A reported value
447
- * outside the published options reads as `undefined` rather than as an unnamed number.
448
- */
441
+ /** Modes come from the thing description (`thing`); unlisted values read as `undefined`. */
449
442
  readonly nightVision: {
450
443
  readonly param: 1277;
451
444
  readonly type: "enum";
@@ -454,18 +447,17 @@ export declare const CAMERA_MEMBERS: {
454
447
  readonly 0: "Off";
455
448
  readonly 1: "Infrared";
456
449
  readonly 2: "Full Color";
450
+ readonly 3: "Infrared On";
457
451
  };
458
- readonly enumValuesFor: (ctx: AvailabilityContext) => {
459
- 0: string;
460
- 1: string;
461
- } | undefined;
452
+ readonly thing: readonly ["nightvision_type_new", "nightvision_type"];
462
453
  readonly provenance: "verified";
463
454
  readonly available: typeof isCameraCodec;
464
455
  readonly readAvailable: (ctx: AvailabilityContext) => boolean;
465
456
  readonly readAliases: readonly [{
466
457
  readonly paramType: 2002;
467
- readonly available: typeof isT8442;
458
+ readonly available: typeof readsNightVisionOn2002;
468
459
  }];
460
+ readonly coerce: (raw: string | number | boolean) => number;
469
461
  readonly description: string;
470
462
  readonly write: (v: string | number | boolean, ctx: CommandContext) => Command | undefined;
471
463
  };
@@ -21,18 +21,6 @@ export declare const CO_MEMBERS: {
21
21
  readonly provenance: "guessed";
22
22
  readonly description: "Carbon-monoxide detected. UNVERIFIED: placeholder id pending capture verification.";
23
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
24
  };
37
25
  /** Bound CO-detector reads — the object returned by `dev.co()`. Read-only. */
38
26
  export type CoActions = Surface<typeof CO_MEMBERS>;
@@ -1,53 +1,42 @@
1
1
  import { type Surface } from "./members.js";
2
- import type { CapabilityModule } from "./types.js";
2
+ import type { AvailabilityContext, CapabilityModule } from "./types.js";
3
3
  /**
4
- * The entry sensor's own **command/param ids** — its built-in alarm buzzer (sounds when the door
5
- * opens while armed), separate from the open/close contact read. Both write wires were captured live
6
- * on a T90E0 (2026-08-03).
4
+ * The entry sensor's own command/param ids, each the app's own (`APP_CMD_*` in the product's settings
5
+ * bundle) and reported by a real sensor.
7
6
  */
8
7
  export declare const CONTACT_CMD: {
9
- /** Alarm sound/tone selection (app `APP_CMD_ALARM_SOUND_TYPE`). See {@link EntryAlarmTone}. */
8
+ /** Contact state (`APP_CMD_ENTRY_SENSOR_STATUS`, identifier `sensor_door_status`). */
9
+ readonly STATUS: 1550;
10
+ /** Removed from its mount (`APP_CMD_DEV_DISASSEMBLE`, identifier `sensor_disassemble_status`). */
11
+ readonly TAMPER: 61015;
12
+ /** Bypassed by the alarm (`APP_CMD_DEV_ENTRY_BYPASS`, identifier `sensor_door_bypass_status`). */
13
+ readonly BYPASS: 61016;
14
+ /** Left-open alert (`APP_CMD_SENSOR_OPEN_STATUS_ALERT`, identifier `sensor_door_open_status_alert_config`). */
15
+ readonly OPEN_ALERT: 1290;
16
+ /** Daily state check (`APP_CMD_SENSOR_DOOR_DAILY_CHECK`, identifier `sensor_door_daily_check_status_config`). */
17
+ readonly DAILY_CHECK: 1291;
18
+ /** Alarm tone (`APP_CMD_ALARM_SOUND_TYPE`, identifier `device_alarm_sound_type`). */
10
19
  readonly ALARM_SOUND_TYPE: 1507;
11
- /** Alarm volume (app `APP_CMD_ALARM_VOLUME_VALUE`). A device level 1-26, not a percentage. */
20
+ /** Alarm volume (`APP_CMD_ALARM_VOLUME_VALUE`, identifier `alarm_volume_value`). */
12
21
  readonly ALARM_VOLUME: 1508;
13
22
  };
14
- /**
15
- * The entry sensor's built-in alarm tone: silent, or one of four chimes. Pass a value to
16
- * `setAlarmSoundType`.
17
- */
18
- export declare const EntryAlarmTone: {
19
- /** Silent — no alarm tone. */
20
- readonly None: 0;
21
- readonly Water: 1;
22
- readonly Classic: 2;
23
- readonly Light: 3;
24
- readonly Ding: 4;
25
- };
26
- /** An entry-sensor alarm tone — the value side of {@link EntryAlarmTone}. */
27
- export type EntryAlarmToneValue = (typeof EntryAlarmTone)[keyof typeof EntryAlarmTone];
28
- /**
29
- * Bound entry-sensor controls — the object returned by `dev.contact()`.
30
- *
31
- * Everything is DERIVED from `CONTACT_MEMBERS`. The open/close read is the headline; the entry
32
- * sensor also carries a built-in alarm buzzer whose tone and volume are writable, each setter present
33
- * only when the device reports the backing param.
34
- */
23
+ /** The left-open alert delays the app offers, in minutes (`sensor_door_open_status_alert_config`). */
24
+ declare const OPEN_ALERT_MINUTES: readonly [5, 10, 15, 30, 60];
25
+ /** Bound entry-sensor controls — the object returned by `dev.contact()`, derived from `CONTACT_MEMBERS`. */
35
26
  export type ContactActions = Surface<typeof CONTACT_MEMBERS>;
36
27
  /**
37
- * Every `contact` feature, declared once. `contact` (1550) and `lastSeen` (1551) are verified reads;
38
- * the built-in alarm tone (1507) and volume (1508) are verified writes captured live on a T90E0.
28
+ * Every `contact` feature, declared once, each on the identifier the product's thing description names
29
+ * and the param the app's settings bundle reads it from.
39
30
  *
40
- * Exported but NOT published: each entry states its wire id and the evidence it was confirmed on,
41
- * which the reference site does not carry.
31
+ * Exported but NOT published: each entry states its wire id and its evidence, which the reference site
32
+ * does not carry.
42
33
  * @internal
43
34
  */
44
35
  export declare const CONTACT_MEMBERS: {
45
36
  /**
46
- * The headline read: `true` when the door or window is open. Polarity is the V6 app's own
47
- * `"1".equals(e)` — see `contactOpen`, which normalises every inbound source through one
48
- * predicate so the poll, the push and the station notify cannot disagree about what open means.
49
- * Reporting 1550 is also this capability's detection evidence, so a device with this getter is
50
- * confirmed to be a contact sensor.
37
+ * The headline read: `true` when the door or window is open. Every inbound source normalises through
38
+ * `contactOpen`, so the poll, the push and the station notify cannot disagree about what open means.
39
+ * Reporting 1550 is also this capability's detection evidence.
51
40
  */
52
41
  readonly open: {
53
42
  readonly param: 1550;
@@ -55,68 +44,128 @@ export declare const CONTACT_MEMBERS: {
55
44
  readonly type: "bool";
56
45
  readonly kind: "boolean";
57
46
  readonly provenance: "verified";
58
- readonly description: "Contact state, true=open (verified: param 1550 entry-sensor contact).";
47
+ readonly description: "Contact state, true=open (1550, sensor_door_status).";
48
+ };
49
+ /** The sensor was removed from its mount. Reported by a T8900; the meaning of a set value is the product bundle's. */
50
+ readonly tampered: {
51
+ readonly param: 61015;
52
+ readonly type: "bool";
53
+ readonly kind: "boolean";
54
+ readonly provenance: "apk";
55
+ readonly description: "Removed from its mount (61015, sensor_disassemble_status).";
56
+ };
57
+ /** The alarm currently skips this sensor. Reported by a T8900; the meaning of a set value is the product bundle's. */
58
+ readonly bypassed: {
59
+ readonly param: 61016;
60
+ readonly type: "bool";
61
+ readonly kind: "boolean";
62
+ readonly provenance: "apk";
63
+ readonly description: "Bypassed by the alarm (61016, sensor_door_bypass_status).";
59
64
  };
60
65
  /**
61
- * Unix seconds at which the sensor last checked in — the liveness read beside the contact state, and
62
- * the way to tell a genuinely closed door from a sensor that stopped reporting. A `timestamp` kind
63
- * takes no `unit`: it is an instant, not a duration.
66
+ * The left-open alert config, whole as the sensor stores it (base64 JSON). Its two fields are the
67
+ * members below; both are set together by `setOpenAlert`, since one frame carries both.
64
68
  */
65
- readonly lastSeen: {
66
- readonly param: 1551;
67
- readonly type: "number";
68
- readonly kind: "timestamp";
69
+ readonly openAlertConfig: {
70
+ readonly param: 1290;
71
+ readonly type: "string";
72
+ readonly kind: "text";
69
73
  readonly provenance: "verified";
70
- readonly description: "Last-seen unix timestamp, seconds (verified: param 1551).";
74
+ readonly unexposed: true;
75
+ readonly writtenElsewhere: true;
76
+ readonly description: "Left-open alert config, base64 JSON {door_enable,door_time_point} (1290).";
71
77
  };
72
- /**
73
- * Link quality to whichever radio the sensor is paired over, in dBm as the device measures it. The
74
- * same param 1141 the other sub-1G sensors report on, so the number is comparable across them —
75
- * unlike a bars mapping, which this SDK never applies.
76
- */
77
- readonly rssi: {
78
- readonly param: 1141;
78
+ /** Whether a notification fires when the door stays open longer than {@link CONTACT_MEMBERS.openAlertMinutes}. */
79
+ readonly openAlert: {
80
+ readonly readsFrom: "openAlertConfig";
81
+ readonly type: "bool";
82
+ readonly kind: "boolean";
83
+ readonly provenance: "verified";
84
+ readonly decode: (raw: unknown) => boolean | undefined;
85
+ readonly description: "Left-open alert on (1290 door_enable). Set with setOpenAlert.";
86
+ };
87
+ /** How long the door may stay open before the alert fires: one of 5, 10, 15, 30 or 60 minutes. */
88
+ readonly openAlertMinutes: {
89
+ readonly readsFrom: "openAlertConfig";
79
90
  readonly type: "number";
80
- readonly unit: "dBm";
81
- readonly kind: "dbm";
91
+ readonly kind: "scalar";
92
+ readonly provenance: "verified";
93
+ readonly decode: (raw: unknown) => number | undefined;
94
+ readonly description: "Left-open alert delay, minutes: 5, 10, 15, 30 or 60 (1290 door_time_point).";
95
+ };
96
+ /** The daily state check config, whole (base64 JSON); its fields are the members below. */
97
+ readonly dailyCheckConfig: {
98
+ readonly param: 1291;
99
+ readonly type: "string";
100
+ readonly kind: "text";
101
+ readonly provenance: "verified";
102
+ readonly unexposed: true;
103
+ readonly writtenElsewhere: true;
104
+ readonly description: "Daily check config, base64 JSON {door_enable,door_time_interval} (1291).";
105
+ };
106
+ /** Whether the sensor's state is notified at each of {@link CONTACT_MEMBERS.dailyCheckTimes}. */
107
+ readonly dailyCheck: {
108
+ readonly readsFrom: "dailyCheckConfig";
109
+ readonly type: "bool";
110
+ readonly kind: "boolean";
82
111
  readonly provenance: "verified";
83
- readonly description: "Sub-1G/Wi-Fi signal strength (verified: param 1141 = RSSI).";
112
+ readonly decode: (raw: unknown) => boolean | undefined;
113
+ readonly description: "Daily state check on (1291 door_enable). Set with setDailyCheck.";
84
114
  };
115
+ /** The times of day the state is notified, `HH:MM` comma-separated in the order the sensor holds them. */
116
+ readonly dailyCheckTimes: {
117
+ readonly readsFrom: "dailyCheckConfig";
118
+ readonly type: "string";
119
+ readonly kind: "text";
120
+ readonly provenance: "verified";
121
+ readonly decode: (raw: unknown) => string | undefined;
122
+ readonly description: "Daily check times, HH:MM comma-separated (1291 door_time_interval, minutes since midnight).";
123
+ };
124
+ /**
125
+ * Turn the left-open alert on or off, with its delay. One frame carries both: `1350` SET_PAYLOAD,
126
+ * sub-command 1290, `{door_enable, door_time_point}` — the product's settings bundle's own frame.
127
+ * Verified live on a T8900: param 1290 read back the written value and the app showed it.
128
+ */
129
+ readonly setOpenAlert: import("./members.js").MethodMember<(on: boolean, minutes: (typeof OPEN_ALERT_MINUTES)[number]) => Promise<void>>;
85
130
  /**
86
- * Rejected, not clamped, outside the tone enum: a fire-and-forget write of a bogus tone would look like
87
- * it worked. The wire is a direct-binary scalar `[ch][value][acct]` at signCode 8 — the app's own
88
- * captured frame.
131
+ * Turn the daily state check on or off, with its times of day. One frame carries both: `1350`
132
+ * SET_PAYLOAD, sub-command 1291, `{door_enable, door_time_interval}` with each time as minutes since
133
+ * midnight — the product's settings bundle's own frame.
134
+ * Verified live on a T8900: param 1291 read back the written times and the app showed them.
135
+ */
136
+ readonly setDailyCheck: import("./members.js").MethodMember<(on: boolean, times: readonly string[]) => Promise<void>>;
137
+ /**
138
+ * The built-in alarm tone, offered where the product's description lists it: a sensor may report the
139
+ * param while the app offers no such setting on it. Rejected, not clamped, outside the listed tones.
140
+ * Write: a direct-binary scalar `[ch][value][acct]` at signCode 8, captured live on a T90E0.
89
141
  */
90
142
  readonly alarmSoundType: {
91
143
  readonly param: 1507;
92
144
  readonly type: "enum";
93
145
  readonly kind: "enum";
94
146
  readonly enumValues: Record<number, string>;
147
+ readonly thing: readonly ["device_alarm_sound_type"];
95
148
  readonly provenance: "verified";
96
- readonly requires: readonly [1507];
149
+ readonly available: (ctx: AvailabilityContext) => boolean;
97
150
  readonly args: readonly [{
98
151
  readonly name: "tone";
99
152
  readonly kind: "enum";
100
- readonly description: "Silent (0) or one of the four chimes.";
153
+ readonly description: "Silent (0) or one of the four tones.";
101
154
  }];
102
- readonly description: string;
155
+ readonly description: "Alarm tone (1507, device_alarm_sound_type): 0=None,1=Water,2=Classics,3=Light,4=Ding.";
103
156
  readonly write: (v: string | number | boolean, ctx: import("./types.js").CommandContext) => import("../../index.js").Command | undefined;
104
157
  };
105
158
  /**
106
- * `1350` SET_PAYLOAD, `mChannel` = the device channel, `mValue3` 0, payload carrying the channel and a
107
- * transaction stamp — the byte-shape of the app's own captured frame. Out of range is refused rather
108
- * than clamped: the app's slider has no values outside it, so one is a caller error, not a nudge.
109
- *
110
- * Level-2 only, though the `mValue3` 0 would allow `"auto"`: an entry sensor's session IS its
111
- * HomeBase's, which always holds a key — the second of `setPayload`'s two conditions, not an oversight
112
- * of the first.
159
+ * The built-in alarm volume, a device level 1-26, offered where the product's description lists it.
160
+ * Write: `1350` SET_PAYLOAD with `mChannel` the device channel, `mValue3` 0, payload `{channel, volume,
161
+ * transaction}` — the app's own captured frame on a T90E0. Out of range is refused, not clamped.
113
162
  */
114
163
  readonly alarmVolume: {
115
164
  readonly param: 1508;
116
165
  readonly type: "number";
117
166
  readonly kind: "scalar";
118
167
  readonly provenance: "verified";
119
- readonly requires: readonly [1508];
168
+ readonly available: (ctx: AvailabilityContext) => boolean;
120
169
  readonly min: 1;
121
170
  readonly max: 26;
122
171
  readonly args: readonly [{
@@ -124,14 +173,12 @@ export declare const CONTACT_MEMBERS: {
124
173
  readonly kind: "scalar";
125
174
  readonly min: 1;
126
175
  readonly max: 26;
127
- readonly description: "A device level, not a percentage.";
176
+ readonly description: "A device level.";
128
177
  }];
129
- readonly description: string;
178
+ readonly description: "Alarm volume (1508, alarm_volume_value), a device level 1-26, not a percentage.";
130
179
  readonly write: (v: string | number | boolean, ctx: import("./types.js").CommandContext) => import("../../index.js").Command | undefined;
131
180
  };
132
181
  };
133
- /**
134
- * `contact` — entry/door-window sensor. `contact` (1550) and `lastSeen` (1551) are verified; the
135
- * built-in alarm tone (1507) and volume (1508) are verified writes captured live on a T90E0.
136
- */
182
+ /** `contact` — entry (door/window) sensor. */
137
183
  export declare const CONTACT: CapabilityModule;
184
+ export {};
@@ -11,7 +11,6 @@ import { type CapabilityDescriptor } from "./manifest.js";
11
11
  import type { CapabilityModule, EventMapping, CapabilityEvent, DecodedState, InboundSignal, CommandContext, AvailabilityContext } from "./types.js";
12
12
  import type { Command } from "../../core/contracts.js";
13
13
  export { RtspRecordingMode, type RtspRecordingModeValue, type RtspAuthScheme } from "./rtsp.js";
14
- export { EntryAlarmTone, type EntryAlarmToneValue } from "./contact.js";
15
14
  export { SirenVolume, type SirenVolumeValue, SirenAlarmDuration, type SirenAlarmDurationValue } from "./siren.js";
16
15
  /**
17
16
  * Ask what a bound capability can be told to change but can never report back, and what it reports without
@@ -37,6 +36,7 @@ import type { ContactActions } from "./contact.js";
37
36
  import type { LeakActions } from "./leak.js";
38
37
  import type { SmokeActions } from "./smoke.js";
39
38
  import type { CoActions } from "./co.js";
39
+ import type { LinkActions } from "./link.js";
40
40
  import type { KeypadActions } from "./keypad.js";
41
41
  import type { RtspActions } from "./rtsp.js";
42
42
  import type { VacuumCleanActions } from "./vacuum-clean.js";
@@ -411,16 +411,18 @@ export interface DeviceActionMap {
411
411
  doorbell: DoorbellActions;
412
412
  /** Motion/PIR: `setDetection(on)` (sensitivity is read-only until its write wire is captured). */
413
413
  motion: MotionActions;
414
- /** Entry (door/window) sensor: reads `open`, `lastSeen`, `rssi`, `alarmSoundType`, `alarmVolume`; writes `setAlarmSoundType`, `setAlarmVolume` (present when the sensor reports the alarm params). */
414
+ /** Entry (door/window) sensor: reads `open`, `alarmSoundType`, `alarmVolume`; writes `setAlarmSoundType`, `setAlarmVolume` (present when the sensor reports the alarm params). */
415
415
  contact: ContactActions;
416
- /** Water-leak / freeze sensor reads (read-only): `leakDetected`, `lastSeen`. */
416
+ /** Water and freeze sensor reads (read-only): `leakDetected`, `lowTemperature`, `lowTemperatureThreshold`. */
417
417
  leak: LeakActions;
418
- /** Smoke-detector reads (read-only): `smokeDetected`, `lastSeen`. */
418
+ /** Smoke-detector reads (read-only): `smokeDetected`. */
419
419
  smoke: SmokeActions;
420
- /** CO-detector reads (read-only): `coDetected`, `lastSeen`. */
420
+ /** CO-detector reads (read-only): `coDetected`. */
421
421
  co: CoActions;
422
- /** Security-keypad reads (read-only): `charging`, `rssi`. */
422
+ /** Security-keypad reads (read-only): `charging`. */
423
423
  keypad: KeypadActions;
424
+ /** Check-in and signal reads (read-only): `lastSeen`, `rssi`, each where the device reports it. */
425
+ link: LinkActions;
424
426
  /** RTSP publish for a NAS/NVR: `publish`/`withdraw` + `published`, `requireAuth`/`allowAnonymous`, `recordingMode`/`setRecordingMode`. One camera at a time per station. */
425
427
  rtsp: RtspActions;
426
428
  /** RoboVac core state and controls: `power`, `activity` (WorkStatus), `volume`, `battery`, `cleanType`; `setPower`, `startCleaning`, `returnToDock`, `pauseCleaning`. */
@@ -528,7 +530,7 @@ export type { ActionSpec } from "./types.js";
528
530
  * `undefined` for an action nothing describes.
529
531
  */
530
532
  export { actionSpecOf } from "./access.js";
531
- export type { PtzActions, LightActions, SmartLightActions, RgbColor, CameraActions, LockActions, SirenActions, ArmingActions, BatteryActions, MotionActions, ContactActions, LeakActions, SmokeActions, CoActions, KeypadActions, RtspActions, VacuumCleanActions, SuctionActions, MowerActions, LocateActions, SmartDropActions, };
533
+ export type { PtzActions, LightActions, SmartLightActions, RgbColor, CameraActions, LockActions, SirenActions, ArmingActions, BatteryActions, MotionActions, ContactActions, LeakActions, SmokeActions, CoActions, KeypadActions, LinkActions, RtspActions, VacuumCleanActions, SuctionActions, MowerActions, LocateActions, SmartDropActions, };
532
534
  /**
533
535
  * The member table each `*Actions` type is DERIVED from (`LockActions = Surface<typeof LOCK_MEMBERS>`),
534
536
  * so the type names the table and the table is part of the published surface.
@@ -545,6 +547,7 @@ export { CO_MEMBERS } from "./co.js";
545
547
  export { CONTACT_MEMBERS } from "./contact.js";
546
548
  export { DOORBELL_MEMBERS } from "./doorbell.js";
547
549
  export { KEYPAD_MEMBERS } from "./keypad.js";
550
+ export { LINK_MEMBERS } from "./link.js";
548
551
  export { LEAK_MEMBERS } from "./leak.js";
549
552
  export { LIGHT_MEMBERS } from "./light.js";
550
553
  export { LOCATE_MEMBERS } from "./locate.js";
@@ -2,8 +2,8 @@ import { isChargingState } from "./battery.js";
2
2
  import { type Surface } from "./members.js";
3
3
  import type { CapabilityModule } from "./types.js";
4
4
  /**
5
- * Every `keypad` feature, declared once. `rssi` is a verified read and `charging` follows the app's own
6
- * decode of the keypad's charger state.
5
+ * Every `keypad` feature, declared once. `charging` follows the app's own decode of the keypad's charger
6
+ * state.
7
7
  *
8
8
  * `batteryLow` is `unexposed`: the app maps its param to the same low-battery field the entry and motion
9
9
  * sensors feed, but its value decode is absent from the app's parser, so the polarity is not evidenced.
@@ -39,18 +39,6 @@ export declare const KEYPAD_MEMBERS: {
39
39
  readonly coerce: typeof isChargingState;
40
40
  readonly description: string;
41
41
  };
42
- /**
43
- * The keypad's link quality in dBm, on the same param 1141 the other sub-1G sensors report signal
44
- * strength on. Reported as the device measures it: raw dBm, never normalised to a bar count.
45
- */
46
- readonly rssi: {
47
- readonly param: 1141;
48
- readonly type: "number";
49
- readonly unit: "dBm";
50
- readonly kind: "dbm";
51
- readonly provenance: "verified";
52
- readonly description: "Keypad signal strength (verified: param 1141 = RSSI).";
53
- };
54
42
  };
55
43
  /** Bound keypad reads — the object returned by `dev.keypad()`. Read-only. */
56
44
  export type KeypadActions = Surface<typeof KEYPAD_MEMBERS>;
@@ -1,7 +1,21 @@
1
1
  import { type Surface } from "./members.js";
2
2
  import type { CapabilityModule } from "./types.js";
3
3
  /**
4
- * Every `leak` feature, declared once — the property schema and the evidence-gated getters derive from here.
4
+ * The water sensor's own param ids, each the app's own (`APP_CMD_*` in the product's settings bundle,
5
+ * the same number in every bundle that defines it).
6
+ */
7
+ export declare const LEAK_PARAM: {
8
+ /** Water detected (`APP_CMD_WATER_SENSOR_WATER_STATE`, identifier `sensor_water_status`). */
9
+ readonly WATER: 1820;
10
+ /** Temperature below the threshold (`APP_CMD_WATER_SENSOR_TEMPERATE_LOW`, `sensor_temperature_low_status`). */
11
+ readonly LOW_TEMPERATURE: 1822;
12
+ /** Low-temperature alarm threshold, °F (`APP_CMD_WATER_SENSOR_TEMPERATURE_ALARM`). */
13
+ readonly LOW_TEMPERATURE_THRESHOLD: 1873;
14
+ };
15
+ /**
16
+ * Every `leak` feature, declared once. The params are read as the app's settings bundle reads them
17
+ * (`asBoolean` for the two states, `asInt` for the threshold); no water sensor has been read yet, so
18
+ * each getter is present only where a sensor reports its param.
5
19
  *
6
20
  * Exported but NOT published: each entry states its wire id and the evidence it was confirmed on,
7
21
  * which the reference site does not carry.
@@ -9,35 +23,47 @@ import type { CapabilityModule } from "./types.js";
9
23
  */
10
24
  export declare const LEAK_MEMBERS: {
11
25
  /**
12
- * The alarm flag, modelled as state even though the sensor announces a leak as a PUSH EVENT rather
13
- * than by holding a param — so 1560 is a `guessed` placeholder and the evidence gate will normally
14
- * leave this getter uninstalled. The push event is the reliable channel for a leak; this read is
15
- * here so the flag has a home once a capture pins a real id.
26
+ * Water is detected. The app's own `event_sensor_water_detected_notify` is this param changing, so
27
+ * the state and the alert are one fact.
16
28
  */
17
29
  readonly leakDetected: {
18
- readonly param: 1560;
30
+ readonly param: 1820;
31
+ readonly type: "bool";
32
+ readonly kind: "boolean";
33
+ readonly provenance: "apk";
34
+ readonly description: "Water detected (1820, sensor_water_status).";
35
+ };
36
+ /** The temperature is below {@link LEAK_MEMBERS.lowTemperatureThreshold}: the freeze alarm. */
37
+ readonly lowTemperature: {
38
+ readonly param: 1822;
19
39
  readonly type: "bool";
20
40
  readonly kind: "boolean";
21
- readonly provenance: "guessed";
22
- readonly description: string;
41
+ readonly provenance: "apk";
42
+ readonly description: "Temperature below the alarm threshold (1822, sensor_temperature_low_status).";
23
43
  };
24
44
  /**
25
- * Unix seconds at which the sensor 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.
45
+ * The temperature, in °F, below which the freeze alarm fires: one of 32, 33, 35, 37 or 40 as the
46
+ * product's description lists them. The write is the bundle's `1350` SET_PAYLOAD on 1873, not yet run
47
+ * on a device, so no setter is installed.
28
48
  */
29
- readonly lastSeen: {
30
- readonly param: 1551;
49
+ readonly lowTemperatureThreshold: {
50
+ readonly param: 1873;
31
51
  readonly type: "number";
32
- readonly kind: "timestamp";
33
- readonly provenance: "verified";
34
- readonly description: "Last-seen unix timestamp, seconds (verified: param 1551).";
52
+ readonly kind: "enum";
53
+ readonly enumValues: {
54
+ readonly 32: "32°F";
55
+ readonly 33: "33°F";
56
+ readonly 35: "35°F";
57
+ readonly 37: "37°F";
58
+ readonly 40: "40°F";
59
+ };
60
+ readonly thing: readonly ["sensor_low_temperature_alarm_threshold"];
61
+ readonly provenance: "apk";
62
+ readonly unverified: true;
63
+ readonly description: "Freeze alarm threshold, °F: 32, 33, 35, 37 or 40 (1873, sensor_low_temperature_alarm_threshold).";
35
64
  };
36
65
  };
37
- /** Bound leak-sensor reads — the object returned by `dev.leak()`. Read-only. */
66
+ /** Bound water-sensor reads — the object returned by `dev.leak()`. Read-only. */
38
67
  export type LeakActions = Surface<typeof LEAK_MEMBERS>;
39
- /**
40
- * `leak` — water/leak (and freeze) sensor. Alarm flag is a placeholder — the T8920 Water & Freeze
41
- * sensor reports leak via a push event, not a stable param id.
42
- */
68
+ /** `leak` — water and freeze sensor (T8920, T90F0). */
43
69
  export declare const LEAK: CapabilityModule;
@@ -0,0 +1,39 @@
1
+ import { type Surface } from "./members.js";
2
+ import type { CapabilityModule } from "./types.js";
3
+ /**
4
+ * Every `link` feature, declared once: the check-in and signal params a security device reports
5
+ * whatever it is (sensor, keypad, lock), each getter present only where the device reports its param.
6
+ * A capability with a reason to declare one of these properties itself takes precedence, since the
7
+ * first declaration of a property wins and `link` is registered after every device capability.
8
+ *
9
+ * Exported but NOT published: each entry states its wire id and the evidence it was confirmed on,
10
+ * which the reference site does not carry.
11
+ * @internal
12
+ */
13
+ export declare const LINK_MEMBERS: {
14
+ /**
15
+ * Unix seconds at which the device last checked in, as the device itself reports it — beside
16
+ * `deviceState(sn).lastSeenMs`, which the SDK derives from the cloud's own update times. A
17
+ * `timestamp` takes no `unit`: it is an instant, not a duration.
18
+ */
19
+ readonly lastSeen: {
20
+ readonly param: 1551;
21
+ readonly type: "number";
22
+ readonly kind: "timestamp";
23
+ readonly provenance: "verified";
24
+ readonly description: "Last-seen unix timestamp, seconds (verified: param 1551).";
25
+ };
26
+ /** Link quality in dBm as the device measures it, never normalised to a bar count. */
27
+ readonly rssi: {
28
+ readonly param: 1141;
29
+ readonly type: "number";
30
+ readonly unit: "dBm";
31
+ readonly kind: "dbm";
32
+ readonly provenance: "verified";
33
+ readonly description: "Sub-1G/Wi-Fi signal strength (verified: param 1141 = RSSI).";
34
+ };
35
+ };
36
+ /** Bound check-in and signal reads — the object returned by `dev.link()`. Read-only. */
37
+ export type LinkActions = Surface<typeof LINK_MEMBERS>;
38
+ /** `link` — the check-in timestamp and signal strength a security device reports. */
39
+ export declare const LINK: CapabilityModule;