@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.
Files changed (196) hide show
  1. package/.github/workflows/beta-release.yml +2 -1
  2. package/CHANGELOG.md +8 -0
  3. package/dist/device/blindtilt.d.ts +1 -4
  4. package/dist/device/blindtilt.d.ts.map +1 -1
  5. package/dist/device/blindtilt.js +18 -19
  6. package/dist/device/blindtilt.js.map +1 -1
  7. package/dist/device/bot.d.ts +1 -4
  8. package/dist/device/bot.d.ts.map +1 -1
  9. package/dist/device/bot.js +15 -16
  10. package/dist/device/bot.js.map +1 -1
  11. package/dist/device/ceilinglight.d.ts +1 -4
  12. package/dist/device/ceilinglight.d.ts.map +1 -1
  13. package/dist/device/ceilinglight.js +35 -39
  14. package/dist/device/ceilinglight.js.map +1 -1
  15. package/dist/device/colorbulb.d.ts +1 -4
  16. package/dist/device/colorbulb.d.ts.map +1 -1
  17. package/dist/device/colorbulb.js +35 -39
  18. package/dist/device/colorbulb.js.map +1 -1
  19. package/dist/device/contact.d.ts +1 -4
  20. package/dist/device/contact.d.ts.map +1 -1
  21. package/dist/device/contact.js +7 -7
  22. package/dist/device/contact.js.map +1 -1
  23. package/dist/device/curtain.d.ts +1 -4
  24. package/dist/device/curtain.d.ts.map +1 -1
  25. package/dist/device/curtain.js +16 -17
  26. package/dist/device/curtain.js.map +1 -1
  27. package/dist/device/device.d.ts +6 -6
  28. package/dist/device/device.d.ts.map +1 -1
  29. package/dist/device/device.js +30 -14
  30. package/dist/device/device.js.map +1 -1
  31. package/dist/device/fan.d.ts +1 -4
  32. package/dist/device/fan.d.ts.map +1 -1
  33. package/dist/device/fan.js +28 -31
  34. package/dist/device/fan.js.map +1 -1
  35. package/dist/device/hub.d.ts +1 -4
  36. package/dist/device/hub.d.ts.map +1 -1
  37. package/dist/device/hub.js +7 -7
  38. package/dist/device/hub.js.map +1 -1
  39. package/dist/device/humidifier.d.ts +1 -4
  40. package/dist/device/humidifier.d.ts.map +1 -1
  41. package/dist/device/humidifier.js +28 -31
  42. package/dist/device/humidifier.js.map +1 -1
  43. package/dist/device/iosensor.d.ts +1 -4
  44. package/dist/device/iosensor.d.ts.map +1 -1
  45. package/dist/device/iosensor.js +7 -7
  46. package/dist/device/iosensor.js.map +1 -1
  47. package/dist/device/lightstrip.d.ts +1 -4
  48. package/dist/device/lightstrip.d.ts.map +1 -1
  49. package/dist/device/lightstrip.js +28 -31
  50. package/dist/device/lightstrip.js.map +1 -1
  51. package/dist/device/lock.d.ts +1 -4
  52. package/dist/device/lock.d.ts.map +1 -1
  53. package/dist/device/lock.js +15 -16
  54. package/dist/device/lock.js.map +1 -1
  55. package/dist/device/meter.d.ts +1 -4
  56. package/dist/device/meter.d.ts.map +1 -1
  57. package/dist/device/meter.js +7 -7
  58. package/dist/device/meter.js.map +1 -1
  59. package/dist/device/meterplus.d.ts +1 -4
  60. package/dist/device/meterplus.d.ts.map +1 -1
  61. package/dist/device/meterplus.js +7 -7
  62. package/dist/device/meterplus.js.map +1 -1
  63. package/dist/device/motion.d.ts +1 -4
  64. package/dist/device/motion.d.ts.map +1 -1
  65. package/dist/device/motion.js +7 -7
  66. package/dist/device/motion.js.map +1 -1
  67. package/dist/device/plug.d.ts +1 -4
  68. package/dist/device/plug.d.ts.map +1 -1
  69. package/dist/device/plug.js +14 -15
  70. package/dist/device/plug.js.map +1 -1
  71. package/dist/device/robotvacuumcleaner.d.ts +1 -4
  72. package/dist/device/robotvacuumcleaner.d.ts.map +1 -1
  73. package/dist/device/robotvacuumcleaner.js +21 -23
  74. package/dist/device/robotvacuumcleaner.js.map +1 -1
  75. package/dist/device/waterdetector.d.ts +1 -4
  76. package/dist/device/waterdetector.d.ts.map +1 -1
  77. package/dist/device/waterdetector.js +7 -7
  78. package/dist/device/waterdetector.js.map +1 -1
  79. package/dist/irdevice/airconditioner.d.ts +1 -1
  80. package/dist/irdevice/airconditioner.d.ts.map +1 -1
  81. package/dist/irdevice/airconditioner.js +11 -12
  82. package/dist/irdevice/airconditioner.js.map +1 -1
  83. package/dist/irdevice/airpurifier.d.ts +1 -1
  84. package/dist/irdevice/airpurifier.d.ts.map +1 -1
  85. package/dist/irdevice/airpurifier.js +11 -12
  86. package/dist/irdevice/airpurifier.js.map +1 -1
  87. package/dist/irdevice/camera.d.ts +1 -1
  88. package/dist/irdevice/camera.d.ts.map +1 -1
  89. package/dist/irdevice/camera.js +9 -10
  90. package/dist/irdevice/camera.js.map +1 -1
  91. package/dist/irdevice/fan.d.ts +1 -1
  92. package/dist/irdevice/fan.d.ts.map +1 -1
  93. package/dist/irdevice/fan.js +15 -16
  94. package/dist/irdevice/fan.js.map +1 -1
  95. package/dist/irdevice/irdevice.d.ts +6 -6
  96. package/dist/irdevice/irdevice.d.ts.map +1 -1
  97. package/dist/irdevice/irdevice.js +7 -13
  98. package/dist/irdevice/irdevice.js.map +1 -1
  99. package/dist/irdevice/light.d.ts +1 -1
  100. package/dist/irdevice/light.d.ts.map +1 -1
  101. package/dist/irdevice/light.js +9 -10
  102. package/dist/irdevice/light.js.map +1 -1
  103. package/dist/irdevice/other.d.ts +1 -1
  104. package/dist/irdevice/other.d.ts.map +1 -1
  105. package/dist/irdevice/other.js +9 -10
  106. package/dist/irdevice/other.js.map +1 -1
  107. package/dist/irdevice/tv.d.ts +1 -1
  108. package/dist/irdevice/tv.d.ts.map +1 -1
  109. package/dist/irdevice/tv.js +27 -28
  110. package/dist/irdevice/tv.js.map +1 -1
  111. package/dist/irdevice/vacuumcleaner.d.ts +1 -1
  112. package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
  113. package/dist/irdevice/vacuumcleaner.js +9 -10
  114. package/dist/irdevice/vacuumcleaner.js.map +1 -1
  115. package/dist/irdevice/waterheater.d.ts +1 -1
  116. package/dist/irdevice/waterheater.d.ts.map +1 -1
  117. package/dist/irdevice/waterheater.js +9 -10
  118. package/dist/irdevice/waterheater.js.map +1 -1
  119. package/dist/platform.d.ts +5 -14
  120. package/dist/platform.d.ts.map +1 -1
  121. package/dist/platform.js +53 -161
  122. package/dist/platform.js.map +1 -1
  123. package/dist/settings.d.ts +1 -3
  124. package/dist/settings.d.ts.map +1 -1
  125. package/dist/settings.js.map +1 -1
  126. package/dist/utils.d.ts +1 -1
  127. package/dist/utils.d.ts.map +1 -1
  128. package/dist/utils.js.map +1 -1
  129. package/package.json +9 -10
  130. package/src/device/blindtilt.ts +20 -24
  131. package/src/device/bot.ts +16 -20
  132. package/src/device/ceilinglight.ts +36 -43
  133. package/src/device/colorbulb.ts +36 -43
  134. package/src/device/contact.ts +8 -11
  135. package/src/device/curtain.ts +18 -22
  136. package/src/device/device.ts +29 -18
  137. package/src/device/fan.ts +29 -35
  138. package/src/device/hub.ts +8 -11
  139. package/src/device/humidifier.ts +29 -35
  140. package/src/device/iosensor.ts +8 -11
  141. package/src/device/lightstrip.ts +29 -35
  142. package/src/device/lock.ts +16 -20
  143. package/src/device/meter.ts +8 -11
  144. package/src/device/meterplus.ts +8 -11
  145. package/src/device/motion.ts +8 -11
  146. package/src/device/plug.ts +15 -19
  147. package/src/device/robotvacuumcleaner.ts +22 -31
  148. package/src/device/waterdetector.ts +8 -11
  149. package/src/irdevice/airconditioner.ts +12 -14
  150. package/src/irdevice/airpurifier.ts +12 -13
  151. package/src/irdevice/camera.ts +10 -11
  152. package/src/irdevice/fan.ts +16 -17
  153. package/src/irdevice/irdevice.ts +9 -17
  154. package/src/irdevice/light.ts +10 -11
  155. package/src/irdevice/other.ts +10 -11
  156. package/src/irdevice/tv.ts +28 -29
  157. package/src/irdevice/vacuumcleaner.ts +10 -11
  158. package/src/irdevice/waterheater.ts +10 -11
  159. package/src/platform.ts +55 -161
  160. package/src/settings.ts +1 -4
  161. package/src/utils.ts +2 -1
  162. package/dist/types/bledevicestatus.d.ts +0 -281
  163. package/dist/types/bledevicestatus.d.ts.map +0 -1
  164. package/dist/types/bledevicestatus.js +0 -2
  165. package/dist/types/bledevicestatus.js.map +0 -1
  166. package/dist/types/devicelist.d.ts +0 -89
  167. package/dist/types/devicelist.d.ts.map +0 -1
  168. package/dist/types/devicelist.js +0 -6
  169. package/dist/types/devicelist.js.map +0 -1
  170. package/dist/types/deviceresponse.d.ts +0 -13
  171. package/dist/types/deviceresponse.d.ts.map +0 -1
  172. package/dist/types/deviceresponse.js +0 -2
  173. package/dist/types/deviceresponse.js.map +0 -1
  174. package/dist/types/devicestatus.d.ts +0 -149
  175. package/dist/types/devicestatus.d.ts.map +0 -1
  176. package/dist/types/devicestatus.js +0 -3
  177. package/dist/types/devicestatus.js.map +0 -1
  178. package/dist/types/devicewebhookstatus.d.ts +0 -156
  179. package/dist/types/devicewebhookstatus.d.ts.map +0 -1
  180. package/dist/types/devicewebhookstatus.js +0 -2
  181. package/dist/types/devicewebhookstatus.js.map +0 -1
  182. package/dist/types/irdevicelist.d.ts +0 -10
  183. package/dist/types/irdevicelist.d.ts.map +0 -1
  184. package/dist/types/irdevicelist.js +0 -2
  185. package/dist/types/irdevicelist.js.map +0 -1
  186. package/dist/types/pushbody.d.ts +0 -6
  187. package/dist/types/pushbody.d.ts.map +0 -1
  188. package/dist/types/pushbody.js +0 -2
  189. package/dist/types/pushbody.js.map +0 -1
  190. package/src/types/bledevicestatus.ts +0 -303
  191. package/src/types/devicelist.ts +0 -124
  192. package/src/types/deviceresponse.ts +0 -14
  193. package/src/types/devicestatus.ts +0 -178
  194. package/src/types/devicewebhookstatus.ts +0 -191
  195. package/src/types/irdevicelist.ts +0 -15
  196. package/src/types/pushbody.ts +0 -9
