@switchbot/homebridge-switchbot 3.8.3 → 4.0.0-beta.1

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 (205) hide show
  1. package/.github/npm-version-script.cjs +81 -0
  2. package/.github/workflows/beta-release.yml +12 -4
  3. package/CHANGELOG.md +15 -1
  4. package/config.schema.json +583 -937
  5. package/dist/device/blindtilt.d.ts +1 -4
  6. package/dist/device/blindtilt.d.ts.map +1 -1
  7. package/dist/device/blindtilt.js +68 -66
  8. package/dist/device/blindtilt.js.map +1 -1
  9. package/dist/device/bot.d.ts +1 -4
  10. package/dist/device/bot.d.ts.map +1 -1
  11. package/dist/device/bot.js +63 -59
  12. package/dist/device/bot.js.map +1 -1
  13. package/dist/device/ceilinglight.d.ts +1 -4
  14. package/dist/device/ceilinglight.d.ts.map +1 -1
  15. package/dist/device/ceilinglight.js +56 -65
  16. package/dist/device/ceilinglight.js.map +1 -1
  17. package/dist/device/colorbulb.d.ts +1 -4
  18. package/dist/device/colorbulb.d.ts.map +1 -1
  19. package/dist/device/colorbulb.js +73 -80
  20. package/dist/device/colorbulb.js.map +1 -1
  21. package/dist/device/contact.d.ts +1 -4
  22. package/dist/device/contact.d.ts.map +1 -1
  23. package/dist/device/contact.js +38 -38
  24. package/dist/device/contact.js.map +1 -1
  25. package/dist/device/curtain.d.ts +1 -4
  26. package/dist/device/curtain.d.ts.map +1 -1
  27. package/dist/device/curtain.js +60 -60
  28. package/dist/device/curtain.js.map +1 -1
  29. package/dist/device/device.d.ts +6 -6
  30. package/dist/device/device.d.ts.map +1 -1
  31. package/dist/device/device.js +86 -20
  32. package/dist/device/device.js.map +1 -1
  33. package/dist/device/fan.d.ts +1 -4
  34. package/dist/device/fan.d.ts.map +1 -1
  35. package/dist/device/fan.js +50 -51
  36. package/dist/device/fan.js.map +1 -1
  37. package/dist/device/hub.d.ts +1 -4
  38. package/dist/device/hub.d.ts.map +1 -1
  39. package/dist/device/hub.js +48 -48
  40. package/dist/device/hub.js.map +1 -1
  41. package/dist/device/humidifier.d.ts +1 -4
  42. package/dist/device/humidifier.d.ts.map +1 -1
  43. package/dist/device/humidifier.js +53 -55
  44. package/dist/device/humidifier.js.map +1 -1
  45. package/dist/device/iosensor.d.ts +1 -4
  46. package/dist/device/iosensor.d.ts.map +1 -1
  47. package/dist/device/iosensor.js +35 -35
  48. package/dist/device/iosensor.js.map +1 -1
  49. package/dist/device/lightstrip.d.ts +1 -4
  50. package/dist/device/lightstrip.d.ts.map +1 -1
  51. package/dist/device/lightstrip.js +57 -65
  52. package/dist/device/lightstrip.js.map +1 -1
  53. package/dist/device/lock.d.ts +1 -4
  54. package/dist/device/lock.d.ts.map +1 -1
  55. package/dist/device/lock.js +38 -39
  56. package/dist/device/lock.js.map +1 -1
  57. package/dist/device/meter.d.ts +1 -4
  58. package/dist/device/meter.d.ts.map +1 -1
  59. package/dist/device/meter.js +35 -35
  60. package/dist/device/meter.js.map +1 -1
  61. package/dist/device/meterplus.d.ts +1 -4
  62. package/dist/device/meterplus.d.ts.map +1 -1
  63. package/dist/device/meterplus.js +35 -35
  64. package/dist/device/meterplus.js.map +1 -1
  65. package/dist/device/motion.d.ts +1 -4
  66. package/dist/device/motion.d.ts.map +1 -1
  67. package/dist/device/motion.js +27 -27
  68. package/dist/device/motion.js.map +1 -1
  69. package/dist/device/plug.d.ts +1 -4
  70. package/dist/device/plug.d.ts.map +1 -1
  71. package/dist/device/plug.js +32 -32
  72. package/dist/device/plug.js.map +1 -1
  73. package/dist/device/robotvacuumcleaner.d.ts +1 -4
  74. package/dist/device/robotvacuumcleaner.d.ts.map +1 -1
  75. package/dist/device/robotvacuumcleaner.js +39 -40
  76. package/dist/device/robotvacuumcleaner.js.map +1 -1
  77. package/dist/device/waterdetector.d.ts +1 -4
  78. package/dist/device/waterdetector.d.ts.map +1 -1
  79. package/dist/device/waterdetector.js +28 -28
  80. package/dist/device/waterdetector.js.map +1 -1
  81. package/dist/irdevice/airconditioner.d.ts +1 -1
  82. package/dist/irdevice/airconditioner.d.ts.map +1 -1
  83. package/dist/irdevice/airconditioner.js +31 -32
  84. package/dist/irdevice/airconditioner.js.map +1 -1
  85. package/dist/irdevice/airpurifier.d.ts +1 -1
  86. package/dist/irdevice/airpurifier.d.ts.map +1 -1
  87. package/dist/irdevice/airpurifier.js +11 -12
  88. package/dist/irdevice/airpurifier.js.map +1 -1
  89. package/dist/irdevice/camera.d.ts +1 -1
  90. package/dist/irdevice/camera.d.ts.map +1 -1
  91. package/dist/irdevice/camera.js +9 -10
  92. package/dist/irdevice/camera.js.map +1 -1
  93. package/dist/irdevice/fan.d.ts +1 -1
  94. package/dist/irdevice/fan.d.ts.map +1 -1
  95. package/dist/irdevice/fan.js +22 -23
  96. package/dist/irdevice/fan.js.map +1 -1
  97. package/dist/irdevice/irdevice.d.ts +6 -6
  98. package/dist/irdevice/irdevice.d.ts.map +1 -1
  99. package/dist/irdevice/irdevice.js +28 -14
  100. package/dist/irdevice/irdevice.js.map +1 -1
  101. package/dist/irdevice/light.d.ts +1 -1
  102. package/dist/irdevice/light.d.ts.map +1 -1
  103. package/dist/irdevice/light.js +12 -13
  104. package/dist/irdevice/light.js.map +1 -1
  105. package/dist/irdevice/other.d.ts +1 -1
  106. package/dist/irdevice/other.d.ts.map +1 -1
  107. package/dist/irdevice/other.js +12 -15
  108. package/dist/irdevice/other.js.map +1 -1
  109. package/dist/irdevice/tv.d.ts +1 -1
  110. package/dist/irdevice/tv.d.ts.map +1 -1
  111. package/dist/irdevice/tv.js +27 -28
  112. package/dist/irdevice/tv.js.map +1 -1
  113. package/dist/irdevice/vacuumcleaner.d.ts +1 -1
  114. package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
  115. package/dist/irdevice/vacuumcleaner.js +9 -10
  116. package/dist/irdevice/vacuumcleaner.js.map +1 -1
  117. package/dist/irdevice/waterheater.d.ts +1 -1
  118. package/dist/irdevice/waterheater.d.ts.map +1 -1
  119. package/dist/irdevice/waterheater.js +9 -10
  120. package/dist/irdevice/waterheater.js.map +1 -1
  121. package/dist/platform.d.ts +9 -22
  122. package/dist/platform.d.ts.map +1 -1
  123. package/dist/platform.js +154 -260
  124. package/dist/platform.js.map +1 -1
  125. package/dist/settings.d.ts +64 -82
  126. package/dist/settings.d.ts.map +1 -1
  127. package/dist/settings.js +0 -20
  128. package/dist/settings.js.map +1 -1
  129. package/dist/utils.d.ts +1 -102
  130. package/dist/utils.d.ts.map +1 -1
  131. package/dist/utils.js +0 -105
  132. package/dist/utils.js.map +1 -1
  133. package/docs/assets/highlight.css +42 -0
  134. package/docs/assets/main.js +1 -1
  135. package/docs/functions/default.html +1 -1
  136. package/docs/index.html +61 -50
  137. package/docs/media/security-privacy-bluetooth.png +0 -0
  138. package/package.json +5 -7
  139. package/src/device/blindtilt.ts +74 -74
  140. package/src/device/bot.ts +68 -67
  141. package/src/device/ceilinglight.ts +59 -70
  142. package/src/device/colorbulb.ts +79 -88
  143. package/src/device/contact.ts +40 -43
  144. package/src/device/curtain.ts +66 -68
  145. package/src/device/device.ts +86 -40
  146. package/src/device/fan.ts +52 -56
  147. package/src/device/hub.ts +50 -53
  148. package/src/device/humidifier.ts +56 -61
  149. package/src/device/iosensor.ts +37 -40
  150. package/src/device/lightstrip.ts +62 -72
  151. package/src/device/lock.ts +41 -45
  152. package/src/device/meter.ts +37 -40
  153. package/src/device/meterplus.ts +37 -40
  154. package/src/device/motion.ts +29 -32
  155. package/src/device/plug.ts +34 -37
  156. package/src/device/robotvacuumcleaner.ts +41 -49
  157. package/src/device/waterdetector.ts +30 -33
  158. package/src/irdevice/airconditioner.ts +33 -35
  159. package/src/irdevice/airpurifier.ts +12 -13
  160. package/src/irdevice/camera.ts +10 -11
  161. package/src/irdevice/fan.ts +24 -25
  162. package/src/irdevice/irdevice.ts +31 -27
  163. package/src/irdevice/light.ts +14 -15
  164. package/src/irdevice/other.ts +14 -17
  165. package/src/irdevice/tv.ts +28 -29
  166. package/src/irdevice/vacuumcleaner.ts +10 -11
  167. package/src/irdevice/waterheater.ts +10 -11
  168. package/src/platform.ts +178 -287
  169. package/src/settings.ts +67 -88
  170. package/src/utils.ts +2 -106
  171. package/dist/types/bledevicestatus.d.ts +0 -281
  172. package/dist/types/bledevicestatus.d.ts.map +0 -1
  173. package/dist/types/bledevicestatus.js +0 -2
  174. package/dist/types/bledevicestatus.js.map +0 -1
  175. package/dist/types/devicelist.d.ts +0 -89
  176. package/dist/types/devicelist.d.ts.map +0 -1
  177. package/dist/types/devicelist.js +0 -6
  178. package/dist/types/devicelist.js.map +0 -1
  179. package/dist/types/deviceresponse.d.ts +0 -13
  180. package/dist/types/deviceresponse.d.ts.map +0 -1
  181. package/dist/types/deviceresponse.js +0 -2
  182. package/dist/types/deviceresponse.js.map +0 -1
  183. package/dist/types/devicestatus.d.ts +0 -149
  184. package/dist/types/devicestatus.d.ts.map +0 -1
  185. package/dist/types/devicestatus.js +0 -3
  186. package/dist/types/devicestatus.js.map +0 -1
  187. package/dist/types/devicewebhookstatus.d.ts +0 -156
  188. package/dist/types/devicewebhookstatus.d.ts.map +0 -1
  189. package/dist/types/devicewebhookstatus.js +0 -2
  190. package/dist/types/devicewebhookstatus.js.map +0 -1
  191. package/dist/types/irdevicelist.d.ts +0 -10
  192. package/dist/types/irdevicelist.d.ts.map +0 -1
  193. package/dist/types/irdevicelist.js +0 -2
  194. package/dist/types/irdevicelist.js.map +0 -1
  195. package/dist/types/pushbody.d.ts +0 -6
  196. package/dist/types/pushbody.d.ts.map +0 -1
  197. package/dist/types/pushbody.js +0 -2
  198. package/dist/types/pushbody.js.map +0 -1
  199. package/src/types/bledevicestatus.ts +0 -303
  200. package/src/types/devicelist.ts +0 -124
  201. package/src/types/deviceresponse.ts +0 -14
  202. package/src/types/devicestatus.ts +0 -178
  203. package/src/types/devicewebhookstatus.ts +0 -191
  204. package/src/types/irdevicelist.ts +0 -15
  205. package/src/types/pushbody.ts +0 -9
