@switchbot/homebridge-switchbot 5.2.2-beta.0 → 5.2.2

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 (45) hide show
  1. package/.github/copilot-instructions.md +4 -0
  2. package/dist/SwitchBotHAPPlatform.d.ts.map +1 -1
  3. package/dist/SwitchBotHAPPlatform.js +8 -6
  4. package/dist/SwitchBotHAPPlatform.js.map +1 -1
  5. package/dist/cacheRepair.d.ts +19 -0
  6. package/dist/cacheRepair.d.ts.map +1 -0
  7. package/dist/cacheRepair.js +68 -0
  8. package/dist/cacheRepair.js.map +1 -0
  9. package/dist/deviceCommandMapper.d.ts +19 -5
  10. package/dist/deviceCommandMapper.d.ts.map +1 -1
  11. package/dist/deviceCommandMapper.js +132 -312
  12. package/dist/deviceCommandMapper.js.map +1 -1
  13. package/dist/devices/genericDevice.d.ts.map +1 -1
  14. package/dist/devices/genericDevice.js +8 -2
  15. package/dist/devices/genericDevice.js.map +1 -1
  16. package/dist/homebridge-ui/deviceCommandMapper.js +132 -312
  17. package/dist/homebridge-ui/deviceCommandMapper.js.map +1 -1
  18. package/dist/homebridge-ui/switchbotClient.js +30 -9
  19. package/dist/homebridge-ui/switchbotClient.js.map +1 -1
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +3 -0
  22. package/dist/index.js.map +1 -1
  23. package/dist/switchbotClient.d.ts +1 -0
  24. package/dist/switchbotClient.d.ts.map +1 -1
  25. package/dist/switchbotClient.js +30 -9
  26. package/dist/switchbotClient.js.map +1 -1
  27. package/dist/utils.d.ts.map +1 -1
  28. package/dist/utils.js +21 -1
  29. package/dist/utils.js.map +1 -1
  30. package/docs/variables/default.html +1 -1
  31. package/package.json +2 -2
  32. package/src/SwitchBotHAPPlatform.ts +10 -6
  33. package/src/cacheRepair.ts +79 -0
  34. package/src/deviceCommandMapper.ts +142 -317
  35. package/src/devices/genericDevice.ts +8 -2
  36. package/src/index.ts +3 -0
  37. package/src/switchbotClient.ts +30 -9
  38. package/src/utils.ts +21 -1
  39. package/test/client/node-switchbot-commands.spec.ts +85 -0
  40. package/test/client/switchbot-client-debounce.spec.ts +17 -0
  41. package/test/client/switchbot-client-discovery.spec.ts +40 -0
  42. package/test/device/genericDevice-blepoll.spec.ts +42 -0
  43. package/test/platform/hap-cache-restart.spec.ts +112 -0
  44. package/test/utils/utils.spec.ts +26 -0
  45. package/.github/npm-version-script-esm.js +0 -100
@@ -1,319 +1,139 @@
1
1
  // deviceCommandMapper.ts
