@switchbot/homebridge-switchbot 3.8.3-beta.3 → 3.8.3-beta.30

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 (201) hide show
  1. package/.github/workflows/beta-release.yml +7 -4
  2. package/.github/workflows/release.yml +7 -6
  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 +32 -34
  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 +6 -14
  120. package/dist/platform.d.ts.map +1 -1
  121. package/dist/platform.js +105 -170
  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/docs/assets/highlight.css +42 -0
  130. package/docs/assets/main.js +1 -1
  131. package/docs/functions/default.html +1 -1
  132. package/docs/index.html +61 -50
  133. package/docs/media/security-privacy-bluetooth.png +0 -0
  134. package/package.json +13 -14
  135. package/src/device/blindtilt.ts +20 -24
  136. package/src/device/bot.ts +16 -20
  137. package/src/device/ceilinglight.ts +36 -43
  138. package/src/device/colorbulb.ts +36 -43
  139. package/src/device/contact.ts +8 -11
  140. package/src/device/curtain.ts +18 -22
  141. package/src/device/device.ts +29 -18
  142. package/src/device/fan.ts +33 -38
  143. package/src/device/hub.ts +8 -11
  144. package/src/device/humidifier.ts +29 -35
  145. package/src/device/iosensor.ts +8 -11
  146. package/src/device/lightstrip.ts +29 -35
  147. package/src/device/lock.ts +16 -20
  148. package/src/device/meter.ts +8 -11
  149. package/src/device/meterplus.ts +8 -11
  150. package/src/device/motion.ts +8 -11
  151. package/src/device/plug.ts +15 -19
  152. package/src/device/robotvacuumcleaner.ts +22 -31
  153. package/src/device/waterdetector.ts +8 -11
  154. package/src/irdevice/airconditioner.ts +12 -14
  155. package/src/irdevice/airpurifier.ts +12 -13
  156. package/src/irdevice/camera.ts +10 -11
  157. package/src/irdevice/fan.ts +16 -17
  158. package/src/irdevice/irdevice.ts +9 -17
  159. package/src/irdevice/light.ts +10 -11
  160. package/src/irdevice/other.ts +10 -11
  161. package/src/irdevice/tv.ts +28 -29
  162. package/src/irdevice/vacuumcleaner.ts +10 -11
  163. package/src/irdevice/waterheater.ts +10 -11
  164. package/src/platform.ts +110 -171
  165. package/src/settings.ts +5 -4
  166. package/src/utils.ts +2 -1
  167. package/dist/types/bledevicestatus.d.ts +0 -281
  168. package/dist/types/bledevicestatus.d.ts.map +0 -1
  169. package/dist/types/bledevicestatus.js +0 -2
  170. package/dist/types/bledevicestatus.js.map +0 -1
  171. package/dist/types/devicelist.d.ts +0 -89
  172. package/dist/types/devicelist.d.ts.map +0 -1
  173. package/dist/types/devicelist.js +0 -6
  174. package/dist/types/devicelist.js.map +0 -1
  175. package/dist/types/deviceresponse.d.ts +0 -13
  176. package/dist/types/deviceresponse.d.ts.map +0 -1
  177. package/dist/types/deviceresponse.js +0 -2
  178. package/dist/types/deviceresponse.js.map +0 -1
  179. package/dist/types/devicestatus.d.ts +0 -149
  180. package/dist/types/devicestatus.d.ts.map +0 -1
  181. package/dist/types/devicestatus.js +0 -3
  182. package/dist/types/devicestatus.js.map +0 -1
  183. package/dist/types/devicewebhookstatus.d.ts +0 -156
  184. package/dist/types/devicewebhookstatus.d.ts.map +0 -1
  185. package/dist/types/devicewebhookstatus.js +0 -2
  186. package/dist/types/devicewebhookstatus.js.map +0 -1
  187. package/dist/types/irdevicelist.d.ts +0 -10
  188. package/dist/types/irdevicelist.d.ts.map +0 -1
  189. package/dist/types/irdevicelist.js +0 -2
  190. package/dist/types/irdevicelist.js.map +0 -1
  191. package/dist/types/pushbody.d.ts +0 -6
  192. package/dist/types/pushbody.d.ts.map +0 -1
  193. package/dist/types/pushbody.js +0 -2
  194. package/dist/types/pushbody.js.map +0 -1
  195. package/src/types/bledevicestatus.ts +0 -303
  196. package/src/types/devicelist.ts +0 -124
  197. package/src/types/deviceresponse.ts +0 -14
  198. package/src/types/devicestatus.ts +0 -178
  199. package/src/types/devicewebhookstatus.ts +0 -191
  200. package/src/types/irdevicelist.ts +0 -15
  201. package/src/types/pushbody.ts +0 -9
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'
@@ -24,11 +17,13 @@ import fakegato from 'fakegato-history'
24
17
  import { EveHomeKitTypes } from 'homebridge-lib/EveHomeKitTypes'
