@switchbot/homebridge-switchbot 3.8.3-beta.2 → 3.8.3-beta.21
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.
- package/.github/workflows/beta-release.yml +2 -1
- package/CHANGELOG.md +8 -0
- package/dist/device/blindtilt.d.ts +1 -4
- package/dist/device/blindtilt.d.ts.map +1 -1
- package/dist/device/blindtilt.js +18 -19
- package/dist/device/blindtilt.js.map +1 -1
- package/dist/device/bot.d.ts +1 -4
- package/dist/device/bot.d.ts.map +1 -1
- package/dist/device/bot.js +15 -16
- package/dist/device/bot.js.map +1 -1
- package/dist/device/ceilinglight.d.ts +1 -4
- package/dist/device/ceilinglight.d.ts.map +1 -1
- package/dist/device/ceilinglight.js +35 -39
- package/dist/device/ceilinglight.js.map +1 -1
- package/dist/device/colorbulb.d.ts +1 -4
- package/dist/device/colorbulb.d.ts.map +1 -1
- package/dist/device/colorbulb.js +35 -39
- package/dist/device/colorbulb.js.map +1 -1
- package/dist/device/contact.d.ts +1 -4
- package/dist/device/contact.d.ts.map +1 -1
- package/dist/device/contact.js +7 -7
- package/dist/device/contact.js.map +1 -1
- package/dist/device/curtain.d.ts +1 -4
- package/dist/device/curtain.d.ts.map +1 -1
- package/dist/device/curtain.js +16 -17
- package/dist/device/curtain.js.map +1 -1
- package/dist/device/device.d.ts +6 -6
- package/dist/device/device.d.ts.map +1 -1
- package/dist/device/device.js +30 -14
- package/dist/device/device.js.map +1 -1
- package/dist/device/fan.d.ts +1 -4
- package/dist/device/fan.d.ts.map +1 -1
- package/dist/device/fan.js +28 -31
- package/dist/device/fan.js.map +1 -1
- package/dist/device/hub.d.ts +1 -4
- package/dist/device/hub.d.ts.map +1 -1
- package/dist/device/hub.js +7 -7
- package/dist/device/hub.js.map +1 -1
- package/dist/device/humidifier.d.ts +1 -4
- package/dist/device/humidifier.d.ts.map +1 -1
- package/dist/device/humidifier.js +28 -31
- package/dist/device/humidifier.js.map +1 -1
- package/dist/device/iosensor.d.ts +1 -4
- package/dist/device/iosensor.d.ts.map +1 -1
- package/dist/device/iosensor.js +7 -7
- package/dist/device/iosensor.js.map +1 -1
- package/dist/device/lightstrip.d.ts +1 -4
- package/dist/device/lightstrip.d.ts.map +1 -1
- package/dist/device/lightstrip.js +28 -31
- package/dist/device/lightstrip.js.map +1 -1
- package/dist/device/lock.d.ts +1 -4
- package/dist/device/lock.d.ts.map +1 -1
- package/dist/device/lock.js +15 -16
- package/dist/device/lock.js.map +1 -1
- package/dist/device/meter.d.ts +1 -4
- package/dist/device/meter.d.ts.map +1 -1
- package/dist/device/meter.js +7 -7
- package/dist/device/meter.js.map +1 -1
- package/dist/device/meterplus.d.ts +1 -4
- package/dist/device/meterplus.d.ts.map +1 -1
- package/dist/device/meterplus.js +7 -7
- package/dist/device/meterplus.js.map +1 -1
- package/dist/device/motion.d.ts +1 -4
- package/dist/device/motion.d.ts.map +1 -1
- package/dist/device/motion.js +7 -7
- package/dist/device/motion.js.map +1 -1
- package/dist/device/plug.d.ts +1 -4
- package/dist/device/plug.d.ts.map +1 -1
- package/dist/device/plug.js +14 -15
- package/dist/device/plug.js.map +1 -1
- package/dist/device/robotvacuumcleaner.d.ts +1 -4
- package/dist/device/robotvacuumcleaner.d.ts.map +1 -1
- package/dist/device/robotvacuumcleaner.js +21 -23
- package/dist/device/robotvacuumcleaner.js.map +1 -1
- package/dist/device/waterdetector.d.ts +1 -4
- package/dist/device/waterdetector.d.ts.map +1 -1
- package/dist/device/waterdetector.js +7 -7
- package/dist/device/waterdetector.js.map +1 -1
- package/dist/irdevice/airconditioner.d.ts +1 -1
- package/dist/irdevice/airconditioner.d.ts.map +1 -1
- package/dist/irdevice/airconditioner.js +11 -12
- package/dist/irdevice/airconditioner.js.map +1 -1
- package/dist/irdevice/airpurifier.d.ts +1 -1
- package/dist/irdevice/airpurifier.d.ts.map +1 -1
- package/dist/irdevice/airpurifier.js +11 -12
- package/dist/irdevice/airpurifier.js.map +1 -1
- package/dist/irdevice/camera.d.ts +1 -1
- package/dist/irdevice/camera.d.ts.map +1 -1
- package/dist/irdevice/camera.js +9 -10
- package/dist/irdevice/camera.js.map +1 -1
- package/dist/irdevice/fan.d.ts +1 -1
- package/dist/irdevice/fan.d.ts.map +1 -1
- package/dist/irdevice/fan.js +15 -16
- package/dist/irdevice/fan.js.map +1 -1
- package/dist/irdevice/irdevice.d.ts +6 -6
- package/dist/irdevice/irdevice.d.ts.map +1 -1
- package/dist/irdevice/irdevice.js +7 -13
- package/dist/irdevice/irdevice.js.map +1 -1
- package/dist/irdevice/light.d.ts +1 -1
- package/dist/irdevice/light.d.ts.map +1 -1
- package/dist/irdevice/light.js +9 -10
- package/dist/irdevice/light.js.map +1 -1
- package/dist/irdevice/other.d.ts +1 -1
- package/dist/irdevice/other.d.ts.map +1 -1
- package/dist/irdevice/other.js +9 -10
- package/dist/irdevice/other.js.map +1 -1
- package/dist/irdevice/tv.d.ts +1 -1
- package/dist/irdevice/tv.d.ts.map +1 -1
- package/dist/irdevice/tv.js +27 -28
- package/dist/irdevice/tv.js.map +1 -1
- package/dist/irdevice/vacuumcleaner.d.ts +1 -1
- package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
- package/dist/irdevice/vacuumcleaner.js +9 -10
- package/dist/irdevice/vacuumcleaner.js.map +1 -1
- package/dist/irdevice/waterheater.d.ts +1 -1
- package/dist/irdevice/waterheater.d.ts.map +1 -1
- package/dist/irdevice/waterheater.js +9 -10
- package/dist/irdevice/waterheater.js.map +1 -1
- package/dist/platform.d.ts +5 -14
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +53 -161
- package/dist/platform.js.map +1 -1
- package/dist/settings.d.ts +1 -3
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js.map +1 -1
- package/dist/utils.d.ts +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js.map +1 -1
- package/package.json +9 -10
- package/src/device/blindtilt.ts +20 -24
- package/src/device/bot.ts +16 -20
- package/src/device/ceilinglight.ts +36 -43
- package/src/device/colorbulb.ts +36 -43
- package/src/device/contact.ts +8 -11
- package/src/device/curtain.ts +18 -22
- package/src/device/device.ts +29 -18
- package/src/device/fan.ts +29 -35
- package/src/device/hub.ts +8 -11
- package/src/device/humidifier.ts +29 -35
- package/src/device/iosensor.ts +8 -11
- package/src/device/lightstrip.ts +29 -35
- package/src/device/lock.ts +16 -20
- package/src/device/meter.ts +8 -11
- package/src/device/meterplus.ts +8 -11
- package/src/device/motion.ts +8 -11
- package/src/device/plug.ts +15 -19
- package/src/device/robotvacuumcleaner.ts +22 -31
- package/src/device/waterdetector.ts +8 -11
- package/src/irdevice/airconditioner.ts +12 -14
- package/src/irdevice/airpurifier.ts +12 -13
- package/src/irdevice/camera.ts +10 -11
- package/src/irdevice/fan.ts +16 -17
- package/src/irdevice/irdevice.ts +9 -17
- package/src/irdevice/light.ts +10 -11
- package/src/irdevice/other.ts +10 -11
- package/src/irdevice/tv.ts +28 -29
- package/src/irdevice/vacuumcleaner.ts +10 -11
- package/src/irdevice/waterheater.ts +10 -11
- package/src/platform.ts +55 -161
- package/src/settings.ts +1 -4
- package/src/utils.ts +2 -1
- package/dist/types/bledevicestatus.d.ts +0 -281
- package/dist/types/bledevicestatus.d.ts.map +0 -1
- package/dist/types/bledevicestatus.js +0 -2
- package/dist/types/bledevicestatus.js.map +0 -1
- package/dist/types/devicelist.d.ts +0 -89
- package/dist/types/devicelist.d.ts.map +0 -1
- package/dist/types/devicelist.js +0 -6
- package/dist/types/devicelist.js.map +0 -1
- package/dist/types/deviceresponse.d.ts +0 -13
- package/dist/types/deviceresponse.d.ts.map +0 -1
- package/dist/types/deviceresponse.js +0 -2
- package/dist/types/deviceresponse.js.map +0 -1
- package/dist/types/devicestatus.d.ts +0 -149
- package/dist/types/devicestatus.d.ts.map +0 -1
- package/dist/types/devicestatus.js +0 -3
- package/dist/types/devicestatus.js.map +0 -1
- package/dist/types/devicewebhookstatus.d.ts +0 -156
- package/dist/types/devicewebhookstatus.d.ts.map +0 -1
- package/dist/types/devicewebhookstatus.js +0 -2
- package/dist/types/devicewebhookstatus.js.map +0 -1
- package/dist/types/irdevicelist.d.ts +0 -10
- package/dist/types/irdevicelist.d.ts.map +0 -1
- package/dist/types/irdevicelist.js +0 -2
- package/dist/types/irdevicelist.js.map +0 -1
- package/dist/types/pushbody.d.ts +0 -6
- package/dist/types/pushbody.d.ts.map +0 -1
- package/dist/types/pushbody.js +0 -2
- package/dist/types/pushbody.js.map +0 -1
- package/src/types/bledevicestatus.ts +0 -303
- package/src/types/devicelist.ts +0 -124
- package/src/types/deviceresponse.ts +0 -14
- package/src/types/devicestatus.ts +0 -178
- package/src/types/devicewebhookstatus.ts +0 -191
- package/src/types/irdevicelist.ts +0 -15
- package/src/types/pushbody.ts +0 -9
package/src/irdevice/tv.ts
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
* tv.ts: @switchbot/homebridge-switchbot.
|
|
4
4
|
*/
|
|
5
5
|
import type { CharacteristicValue, PlatformAccessory, Service } from 'homebridge'
|
|
6
|
+
import type { bodyChange, irdevice } from 'node-switchbot'
|
|
6
7
|
|
|
7
8
|
import type { SwitchBotPlatform } from '../platform.js'
|
|
8
9
|
import type { irDevicesConfig } from '../settings.js'
|
|
9
|
-
import type { irdevice } from '../types/irdevicelist.js'
|
|
10
10
|
|
|
11
11
|
import { irdeviceBase } from './irdevice.js'
|
|
12
12
|
|
|
@@ -210,11 +210,11 @@ export class TV extends irdeviceBase {
|
|
|
210
210
|
if (this.Television.Active === this.hap.Characteristic.Active.ACTIVE && !this.disablePushOn) {
|
|
211
211
|
const commandType: string = await this.commandType()
|
|
212
212
|
const command: string = await this.commandOn()
|
|
213
|
-
const bodyChange =
|
|
213
|
+
const bodyChange: bodyChange = {
|
|
214
214
|
command,
|
|
215
215
|
parameter: 'default',
|
|
216
216
|
commandType,
|
|
217
|
-
}
|
|
217
|
+
}
|
|
218
218
|
await this.pushTVChanges(bodyChange)
|
|
219
219
|
}
|
|
220
220
|
}
|
|
@@ -224,11 +224,11 @@ export class TV extends irdeviceBase {
|
|
|
224
224
|
if (this.Television.Active === this.hap.Characteristic.Active.INACTIVE && !this.disablePushOff) {
|
|
225
225
|
const commandType: string = await this.commandType()
|
|
226
226
|
const command: string = await this.commandOff()
|
|
227
|
-
const bodyChange =
|
|
227
|
+
const bodyChange: bodyChange = {
|
|
228
228
|
command,
|
|
229
229
|
parameter: 'default',
|
|
230
230
|
commandType,
|
|
231
|
-
}
|
|
231
|
+
}
|
|
232
232
|
await this.pushTVChanges(bodyChange)
|
|
233
233
|
}
|
|
234
234
|
}
|
|
@@ -236,11 +236,11 @@ export class TV extends irdeviceBase {
|
|
|
236
236
|
async pushOkChanges(): Promise<void> {
|
|
237
237
|
await this.debugLog(`pushOkChanges disablePushDetail: ${this.disablePushDetail}`)
|
|
238
238
|
if (!this.disablePushDetail) {
|
|
239
|
-
const bodyChange =
|
|
239
|
+
const bodyChange: bodyChange = {
|
|
240
240
|
command: 'Ok',
|
|
241
241
|
parameter: 'default',
|
|
242
242
|
commandType: 'command',
|
|
243
|
-
}
|
|
243
|
+
}
|
|
244
244
|
await this.pushTVChanges(bodyChange)
|
|
245
245
|
}
|
|
246
246
|
}
|
|
@@ -248,11 +248,11 @@ export class TV extends irdeviceBase {
|
|
|
248
248
|
async pushBackChanges(): Promise<void> {
|
|
249
249
|
await this.debugLog(`pushBackChanges disablePushDetail: ${this.disablePushDetail}`)
|
|
250
250
|
if (!this.disablePushDetail) {
|
|
251
|
-
const bodyChange =
|
|
251
|
+
const bodyChange: bodyChange = {
|
|
252
252
|
command: 'Back',
|
|
253
253
|
parameter: 'default',
|
|
254
254
|
commandType: 'command',
|
|
255
|
-
}
|
|
255
|
+
}
|
|
256
256
|
await this.pushTVChanges(bodyChange)
|
|
257
257
|
}
|
|
258
258
|
}
|
|
@@ -260,11 +260,11 @@ export class TV extends irdeviceBase {
|
|
|
260
260
|
async pushMenuChanges(): Promise<void> {
|
|
261
261
|
await this.debugLog(`pushMenuChanges disablePushDetail: ${this.disablePushDetail}`)
|
|
262
262
|
if (!this.disablePushDetail) {
|
|
263
|
-
const bodyChange =
|
|
263
|
+
const bodyChange: bodyChange = {
|
|
264
264
|
command: 'Menu',
|
|
265
265
|
parameter: 'default',
|
|
266
266
|
commandType: 'command',
|
|
267
|
-
}
|
|
267
|
+
}
|
|
268
268
|
await this.pushTVChanges(bodyChange)
|
|
269
269
|
}
|
|
270
270
|
}
|
|
@@ -272,11 +272,11 @@ export class TV extends irdeviceBase {
|
|
|
272
272
|
async pushUpChanges(): Promise<void> {
|
|
273
273
|
await this.debugLog(`pushUpChanges disablePushDetail: ${this.disablePushDetail}`)
|
|
274
274
|
if (!this.disablePushDetail) {
|
|
275
|
-
const bodyChange =
|
|
275
|
+
const bodyChange: bodyChange = {
|
|
276
276
|
command: 'Up',
|
|
277
277
|
parameter: 'default',
|
|
278
278
|
commandType: 'command',
|
|
279
|
-
}
|
|
279
|
+
}
|
|
280
280
|
await this.pushTVChanges(bodyChange)
|
|
281
281
|
}
|
|
282
282
|
}
|
|
@@ -284,11 +284,11 @@ export class TV extends irdeviceBase {
|
|
|
284
284
|
async pushDownChanges(): Promise<void> {
|
|
285
285
|
await this.debugLog(`pushDownChanges disablePushDetail: ${this.disablePushDetail}`)
|
|
286
286
|
if (!this.disablePushDetail) {
|
|
287
|
-
const bodyChange =
|
|
287
|
+
const bodyChange: bodyChange = {
|
|
288
288
|
command: 'Down',
|
|
289
289
|
parameter: 'default',
|
|
290
290
|
commandType: 'command',
|
|
291
|
-
}
|
|
291
|
+
}
|
|
292
292
|
await this.pushTVChanges(bodyChange)
|
|
293
293
|
}
|
|
294
294
|
}
|
|
@@ -296,11 +296,11 @@ export class TV extends irdeviceBase {
|
|
|
296
296
|
async pushRightChanges(): Promise<void> {
|
|
297
297
|
await this.debugLog(`pushRightChanges disablePushDetail: ${this.disablePushDetail}`)
|
|
298
298
|
if (!this.disablePushDetail) {
|
|
299
|
-
const bodyChange =
|
|
299
|
+
const bodyChange: bodyChange = {
|
|
300
300
|
command: 'Right',
|
|
301
301
|
parameter: 'default',
|
|
302
302
|
commandType: 'command',
|
|
303
|
-
}
|
|
303
|
+
}
|
|
304
304
|
await this.pushTVChanges(bodyChange)
|
|
305
305
|
}
|
|
306
306
|
}
|
|
@@ -308,11 +308,11 @@ export class TV extends irdeviceBase {
|
|
|
308
308
|
async pushLeftChanges(): Promise<void> {
|
|
309
309
|
await this.debugLog(`pushLeftChanges disablePushDetail: ${this.disablePushDetail}`)
|
|
310
310
|
if (!this.disablePushDetail) {
|
|
311
|
-
const bodyChange =
|
|
311
|
+
const bodyChange: bodyChange = {
|
|
312
312
|
command: 'Left',
|
|
313
313
|
parameter: 'default',
|
|
314
314
|
commandType: 'command',
|
|
315
|
-
}
|
|
315
|
+
}
|
|
316
316
|
await this.pushTVChanges(bodyChange)
|
|
317
317
|
}
|
|
318
318
|
}
|
|
@@ -320,11 +320,11 @@ export class TV extends irdeviceBase {
|
|
|
320
320
|
async pushVolumeUpChanges(): Promise<void> {
|
|
321
321
|
await this.debugLog(`pushVolumeUpChanges disablePushDetail: ${this.disablePushDetail}`)
|
|
322
322
|
if (!this.disablePushDetail) {
|
|
323
|
-
const bodyChange =
|
|
323
|
+
const bodyChange: bodyChange = {
|
|
324
324
|
command: 'volumeAdd',
|
|
325
325
|
parameter: 'default',
|
|
326
326
|
commandType: 'command',
|
|
327
|
-
}
|
|
327
|
+
}
|
|
328
328
|
await this.pushTVChanges(bodyChange)
|
|
329
329
|
}
|
|
330
330
|
}
|
|
@@ -332,11 +332,11 @@ export class TV extends irdeviceBase {
|
|
|
332
332
|
async pushVolumeDownChanges(): Promise<void> {
|
|
333
333
|
await this.debugLog(`pushVolumeDownChanges disablePushDetail: ${this.disablePushDetail}`)
|
|
334
334
|
if (!this.disablePushDetail) {
|
|
335
|
-
const bodyChange =
|
|
335
|
+
const bodyChange: bodyChange = {
|
|
336
336
|
command: 'volumeSub',
|
|
337
337
|
parameter: 'default',
|
|
338
338
|
commandType: 'command',
|
|
339
|
-
}
|
|
339
|
+
}
|
|
340
340
|
await this.pushTVChanges(bodyChange)
|
|
341
341
|
}
|
|
342
342
|
}
|
|
@@ -346,14 +346,13 @@ export class TV extends irdeviceBase {
|
|
|
346
346
|
if (this.device.connectionType === 'OpenAPI') {
|
|
347
347
|
await this.infoLog(`Sending request to SwitchBot API, body: ${bodyChange},`)
|
|
348
348
|
try {
|
|
349
|
-
const { body
|
|
350
|
-
const deviceStatus: any = await body
|
|
351
|
-
await this.pushStatusCodes(
|
|
352
|
-
if (await this.successfulStatusCodes(
|
|
353
|
-
await this.successfulPushChange(
|
|
349
|
+
const { body } = await this.pushChangeRequest(bodyChange)
|
|
350
|
+
const deviceStatus: any = await body
|
|
351
|
+
await this.pushStatusCodes(deviceStatus)
|
|
352
|
+
if (await this.successfulStatusCodes(deviceStatus)) {
|
|
353
|
+
await this.successfulPushChange(deviceStatus, bodyChange)
|
|
354
354
|
await this.updateHomeKitCharacteristics()
|
|
355
355
|
} else {
|
|
356
|
-
await this.statusCode(statusCode)
|
|
357
356
|
await this.statusCode(deviceStatus.statusCode)
|
|
358
357
|
}
|
|
359
358
|
} catch (e: any) {
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
* vacuumcleaner.ts: @switchbot/homebridge-switchbot.
|
|
4
4
|
*/
|
|
5
5
|
import type { CharacteristicValue, PlatformAccessory, Service } from 'homebridge'
|
|
6
|
+
import type { bodyChange, irdevice } from 'node-switchbot'
|
|
6
7
|
|
|
7
8
|
import type { SwitchBotPlatform } from '../platform.js'
|
|
8
9
|
import type { irDevicesConfig } from '../settings.js'
|
|
9
|
-
import type { irdevice } from '../types/irdevicelist.js'
|
|
10
10
|
|
|
11
11
|
import { irdeviceBase } from './irdevice.js'
|
|
12
12
|
|
|
@@ -69,11 +69,11 @@ export class VacuumCleaner extends irdeviceBase {
|
|
|
69
69
|
if (this.Switch.On && !this.disablePushOn) {
|
|
70
70
|
const commandType: string = await this.commandType()
|
|
71
71
|
const command: string = await this.commandOn()
|
|
72
|
-
const bodyChange =
|
|
72
|
+
const bodyChange: bodyChange = {
|
|
73
73
|
command,
|
|
74
74
|
parameter: 'default',
|
|
75
75
|
commandType,
|
|
76
|
-
}
|
|
76
|
+
}
|
|
77
77
|
await this.pushChanges(bodyChange)
|
|
78
78
|
}
|
|
79
79
|
}
|
|
@@ -83,11 +83,11 @@ export class VacuumCleaner extends irdeviceBase {
|
|
|
83
83
|
if (!this.Switch.On && !this.disablePushOff) {
|
|
84
84
|
const commandType: string = await this.commandType()
|
|
85
85
|
const command: string = await this.commandOff()
|
|
86
|
-
const bodyChange =
|
|
86
|
+
const bodyChange: bodyChange = {
|
|
87
87
|
command,
|
|
88
88
|
parameter: 'default',
|
|
89
89
|
commandType,
|
|
90
|
-
}
|
|
90
|
+
}
|
|
91
91
|
await this.pushChanges(bodyChange)
|
|
92
92
|
}
|
|
93
93
|
}
|
|
@@ -97,14 +97,13 @@ export class VacuumCleaner extends irdeviceBase {
|
|
|
97
97
|
if (this.device.connectionType === 'OpenAPI') {
|
|
98
98
|
await this.infoLog(`Sending request to SwitchBot API, body: ${bodyChange},`)
|
|
99
99
|
try {
|
|
100
|
-
const { body
|
|
101
|
-
const deviceStatus: any = await body
|
|
102
|
-
await this.pushStatusCodes(
|
|
103
|
-
if (await this.successfulStatusCodes(
|
|
104
|
-
await this.successfulPushChange(
|
|
100
|
+
const { body } = await this.pushChangeRequest(bodyChange)
|
|
101
|
+
const deviceStatus: any = await body
|
|
102
|
+
await this.pushStatusCodes(deviceStatus)
|
|
103
|
+
if (await this.successfulStatusCodes(deviceStatus)) {
|
|
104
|
+
await this.successfulPushChange(deviceStatus, bodyChange)
|
|
105
105
|
await this.updateHomeKitCharacteristics()
|
|
106
106
|
} else {
|
|
107
|
-
await this.statusCode(statusCode)
|
|
108
107
|
await this.statusCode(deviceStatus.statusCode)
|
|
109
108
|
}
|
|
110
109
|
} catch (e: any) {
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
* waterheater.ts: @switchbot/homebridge-switchbot.
|
|
4
4
|
*/
|
|
5
5
|
import type { CharacteristicValue, PlatformAccessory, Service } from 'homebridge'
|
|
6
|
+
import type { bodyChange, irdevice } from 'node-switchbot'
|
|
6
7
|
|
|
7
8
|
import type { SwitchBotPlatform } from '../platform.js'
|
|
8
9
|
import type { irDevicesConfig } from '../settings.js'
|
|
9
|
-
import type { irdevice } from '../types/irdevicelist.js'
|
|
10
10
|
|
|
11
11
|
import { irdeviceBase } from './irdevice.js'
|
|
12
12
|
|
|
@@ -70,11 +70,11 @@ export class WaterHeater extends irdeviceBase {
|
|
|
70
70
|
if (this.Valve.Active === this.hap.Characteristic.Active.ACTIVE && !this.disablePushOn) {
|
|
71
71
|
const commandType: string = await this.commandType()
|
|
72
72
|
const command: string = await this.commandOn()
|
|
73
|
-
const bodyChange =
|
|
73
|
+
const bodyChange: bodyChange = {
|
|
74
74
|
command,
|
|
75
75
|
parameter: 'default',
|
|
76
76
|
commandType,
|
|
77
|
-
}
|
|
77
|
+
}
|
|
78
78
|
await this.pushChanges(bodyChange)
|
|
79
79
|
}
|
|
80
80
|
}
|
|
@@ -84,11 +84,11 @@ export class WaterHeater extends irdeviceBase {
|
|
|
84
84
|
if (this.Valve.Active === this.hap.Characteristic.Active.INACTIVE && !this.disablePushOff) {
|
|
85
85
|
const commandType: string = await this.commandType()
|
|
86
86
|
const command: string = await this.commandOff()
|
|
87
|
-
const bodyChange =
|
|
87
|
+
const bodyChange: bodyChange = {
|
|
88
88
|
command,
|
|
89
89
|
parameter: 'default',
|
|
90
90
|
commandType,
|
|
91
|
-
}
|
|
91
|
+
}
|
|
92
92
|
await this.pushChanges(bodyChange)
|
|
93
93
|
}
|
|
94
94
|
}
|
|
@@ -98,14 +98,13 @@ export class WaterHeater extends irdeviceBase {
|
|
|
98
98
|
if (this.device.connectionType === 'OpenAPI') {
|
|
99
99
|
this.infoLog(`Sending request to SwitchBot API, body: ${bodyChange},`)
|
|
100
100
|
try {
|
|
101
|
-
const { body
|
|
102
|
-
const deviceStatus: any = await body
|
|
103
|
-
await this.pushStatusCodes(
|
|
104
|
-
if (await this.successfulStatusCodes(
|
|
105
|
-
await this.successfulPushChange(
|
|
101
|
+
const { body } = await this.pushChangeRequest(bodyChange)
|
|
102
|
+
const deviceStatus: any = await body
|
|
103
|
+
await this.pushStatusCodes(deviceStatus)
|
|
104
|
+
if (await this.successfulStatusCodes(deviceStatus)) {
|
|
105
|
+
await this.successfulPushChange(deviceStatus, bodyChange)
|
|
106
106
|
await this.updateHomeKitCharacteristics()
|
|
107
107
|
} else {
|
|
108
|
-
await this.statusCode(statusCode)
|
|
109
108
|
await this.statusCode(deviceStatus.statusCode)
|
|
110
109
|
}
|
|
111
110
|
} catch (e: any) {
|
package/src/platform.ts
CHANGED
|
@@ -2,21 +2,14 @@
|
|
|
2
2
|
*
|
|
3
3
|
* platform.ts: @switchbot/homebridge-switchbot platform class.
|
|
4
4
|
*/
|
|
5
|
-
import type {
|
|
6
|
-
import type { UrlObject } from 'node:url'
|
|
5
|
+
import type { Server } from 'node:http'
|
|
7
6
|
|
|
8
7
|
import type { API, DynamicPlatformPlugin, Logging, PlatformAccessory } from 'homebridge'
|
|
9
8
|
import type { MqttClient } from 'mqtt'
|
|
10
|
-
import type { Dispatcher } from 'undici'
|
|
11
9
|
|
|
12
10
|
import type { devicesConfig, irDevicesConfig, options, SwitchBotPlatformConfig } from './settings.js'
|
|
13
|
-
import type { blindTilt, curtain, curtain3, device } from './types/devicelist.js'
|
|
14
|
-
import type { irdevice } from './types/irdevicelist.js'
|
|
15
11
|
|
|
16
|
-
import { Buffer } from 'node:buffer'
|
|
17
|
-
import crypto, { randomUUID } from 'node:crypto'
|
|
18
12
|
import { readFileSync, writeFileSync } from 'node:fs'
|
|
19
|
-
import { createServer } from 'node:http'
|
|
20
13
|
import process from 'node:process'
|
|
21
14
|
|
|
22
15
|
import asyncmqtt from 'async-mqtt'
|
|
@@ -26,9 +19,10 @@ import { EveHomeKitTypes } from 'homebridge-lib/EveHomeKitTypes'
|
|
|
26
19
|
* For Testing Locally:
|
|
27
20
|
* import { SwitchBotModel } from '/Users/Shared/GitHub/OpenWonderLabs/node-switchbot/dist/index.js';
|
|
28
21
|
*/
|
|
29
|
-
import {
|
|
22
|
+
import type { blindTilt, curtain, curtain3, device, devices, irdevice } from 'node-switchbot'
|
|
23
|
+
|
|
24
|
+
import { LogLevel, SwitchBot, SwitchBotModel, SwitchBotOpenAPI } from 'node-switchbot'
|
|
30
25
|
import { queueScheduler } from 'rxjs'
|
|
31
|
-
import { request } from 'undici'
|
|
32
26
|
|
|
33
27
|
import { BlindTilt } from './device/blindtilt.js'
|
|
34
28
|
import { Bot } from './device/bot.js'
|
|
@@ -57,7 +51,7 @@ import { Others } from './irdevice/other.js'
|
|
|
57
51
|
import { TV } from './irdevice/tv.js'
|
|
58
52
|
import { VacuumCleaner } from './irdevice/vacuumcleaner.js'
|
|
59
53
|
import { WaterHeater } from './irdevice/waterheater.js'
|
|
60
|
-
import {
|
|
54
|
+
import { PLATFORM_NAME, PLUGIN_NAME } from './settings.js'
|
|
61
55
|
import { formatDeviceIdAsMac, isBlindTiltDevice, isCurtainDevice, sleep } from './utils.js'
|
|
62
56
|
|
|
63
57
|
/**
|
|
@@ -92,6 +86,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
92
86
|
// Event Handlers
|
|
93
87
|
public readonly webhookEventHandler: { [x: string]: (context: any) => void } = {}
|
|
94
88
|
public readonly bleEventHandler: { [x: string]: (context: any) => void } = {}
|
|
89
|
+
switchBotAPI!: SwitchBotOpenAPI
|
|
95
90
|
|
|
96
91
|
constructor(
|
|
97
92
|
log: Logging,
|
|
@@ -132,6 +127,24 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
132
127
|
return
|
|
133
128
|
}
|
|
134
129
|
|
|
130
|
+
// SwitchBot OpenAPI
|
|
131
|
+
this.switchBotAPI = new SwitchBotOpenAPI(this.config.credentials?.token, this.config.credentials?.secret)
|
|
132
|
+
// Listen for log events
|
|
133
|
+
this.switchBotAPI.on('log', (log) => {
|
|
134
|
+
switch (log.level) {
|
|
135
|
+
case LogLevel.ERROR:
|
|
136
|
+
this.errorLog(log.message)
|
|
137
|
+
break
|
|
138
|
+
case LogLevel.WARN:
|
|
139
|
+
this.warnLog(log.message)
|
|
140
|
+
break
|
|
141
|
+
case LogLevel.DEBUG:
|
|
142
|
+
this.debugLog(log.message)
|
|
143
|
+
break
|
|
144
|
+
default:
|
|
145
|
+
this.infoLog(log.message)
|
|
146
|
+
}
|
|
147
|
+
})
|
|
135
148
|
// import fakegato-history module and EVE characteristics
|
|
136
149
|
this.fakegatoAPI = fakegato(api)
|
|
137
150
|
this.eve = new EveHomeKitTypes(api)
|
|
@@ -208,121 +221,24 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
208
221
|
// webhook configuration
|
|
209
222
|
if (this.config.options?.webhookURL) {
|
|
210
223
|
const url = this.config.options?.webhookURL
|
|
211
|
-
|
|
212
224
|
try {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
try {
|
|
221
|
-
const body = JSON.parse(data)
|
|
222
|
-
await this.debugLog(`Received Webhook: ${JSON.stringify(body)}`)
|
|
223
|
-
if (this.config.options?.mqttURL) {
|
|
224
|
-
const mac = body.context.deviceMac?.toLowerCase().match(/[\s\S]{1,2}/g)?.join(':')
|
|
225
|
-
const options = this.config.options?.mqttPubOptions || {}
|
|
226
|
-
this.mqttClient?.publish(`homebridge-switchbot/webhook/${mac}`, `${JSON.stringify(body.context)}`, options)
|
|
227
|
-
}
|
|
228
|
-
this.webhookEventHandler[body.context.deviceMac]?.(body.context)
|
|
229
|
-
} catch (e: any) {
|
|
230
|
-
await this.errorLog(`Failed to handle webhook event. Error:${e}`)
|
|
231
|
-
}
|
|
232
|
-
})
|
|
233
|
-
response.writeHead(200, { 'Content-Type': 'text/plain' })
|
|
234
|
-
response.end('OK')
|
|
235
|
-
}
|
|
236
|
-
// else {
|
|
237
|
-
// response.writeHead(403, {'Content-Type': 'text/plain'});
|
|
238
|
-
// response.end(`NG`);
|
|
239
|
-
// }
|
|
240
|
-
} catch (e: any) {
|
|
241
|
-
this.errorLog(`Failed to handle webhook event. Error:${e}`)
|
|
225
|
+
this.switchBotAPI.setupWebhook(url)
|
|
226
|
+
// Listen for webhook events
|
|
227
|
+
this.switchBotAPI.on('webhookEvent', (body) => {
|
|
228
|
+
if (this.config.options?.mqttURL) {
|
|
229
|
+
const mac = body.context.deviceMac?.toLowerCase().match(/[\s\S]{1,2}/g)?.join(':')
|
|
230
|
+
const options = this.config.options?.mqttPubOptions || {}
|
|
231
|
+
this.mqttClient?.publish(`homebridge-switchbot/webhook/${mac}`, `${JSON.stringify(body.context)}`, options)
|
|
242
232
|
}
|
|
243
|
-
|
|
244
|
-
} catch (e: any) {
|
|
245
|
-
await this.errorLog(`Failed to create webhook listener. Error:${e.message}`)
|
|
246
|
-
return
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
try {
|
|
250
|
-
const { body, statusCode } = await request(setupWebhook, {
|
|
251
|
-
method: 'POST',
|
|
252
|
-
headers: this.generateHeaders(),
|
|
253
|
-
body: JSON.stringify({
|
|
254
|
-
action: 'setupWebhook',
|
|
255
|
-
url,
|
|
256
|
-
deviceList: 'ALL',
|
|
257
|
-
}),
|
|
258
|
-
})
|
|
259
|
-
const response: any = await body.json()
|
|
260
|
-
await this.debugLog(`setupWebhook: url:${url}, body:${JSON.stringify(response)}, statusCode:${statusCode}`)
|
|
261
|
-
if (statusCode !== 200 || response?.statusCode !== 100) {
|
|
262
|
-
await this.errorLog(`Failed to configure webhook. Existing webhook well be overridden. HTTP:${statusCode} API:${response?.statusCode} message:${response?.message}`)
|
|
263
|
-
}
|
|
264
|
-
} catch (e: any) {
|
|
265
|
-
await this.errorLog(`Failed to configure webhook. Error: ${e.message}`)
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
try {
|
|
269
|
-
const { body, statusCode } = await request(updateWebhook, {
|
|
270
|
-
method: 'POST',
|
|
271
|
-
headers: this.generateHeaders(),
|
|
272
|
-
body: JSON.stringify({
|
|
273
|
-
action: 'updateWebhook',
|
|
274
|
-
config: {
|
|
275
|
-
url,
|
|
276
|
-
enable: true,
|
|
277
|
-
},
|
|
278
|
-
}),
|
|
233
|
+
this.webhookEventHandler[body.context.deviceMac]?.(body.context)
|
|
279
234
|
})
|
|
280
|
-
const response: any = await body.json()
|
|
281
|
-
await this.debugLog(`updateWebhook: url:${url}, body:${JSON.stringify(response)}, statusCode:${statusCode}`)
|
|
282
|
-
if (statusCode !== 200 || response?.statusCode !== 100) {
|
|
283
|
-
await this.errorLog(`Failed to update webhook. HTTP:${statusCode} API:${response?.statusCode} message:${response?.message}`)
|
|
284
|
-
}
|
|
285
|
-
} catch (e: any) {
|
|
286
|
-
await this.errorLog(`Failed to update webhook. Error:${e.message}`)
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
try {
|
|
290
|
-
const { body, statusCode } = await request(queryWebhook, {
|
|
291
|
-
method: 'POST',
|
|
292
|
-
headers: this.generateHeaders(),
|
|
293
|
-
body: JSON.stringify({
|
|
294
|
-
action: 'queryUrl',
|
|
295
|
-
}),
|
|
296
|
-
})
|
|
297
|
-
const response: any = await body.json()
|
|
298
|
-
await this.debugLog(`queryWebhook: body:${JSON.stringify(response)}`)
|
|
299
|
-
await this.debugLog(`queryWebhook: statusCode:${statusCode}`)
|
|
300
|
-
if (statusCode !== 200 || response?.statusCode !== 100) {
|
|
301
|
-
await this.errorLog(`Failed to query webhook. HTTP:${statusCode} API:${response?.statusCode} message:${response?.message}`)
|
|
302
|
-
} else {
|
|
303
|
-
await this.infoLog(`Listening webhook on ${response?.body?.urls[0]}`)
|
|
304
|
-
}
|
|
305
235
|
} catch (e: any) {
|
|
306
|
-
await this.errorLog(`Failed to
|
|
236
|
+
await this.errorLog(`Failed to setup webhook. Error:${e.message}`)
|
|
307
237
|
}
|
|
308
238
|
|
|
309
239
|
this.api.on('shutdown', async () => {
|
|
310
240
|
try {
|
|
311
|
-
|
|
312
|
-
method: 'POST',
|
|
313
|
-
headers: this.generateHeaders(),
|
|
314
|
-
body: JSON.stringify({
|
|
315
|
-
action: 'deleteWebhook',
|
|
316
|
-
url,
|
|
317
|
-
}),
|
|
318
|
-
})
|
|
319
|
-
const response: any = await body.json()
|
|
320
|
-
await this.debugLog(`deleteWebhook: url:${url}, body:${JSON.stringify(response)}, statusCode:${statusCode}`)
|
|
321
|
-
if (statusCode !== 200 || response?.statusCode !== 100) {
|
|
322
|
-
await this.errorLog(`Failed to delete webhook. HTTP:${statusCode} API:${response?.statusCode} message:${response?.message}`)
|
|
323
|
-
} else {
|
|
324
|
-
await this.infoLog('Unregistered webhook to close listening.')
|
|
325
|
-
}
|
|
241
|
+
this.switchBotAPI.deleteWebhook(url)
|
|
326
242
|
} catch (e: any) {
|
|
327
243
|
await this.errorLog(`Failed to delete webhook. Error:${e.message}`)
|
|
328
244
|
}
|
|
@@ -341,7 +257,11 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
341
257
|
(async () => {
|
|
342
258
|
// Start to monitor advertisement packets
|
|
343
259
|
await this.debugLog('Scanning for BLE SwitchBot devices...')
|
|
344
|
-
|
|
260
|
+
try {
|
|
261
|
+
await switchbot.startScan()
|
|
262
|
+
} catch (e: any) {
|
|
263
|
+
await this.errorLog(`Failed to start BLE scanning. Error:${e}`)
|
|
264
|
+
}
|
|
345
265
|
// Set an event handler to monitor advertisement packets
|
|
346
266
|
switchbot.onadvertisement = async (ad: any) => {
|
|
347
267
|
try {
|
|
@@ -531,25 +451,6 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
531
451
|
}
|
|
532
452
|
}
|
|
533
453
|
|
|
534
|
-
generateHeaders = () => {
|
|
535
|
-
const t = `${Date.now()}`
|
|
536
|
-
const nonce = randomUUID()
|
|
537
|
-
const data = this.config.credentials?.token + t + nonce
|
|
538
|
-
const signTerm = crypto
|
|
539
|
-
.createHmac('sha256', this.config.credentials?.secret)
|
|
540
|
-
.update(Buffer.from(data, 'utf-8'))
|
|
541
|
-
.digest()
|
|
542
|
-
const sign = signTerm.toString('base64')
|
|
543
|
-
|
|
544
|
-
return {
|
|
545
|
-
'Authorization': this.config.credentials?.token,
|
|
546
|
-
'sign': sign,
|
|
547
|
-
'nonce': nonce,
|
|
548
|
-
't': t,
|
|
549
|
-
'Content-Type': 'application/json',
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
|
|
553
454
|
async discoverDevices() {
|
|
554
455
|
if (!this.config.credentials?.token) {
|
|
555
456
|
return this.handleManualConfig()
|
|
@@ -565,17 +466,14 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
565
466
|
|
|
566
467
|
while (retryCount < maxRetries) {
|
|
567
468
|
try {
|
|
568
|
-
const {
|
|
569
|
-
await this.
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
if (this.isSuccessfulResponse(statusCode, devicesAPI.statusCode)) {
|
|
574
|
-
await this.handleDevices(devicesAPI.body.deviceList)
|
|
575
|
-
await this.handleIRDevices(devicesAPI.body.infraredRemoteList)
|
|
469
|
+
const { response, statusCode } = await this.switchBotAPI.getDevices()
|
|
470
|
+
await this.debugLog(`response: ${JSON.stringify(response)}`)
|
|
471
|
+
if (this.isSuccessfulResponse(statusCode)) {
|
|
472
|
+
await this.handleDevices(Array.isArray(response.body.deviceList) ? response.body.deviceList : [])
|
|
473
|
+
await this.handleIRDevices(Array.isArray(response.body.infraredRemoteList) ? response.body.infraredRemoteList : [])
|
|
576
474
|
break
|
|
577
475
|
} else {
|
|
578
|
-
await this.handleErrorResponse(statusCode,
|
|
476
|
+
await this.handleErrorResponse(statusCode, retryCount, maxRetries, delayBetweenRetries)
|
|
579
477
|
retryCount++
|
|
580
478
|
}
|
|
581
479
|
} catch (e: any) {
|
|
@@ -608,8 +506,8 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
608
506
|
}
|
|
609
507
|
}
|
|
610
508
|
|
|
611
|
-
private isSuccessfulResponse(
|
|
612
|
-
return (
|
|
509
|
+
private isSuccessfulResponse(apiStatusCode: number): boolean {
|
|
510
|
+
return (apiStatusCode === 200 || apiStatusCode === 100)
|
|
613
511
|
}
|
|
614
512
|
|
|
615
513
|
private async handleDevices(deviceLists: any[]) {
|
|
@@ -674,11 +572,10 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
674
572
|
})
|
|
675
573
|
}
|
|
676
574
|
|
|
677
|
-
private async handleErrorResponse(
|
|
678
|
-
await this.statusCode(statusCode)
|
|
575
|
+
private async handleErrorResponse(apiStatusCode: number, retryCount: number, maxRetries: number, delayBetweenRetries: number) {
|
|
679
576
|
await this.statusCode(apiStatusCode)
|
|
680
|
-
if (
|
|
681
|
-
this.infoLog(`statusCode: ${
|
|
577
|
+
if (apiStatusCode === 500) {
|
|
578
|
+
this.infoLog(`statusCode: ${apiStatusCode} Attempt ${retryCount + 1} of ${maxRetries}`)
|
|
682
579
|
await sleep(delayBetweenRetries)
|
|
683
580
|
}
|
|
684
581
|
}
|
|
@@ -2639,18 +2536,15 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
2639
2536
|
}
|
|
2640
2537
|
}
|
|
2641
2538
|
|
|
2642
|
-
async retryRequest(
|
|
2539
|
+
async retryRequest(deviceId: string, deviceMaxRetries: number, deviceDelayBetweenRetries: number): Promise<{ response: any, statusCode: number }> {
|
|
2643
2540
|
let retryCount = 0
|
|
2644
2541
|
const maxRetries = deviceMaxRetries
|
|
2645
2542
|
const delayBetweenRetries = deviceDelayBetweenRetries
|
|
2646
2543
|
while (retryCount < maxRetries) {
|
|
2647
2544
|
try {
|
|
2648
|
-
const {
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
} else {
|
|
2652
|
-
await this.debugLog(`Received status code: ${statusCode}`)
|
|
2653
|
-
}
|
|
2545
|
+
const { response, statusCode } = await this.switchBotAPI.getDeviceStatus(deviceId)
|
|
2546
|
+
await this.warnLog(`response: ${JSON.stringify(response)}`)
|
|
2547
|
+
return { response, statusCode }
|
|
2654
2548
|
} catch (error: any) {
|
|
2655
2549
|
await this.errorLog(`Error making request: ${error.message}`)
|
|
2656
2550
|
}
|
|
@@ -2658,7 +2552,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
2658
2552
|
await this.debugLog(`Retry attempt ${retryCount} of ${maxRetries}`)
|
|
2659
2553
|
await sleep(delayBetweenRetries)
|
|
2660
2554
|
}
|
|
2661
|
-
return {
|
|
2555
|
+
return { response: null, statusCode: 500 }
|
|
2662
2556
|
}
|
|
2663
2557
|
|
|
2664
2558
|
// BLE Connection
|
package/src/settings.ts
CHANGED
|
@@ -4,10 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import type { IClientOptions } from 'async-mqtt'
|
|
6
6
|
import type { PlatformConfig } from 'homebridge'
|
|
7
|
-
import type { SwitchBotBLEModel, SwitchBotBLEModelFriendlyName, SwitchBotBLEModelName } from 'node-switchbot'
|
|
8
|
-
|
|
9
|
-
import type { device } from './types/devicelist'
|
|
10
|
-
import type { irdevice } from './types/irdevicelist'
|
|
7
|
+
import type { device, irdevice, SwitchBotBLEModel, SwitchBotBLEModelFriendlyName, SwitchBotBLEModelName } from 'node-switchbot'
|
|
11
8
|
/**
|
|
12
9
|
* This is the name of the platform that users will use to register the plugin in the Homebridge config.json
|
|
13
10
|
*/
|
package/src/utils.ts
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
*
|
|
3
3
|
* util.ts: @switchbot/homebridge-switchbot platform class.
|
|
4
4
|
*/
|
|
5
|
+
import type { blindTilt, curtain, curtain3, device } from 'node-switchbot'
|
|
6
|
+
|
|
5
7
|
import type { devicesConfig } from './settings.js'
|
|
6
|
-
import type { blindTilt, curtain, curtain3, device } from './types/devicelist.js'
|
|
7
8
|
|
|
8
9
|
export enum SwitchBotModel {
|
|
9
10
|
HubMini = 'W0202200',
|