2
- // Maps HAP/Matter commands to node-switchbot device methods for all supported device types
3
- export const deviceTypeCommandMap = {
4
- // SwitchBot AI Hub (read-only/generic)
5
- 'ai hub': {},
6
- // SwitchBot Cameras (read-only/generic)
7
- 'indoor cam': {},
8
- 'pan/tilt cam': {},
9
- 'pan/tilt cam 2k': {},
10
- 'pan/tilt cam plus 2k': {},
11
- 'pan/tilt cam plus 3k': {},
12
- // SwitchBot Air Purifiers (read-only/generic)
13
- 'air purifier pm2.5': {},
14
- 'air purifier table pm2.5': {},
15
- 'air purifier voc': {},
16
- 'air purifier table voc': {},
17
- // SwitchBot Home Climate Panel (read-only/generic)
18
- 'home climate panel': {},
19
- // SwitchBot WoIOSensor (read-only/generic)
20
- 'woiosensor': {},
21
- // SwitchBot Candle Warmer Lamp
22
- 'candle warmer lamp': {
23
- turnOn: async (device) => device.turnOn(),
24
- turnOff: async (device) => device.turnOff(),
25
- },
26
- // SwitchBot Hubs (read-only/generic)
27
- 'hub': {},
28
- 'hub 2': {},
29
- 'hub 3': {},
30
- 'hub mini': {},
31
- 'hub plus': {},
32
- // SwitchBot Robot Vacuum Cleaner K20 Plus Pro
33
- 'robot vacuum cleaner k20 plus pro': {
34
- start: async (device) => device.start(),
35
- stop: async (device) => device.stop(),
36
- pause: async (device) => device.pause(),
37
- dock: async (device) => device.dock(),
38
- resume: async (device) => device.resume(),
39
- locate: async (device) => device.locate(),
40
- },
41
- // SwitchBot Robot Vacuum Cleaner S1
42
- 'robot vacuum cleaner s1': {
43
- start: async (device) => device.start(),
44
- stop: async (device) => device.stop(),
45
- pause: async (device) => device.pause(),
46
- dock: async (device) => device.dock(),
47
- resume: async (device) => device.resume(),
48
- locate: async (device) => device.locate(),
49
- },
50
- // SwitchBot Robot Vacuum Cleaner S1 Plus
51
- 'robot vacuum cleaner s1 plus': {
52
- start: async (device) => device.start(),
53
- stop: async (device) => device.stop(),
54
- pause: async (device) => device.pause(),
55
- dock: async (device) => device.dock(),
56
- resume: async (device) => device.resume(),
57
- locate: async (device) => device.locate(),
58
- },
59
- // SwitchBot Robot Vacuum Cleaner S10
60
- 'robot vacuum cleaner s10': {
61
- start: async (device) => device.start(),
62
- stop: async (device) => device.stop(),
63
- pause: async (device) => device.pause(),
64
- dock: async (device) => device.dock(),
65
- resume: async (device) => device.resume(),
66
- locate: async (device) => device.locate(),
67
- },
68
- // SwitchBot Robot Vacuum Cleaner S20
69
- 'robot vacuum cleaner s20': {
70
- start: async (device) => device.start(),
71
- stop: async (device) => device.stop(),
72
- pause: async (device) => device.pause(),
73
- dock: async (device) => device.dock(),
74
- resume: async (device) => device.resume(),
75
- locate: async (device) => device.locate(),
76
- },
77
- // SwitchBot Relay Switch 2PM
78
- 'relay switch 2pm': {
79
- turnOn: async (device) => device.turnOn(),
80
- turnOff: async (device) => device.turnOff(),
81
- },
82
- // SwitchBot K10+
83
- 'k10+': {
84
- start: async (device) => device.start(),
85
- stop: async (device) => device.stop(),
86
- pause: async (device) => device.pause(),
87
- dock: async (device) => device.dock(),
88
- resume: async (device) => device.resume(),
89
- locate: async (device) => device.locate(),
90
- },
91
- // SwitchBot K10+ Pro
92
- 'k10+ pro': {
93
- start: async (device) => device.start(),
94
- stop: async (device) => device.stop(),
95
- pause: async (device) => device.pause(),
96
- dock: async (device) => device.dock(),
97
- resume: async (device) => device.resume(),
98
- locate: async (device) => device.locate(),
99
- },
100
- // SwitchBot Robot Vacuum Cleaner K10+ Pro Combo
101
- 'robot vacuum cleaner k10+ pro combo': {
102
- start: async (device) => device.start(),
103
- stop: async (device) => device.stop(),
104
- pause: async (device) => device.pause(),
105
- dock: async (device) => device.dock(),
106
- resume: async (device) => device.resume(),
107
- locate: async (device) => device.locate(),
108
- },
109
- // SwitchBot Robot Vacuum Cleaner K11+
110
- 'robot vacuum cleaner k11+': {
111
- start: async (device) => device.start(),
112
- stop: async (device) => device.stop(),
113
- pause: async (device) => device.pause(),
114
- dock: async (device) => device.dock(),
115
- resume: async (device) => device.resume(),
116
- locate: async (device) => device.locate(),
117
- },
118
- // SwitchBot MeterPro(CO2) (read-only)
119
- 'meterpro(co2)': {},
120
- // SwitchBot Water Detector (read-only)
121
- 'water detector': {},
122
- // SwitchBot Garage Door Opener
123
- 'garage door opener': {
124
- open: async (device) => device.open(),
125
- close: async (device) => device.close(),
126
- stop: async (device) => device.stop(),
127
- },
128
- // SwitchBot Relay Switch 1
129
- 'relay switch 1': {
130
- turnOn: async (device) => device.turnOn(),
131
- turnOff: async (device) => device.turnOff(),
132
- },
133
- // SwitchBot Relay Switch 1PM
134
- 'relay switch 1pm': {
135
- turnOn: async (device) => device.turnOn(),
136
- turnOff: async (device) => device.turnOff(),
137
- },
138
- // SwitchBot Smart Radiator Thermostat (read-only or not directly controllable)
139
- 'smart radiator thermostat': {},
140
- // SwitchBot Humidifier2
141
- 'humidifier2': {
142
- turnOn: async (device) => device.turnOn(),
143
- turnOff: async (device) => device.turnOff(),
144
- setMode: async (device, body) => device.setMode(body?.parameter),
145
- setHumidity: async (device, body) => device.setHumidity(body?.parameter),
146
- },
147
- // SwitchBot MeterPlus (read-only)
148
- 'meterplus': {},
149
- // SwitchBot Meter Pro (read-only)
150
- 'meter pro': {},
151
- // SwitchBot MeterPro (read-only)
152
- 'meterpro': {},
153
- // SwitchBot RGBICWW Floor Lamp
154
- 'rgbicww floor lamp': {
155
- turnOn: async (device) => device.turnOn(),
156
- turnOff: async (device) => device.turnOff(),
157
- setBrightness: async (device, body) => device.setBrightness(body?.parameter),
158
- setColor: async (device, body) => device.setColor(body?.parameter),
159
- },
160
- // SwitchBot RGBICWW Strip Light
161
- 'rgbicww strip light': {
162
- turnOn: async (device) => device.turnOn(),
163
- turnOff: async (device) => device.turnOff(),
164
- setBrightness: async (device, body) => device.setBrightness(body?.parameter),
165
- setColor: async (device, body) => device.setColor(body?.parameter),
166
- },
167
- // SwitchBot Circulator Fan
168
- 'circulator fan': {
169
- turnOn: async (device) => device.turnOn(),
170
- turnOff: async (device) => device.turnOff(),
171
- setSpeed: async (device, body) => device.setSpeed(body?.parameter),
172
- swing: async (device) => device.swing(),
173
- },
174
- // SwitchBot Battery Circulator Fan
175
- 'battery circulator fan': {
176
- turnOn: async (device) => device.turnOn(),
177
- turnOff: async (device) => device.turnOff(),
178
- setSpeed: async (device, body) => device.setSpeed(body?.parameter),
179
- swing: async (device) => device.swing(),
180
- },
181
- // SwitchBot Standing Circulator Fan
182
- 'standing circulator fan': {
183
- turnOn: async (device) => device.turnOn(),
184
- turnOff: async (device) => device.turnOff(),
185
- setSpeed: async (device, body) => device.setSpeed(body?.parameter),
186
- swing: async (device) => device.swing(),
187
- },
188
- // SwitchBot Bot
189
- 'bot': {
190
- turnOn: async (device) => device.turnOn(),
191
- turnOff: async (device) => device.turnOff(),
192
- press: async (device) => device.press(),
193
- },
194
- // SwitchBot Curtain
195
- 'curtain': {
196
- open: async (device) => device.open(),
197
- close: async (device) => device.close(),
198
- pause: async (device) => device.pause(),
199
- setPosition: async (device, body) => device.setPosition(body?.parameter),
200
- },
201
- // SwitchBot Blind Tilt
202
- 'blind tilt': {
203
- open: async (device) => device.open(),
204
- close: async (device) => device.close(),
205
- pause: async (device) => device.pause(),
206
- setPosition: async (device, body) => device.setPosition(body?.parameter),
207
- },
208
- // SwitchBot Roller Shade
209
- 'roller shade': {
210
- open: async (device) => device.open(),
211
- close: async (device) => device.close(),
212
- pause: async (device) => device.pause(),
213
- setPosition: async (device, body) => device.setPosition(body?.parameter),
214
- },
215
- // SwitchBot Plug
216
- 'plug': {
217
- turnOn: async (device) => device.turnOn(),
218
- turnOff: async (device) => device.turnOff(),
219
- },
220
- // SwitchBot Strip Light 3
221
- 'strip light 3': {
222
- turnOn: async (device) => device.turnOn(),
223
- turnOff: async (device) => device.turnOff(),
224
- setBrightness: async (device, body) => device.setBrightness(body?.parameter),
225
- setColor: async (device, body) => device.setColor(body?.parameter),
226
- },
227
- // SwitchBot Floor Lamp
228
- 'floor lamp': {
229
- turnOn: async (device) => device.turnOn(),
230
- turnOff: async (device) => device.turnOff(),
231
- setBrightness: async (device, body) => device.setBrightness(body?.parameter),
232
- setColor: async (device, body) => device.setColor(body?.parameter),
233
- },
234
- // SwitchBot RGBIC Neon Rope Light
235
- 'rgbic neon rope light': {
236
- turnOn: async (device) => device.turnOn(),
237
- turnOff: async (device) => device.turnOff(),
238
- setBrightness: async (device, body) => device.setBrightness(body?.parameter),
239
- setColor: async (device, body) => device.setColor(body?.parameter),
240
- },
241
- // SwitchBot RGBIC Neon Wire Rope Light
242
- 'rgbic neon wire rope light': {
243
- turnOn: async (device) => device.turnOn(),
244
- turnOff: async (device) => device.turnOff(),
245
- setBrightness: async (device, body) => device.setBrightness(body?.parameter),
246
- setColor: async (device, body) => device.setColor(body?.parameter),
247
- },
248
- // SwitchBot Plug Mini
249
- 'plug mini': {
250
- turnOn: async (device) => device.turnOn(),
251
- turnOff: async (device) => device.turnOff(),
252
- },
253
- // SwitchBot Color Bulb
254
- 'color bulb': {
255
- turnOn: async (device) => device.turnOn(),
256
- turnOff: async (device) => device.turnOff(),
257
- setBrightness: async (device, body) => device.setBrightness(body?.parameter),
258
- setColor: async (device, body) => device.setColor(body?.parameter),
259
- },
260
- // SwitchBot Light Strip
261
- 'light strip': {
262
- turnOn: async (device) => device.turnOn(),
263
- turnOff: async (device) => device.turnOff(),
264
- setBrightness: async (device, body) => device.setBrightness(body?.parameter),
265
- setColor: async (device, body) => device.setColor(body?.parameter),
266
- },
267
- // SwitchBot Fan
268
- 'fan': {
269
- turnOn: async (device) => device.turnOn(),
270
- turnOff: async (device) => device.turnOff(),
271
- setSpeed: async (device, body) => device.setSpeed(body?.parameter),
272
- swing: async (device) => device.swing(),
273
- },
274
- // SwitchBot Lock
275
- 'lock': {
276
- lock: async (device) => device.lock(),
277
- unlock: async (device) => device.unlock(),
278
- },
279
- // SwitchBot Curtain 3
280
- 'curtain3': {
281
- open: async (device) => device.open(),
282
- close: async (device) => device.close(),
283
- pause: async (device) => device.pause(),
284
- setPosition: async (device, body) => device.setPosition(body?.parameter),
285
- },
286
- // SwitchBot Meter
287
- 'meter': {}, // Read-only
288
- // SwitchBot Motion Sensor
289
- 'motion sensor': {}, // Read-only
290
- // SwitchBot Contact Sensor
291
- 'contact sensor': {}, // Read-only
292
- // SwitchBot Humidifier
293
- 'humidifier': {
294
- turnOn: async (device) => device.turnOn(),
295
- turnOff: async (device) => device.turnOff(),
296
- setMode: async (device, body) => device.setMode(body?.parameter),
297
- setHumidity: async (device, body) => device.setHumidity(body?.parameter),
298
- },
299
- // SwitchBot Vacuum
300
- 'vacuum': {
301
- start: async (device) => device.start(),
302
- stop: async (device) => device.stop(),
303
- pause: async (device) => device.pause(),
304
- dock: async (device) => device.dock(),
305
- resume: async (device) => device.resume(),
306
- locate: async (device) => device.locate(),
2
+ // Maps HAP/Matter commands to node-switchbot device methods.
3
+ //
4
+ // Accessories send generic commands (turnOn, setBrightness, setPosition, ...). Each command maps to
5
+ // the node-switchbot method that performs it, and is used when the device has that method. This
6
+ // works for every node-switchbot device class without listing device type strings, which differ
7
+ // between the OpenAPI ("Plug Mini (US)") and BLE ("Meter Plus") and were often missing here.
8
+ function numberParameter(body) {
9
+ const value = Number(body?.parameter);
10
+ if (!Number.isFinite(value)) {
11
+ throw new TypeError(`Expected a number, got ${JSON.stringify(body?.parameter)}`);
12
+ }
13
+ return value;
14
+ }
15
+ /**
16
+ * HomeKit and Matter send color temperature in mireds (about 140-500); node-switchbot expects
17
+ * kelvin (2700-6500). Values above 1000 are taken as kelvin already.
18
+ */
19
+ export function toKelvin(value) {
20
+ const kelvin = value > 1000 ? value : 1_000_000 / value;
21
+ return Math.round(Math.min(6500, Math.max(2700, kelvin)));
22
+ }
23
+ /** Hue 0-360, saturation 0-100, at full value, to RGB 0-255 */
24
+ export function hsToRgb(hue, saturation) {
25
+ const h = (((hue % 360) + 360) % 360) / 60;
26
+ const s = Math.min(100, Math.max(0, saturation)) / 100;
27
+ const c = s;
28
+ const x = c * (1 - Math.abs((h % 2) - 1));
29
+ const [r, g, b] = h < 1
30
+ ? [c, x, 0]
31
+ : h < 2
32
+ ? [x, c, 0]
33
+ : h < 3
34
+ ? [0, c, x]
35
+ : h < 4
36
+ ? [0, x, c]
37
+ : h < 5 ? [x, 0, c] : [c, 0, x];
38
+ const m = 1 - c;
39
+ return [r, g, b].map(v => Math.round((v + m) * 255));
40
+ }
41
+ /**
42
+ * Parse a color parameter: `"hue,saturation"` (from HomeKit), `"r:g:b"` (OpenAPI style) or
43
+ * `"#rrggbb"`.
44
+ */
45
+ export function toRgb(parameter) {
46
+ const text = String(parameter ?? '').trim();
47
+ const hex = /^#?([0-9a-f]{6})$/i.exec(text);
48
+ if (hex) {
49
+ const n = Number.parseInt(hex[1], 16);
50
+ return [(n >> 16) & 0xFF, (n >> 8) & 0xFF, n & 0xFF];
51
+ }
52
+ if (text.includes(':')) {
53
+ const parts = text.split(':').map(Number);
54
+ if (parts.length === 3 && parts.every(Number.isFinite)) {
55
+ return parts.map(v => Math.round(Math.min(255, Math.max(0, v))));
56
+ }
57
+ }
58
+ if (text.includes(',')) {
59
+ const [hue, saturation] = text.split(',').map(Number);
60
+ if (Number.isFinite(hue) && Number.isFinite(saturation)) {
61
+ return hsToRgb(hue, saturation);
62
+ }
63
+ }
64
+ throw new TypeError(`Unrecognised color ${JSON.stringify(parameter)}`);
65
+ }
66
+ const call = (method) => ({ methods: [method], handler: (device) => device[method]() });
67
+ const commandSpecs = {
68
+ turnOn: call('turnOn'),
69
+ turnOff: call('turnOff'),
70
+ toggle: call('toggle'),
71
+ press: call('press'),
72
+ open: call('open'),
73
+ close: call('close'),
74
+ pause: call('pause'),
75
+ lock: call('lock'),
76
+ unlock: call('unlock'),
77
+ setBrightness: {
78
+ methods: ['setBrightness'],
79
+ handler: (device, body) => device.setBrightness(numberParameter(body)),
80
+ },
81
+ setColorTemperature: {
82
+ methods: ['setColorTemperature', 'setColorTemp'],
83
+ handler: (device, body, method) => {
84
+ const kelvin = toKelvin(numberParameter(body));
85
+ return method === 'setColorTemp' ? device.setColorTemp(2700, 6500, kelvin) : device.setColorTemperature(kelvin);
86
+ },
87
+ },
88
+ setColor: {
89
+ methods: ['setColor'],
90
+ handler: (device, body) => device.setColor(...toRgb(body?.parameter)),
91
+ },
92
+ setPosition: {
93
+ methods: ['setPosition'],
94
+ handler: (device, body) => device.setPosition(numberParameter(body)),
95
+ },
96
+ setFanSpeed: {
97
+ methods: ['setFanSpeed', 'setSpeed'],
98
+ handler: (device, body, method) => device[method](numberParameter(body)),
99
+ },
100
+ setMode: {
101
+ methods: ['setMode'],
102
+ handler: (device, body) => device.setMode(body?.parameter),
103
+ },
104
+ setHumidity: {
105
+ methods: ['setTargetHumidity', 'setHumidity', 'setLevel'],
106
+ handler: (device, body, method) => device[method](numberParameter(body)),
107
+ },
108
+ // Vacuums: node-switchbot uses cleanUp/returnToDock with the BLE protocol version
109
+ start: {
110
+ methods: ['cleanUp', 'start'],
111
+ handler: (device, body, method) => method === 'cleanUp' ? device.cleanUp(Number(body?.protocolVersion) || 1) : device.start(),
112
+ },
113
+ dock: {
114
+ methods: ['returnToDock', 'dock'],
115
+ handler: (device, body, method) => method === 'returnToDock' ? device.returnToDock(Number(body?.protocolVersion) || 1) : device.dock(),
116
+ },
117
+ stop: {
118
+ methods: ['returnToDock', 'stop', 'pause'],
119
+ handler: (device, body, method) => method === 'returnToDock' ? device.returnToDock(Number(body?.protocolVersion) || 1) : device[method](),
307
120
  },
308
- // Add more device types and commands as needed
309
121
  };
310
- // Helper to get the handler for a device type and command
311
- export function getDeviceCommandHandler(deviceType, command) {
312
- const typeKey = deviceType.toLowerCase();
313
- const typeMap = deviceTypeCommandMap[typeKey];
314
- if (!typeMap) {
122
+ /** Commands this module can map, for documentation and tests */
123
+ export const supportedCommands = Object.keys(commandSpecs);
124
+ /**
125
+ * Get the handler for a command on a node-switchbot device, or undefined when the device has no
126
+ * method for it. `deviceType` is kept for callers and logging; dispatch uses the device itself.
127
+ */
128
+ export function getDeviceCommandHandler(deviceType, command, device) {
129
+ const spec = Object.hasOwn(commandSpecs, command) ? commandSpecs[command] : undefined;
130
+ if (!spec) {
131
+ return undefined;
132
+ }
133
+ const method = device ? spec.methods.find(name => typeof device[name] === 'function') : spec.methods[0];
134
+ if (!method) {
315
135
  return undefined;
316
136
  }
317
- return typeMap[command];
137
+ return async (target, body) => spec.handler(target, body, method);
318
138
  }
319
139
  //# sourceMappingURL=deviceCommandMapper.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"deviceCommandMapper.js","sourceRoot":"","sources":["../../src/deviceCommandMapper.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"deviceCommandMapper.js","sourceRoot":"","sources":["../../src/deviceCommandMapper.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,7 @@
1
1
  import { getDeviceCommandHandler } from './deviceCommandMapper.js';
2
2
  import { CharacteristicMissingError, SwitchbotAuthenticationError, SwitchbotOperationError } from './errors.js';
3
+ // Commands that set the same state and may replace each other while debounced
4
+ const WRITE_GROUP = { turnOn: 'power', turnOff: 'power', toggle: 'power' };
3
5
  /**
4
6
  * Thin wrapper around node-switchbot v4.0.0+
5
7
  * Leverages upstream resilience features (retry, circuit breaker, connection intelligence)
@@ -11,6 +13,7 @@ export class SwitchBotClient {
11
13
  writeDebounceMs = 100;
12
14
  discoveryCacheTtlMs = 30_000;
13
15
  lastDiscoveryAt = 0;
16
+ discoveryInFlight;
14
17
  logger;
15
18
  pendingWrites = new Map();
16
19
  constructor(cfg) {
@@ -112,8 +115,12 @@ export class SwitchBotClient {
112
115
  if (!this.writeDebounceMs || this.writeDebounceMs <= 0) {
113
116
  return this._doSetDeviceState(id, body);
114
117
  }
118
+ // Coalesce repeated writes of the same operation only. Power commands share one key, so a
119
+ // quick on/off/on sends the last one; other commands (brightness, color, position...) keep
120
+ // their own key so a turnOn sent together with setBrightness is not dropped.
121
+ const key = `${id}\u0000${WRITE_GROUP[body?.command] ?? body?.command ?? ''}`;
115
122
  return new Promise((resolve, reject) => {
116
- const existing = this.pendingWrites.get(id);
123
+ const existing = this.pendingWrites.get(key);
117
124
  if (existing) {
118
125
  existing.body = body;
119
126
  existing.resolvers.push({ resolve, reject });
@@ -121,11 +128,11 @@ export class SwitchBotClient {
121
128
  }
122
129
  const resolvers = [{ resolve, reject }];
123
130
  const timer = setTimeout(async () => {
124
- const entry = this.pendingWrites.get(id);
131
+ const entry = this.pendingWrites.get(key);
125
132
  if (!entry) {
126
133
  return;
127
134
  }
128
- this.pendingWrites.delete(id);
135
+ this.pendingWrites.delete(key);
129
136
  try {
130
137
  const out = await this._doSetDeviceState(id, entry.body);
131
138
  for (const r of entry.resolvers)
@@ -145,7 +152,7 @@ export class SwitchBotClient {
145
152
  r.reject(e);
146
153
  }
147
154
  }, this.writeDebounceMs);
148
- this.pendingWrites.set(id, { timer, body, resolvers });
155
+ this.pendingWrites.set(key, { timer, body, resolvers });
149
156
  });
150
157
  }
151
158
  async _doSetDeviceState(id, body) {
@@ -162,7 +169,7 @@ export class SwitchBotClient {
162
169
  if (!command) {
163
170
  throw new SwitchbotOperationError('No command specified in body', 'no_command');
164
171
  }
165
- const handler = getDeviceCommandHandler(deviceType, command);
172
+ const handler = getDeviceCommandHandler(deviceType, command, device);
166
173
  if (!handler) {
167
174
  throw new SwitchbotOperationError(`Unsupported command '${command}' for device type '${deviceType}'`, 'unsupported_command');
168
175
  }
@@ -236,12 +243,26 @@ export class SwitchBotClient {
236
243
  }
237
244
  const fromManager = this.getManagedDevices();
238
245
  const cacheValid = this.discoveryCacheTtlMs > 0 && (Date.now() - this.lastDiscoveryAt) < this.discoveryCacheTtlMs;
239
- if (!force && cacheValid && fromManager.length > 0) {
246
+ // A forced refresh (a device was not found) still respects the cache period once a discovery
247
+ // has run: an offline device would otherwise trigger a BLE scan and an OpenAPI call per lookup.
248
+ if (cacheValid && (!force || fromManager.length > 0)) {
240
249
  return fromManager;
241
250
  }
242
- const discovered = await this.client.discover();
243
- this.lastDiscoveryAt = Date.now();
244
- return discovered;
251
+ // Share one discovery between concurrent callers; each BLE scan also resets the last one's results.
252
+ if (!this.discoveryInFlight) {
253
+ const client = this.client;
254
+ this.discoveryInFlight = (async () => {
255
+ try {
256
+ const discovered = await client.discover();
257
+ this.lastDiscoveryAt = Date.now();
258
+ return discovered;
259
+ }
260
+ finally {
261
+ this.discoveryInFlight = undefined;
262
+ }
263
+ })();
264
+ }
265
+ return this.discoveryInFlight;
245
266
  }
246
267
  }
247
268
  //# sourceMappingURL=switchbotClient.js.map