25
18
  /*
26
19
  * For Testing Locally:
27
- * import { SwitchBotModel } from '/Users/Shared/GitHub/OpenWonderLabs/node-switchbot/dist/index.js';
20
+ * import type { blindTilt, curtain, curtain3, device, irdevice } from '/Users/Shared/GitHub/OpenWonderLabs/node-switchbot/dist/index.js';
21
+ * import { LogLevel, SwitchBotBLE, SwitchBotModel, SwitchBotOpenAPI } from '/Users/Shared/GitHub/OpenWonderLabs/node-switchbot/dist/index.js';
28
22
  */
29
- import { SwitchBot, SwitchBotModel } from 'node-switchbot'
23
+ import type { blindTilt, curtain, curtain3, device, irdevice } from 'node-switchbot'
24
+
25
+ import { LogLevel, SwitchBotBLE, SwitchBotModel, SwitchBotOpenAPI } from 'node-switchbot'
30
26
  import { queueScheduler } from 'rxjs'
31
- import { request } from 'undici'
32
27
 
33
28
  import { BlindTilt } from './device/blindtilt.js'
34
29
  import { Bot } from './device/bot.js'
@@ -57,7 +52,7 @@ import { Others } from './irdevice/other.js'
57
52
  import { TV } from './irdevice/tv.js'
58
53
  import { VacuumCleaner } from './irdevice/vacuumcleaner.js'
59
54
  import { WaterHeater } from './irdevice/waterheater.js'
60
- import { deleteWebhook, Devices, PLATFORM_NAME, PLUGIN_NAME, queryWebhook, setupWebhook, updateWebhook } from './settings.js'
55
+ import { PLATFORM_NAME, PLUGIN_NAME } from './settings.js'
61
56
  import { formatDeviceIdAsMac, isBlindTiltDevice, isCurtainDevice, sleep } from './utils.js'
62
57
 