@@ -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 = JSON.stringify({
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 = JSON.stringify({
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 = JSON.stringify({
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 = JSON.stringify({
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 = JSON.stringify({
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 = JSON.stringify({
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 = JSON.stringify({
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 = JSON.stringify({
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 = JSON.stringify({
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 = JSON.stringify({
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 = JSON.stringify({
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, statusCode } = await this.pushChangeRequest(bodyChange)
350
- const deviceStatus: any = await body.json()
351
- await this.pushStatusCodes(statusCode, deviceStatus)
352
- if (await this.successfulStatusCodes(statusCode, deviceStatus)) {
353
- await this.successfulPushChange(statusCode, deviceStatus, bodyChange)
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 = JSON.stringify({
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 = JSON.stringify({
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, statusCode } = await this.pushChangeRequest(bodyChange)
101
- const deviceStatus: any = await body.json()
102
- await this.pushStatusCodes(statusCode, deviceStatus)
103
- if (await this.successfulStatusCodes(statusCode, deviceStatus)) {
104
- await this.successfulPushChange(statusCode, deviceStatus, bodyChange)
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 = JSON.stringify({
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 = JSON.stringify({
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, statusCode } = await this.pushChangeRequest(bodyChange)
102
- const deviceStatus: any = await body.json()
103
- await this.pushStatusCodes(statusCode, deviceStatus)
104
- if (await this.successfulStatusCodes(statusCode, deviceStatus)) {
105
- await this.successfulPushChange(statusCode, deviceStatus, bodyChange)
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 { IncomingMessage, Server, ServerResponse } from 'node:http'
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 { SwitchBot, SwitchBotModel } from 'node-switchbot'
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 { deleteWebhook, Devices, PLATFORM_NAME, PLUGIN_NAME, queryWebhook, setupWebhook, updateWebhook } from './settings.js'
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
- const xurl = new URL(url)
214
- const port = Number(xurl.port)
215
- const path = xurl.pathname
216
- this.webhookEventListener = createServer((request: IncomingMessage, response: ServerResponse) => {
217
- try {
218
- if (request.url === path && request.method === 'POST') {
219
- request.on('data', async (data) => {
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
- }).listen(port || 80)
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 query webhook. Error:${e}`)
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
- const { body, statusCode } = await request(deleteWebhook, {
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
- await switchbot.startScan()
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 { body, statusCode } = await request(Devices, { headers: this.generateHeaders() })
569
- await this.debugWarnLog(`statusCode: ${statusCode}`)
570
- const devicesAPI: any = await body.json()
571
- await this.debugWarnLog(`devicesAPI: ${JSON.stringify(devicesAPI)}`)
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, devicesAPI.statusCode, retryCount, maxRetries, delayBetweenRetries)
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(statusCode: number, apiStatusCode: number): boolean {
612
- return (statusCode === 200 || statusCode === 100) && (apiStatusCode === 200 || apiStatusCode === 100)
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(statusCode: number, apiStatusCode: number, retryCount: number, maxRetries: number, delayBetweenRetries: number) {
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 (statusCode === 500) {
681
- this.infoLog(`statusCode: ${statusCode} Attempt ${retryCount + 1} of ${maxRetries}`)
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(deviceMaxRetries: number, deviceDelayBetweenRetries: number, url: string | URL | UrlObject, options?: { dispatcher?: Dispatcher } & Omit<Dispatcher.RequestOptions, 'origin' | 'path' | 'method'> & Partial<Pick<Dispatcher.RequestOptions, 'method'>>): Promise<{ body: any, statusCode: number }> {
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 { body, statusCode } = await request(url, options)
2649
- if (statusCode === 200 || statusCode === 100) {
2650
- return { body, statusCode }
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 { body: null, statusCode: -1 }
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',