@@ -3,25 +3,23 @@
3
3
  * curtain.ts: @switchbot/homebridge-switchbot.
4
4
  */
5
5
  import type { CharacteristicChange, CharacteristicValue, PlatformAccessory, Service } from 'homebridge'
6
+ import type { bodyChange, curtain3ServiceData, curtain3WebhookContext, curtainServiceData, curtainStatus, curtainWebhookContext, device, SwitchbotDevice, WoCurtain } from 'node-switchbot'
6
7
 
7
8
  import type { SwitchBotPlatform } from '../platform.js'
8
- import type { devicesConfig } from '../settings.js'
9
- import type { curtain3ServiceData, curtainServiceData } from '../types/bledevicestatus.js'
10
- import type { device } from '../types/devicelist.js'
11
- import type { curtainStatus } from '../types/devicestatus.js'
12
- import type { curtain3WebhookContext, curtainWebhookContext } from '../types/devicewebhookstatus.js'
9
+ import type { curtainConfig, devicesConfig } from '../settings.js'
13
10
 
14
11
  import { hostname } from 'node:os'
15
12
 
13
+ import { debounceTime, interval, skipWhile, Subject, take, tap } from 'rxjs'
14
+
15
+ import { formatDeviceIdAsMac } from '../utils.js'
16
+ import { deviceBase } from './device.js'
17
+
16
18
  /*
17
19
  * For Testing Locally:
18
20
  * import { SwitchBotBLEModel, SwitchBotBLEModelName } from '/Users/Shared/GitHub/OpenWonderLabs/node-switchbot/dist/index.js';
19
21
  */