63
58
  /**
@@ -85,6 +80,10 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
85
80
  mqttClient: MqttClient | null = null
86
81
  webhookEventListener: Server | null = null
87
82
 
83
+ // SwitchBot APIs
84
+ switchBotAPI!: SwitchBotOpenAPI
85
+ switchBotBLE!: SwitchBotBLE
86
+
88
87
  // External APIs
89
88
  public readonly eve: any
90
89
  public readonly fakegatoAPI: any
@@ -132,6 +131,37 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
132
131
  return
133
132
  }
134
133
 
134
+ // SwitchBot OpenAPI
135
+ this.switchBotAPI = new SwitchBotOpenAPI(this.config.credentials?.token, this.config.credentials?.secret)
136
+ // Listen for log events
137
+ this.switchBotAPI.on('log', (log) => {
138
+ switch (log.level) {
139
+ case LogLevel.SUCCESS:
140
+ this.successLog(log.message)
141
+ break
142
+ case LogLevel.DEBUGSUCCESS:
143
+ this.debugSuccessLog(log.message)
144
+ break
145
+ case LogLevel.WARN:
146
+ this.warnLog(log.message)
147
+ break
148
+ case LogLevel.DEBUGWARN:
149
+ this.debugWarnLog(log.message)
150
+ break
151
+ case LogLevel.ERROR:
152
+ this.errorLog(log.message)
153
+ break
154
+ case LogLevel.DEBUGERROR:
155
+ this.debugErrorLog(log.message)
156
+ break
157
+ case LogLevel.DEBUG:
158
+ this.debugLog(log.message)
159
+ break
160
+ case LogLevel.INFO:
161
+ default:
162
+ this.infoLog(log.message)
163
+ }
164
+ })
135
165
  // import fakegato-history module and EVE characteristics
136
166
  this.fakegatoAPI = fakegato(api)
137
167
  this.eve = new EveHomeKitTypes(api)
@@ -208,121 +238,24 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
208
238
  // webhook configuration
209
239
  if (this.config.options?.webhookURL) {
210
240
  const url = this.config.options?.webhookURL
211
-
212
241
  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}`)
242
+ this.switchBotAPI.setupWebhook(url)
243
+ // Listen for webhook events
244
+ this.switchBotAPI.on('webhookEvent', (body) => {
245
+ if (this.config.options?.mqttURL) {
246
+ const mac = body.context.deviceMac?.toLowerCase().match(/[\s\S]{1,2}/g)?.join(':')
247
+ const options = this.config.options?.mqttPubOptions || {}
248
+ this.mqttClient?.publish(`homebridge-switchbot/webhook/${mac}`, `${JSON.stringify(body.context)}`, options)
242
249
  }
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
- }),
279
- })
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
- }),
250
+ this.webhookEventHandler[body.context.deviceMac]?.(body.context)
296
251
  })
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
252
  } catch (e: any) {
306
- await this.errorLog(`Failed to query webhook. Error:${e}`)
253
+ await this.errorLog(`Failed to setup webhook. Error:${e.message}`)
307
254
  }
308
255
 
309
256
  this.api.on('shutdown', async () => {
310
257
  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
- }
258
+ this.switchBotAPI.deleteWebhook(url)
326
259
  } catch (e: any) {
327
260
  await this.errorLog(`Failed to delete webhook. Error:${e.message}`)
328
261
  }
@@ -331,19 +264,52 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
331
264
  }
332
265
 
333
266
  async setupBlE() {
267
+ this.switchBotBLE = new SwitchBotBLE()
268
+ // Listen for log events
269
+ this.switchBotBLE.on('log', (log) => {
270
+ switch (log.level) {
271
+ case LogLevel.SUCCESS:
272
+ this.successLog(log.message)
273
+ break
274
+ case LogLevel.DEBUGSUCCESS:
275
+ this.debugSuccessLog(log.message)
276
+ break
277
+ case LogLevel.WARN:
278
+ this.warnLog(log.message)
279
+ break
280
+ case LogLevel.DEBUGWARN:
281
+ this.debugWarnLog(log.message)
282
+ break
283
+ case LogLevel.ERROR:
284
+ this.errorLog(log.message)
285
+ break
286
+ case LogLevel.DEBUGERROR:
287
+ this.debugErrorLog(log.message)
288
+ break
289
+ case LogLevel.DEBUG:
290
+ this.debugLog(log.message)
291
+ break
292
+ case LogLevel.INFO:
293
+ default:
294
+ this.infoLog(log.message)
295
+ }
296
+ })
334
297
  if (this.config.options?.BLE) {
335
298
  await this.debugLog('setupBLE')
336
- const switchbot = new SwitchBot()
337
- if (switchbot === undefined) {
338
- await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`)
299
+ if (this.switchBotBLE === undefined) {
300
+ await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${this.switchBotBLE}`)
339
301
  } else {
340
302
  // Start to monitor advertisement packets
341
303
  (async () => {
342
304
  // Start to monitor advertisement packets
343
305
  await this.debugLog('Scanning for BLE SwitchBot devices...')
344
- await switchbot.startScan()
306
+ try {
307
+ await this.switchBotBLE.startScan()
308
+ } catch (e: any) {
309
+ await this.errorLog(`Failed to start BLE scanning. Error:${e}`)
310
+ }
345
311
  // Set an event handler to monitor advertisement packets
346
- switchbot.onadvertisement = async (ad: any) => {
312
+ this.switchBotBLE.onadvertisement = async (ad: any) => {
347
313
  try {
348
314
  this.bleEventHandler[ad.address]?.(ad.serviceData)
349
315
  } catch (e: any) {
@@ -354,7 +320,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
354
320
 
355
321
  this.api.on('shutdown', async () => {
356
322
  try {
357
- switchbot.stopScan()
323
+ this.switchBotBLE.stopScan()
358
324
  await this.infoLog('Stopped BLE scanning to close listening.')
359
325
  } catch (e: any) {
360
326
  await this.errorLog(`Failed to stop Platform BLE scanning. Error:${e.message}`)
@@ -531,25 +497,6 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
531
497
  }
532
498
  }
533
499
 
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
500
  async discoverDevices() {
554
501
  if (!this.config.credentials?.token) {
555
502
  return this.handleManualConfig()
@@ -565,17 +512,14 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
565
512
 
566
513
  while (retryCount < maxRetries) {
567
514
  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)
515
+ const { response, statusCode } = await this.switchBotAPI.getDevices()
516
+ await this.debugLog(`response: ${JSON.stringify(response)}`)
517
+ if (this.isSuccessfulResponse(statusCode)) {
518
+ await this.handleDevices(Array.isArray(response.body.deviceList) ? response.body.deviceList : [])
519
+ await this.handleIRDevices(Array.isArray(response.body.infraredRemoteList) ? response.body.infraredRemoteList : [])
576
520
  break
577
521
  } else {
578
- await this.handleErrorResponse(statusCode, devicesAPI.statusCode, retryCount, maxRetries, delayBetweenRetries)
522
+ await this.handleErrorResponse(statusCode, retryCount, maxRetries, delayBetweenRetries)
579
523
  retryCount++
580
524
  }
581
525
  } catch (e: any) {
@@ -608,8 +552,8 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
608
552
  }
609
553
  }
610
554
 
611
- private isSuccessfulResponse(statusCode: number, apiStatusCode: number): boolean {
612
- return (statusCode === 200 || statusCode === 100) && (apiStatusCode === 200 || apiStatusCode === 100)
555
+ private isSuccessfulResponse(apiStatusCode: number): boolean {
556
+ return (apiStatusCode === 200 || apiStatusCode === 100)
613
557
  }
614
558
 
615
559
  private async handleDevices(deviceLists: any[]) {
@@ -674,11 +618,10 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
674
618
  })
675
619
  }
676
620
 
677
- private async handleErrorResponse(statusCode: number, apiStatusCode: number, retryCount: number, maxRetries: number, delayBetweenRetries: number) {
678
- await this.statusCode(statusCode)
621
+ private async handleErrorResponse(apiStatusCode: number, retryCount: number, maxRetries: number, delayBetweenRetries: number) {
679
622
  await this.statusCode(apiStatusCode)
680
- if (statusCode === 500) {
681
- this.infoLog(`statusCode: ${statusCode} Attempt ${retryCount + 1} of ${maxRetries}`)
623
+ if (apiStatusCode === 500) {
624
+ this.infoLog(`statusCode: ${apiStatusCode} Attempt ${retryCount + 1} of ${maxRetries}`)
682
625
  await sleep(delayBetweenRetries)
683
626
  }
684
627
  }
@@ -2639,18 +2582,15 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
2639
2582
  }
2640
2583
  }
2641
2584
 
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 }> {
2585
+ async retryRequest(deviceId: string, deviceMaxRetries: number, deviceDelayBetweenRetries: number): Promise<{ response: any, statusCode: number }> {
2643
2586
  let retryCount = 0
2644
2587
  const maxRetries = deviceMaxRetries
2645
2588
  const delayBetweenRetries = deviceDelayBetweenRetries
2646
2589
  while (retryCount < maxRetries) {
2647
2590
  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
- }
2591
+ const { response, statusCode } = await this.switchBotAPI.getDeviceStatus(deviceId)
2592
+ await this.debugLog(`response: ${JSON.stringify(response)}`)
2593
+ return { response, statusCode }
2654
2594
  } catch (error: any) {
2655
2595
  await this.errorLog(`Error making request: ${error.message}`)
2656
2596
  }
@@ -2658,16 +2598,15 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
2658
2598
  await this.debugLog(`Retry attempt ${retryCount} of ${maxRetries}`)
2659
2599
  await sleep(delayBetweenRetries)
2660
2600
  }
2661
- return { body: null, statusCode: -1 }
2601
+ return { response: null, statusCode: 500 }
2662
2602
  }
2663
2603
 
2664
2604
  // BLE Connection
2665
2605
  async connectBLE(accessory: PlatformAccessory, device: device & devicesConfig): Promise<any> {
2666
2606
  try {
2667
- const switchbot = new SwitchBot()
2668
- queueScheduler.schedule(async () => switchbot)
2669
- await this.debugLog(`${device.deviceType}: ${accessory.displayName} 'node-switchbot' found: ${switchbot}`)
2670
- return switchbot
2607
+ queueScheduler.schedule(async () => this.switchBotBLE)
2608
+ await this.debugLog(`${device.deviceType}: ${accessory.displayName} 'node-switchbot' found: ${this.switchBotBLE}`)
2609
+ return this.switchBotBLE
2671
2610
  } catch (e: any) {
2672
2611
  await this.errorLog(`${device.deviceType}: ${accessory.displayName} 'node-switchbot' not found, Error: ${e}`)
2673
2612
  return false
package/src/settings.ts CHANGED
@@ -4,10 +4,11 @@
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
+ /*
8
+ * For Testing Locally:
9
+ * import type { device, irdevice, SwitchBotBLEModel, SwitchBotBLEModelFriendlyName, SwitchBotBLEModelName } from '/Users/Shared/GitHub/OpenWonderLabs/node-switchbot/dist/index.js';
10
+ */
11
+ import type { device, irdevice, SwitchBotBLEModel, SwitchBotBLEModelFriendlyName, SwitchBotBLEModelName } from 'node-switchbot'
11
12
  /**
12
13
  * This is the name of the platform that users will use to register the plugin in the Homebridge config.json
13
14
  */
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',