20
22
  import { SwitchBotBLEModel, SwitchBotBLEModelName } from 'node-switchbot'
21
- import { debounceTime, interval, skipWhile, Subject, take, tap } from 'rxjs'
22
-
23
- import { formatDeviceIdAsMac } from '../utils.js'
24
- import { deviceBase } from './device.js'
25
23
 
26
24
  export class Curtain extends deviceBase {
27
25
  // Services
@@ -113,7 +111,7 @@ export class Curtain extends deviceBase {
113
111
 
114
112
  // Initialize WindowCovering CurrentPosition
115
113
  this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.CurrentPosition).setProps({
116
- minStep: device.curtain?.set_minStep ?? 1,
114
+ minStep: (device as curtainConfig).set_minStep ?? 1,
117
115
  minValue: 0,
118
116
  maxValue: 100,
119
117
  validValueRanges: [0, 100],
@@ -123,7 +121,7 @@ export class Curtain extends deviceBase {
123
121
 
124
122
  // Initialize WindowCovering TargetPosition
125
123
  this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.TargetPosition).setProps({
126
- minStep: device.curtain?.set_minStep ?? 1,
124
+ minStep: (device as curtainConfig).set_minStep ?? 1,
127
125
  minValue: 0,
128
126
  maxValue: 100,
129
127
  validValueRanges: [0, 100],
@@ -161,7 +159,7 @@ export class Curtain extends deviceBase {
161
159
  })
162
160
 
163
161
  // Initialize LightSensor Service
164
- if (device.curtain?.hide_lightsensor || (device.deviceType !== 'curtain' && device.deviceType !== 'curtain3')) {
162
+ if ((device as curtainConfig).hide_lightsensor || (device.deviceType !== 'curtain' && device.deviceType !== 'curtain3')) {
165
163
  if (this.LightSensor?.Service) {
166
164
  this.debugLog('Removing Light Sensor Service')
167
165
  this.LightSensor.Service = this.accessory.getService(this.hap.Service.LightSensor) as Service
@@ -184,7 +182,7 @@ export class Curtain extends deviceBase {
184
182
  }
185
183
 
186
184
  // Initialize Open Mode Switch Service
187
- if (!device.curtain?.silentModeSwitch) {
185
+ if (!(device as curtainConfig).silentModeSwitch) {
188
186
  if (this.OpenModeSwitch?.Service) {
189
187
  this.debugLog('Removing Open Mode Switch Service')
190
188
  this.OpenModeSwitch.Service = this.accessory.getService(this.hap.Service.Switch) as Service
@@ -212,7 +210,7 @@ export class Curtain extends deviceBase {
212
210
  }
213
211
 
214
212
  // Initialize Close Mode Switch Service
215
- if (!device.curtain?.silentModeSwitch) {
213
+ if (!(device as curtainConfig).silentModeSwitch) {
216
214
  if (this.CloseModeSwitch?.Service) {
217
215
  this.debugLog('Removing Close Mode Switch Service')
218
216
  this.CloseModeSwitch.Service = this.accessory.getService(this.hap.Service.Switch) as Service
@@ -244,7 +242,7 @@ export class Curtain extends deviceBase {
244
242
  this.debugLog('Retrieve initial values and update Homekit')
245
243
  this.refreshStatus()
246
244
  } catch (e: any) {
247
- this.errorLog(`failed to retrieve initial values and update Homekit, Error: ${e}`)
245
+ this.errorLog(`failed to retrieve initial values and update Homekit, Error: ${e.message ?? e}`)
248
246
  }
249
247
 
250
248
  // regisiter webhook event handler if enabled
@@ -252,7 +250,7 @@ export class Curtain extends deviceBase {
252
250
  this.debugLog('Registering Webhook Event Handler')
253
251
  this.registerWebhook()
254
252
  } catch (e: any) {
255
- this.errorLog(`failed to registerWebhook, Error: ${e}`)
253
+ this.errorLog(`failed to registerWebhook, Error: ${e.message ?? e}`)
256
254
  }
257
255
 
258
256
  // regisiter platform BLE event handler if enabled
@@ -260,7 +258,7 @@ export class Curtain extends deviceBase {
260
258
  this.debugLog('Registering Platform BLE Event Handler')
261
259
  this.registerPlatformBLE()
262
260
  } catch (e: any) {
263
- this.errorLog(`failed to registerPlatformBLE, Error: ${e}`)
261
+ this.errorLog(`failed to registerPlatformBLE, Error: ${e.message ?? e}`)
264
262
  }
265
263
 
266
264
  // History
@@ -384,9 +382,9 @@ export class Curtain extends deviceBase {
384
382
  this.WindowCovering.CurrentPosition = 100 - this.serviceData.position
385
383
  await this.getCurrentPostion()
386
384
  // CurrentAmbientLightLevel
387
- if (!this.device.curtain?.hide_lightsensor && this.LightSensor?.Service) {
388
- const set_minLux = this.device.curtain?.set_minLux ?? 1
389
- const set_maxLux = this.device.curtain?.set_maxLux ?? 6001
385
+ if (!(this.device as curtainConfig).hide_lightsensor && this.LightSensor?.Service) {
386
+ const set_minLux = (this.device as curtainConfig).set_minLux ?? 1
387
+ const set_maxLux = (this.device as curtainConfig).set_maxLux ?? 6001
390
388
  const lightLevel = this.serviceData.lightLevel
391
389
  this.LightSensor.CurrentAmbientLightLevel = await this.getLightLevel(lightLevel, set_minLux, set_maxLux, 19)
392
390
  this.debugLog(`LightLevel: ${this.serviceData.lightLevel}, CurrentAmbientLightLevel: ${this.LightSensor.CurrentAmbientLightLevel}`)
@@ -409,9 +407,9 @@ export class Curtain extends deviceBase {
409
407
  await this.getCurrentPostion()
410
408
 
411
409
  // Brightness
412
- if (!this.device.curtain?.hide_lightsensor && this.LightSensor?.Service) {
413
- const set_minLux = this.device.curtain?.set_minLux ?? 1
414
- const set_maxLux = this.device.curtain?.set_maxLux ?? 6001
410
+ if (!(this.device as curtainConfig).hide_lightsensor && this.LightSensor?.Service) {
411
+ const set_minLux = (this.device as curtainConfig).set_minLux ?? 1
412
+ const set_maxLux = (this.device as curtainConfig).set_maxLux ?? 6001
415
413
  const lightLevel = this.deviceStatus.lightLevel === 'bright' ? set_maxLux : set_minLux
416
414
  this.LightSensor.CurrentAmbientLightLevel = await this.getLightLevel(lightLevel, set_minLux, set_maxLux, 2)
417
415
  await this.debugLog(`CurrentAmbientLightLevel: ${this.LightSensor.CurrentAmbientLightLevel}`)
@@ -480,14 +478,14 @@ export class Curtain extends deviceBase {
480
478
 
481
479
  async BLERefreshStatus(): Promise<void> {
482
480
  await this.debugLog('BLERefreshStatus')
483
- const switchbot = await this.switchbotBLE()
484
- if (switchbot === undefined) {
485
- await this.BLERefreshConnection(switchbot)
481
+ const switchBotBLE = await this.switchbotBLE()
482
+ if (switchBotBLE === undefined) {
483
+ await this.BLERefreshConnection(switchBotBLE)
486
484
  } else {
487
485
  // Start to monitor advertisement packets
488
486
  (async () => {
489
487
  // Start to monitor advertisement packets
490
- const serviceData = await this.monitorAdvertisementPackets(switchbot) as curtainServiceData | curtain3ServiceData
488
+ const serviceData = await this.monitorAdvertisementPackets(switchBotBLE) as curtainServiceData | curtain3ServiceData
491
489
  // Update HomeKit
492
490
  if ((serviceData.model === SwitchBotBLEModel.Curtain || SwitchBotBLEModel.Curtain3)
493
491
  && (serviceData.modelName === SwitchBotBLEModelName.Curtain || SwitchBotBLEModelName.Curtain3)) {
@@ -495,8 +493,8 @@ export class Curtain extends deviceBase {
495
493
  await this.BLEparseStatus()
496
494
  await this.updateHomeKitCharacteristics()
497
495
  } else {
498
- await this.errorLog(`failed to get serviceData, serviceData: ${serviceData}`)
499
- await this.BLERefreshConnection(switchbot)
496
+ await this.errorLog(`failed to get serviceData, serviceData: ${JSON.stringify(serviceData)}`)
497
+ await this.BLERefreshConnection(switchBotBLE)
500
498
  }
501
499
  })()
502
500
  }
@@ -505,17 +503,17 @@ export class Curtain extends deviceBase {
505
503
  async openAPIRefreshStatus(): Promise<void> {
506
504
  await this.debugLog('openAPIRefreshStatus')
507
505
  try {
508
- const { body, statusCode } = await this.deviceRefreshStatus()
509
- const deviceStatus: any = await body.json()
510
- await this.debugLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)
511
- if (await this.successfulStatusCodes(statusCode, deviceStatus)) {
512
- await this.debugSuccessLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)
506
+ const { body } = await this.deviceRefreshStatus()
507
+ const deviceStatus: any = await body
508
+ await this.debugLog(`statusCode: ${deviceStatus.statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)
509
+ if (await this.successfulStatusCodes(deviceStatus)) {
510
+ await this.debugSuccessLog(`statusCode: ${deviceStatus.statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)
513
511
  this.deviceStatus = deviceStatus.body
514
512
  await this.openAPIparseStatus()
515
513
  await this.updateHomeKitCharacteristics()
516
514
  } else {
517
- await this.debugWarnLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)
518
- await this.debugWarnLog(statusCode, deviceStatus)
515
+ await this.debugWarnLog(`statusCode: ${deviceStatus.statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)
516
+ await this.debugWarnLog(deviceStatus)
519
517
  }
520
518
  } catch (e: any) {
521
519
  await this.apiError(e)
@@ -533,7 +531,7 @@ export class Curtain extends deviceBase {
533
531
  await this.parseStatusWebhook()
534
532
  await this.updateHomeKitCharacteristics()
535
533
  } catch (e: any) {
536
- await this.errorLog(`failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e}`)
534
+ await this.errorLog(`failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e.message ?? e}`)
537
535
  }
538
536
  }
539
537
  } else {
@@ -556,7 +554,7 @@ export class Curtain extends deviceBase {
556
554
  await this.BLEparseStatus()
557
555
  await this.updateHomeKitCharacteristics()
558
556
  } catch (e: any) {
559
- await this.errorLog(`failed to handle BLE. Received: ${JSON.stringify(context)} Error: ${e}`)
557
+ await this.errorLog(`failed to handle BLE. Received: ${JSON.stringify(context)} Error: ${e.message ?? e}`)
560
558
  }
561
559
  }
562
560
  } catch (error) {
@@ -593,7 +591,7 @@ export class Curtain extends deviceBase {
593
591
  async BLEpushChanges(): Promise<void> {
594
592
  await this.debugLog('BLEpushChanges')
595
593
  if (this.WindowCovering.TargetPosition !== this.WindowCovering.CurrentPosition) {
596
- const switchbot = await this.platform.connectBLE(this.accessory, this.device)
594
+ const switchBotBLE = await this.platform.connectBLE(this.accessory, this.device)
597
595
  try {
598
596
  const formattedDeviceId = formatDeviceIdAsMac(this.device.deviceId)
599
597
  this.device.bleMac = formattedDeviceId
@@ -601,14 +599,15 @@ export class Curtain extends deviceBase {
601
599
  const { setPositionMode, Mode }: { setPositionMode: number, Mode: string } = await this.setPerformance()
602
600
  const adjustedMode = setPositionMode === 1 ? 0x01 : 0xFF
603
601
  await this.debugLog(`Mode: ${Mode}, setPositionMode: ${setPositionMode}`)
604
- if (switchbot !== false) {
605
- switchbot
602
+ if (switchBotBLE !== false) {
603
+ switchBotBLE
606
604
  .discover({ model: this.device.bleModel, quick: true, id: this.device.bleMac })
607
- .then(async (device_list: any) => {
605
+ .then(async (device_list: SwitchbotDevice[]) => {
606
+ const deviceList = device_list as unknown as WoCurtain[]
608
607
  return await this.retryBLE({
609
608
  max: await this.maxRetryBLE(),
610
609
  fn: async () => {
611
- return await device_list[0].runToPos(100 - Number(this.WindowCovering.TargetPosition), adjustedMode)
610
+ return await deviceList[0].runToPos(100 - Number(this.WindowCovering.TargetPosition), adjustedMode)
612
611
  },
613
612
  })
614
613
  })
@@ -622,7 +621,7 @@ export class Curtain extends deviceBase {
622
621
  await this.BLEPushConnection()
623
622
  })
624
623
  } else {
625
- await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`)
624
+ await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${JSON.stringify(switchBotBLE)}`)
626
625
  await this.BLEPushConnection()
627
626
  }
628
627
  } catch (error) {
@@ -641,30 +640,29 @@ export class Curtain extends deviceBase {
641
640
  const { setPositionMode, Mode }: { setPositionMode: number, Mode: string } = await this.setPerformance()
642
641
  await this.debugLog(`Mode: ${Mode}, setPositionMode: ${setPositionMode}`)
643
642
  const adjustedMode = setPositionMode || 'ff'
644
- let bodyChange: string
643
+ let bodyChange: bodyChange
645
644
  if (this.WindowCovering.HoldPosition) {
646
- bodyChange = JSON.stringify({
645
+ bodyChange = {
647
646
  command: 'pause',
648
647
  parameter: 'default',
649
648
  commandType: 'command',
650
- })
649
+ }
651
650
  } else {
652
- bodyChange = JSON.stringify({
651
+ bodyChange = {
653
652
  command: 'setPosition',
654
653
  parameter: `0,${adjustedMode},${adjustedTargetPosition}`,
655
654
  commandType: 'command',
656
- })
655
+ }
657
656
  }
658
657
  await this.debugLog(`SwitchBot OpenAPI bodyChange: ${JSON.stringify(bodyChange)}`)
659
658
  try {
660
- const { body, statusCode } = await this.pushChangeRequest(bodyChange)
661
- const deviceStatus: any = await body.json()
662
- await this.debugLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)
663
- if (await this.successfulStatusCodes(statusCode, deviceStatus)) {
664
- await this.debugSuccessLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)
659
+ const { body } = await this.pushChangeRequest(bodyChange)
660
+ const deviceStatus: any = await body
661
+ await this.debugLog(`statusCode: ${deviceStatus.statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)
662
+ if (await this.successfulStatusCodes(deviceStatus)) {
663
+ await this.debugSuccessLog(`statusCode: ${deviceStatus.statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)
665
664
  await this.updateHomeKitCharacteristics()
666
665
  } else {
667
- await this.statusCode(statusCode)
668
666
  await this.statusCode(deviceStatus.statusCode)
669
667
  }
670
668
  } catch (e: any) {
@@ -742,7 +740,7 @@ export class Curtain extends deviceBase {
742
740
  * Handle requests to set the value of the "Target Position" characteristic
743
741
  */
744
742
  async OpenModeSwitchSet(value: CharacteristicValue): Promise<void> {
745
- if (this.OpenModeSwitch && this.device.curtain?.silentModeSwitch) {
743
+ if (this.OpenModeSwitch && (this.device as curtainConfig).silentModeSwitch) {
746
744
  this.debugLog(`Silent Open Mode: ${value}`)
747
745
  this.OpenModeSwitch.On = value
748
746
  this.accessory.context.OpenModeSwitch.On = value
@@ -756,7 +754,7 @@ export class Curtain extends deviceBase {
756
754
  * Handle requests to set the value of the "Target Position" characteristic
757
755
  */
758
756
  async CloseModeSwitchSet(value: CharacteristicValue): Promise<void> {
759
- if (this.CloseModeSwitch && this.device.curtain?.silentModeSwitch) {
757
+ if (this.CloseModeSwitch && (this.device as curtainConfig).silentModeSwitch) {
760
758
  this.debugLog(`Silent Close Mode: ${value}`)
761
759
  this.CloseModeSwitch.On = value
762
760
  this.accessory.context.CloseModeSwitch.On = value
@@ -777,7 +775,7 @@ export class Curtain extends deviceBase {
777
775
  // HoldPosition
778
776
  await this.updateCharacteristic(this.WindowCovering.Service, this.hap.Characteristic.HoldPosition, this.WindowCovering.HoldPosition, 'HoldPosition')
779
777
  // CurrentAmbientLightLevel
780
- if (!this.device.curtain?.hide_lightsensor && this.LightSensor?.Service) {
778
+ if (!(this.device as curtainConfig).hide_lightsensor && this.LightSensor?.Service) {
781
779
  const history = { time: Math.round(new Date().valueOf() / 1000), lux: this.LightSensor.CurrentAmbientLightLevel }
782
780
  await this.updateCharacteristic(this.LightSensor?.Service, this.hap.Characteristic.CurrentAmbientLightLevel, this.LightSensor?.CurrentAmbientLightLevel, 'CurrentAmbientLightLevel', history)
783
781
  }
@@ -808,10 +806,10 @@ export class Curtain extends deviceBase {
808
806
  let setPositionMode: number
809
807
  let Mode: string
810
808
  if (Number(this.WindowCovering.TargetPosition) > 50) {
811
- if (this.device.curtain?.setOpenMode === '1' || this.OpenModeSwitch?.On) {
809
+ if ((this.device as curtainConfig).setOpenMode === '1' || this.OpenModeSwitch?.On) {
812
810
  setPositionMode = 1
813
811
  Mode = 'Silent Mode'
814
- } else if (this.device.curtain?.setOpenMode === '0' || !this.OpenModeSwitch?.On) {
812
+ } else if ((this.device as curtainConfig).setOpenMode === '0' || !this.OpenModeSwitch?.On) {
815
813
  setPositionMode = 0
816
814
  Mode = 'Performance Mode'
817
815
  } else {
@@ -819,10 +817,10 @@ export class Curtain extends deviceBase {
819
817
  Mode = 'Default Mode'
820
818
  }
821
819
  } else {
822
- if (this.device.curtain?.setCloseMode === '1' || this.CloseModeSwitch?.On) {
820
+ if ((this.device as curtainConfig).setCloseMode === '1' || this.CloseModeSwitch?.On) {
823
821
  setPositionMode = 1
824
822
  Mode = 'Silent Mode'
825
- } else if (this.device.curtain?.setCloseMode === '0' || !this.CloseModeSwitch?.On) {
823
+ } else if ((this.device as curtainConfig).setCloseMode === '0' || !this.CloseModeSwitch?.On) {
826
824
  setPositionMode = 0
827
825
  Mode = 'Performance Mode'
828
826
  } else {
@@ -838,7 +836,7 @@ export class Curtain extends deviceBase {
838
836
  await this.setMinMax()
839
837
  await this.debugLog(`CurrentPosition ${this.WindowCovering.CurrentPosition}`)
840
838
  this.hasLoggedStandby = this.hasLoggedStandby ?? false
841
- if (this.setNewTarget || this.deviceStatus.moving) {
839
+ if (this.deviceStatus ? (this.setNewTarget || this.deviceStatus.moving) : this.setNewTarget) {
842
840
  this.hasLoggedStandby = false
843
841
  this.infoLog('Checking Status ...')
844
842
  this.curtainMoving = true
@@ -874,13 +872,13 @@ export class Curtain extends deviceBase {
874
872
  }
875
873
 
876
874
  async setMinMax(): Promise<void> {
877
- if (this.device.curtain?.set_min) {
878
- if (Number(this.WindowCovering.CurrentPosition) <= this.device.curtain?.set_min) {
875
+ if ((this.device as curtainConfig).set_min) {
876
+ if (Number(this.WindowCovering.CurrentPosition) <= (this.device as curtainConfig).set_min!) {
879
877
  this.WindowCovering.CurrentPosition = 0
880
878
  }
881
879
  }
882
- if (this.device.curtain?.set_max) {
883
- if (Number(this.WindowCovering.CurrentPosition) >= this.device.curtain?.set_max) {
880
+ if ((this.device as curtainConfig).set_max) {
881
+ if (Number(this.WindowCovering.CurrentPosition) >= (this.device as curtainConfig).set_max!) {
884
882
  this.WindowCovering.CurrentPosition = 100
885
883
  }
886
884
  }
@@ -906,7 +904,7 @@ export class Curtain extends deviceBase {
906
904
  this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, e)
907
905
  this.Battery.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, e)
908
906
  this.Battery.Service.updateCharacteristic(this.hap.Characteristic.ChargingState, e)
909
- if (!this.device.curtain?.hide_lightsensor && this.LightSensor?.Service) {
907
+ if (!(this.device as curtainConfig).hide_lightsensor && this.LightSensor?.Service) {
910
908
  this.LightSensor.Service.updateCharacteristic(this.hap.Characteristic.CurrentAmbientLightLevel, e)
911
909
  this.LightSensor.Service.updateCharacteristic(this.hap.Characteristic.StatusActive, e)
912
910
  }
@@ -5,19 +5,16 @@
5
5
 
6
6
  import type { API, CharacteristicValue, HAP, Logging, PlatformAccessory, Service } from 'homebridge'
7
7
  import type { MqttClient } from 'mqtt'
8
+ import type { ad, bodyChange, device } from 'node-switchbot'
8
9
 
9
10
  import type { SwitchBotPlatform } from '../platform.js'
10
- import type { devicesConfig, SwitchBotPlatformConfig } from '../settings.js'
11
- import type { ad } from '../types/bledevicestatus.js'
12
- import type { device } from '../types/devicelist.js'
11
+ import type { blindTiltConfig, botConfig, ceilingLightConfig, colorBulbConfig, contactConfig, curtainConfig, devicesConfig, hubConfig, humidifierConfig, indoorOutdoorSensorConfig, lockConfig, meterConfig, motionConfig, stripLightConfig, SwitchBotPlatformConfig, waterDetectorConfig } from '../settings.js'
13
12
 
14
13
  import { hostname } from 'node:os'
15
14
 
16
15
  import { SwitchBotBLEModel, SwitchBotBLEModelFriendlyName, SwitchBotBLEModelName, SwitchBotModel } from 'node-switchbot'
17
- import { request } from 'undici'
18
16
 
19
- import { Devices } from '../settings.js'
20
- import { BlindTiltMappingMode, formatDeviceIdAsMac, sleep } from '../utils.js'
17
+ import { formatDeviceIdAsMac, sleep } from '../utils.js'
21
18
 
22
19
  export abstract class deviceBase {
23
20
  public readonly api: API
@@ -182,25 +179,60 @@ export abstract class deviceBase {
182
179
  device.maxRetries !== 0 && { maxRetries: device.maxRetries },
183
180
  device.delayBetweenRetries !== 0 && { delayBetweenRetries: device.delayBetweenRetries },
184
181
  )
182
+ let deviceSpecificConfig = {}
183
+ switch (device.configDeviceType) {
184
+ case 'Bot':
185
+ deviceSpecificConfig = device as botConfig
186
+ break
187
+ case 'Meter':
188
+ case 'MeterPlus':
189
+ deviceSpecificConfig = device as meterConfig
190
+ break
191
+ case 'IOSensor':
192
+ deviceSpecificConfig = device as indoorOutdoorSensorConfig
193
+ break
194
+ case 'Humidifier':
195
+ deviceSpecificConfig = device as humidifierConfig
196
+ break
197
+ case 'Curtain':
198
+ case 'Curtain3':
199
+ deviceSpecificConfig = device as curtainConfig
200
+ break
201
+ case 'Blind Tilt':
202
+ deviceSpecificConfig = device as blindTiltConfig
203
+ break
204
+ case 'Contact Sensor':
205
+ deviceSpecificConfig = device as contactConfig
206
+ break
207
+ case 'Motion Sensor':
208
+ deviceSpecificConfig = device as motionConfig
209
+ break
210
+ case 'Water Detector':
211
+ deviceSpecificConfig = device as waterDetectorConfig
212
+ break
213
+ case 'Color Bulb':
214
+ deviceSpecificConfig = device as colorBulbConfig
215
+ break
216
+ case 'Strip Light':
217
+ deviceSpecificConfig = device as stripLightConfig
218
+ break
219
+ case 'Ceiling Light':
220
+ case 'Ceiling Light Pro':
221
+ deviceSpecificConfig = device as ceilingLightConfig
222
+ break
223
+ case 'Lock':
224
+ case 'Lock Pro':
225
+ deviceSpecificConfig = device as lockConfig
226
+ break
227
+ case 'Hub2':
228
+ deviceSpecificConfig = device as hubConfig
229
+ break
230
+ default:
231
+ }
185
232
  const config = Object.assign(
186
233
  {},
187
234
  deviceConfig,
188
- device.bot,
189
- device.lock,
190
- device.ceilinglight,
191
- device.colorbulb,
192
- device.contact,
193
- device.motion,
194
- device.curtain,
195
- device.hub,
196
- device.waterdetector,
197
- device.humidifier,
198
- device.meter,
199
- device.iosensor,
200
- device.striplight,
201
- device.plug,
202
- device.blindTilt?.mode === undefined ? { mode: BlindTiltMappingMode.OnlyUp } : {},
203
- device.blindTilt,
235
+ deviceSpecificConfig,
204
236
  )
205
237
 
206
238
  if (Object.keys(config).length !== 0) {
@@ -278,14 +310,14 @@ export abstract class deviceBase {
278
310
  }
279
311
 
280
312
  async switchbotBLE(): Promise<any> {
281
- const switchbot = await this.platform.connectBLE(this.accessory, this.device)
313
+ const switchBotBLE = await this.platform.connectBLE(this.accessory, this.device)
282
314
  // Convert to BLE Address
283
315
  try {
284
316
  const formattedDeviceId = formatDeviceIdAsMac(this.device.deviceId)
285
317
  this.device.bleMac = formattedDeviceId
286
318
  await this.debugLog(`bleMac: ${this.device.bleMac}`)
287
- await this.getCustomBLEAddress(switchbot)
288
- return switchbot
319
+ await this.getCustomBLEAddress(switchBotBLE)
320
+ return switchBotBLE
289
321
  } catch (error) {
290
322
  await this.errorLog(`failed to format device ID as MAC, Error: ${error}`)
291
323
  }
@@ -293,7 +325,11 @@ export abstract class deviceBase {
293
325
 
294
326
  async monitorAdvertisementPackets(switchbot: any) {
295
327
  await this.debugLog(`Scanning for ${this.device.bleModelName} devices...`)
296
- await switchbot.startScan({ model: this.device.bleModel, id: this.device.bleMac })
328
+ try {
329
+ await switchbot.startScan({ model: this.device.bleModel, id: this.device.bleMac })
330
+ } catch (e: any) {
331
+ await this.errorLog(`Failed to start BLE scanning. Error:${e.message ?? e}`)
332
+ }
297
333
  // Set an event handler
298
334
  let serviceData = { model: this.device.bleModel, modelName: this.device.bleModelName } as ad['serviceData']
299
335
  switchbot.onadvertisement = async (ad: ad) => {
@@ -303,14 +339,18 @@ export abstract class deviceBase {
303
339
  this.debugLog(`serviceData: ${JSON.stringify(ad.serviceData)}`)
304
340
  serviceData = ad.serviceData
305
341
  } else {
306
- serviceData = { model: '', modelName: '' } as ad['serviceData']
342
+ serviceData = { model: '', modelName: '', modelFriendlyName: '' } as unknown as ad['serviceData']
307
343
  this.debugLog(`serviceData: ${JSON.stringify(ad.serviceData)}`)
308
344
  }
309
345
  }
310
346
  // Wait
311
347
  await switchbot.wait(this.scanDuration * 1000)
312
348
  // Stop to monitor
313
- await switchbot.stopScan()
349
+ try {
350
+ await switchbot.stopScan()
351
+ } catch (e: any) {
352
+ await this.errorLog(`Failed to stop BLE scanning. Error:${e.message ?? e}`)
353
+ }
314
354
  return serviceData
315
355
  }
316
356
 
@@ -319,32 +359,38 @@ export abstract class deviceBase {
319
359
  this.debugLog(`customBLEaddress: ${this.device.customBLEaddress}`);
320
360
  (async () => {
321
361
  // Start to monitor advertisement packets
322
- await switchbot.startScan({ model: this.device.bleModel })
362
+ try {
363
+ await switchbot.startScan({ model: this.device.bleModel })
364
+ } catch (e: any) {
365
+ await this.errorLog(`Failed to start BLE scanning. Error:${e.message ?? e}`)
366
+ }
323
367
  // Set an event handler
324
368
  switchbot.onadvertisement = async (ad: ad) => {
325
369
  this.warnLog(`ad: ${JSON.stringify(ad, null, ' ')}`)
326
370
  }
327
371
  await sleep(10000)
328
372
  // Stop to monitor
329
- switchbot.stopScan()
373
+ try {
374
+ switchbot.stopScan()
375
+ } catch (e: any) {
376
+ await this.errorLog(`Failed to stop BLE scanning. Error:${e.message ?? e}`)
377
+ }
330
378
  })()
331
379
  }
332
380
  }
333
381
 
334
- async pushChangeRequest(bodyChange: string): Promise<{ body: any, statusCode: any }> {
335
- return await request(`${Devices}/${this.device.deviceId}/commands`, {
336
- body: bodyChange,
337
- method: 'POST',
338
- headers: this.platform.generateHeaders(),
339
- })
382
+ async pushChangeRequest(bodyChange: bodyChange): Promise<{ body: any, statusCode: number }> {
383
+ const { response, statusCode } = await this.platform.switchBotAPI.controlDevice(this.device.deviceId, bodyChange.command, bodyChange.parameter, bodyChange.commandType)
384
+ return { body: response, statusCode }
340
385
  }
341
386
 
342
- async deviceRefreshStatus(): Promise<{ body: any, statusCode: any }> {
343
- return await this.platform.retryRequest(this.deviceMaxRetries, this.deviceDelayBetweenRetries, `${Devices}/${this.device.deviceId}/status`, { headers: this.platform.generateHeaders() })
387
+ async deviceRefreshStatus(): Promise<{ body: any, statusCode: number }> {
388
+ const { response, statusCode } = await this.platform.retryRequest(this.device.deviceId, this.deviceMaxRetries, this.deviceDelayBetweenRetries)
389
+ return { body: response, statusCode }
344
390
  }
345
391
 
346
- async successfulStatusCodes(statusCode: any, deviceStatus: any) {
347
- return (statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)
392
+ async successfulStatusCodes(deviceStatus: any) {
393
+ return (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)
348
394
  }
349
395
 
350
396
  /**