@switchbot/homebridge-switchbot 5.0.0-beta.6 → 5.0.0-beta.60

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 (267) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +45 -3
  3. package/config.schema.json +866 -13754
  4. package/dist/devices-hap/airpurifier.d.ts.map +1 -1
  5. package/dist/devices-hap/airpurifier.js +12 -6
  6. package/dist/devices-hap/airpurifier.js.map +1 -1
  7. package/dist/devices-hap/blindtilt.js +3 -3
  8. package/dist/devices-hap/bot.d.ts.map +1 -1
  9. package/dist/devices-hap/bot.js +16 -5
  10. package/dist/devices-hap/bot.js.map +1 -1
  11. package/dist/devices-hap/ceilinglight.d.ts.map +1 -1
  12. package/dist/devices-hap/ceilinglight.js +13 -7
  13. package/dist/devices-hap/ceilinglight.js.map +1 -1
  14. package/dist/devices-hap/colorbulb.d.ts.map +1 -1
  15. package/dist/devices-hap/colorbulb.js +49 -9
  16. package/dist/devices-hap/colorbulb.js.map +1 -1
  17. package/dist/devices-hap/contact.js +3 -3
  18. package/dist/devices-hap/curtain.js +2 -2
  19. package/dist/devices-hap/curtain.js.map +1 -1
  20. package/dist/devices-hap/device.d.ts +18 -8
  21. package/dist/devices-hap/device.d.ts.map +1 -1
  22. package/dist/devices-hap/device.js +141 -69
  23. package/dist/devices-hap/device.js.map +1 -1
  24. package/dist/devices-hap/fan.d.ts.map +1 -1
  25. package/dist/devices-hap/fan.js +12 -6
  26. package/dist/devices-hap/fan.js.map +1 -1
  27. package/dist/devices-hap/hub.d.ts.map +1 -1
  28. package/dist/devices-hap/hub.js +6 -5
  29. package/dist/devices-hap/hub.js.map +1 -1
  30. package/dist/devices-hap/humidifier.d.ts +5 -0
  31. package/dist/devices-hap/humidifier.d.ts.map +1 -1
  32. package/dist/devices-hap/humidifier.js +92 -4
  33. package/dist/devices-hap/humidifier.js.map +1 -1
  34. package/dist/devices-hap/iosensor.d.ts.map +1 -1
  35. package/dist/devices-hap/iosensor.js +36 -21
  36. package/dist/devices-hap/iosensor.js.map +1 -1
  37. package/dist/devices-hap/lightstrip.d.ts.map +1 -1
  38. package/dist/devices-hap/lightstrip.js +38 -8
  39. package/dist/devices-hap/lightstrip.js.map +1 -1
  40. package/dist/devices-hap/lock.d.ts.map +1 -1
  41. package/dist/devices-hap/lock.js +14 -6
  42. package/dist/devices-hap/lock.js.map +1 -1
  43. package/dist/devices-hap/meter.d.ts.map +1 -1
  44. package/dist/devices-hap/meter.js +6 -5
  45. package/dist/devices-hap/meter.js.map +1 -1
  46. package/dist/devices-hap/meterplus.d.ts.map +1 -1
  47. package/dist/devices-hap/meterplus.js +6 -5
  48. package/dist/devices-hap/meterplus.js.map +1 -1
  49. package/dist/devices-hap/meterpro.d.ts.map +1 -1
  50. package/dist/devices-hap/meterpro.js +7 -6
  51. package/dist/devices-hap/meterpro.js.map +1 -1
  52. package/dist/devices-hap/motion.js +3 -3
  53. package/dist/devices-hap/plug.d.ts.map +1 -1
  54. package/dist/devices-hap/plug.js +11 -6
  55. package/dist/devices-hap/plug.js.map +1 -1
  56. package/dist/devices-hap/relayswitch.js +3 -3
  57. package/dist/devices-hap/robotvacuumcleaner.d.ts.map +1 -1
  58. package/dist/devices-hap/robotvacuumcleaner.js +13 -6
  59. package/dist/devices-hap/robotvacuumcleaner.js.map +1 -1
  60. package/dist/devices-hap/waterdetector.js +3 -3
  61. package/dist/devices-matter/BaseMatterAccessory.d.ts +27 -0
  62. package/dist/devices-matter/BaseMatterAccessory.d.ts.map +1 -1
  63. package/dist/devices-matter/BaseMatterAccessory.js +169 -5
  64. package/dist/devices-matter/BaseMatterAccessory.js.map +1 -1
  65. package/dist/devices-matter/ColorLightAccessory.d.ts.map +1 -1
  66. package/dist/devices-matter/ColorLightAccessory.js +12 -12
  67. package/dist/devices-matter/ColorLightAccessory.js.map +1 -1
  68. package/dist/devices-matter/ColorTemperatureLightAccessory.d.ts.map +1 -1
  69. package/dist/devices-matter/ColorTemperatureLightAccessory.js +5 -7
  70. package/dist/devices-matter/ColorTemperatureLightAccessory.js.map +1 -1
  71. package/dist/devices-matter/DimmableLightAccessory.js +9 -9
  72. package/dist/devices-matter/DimmableLightAccessory.js.map +1 -1
  73. package/dist/devices-matter/ExtendedColorLightAccessory.d.ts.map +1 -1
  74. package/dist/devices-matter/ExtendedColorLightAccessory.js +14 -15
  75. package/dist/devices-matter/ExtendedColorLightAccessory.js.map +1 -1
  76. package/dist/devices-matter/OnOffLightAccessory.d.ts.map +1 -1
  77. package/dist/devices-matter/OnOffLightAccessory.js +8 -16
  78. package/dist/devices-matter/OnOffLightAccessory.js.map +1 -1
  79. package/dist/devices-matter/OnOffOutletAccessory.d.ts +2 -0
  80. package/dist/devices-matter/OnOffOutletAccessory.d.ts.map +1 -1
  81. package/dist/devices-matter/OnOffOutletAccessory.js +10 -7
  82. package/dist/devices-matter/OnOffOutletAccessory.js.map +1 -1
  83. package/dist/devices-matter/OnOffSwitchAccessory.js +2 -2
  84. package/dist/devices-matter/OnOffSwitchAccessory.js.map +1 -1
  85. package/dist/devices-matter/RoboticVacuumAccessory.d.ts +29 -43
  86. package/dist/devices-matter/RoboticVacuumAccessory.d.ts.map +1 -1
  87. package/dist/devices-matter/RoboticVacuumAccessory.js +287 -262
  88. package/dist/devices-matter/RoboticVacuumAccessory.js.map +1 -1
  89. package/dist/homebridge-ui/public/index.html +200 -18
  90. package/dist/homebridge-ui/server.js +82 -9
  91. package/dist/homebridge-ui/server.js.map +1 -1
  92. package/dist/index.d.ts.map +1 -1
  93. package/dist/index.js +4 -7
  94. package/dist/index.js.map +1 -1
  95. package/dist/irdevice/irdevice.d.ts +11 -10
  96. package/dist/irdevice/irdevice.d.ts.map +1 -1
  97. package/dist/irdevice/irdevice.js +76 -35
  98. package/dist/irdevice/irdevice.js.map +1 -1
  99. package/dist/platform-hap.d.ts +26 -15
  100. package/dist/platform-hap.d.ts.map +1 -1
  101. package/dist/platform-hap.js +333 -153
  102. package/dist/platform-hap.js.map +1 -1
  103. package/dist/platform-matter.d.ts +93 -6
  104. package/dist/platform-matter.d.ts.map +1 -1
  105. package/dist/platform-matter.js +1822 -224
  106. package/dist/platform-matter.js.map +1 -1
  107. package/dist/settings.d.ts +58 -7
  108. package/dist/settings.d.ts.map +1 -1
  109. package/dist/settings.js.map +1 -1
  110. package/dist/test/apiRequestTracker.test.d.ts +2 -0
  111. package/dist/test/apiRequestTracker.test.d.ts.map +1 -0
  112. package/dist/test/apiRequestTracker.test.js +392 -0
  113. package/dist/test/apiRequestTracker.test.js.map +1 -0
  114. package/dist/test/hap/device-webhook-context.test.d.ts +2 -0
  115. package/dist/test/hap/device-webhook-context.test.d.ts.map +1 -0
  116. package/dist/test/hap/device-webhook-context.test.js +128 -0
  117. package/dist/test/hap/device-webhook-context.test.js.map +1 -0
  118. package/dist/test/hap/platform-hap.logging.test.d.ts +2 -0
  119. package/dist/test/hap/platform-hap.logging.test.d.ts.map +1 -0
  120. package/dist/test/hap/platform-hap.logging.test.js +33 -0
  121. package/dist/test/hap/platform-hap.logging.test.js.map +1 -0
  122. package/dist/test/hap/platform-hap.test.d.ts +2 -0
  123. package/dist/test/hap/platform-hap.test.d.ts.map +1 -0
  124. package/dist/test/hap/platform-hap.test.js +62 -0
  125. package/dist/test/hap/platform-hap.test.js.map +1 -0
  126. package/dist/test/helpers/platform-fixtures.d.ts +9 -0
  127. package/dist/test/helpers/platform-fixtures.d.ts.map +1 -0
  128. package/dist/test/helpers/platform-fixtures.js +30 -0
  129. package/dist/test/helpers/platform-fixtures.js.map +1 -0
  130. package/dist/test/homebridge-ui/server.test.d.ts +2 -0
  131. package/dist/test/homebridge-ui/server.test.d.ts.map +1 -0
  132. package/dist/test/homebridge-ui/server.test.js +445 -0
  133. package/dist/test/homebridge-ui/server.test.js.map +1 -0
  134. package/dist/{index.test.d.ts.map → test/index.test.d.ts.map} +1 -1
  135. package/dist/test/index.test.js +19 -0
  136. package/dist/test/index.test.js.map +1 -0
  137. package/dist/test/matter/devices-matter/baseMatterAccessory.test.d.ts +2 -0
  138. package/dist/test/matter/devices-matter/baseMatterAccessory.test.d.ts.map +1 -0
  139. package/dist/test/matter/devices-matter/baseMatterAccessory.test.js +71 -0
  140. package/dist/test/matter/devices-matter/baseMatterAccessory.test.js.map +1 -0
  141. package/dist/test/matter/devices-matter/roboticVacuumAccessory.test.d.ts +2 -0
  142. package/dist/test/matter/devices-matter/roboticVacuumAccessory.test.d.ts.map +1 -0
  143. package/dist/test/matter/devices-matter/roboticVacuumAccessory.test.js +366 -0
  144. package/dist/test/matter/devices-matter/roboticVacuumAccessory.test.js.map +1 -0
  145. package/dist/test/matter/platform-matter.additional.test.d.ts +2 -0
  146. package/dist/test/matter/platform-matter.additional.test.d.ts.map +1 -0
  147. package/dist/test/matter/platform-matter.additional.test.js +35 -0
  148. package/dist/test/matter/platform-matter.additional.test.js.map +1 -0
  149. package/dist/test/matter/platform-matter.bleparse.test.d.ts +2 -0
  150. package/dist/test/matter/platform-matter.bleparse.test.d.ts.map +1 -0
  151. package/dist/test/matter/platform-matter.bleparse.test.js +43 -0
  152. package/dist/test/matter/platform-matter.bleparse.test.js.map +1 -0
  153. package/dist/test/matter/platform-matter.cleanup.test.d.ts +2 -0
  154. package/dist/test/matter/platform-matter.cleanup.test.d.ts.map +1 -0
  155. package/dist/test/matter/platform-matter.cleanup.test.js +70 -0
  156. package/dist/test/matter/platform-matter.cleanup.test.js.map +1 -0
  157. package/dist/test/matter/platform-matter.keepstale.test.d.ts +2 -0
  158. package/dist/test/matter/platform-matter.keepstale.test.d.ts.map +1 -0
  159. package/dist/test/matter/platform-matter.keepstale.test.js +27 -0
  160. package/dist/test/matter/platform-matter.keepstale.test.js.map +1 -0
  161. package/dist/test/matter/platform-matter.logging.test.d.ts +2 -0
  162. package/dist/test/matter/platform-matter.logging.test.d.ts.map +1 -0
  163. package/dist/test/matter/platform-matter.logging.test.js +29 -0
  164. package/dist/test/matter/platform-matter.logging.test.js.map +1 -0
  165. package/dist/test/matter/platform-matter.mapping.test.d.ts +2 -0
  166. package/dist/test/matter/platform-matter.mapping.test.d.ts.map +1 -0
  167. package/dist/test/matter/platform-matter.mapping.test.js +43 -0
  168. package/dist/test/matter/platform-matter.mapping.test.js.map +1 -0
  169. package/dist/test/matter/platform-matter.openapi-mapping.test.d.ts +2 -0
  170. package/dist/test/matter/platform-matter.openapi-mapping.test.d.ts.map +1 -0
  171. package/dist/test/matter/platform-matter.openapi-mapping.test.js +84 -0
  172. package/dist/test/matter/platform-matter.openapi-mapping.test.js.map +1 -0
  173. package/dist/test/matter/platform-matter.test.d.ts +2 -0
  174. package/dist/test/matter/platform-matter.test.d.ts.map +1 -0
  175. package/dist/test/matter/platform-matter.test.js +117 -0
  176. package/dist/test/matter/platform-matter.test.js.map +1 -0
  177. package/dist/test/matter/platform-matter.unregister.test.d.ts +2 -0
  178. package/dist/test/matter/platform-matter.unregister.test.d.ts.map +1 -0
  179. package/dist/test/matter/platform-matter.unregister.test.js +30 -0
  180. package/dist/test/matter/platform-matter.unregister.test.js.map +1 -0
  181. package/dist/test/matter/platform-matter.webhook.test.d.ts +2 -0
  182. package/dist/test/matter/platform-matter.webhook.test.d.ts.map +1 -0
  183. package/dist/test/matter/platform-matter.webhook.test.js +46 -0
  184. package/dist/test/matter/platform-matter.webhook.test.js.map +1 -0
  185. package/dist/test/utils.test.d.ts +2 -0
  186. package/dist/test/utils.test.d.ts.map +1 -0
  187. package/dist/test/utils.test.js +95 -0
  188. package/dist/test/utils.test.js.map +1 -0
  189. package/dist/test/verifyconfig.test.d.ts.map +1 -0
  190. package/dist/{verifyconfig.test.js → test/verifyconfig.test.js} +2 -2
  191. package/dist/test/verifyconfig.test.js.map +1 -0
  192. package/dist/utils.d.ts +204 -3
  193. package/dist/utils.d.ts.map +1 -1
  194. package/dist/utils.js +713 -33
  195. package/dist/utils.js.map +1 -1
  196. package/docs/assets/highlight.css +14 -0
  197. package/docs/assets/main.js +2 -2
  198. package/docs/index.html +31 -2
  199. package/docs/variables/default.html +1 -1
  200. package/package.json +15 -15
  201. package/src/devices-hap/airpurifier.ts +11 -6
  202. package/src/devices-hap/blindtilt.ts +3 -3
  203. package/src/devices-hap/bot.ts +15 -5
  204. package/src/devices-hap/ceilinglight.ts +12 -7
  205. package/src/devices-hap/colorbulb.ts +46 -10
  206. package/src/devices-hap/contact.ts +3 -3
  207. package/src/devices-hap/curtain.ts +2 -2
  208. package/src/devices-hap/device.ts +149 -70
  209. package/src/devices-hap/fan.ts +11 -6
  210. package/src/devices-hap/hub.ts +6 -5
  211. package/src/devices-hap/humidifier.ts +97 -4
  212. package/src/devices-hap/iosensor.ts +36 -21
  213. package/src/devices-hap/lightstrip.ts +35 -8
  214. package/src/devices-hap/lock.ts +13 -6
  215. package/src/devices-hap/meter.ts +6 -5
  216. package/src/devices-hap/meterplus.ts +6 -5
  217. package/src/devices-hap/meterpro.ts +7 -6
  218. package/src/devices-hap/motion.ts +3 -3
  219. package/src/devices-hap/plug.ts +10 -6
  220. package/src/devices-hap/relayswitch.ts +3 -3
  221. package/src/devices-hap/robotvacuumcleaner.ts +12 -6
  222. package/src/devices-hap/waterdetector.ts +3 -3
  223. package/src/devices-matter/BaseMatterAccessory.ts +176 -5
  224. package/src/devices-matter/ColorLightAccessory.ts +12 -12
  225. package/src/devices-matter/ColorTemperatureLightAccessory.ts +5 -7
  226. package/src/devices-matter/DimmableLightAccessory.ts +9 -9
  227. package/src/devices-matter/ExtendedColorLightAccessory.ts +14 -15
  228. package/src/devices-matter/OnOffLightAccessory.ts +8 -16
  229. package/src/devices-matter/OnOffOutletAccessory.ts +12 -7
  230. package/src/devices-matter/OnOffSwitchAccessory.ts +2 -2
  231. package/src/devices-matter/RoboticVacuumAccessory.ts +340 -313
  232. package/src/homebridge-ui/public/index.html +200 -18
  233. package/src/homebridge-ui/server.ts +85 -9
  234. package/src/index.ts +4 -7
  235. package/src/irdevice/irdevice.ts +74 -35
  236. package/src/platform-hap.ts +365 -169
  237. package/src/platform-matter.ts +1872 -229
  238. package/src/settings.ts +62 -3
  239. package/src/test/apiRequestTracker.test.ts +417 -0
  240. package/src/test/hap/device-webhook-context.test.ts +136 -0
  241. package/src/test/hap/platform-hap.logging.test.ts +36 -0
  242. package/src/test/hap/platform-hap.test.ts +70 -0
  243. package/src/test/helpers/platform-fixtures.ts +33 -0
  244. package/src/test/homebridge-ui/server.test.ts +486 -0
  245. package/src/test/index.test.ts +24 -0
  246. package/src/test/matter/devices-matter/baseMatterAccessory.test.ts +88 -0
  247. package/src/test/matter/devices-matter/roboticVacuumAccessory.test.ts +453 -0
  248. package/src/test/matter/platform-matter.additional.test.ts +44 -0
  249. package/src/test/matter/platform-matter.bleparse.test.ts +47 -0
  250. package/src/test/matter/platform-matter.cleanup.test.ts +86 -0
  251. package/src/test/matter/platform-matter.keepstale.test.ts +37 -0
  252. package/src/test/matter/platform-matter.logging.test.ts +33 -0
  253. package/src/test/matter/platform-matter.mapping.test.ts +57 -0
  254. package/src/test/matter/platform-matter.openapi-mapping.test.ts +109 -0
  255. package/src/test/matter/platform-matter.test.ts +144 -0
  256. package/src/test/matter/platform-matter.unregister.test.ts +39 -0
  257. package/src/test/matter/platform-matter.webhook.test.ts +54 -0
  258. package/src/test/utils.test.ts +96 -0
  259. package/src/{verifyconfig.test.ts → test/verifyconfig.test.ts} +12 -11
  260. package/src/utils.ts +777 -36
  261. package/dist/index.test.js +0 -14
  262. package/dist/index.test.js.map +0 -1
  263. package/dist/verifyconfig.test.d.ts.map +0 -1
  264. package/dist/verifyconfig.test.js.map +0 -1
  265. package/src/index.test.ts +0 -19
  266. /package/dist/{index.test.d.ts → test/index.test.d.ts} +0 -0
  267. /package/dist/{verifyconfig.test.d.ts → test/verifyconfig.test.d.ts} +0 -0
@@ -328,7 +328,7 @@ export class StripLight extends deviceBase {
328
328
  // Update HomeKit
329
329
  if (serviceData.model === SwitchBotBLEModel.StripLight && serviceData.modelName === SwitchBotBLEModelName.StripLight) {
330
330
  this.serviceData = serviceData
331
- if (serviceData !== undefined || serviceData !== null) {
331
+ if (serviceData !== undefined && serviceData !== null) {
332
332
  await this.BLEparseStatus()
333
333
  await this.updateHomeKitCharacteristics()
334
334
  } else {
@@ -354,7 +354,7 @@ export class StripLight extends deviceBase {
354
354
  this.platform.bleEventHandler[this.device.bleMac] = async (context: stripLightServiceData) => {
355
355
  try {
356
356
  this.serviceData = context
357
- if (context !== undefined || context !== null) {
357
+ if (context !== undefined && context !== null) {
358
358
  this.debugLog(`received BLE: ${JSON.stringify(context)}`)
359
359
  await this.BLEparseStatus()
360
360
  await this.updateHomeKitCharacteristics()
@@ -399,7 +399,7 @@ export class StripLight extends deviceBase {
399
399
  this.platform.webhookEventHandler[this.device.deviceId] = async (context: stripLightWebhookContext) => {
400
400
  try {
401
401
  this.webhookContext = context
402
- if (context !== undefined || context !== null) {
402
+ if (context !== undefined && context !== null) {
403
403
  this.debugLog(`received Webhook: ${JSON.stringify(context)}`)
404
404
  await this.parseStatusWebhook()
405
405
  await this.updateHomeKitCharacteristics()
@@ -485,13 +485,18 @@ export class StripLight extends deviceBase {
485
485
  .then(async (device_list: SwitchbotDevice[]) => {
486
486
  const deviceList = device_list as WoStrip[]
487
487
  this.infoLog(`On: ${this.LightBulb.On}`)
488
+ this.debugLog(`device_list: ${JSON.stringify(device_list)}`)
488
489
  return await this.retryBLE({
489
490
  max: this.maxRetryBLE(),
490
491
  fn: async () => {
491
- if (this.LightBulb.On) {
492
- return await deviceList[0].turnOn()
492
+ if (deviceList.length > 0) {
493
+ if (this.LightBulb.On) {
494
+ return await deviceList[0].turnOn()
495
+ } else {
496
+ return await deviceList[0].turnOff()
497
+ }
493
498
  } else {
494
- return await deviceList[0].turnOff()
499
+ throw new Error('No devices found during discovery.')
495
500
  }
496
501
  },
497
502
  })
@@ -529,8 +534,19 @@ export class StripLight extends deviceBase {
529
534
  switchBotBLE
530
535
  .discover({ model: this.device.bleModel, id: this.device.bleMac })
531
536
  .then(async (device_list: SwitchbotDevice[]) => {
537
+ const deviceList = device_list as WoStrip[]
532
538
  this.infoLog(`Brightness: ${this.LightBulb.Brightness}`)
533
- return await (device_list[0] as WoStrip).setBrightness(Number(this.LightBulb.Brightness))
539
+ this.debugLog(`device_list: ${JSON.stringify(device_list)}`)
540
+ return await this.retryBLE({
541
+ max: this.maxRetryBLE(),
542
+ fn: async () => {
543
+ if (deviceList.length > 0) {
544
+ return await deviceList[0].setBrightness(Number(this.LightBulb.Brightness))
545
+ } else {
546
+ throw new Error('No devices found during discovery.')
547
+ }
548
+ },
549
+ })
534
550
  })
535
551
  .then(async () => {
536
552
  this.successLog(`Brightness: ${this.LightBulb.Brightness} sent over SwitchBot BLE, sent successfully`)
@@ -568,8 +584,19 @@ export class StripLight extends deviceBase {
568
584
  switchBotBLE
569
585
  .discover({ model: this.device.bleModel, id: this.device.bleMac })
570
586
  .then(async (device_list: SwitchbotDevice[]) => {
587
+ const deviceList = device_list as WoStrip[]
571
588
  this.infoLog(`RGB: ${(this.LightBulb.Brightness, red, green, blue)}`)
572
- return await (device_list[0] as WoStrip).setRGB(Number(this.LightBulb.Brightness), red, green, blue)
589
+ this.debugLog(`device_list: ${JSON.stringify(device_list)}`)
590
+ return await this.retryBLE({
591
+ max: this.maxRetryBLE(),
592
+ fn: async () => {
593
+ if (deviceList.length > 0) {
594
+ return await deviceList[0].setRGB(Number(this.LightBulb.Brightness), red, green, blue)
595
+ } else {
596
+ throw new Error('No devices found during discovery.')
597
+ }
598
+ },
599
+ })
573
600
  })
574
601
  .then(async () => {
575
602
  this.successLog(`RGB: ${(this.LightBulb.Brightness, red, green, blue)} sent over SwitchBot BLE, sent successfully`)
@@ -332,7 +332,7 @@ export class Lock extends deviceBase {
332
332
  if ((serviceData.model === SwitchBotBLEModel.Lock || SwitchBotBLEModel.LockPro)
333
333
  && (serviceData.modelName === SwitchBotBLEModelName.Lock || SwitchBotBLEModelName.LockPro)) {
334
334
  this.serviceData = serviceData
335
- if (serviceData !== undefined || serviceData !== null) {
335
+ if (serviceData !== undefined && serviceData !== null) {
336
336
  await this.BLEparseStatus()
337
337
  await this.updateHomeKitCharacteristics()
338
338
  } else {
@@ -358,7 +358,7 @@ export class Lock extends deviceBase {
358
358
  this.platform.bleEventHandler[this.device.bleMac] = async (context: lockServiceData | lockProServiceData) => {
359
359
  try {
360
360
  this.serviceData = context
361
- if (context !== undefined || context !== null) {
361
+ if (context !== undefined && context !== null) {
362
362
  this.debugLog(`received BLE: ${JSON.stringify(context)}`)
363
363
  await this.BLEparseStatus()
364
364
  await this.updateHomeKitCharacteristics()
@@ -403,7 +403,7 @@ export class Lock extends deviceBase {
403
403
  this.platform.webhookEventHandler[this.device.deviceId] = async (context: lockWebhookContext | lockProWebhookContext) => {
404
404
  try {
405
405
  this.webhookContext = context
406
- if (context !== undefined || context !== null) {
406
+ if (context !== undefined && context !== null) {
407
407
  this.debugLog(`received Webhook: ${JSON.stringify(context)}`)
408
408
  await this.parseStatusWebhook()
409
409
  await this.updateHomeKitCharacteristics()
@@ -455,13 +455,20 @@ export class Lock extends deviceBase {
455
455
  switchBotBLE
456
456
  .discover({ model: this.device.bleModel, id: this.device.bleMac })
457
457
  .then(async (device_list: SwitchbotDevice[]) => {
458
+ const deviceList = device_list as WoSmartLock[]
459
+ this.infoLog(`LockTargetState: ${this.LockMechanism.LockTargetState}`)
460
+ this.warnLog(`device_list: ${JSON.stringify(device_list)}`)
458
461
  return await this.retryBLE({
459
462
  max: this.maxRetryBLE(),
460
463
  fn: async () => {
461
- if (this.LockMechanism.LockTargetState === this.hap.Characteristic.LockTargetState.SECURED) {
462
- return await (device_list[0] as WoSmartLock).lock()
464
+ if (deviceList && Array.isArray(deviceList) && deviceList.length > 0) {
465
+ if (this.LockMechanism.LockTargetState === this.hap.Characteristic.LockTargetState.SECURED) {
466
+ return await deviceList[0].lock()
467
+ } else {
468
+ return await deviceList[0].unlock()
469
+ }
463
470
  } else {
464
- return await (device_list[0] as WoSmartLock).unlock()
471
+ throw new Error('No devices found during discovery.')
465
472
  }
466
473
  },
467
474
  })
@@ -209,8 +209,9 @@ export class Meter extends deviceBase {
209
209
 
210
210
  // CurrentTemperature
211
211
  if (!(this.device as meterConfig).hide_temperature && this.TemperatureSensor?.Service) {
212
- this.TemperatureSensor.CurrentTemperature = this.deviceStatus.temperature
213
- this.debugLog(`CurrentTemperature: ${this.TemperatureSensor.CurrentTemperature}°c`)
212
+ // OpenAPI returns Celsius; convert if user configured a different unit
213
+ this.TemperatureSensor.CurrentTemperature = convertUnits(this.deviceStatus.temperature, 'CELSIUS', (this.device as meterConfig).convertUnitTo)
214
+ this.debugLog(`CurrentTemperature: ${this.TemperatureSensor.CurrentTemperature}`)
214
215
  }
215
216
 
216
217
  // BatteryLevel
@@ -287,7 +288,7 @@ export class Meter extends deviceBase {
287
288
  // Update HomeKit
288
289
  if (serviceData.model === SwitchBotBLEModel.Meter && serviceData.modelName === SwitchBotBLEModelName.Meter) {
289
290
  this.serviceData = serviceData
290
- if (serviceData !== undefined || serviceData !== null) {
291
+ if (serviceData !== undefined && serviceData !== null) {
291
292
  await this.BLEparseStatus()
292
293
  await this.updateHomeKitCharacteristics()
293
294
  } else {
@@ -313,7 +314,7 @@ export class Meter extends deviceBase {
313
314
  this.platform.bleEventHandler[this.device.bleMac] = async (context: meterServiceData) => {
314
315
  try {
315
316
  this.serviceData = context
316
- if (context !== undefined || context !== null) {
317
+ if (context !== undefined && context !== null) {
317
318
  this.debugLog(`received BLE: ${JSON.stringify(context)}`)
318
319
  await this.BLEparseStatus()
319
320
  await this.updateHomeKitCharacteristics()
@@ -358,7 +359,7 @@ export class Meter extends deviceBase {
358
359
  this.platform.webhookEventHandler[this.device.deviceId] = async (context: meterWebhookContext) => {
359
360
  try {
360
361
  this.webhookContext = context
361
- if (context !== undefined || context !== null) {
362
+ if (context !== undefined && context !== null) {
362
363
  this.debugLog(`received Webhook: ${JSON.stringify(context)}`)
363
364
  await this.parseStatusWebhook()
364
365
  await this.updateHomeKitCharacteristics()
@@ -213,8 +213,9 @@ export class MeterPlus extends deviceBase {
213
213
 
214
214
  // CurrentTemperature
215
215
  if (!(this.device as meterConfig).hide_temperature && this.TemperatureSensor?.Service) {
216
- this.TemperatureSensor.CurrentTemperature = this.deviceStatus.temperature
217
- this.debugLog(`CurrentTemperature: ${this.TemperatureSensor.CurrentTemperature}°c`)
216
+ // OpenAPI returns Celsius; convert if user configured a different unit
217
+ this.TemperatureSensor.CurrentTemperature = convertUnits(this.deviceStatus.temperature, 'CELSIUS', (this.device as meterConfig).convertUnitTo)
218
+ this.debugLog(`CurrentTemperature: ${this.TemperatureSensor.CurrentTemperature}`)
218
219
  }
219
220
 
220
221
  // BatteryLevel
@@ -291,7 +292,7 @@ export class MeterPlus extends deviceBase {
291
292
  // Update HomeKit
292
293
  if (serviceData.model === SwitchBotBLEModel.MeterPlus && serviceData.modelName === SwitchBotBLEModelName.MeterPlus) {
293
294
  this.serviceData = serviceData
294
- if (serviceData !== undefined || serviceData !== null) {
295
+ if (serviceData !== undefined && serviceData !== null) {
295
296
  await this.BLEparseStatus()
296
297
  await this.updateHomeKitCharacteristics()
297
298
  } else {
@@ -317,7 +318,7 @@ export class MeterPlus extends deviceBase {
317
318
  this.platform.bleEventHandler[this.device.bleMac] = async (context: meterPlusServiceData) => {
318
319
  try {
319
320
  this.serviceData = context
320
- if (context !== undefined || context !== null) {
321
+ if (context !== undefined && context !== null) {
321
322
  this.debugLog(`received BLE: ${JSON.stringify(context)}`)
322
323
  await this.BLEparseStatus()
323
324
  await this.updateHomeKitCharacteristics()
@@ -362,7 +363,7 @@ export class MeterPlus extends deviceBase {
362
363
  this.platform.webhookEventHandler[this.device.deviceId] = async (context: meterPlusWebhookContext) => {
363
364
  try {
364
365
  this.webhookContext = context
365
- if (context !== undefined || context !== null) {
366
+ if (context !== undefined && context !== null) {
366
367
  this.debugLog(`received Webhook: ${JSON.stringify(context)}`)
367
368
  await this.parseStatusWebhook()
368
369
  await this.updateHomeKitCharacteristics()
@@ -263,8 +263,9 @@ export class MeterPro extends deviceBase {
263
263
 
264
264
  // CurrentTemperature
265
265
  if (!(this.device as meterProConfig).hide_temperature && this.TemperatureSensor?.Service) {
266
- this.TemperatureSensor.CurrentTemperature = this.deviceStatus.temperature
267
- this.debugLog(`CurrentTemperature: ${this.TemperatureSensor.CurrentTemperature}°c`)
266
+ // OpenAPI returns Celsius; convert if user configured a different unit
267
+ this.TemperatureSensor.CurrentTemperature = convertUnits(this.deviceStatus.temperature as number, 'CELSIUS', (this.device as meterProConfig).convertUnitTo)
268
+ this.debugLog(`CurrentTemperature: ${this.TemperatureSensor.CurrentTemperature}`)
268
269
  }
269
270
 
270
271
  // Carbon Dioxide Sensor
@@ -367,7 +368,7 @@ export class MeterPro extends deviceBase {
367
368
  if ((serviceData.model === SwitchBotBLEModel.MeterPro && serviceData.modelName === SwitchBotBLEModelName.MeterPro)
368
369
  || (serviceData.model === SwitchBotBLEModel.MeterProCO2 && serviceData.modelName === SwitchBotBLEModelName.MeterProCO2)) {
369
370
  this.serviceData = serviceData
370
- if (serviceData !== undefined || serviceData !== null) {
371
+ if (serviceData !== undefined && serviceData !== null) {
371
372
  await this.BLEparseStatus()
372
373
  await this.updateHomeKitCharacteristics()
373
374
  } else {
@@ -393,7 +394,7 @@ export class MeterPro extends deviceBase {
393
394
  this.platform.bleEventHandler[this.device.bleMac] = async (context: meterProServiceData) => {
394
395
  try {
395
396
  this.serviceData = context
396
- if (context !== undefined || context !== null) {
397
+ if (context !== undefined && context !== null) {
397
398
  this.debugLog(`received BLE: ${JSON.stringify(context)}`)
398
399
  await this.BLEparseStatus()
399
400
  await this.updateHomeKitCharacteristics()
@@ -428,7 +429,7 @@ export class MeterPro extends deviceBase {
428
429
  }
429
430
  } catch (e: any) {
430
431
  await this.apiError(e)
431
- this.errorLog(`failed openAPIRefreshStatus with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`)
432
+ this.errorLog(`failed openAPIRefreshStatus with ${this.device.connectionType} Connection, Error: ${e.message ?? e}`)
432
433
  }
433
434
  }
434
435
 
@@ -438,7 +439,7 @@ export class MeterPro extends deviceBase {
438
439
  this.platform.webhookEventHandler[this.device.deviceId] = async (context: meterProWebhookContext) => {
439
440
  try {
440
441
  this.webhookContext = context
441
- if (context !== undefined || context !== null) {
442
+ if (context !== undefined && context !== null) {
442
443
  this.debugLog(`received Webhook: ${JSON.stringify(context)}`)
443
444
  await this.parseStatusWebhook()
444
445
  await this.updateHomeKitCharacteristics()
@@ -262,7 +262,7 @@ export class Motion extends deviceBase {
262
262
  // Update HomeKit
263
263
  if (serviceData.model === SwitchBotBLEModel.MotionSensor && serviceData.modelName === SwitchBotBLEModelName.MotionSensor) {
264
264
  this.serviceData = serviceData
265
- if (serviceData !== undefined || serviceData !== null) {
265
+ if (serviceData !== undefined && serviceData !== null) {
266
266
  await this.BLEparseStatus()
267
267
  await this.updateHomeKitCharacteristics()
268
268
  } else {
@@ -288,7 +288,7 @@ export class Motion extends deviceBase {
288
288
  this.platform.bleEventHandler[this.device.bleMac] = async (context: motionSensorServiceData) => {
289
289
  try {
290
290
  this.serviceData = context
291
- if (context !== undefined || context !== null) {
291
+ if (context !== undefined && context !== null) {
292
292
  this.debugLog(`received BLE: ${JSON.stringify(context)}`)
293
293
  await this.BLEparseStatus()
294
294
  await this.updateHomeKitCharacteristics()
@@ -333,7 +333,7 @@ export class Motion extends deviceBase {
333
333
  this.platform.webhookEventHandler[this.device.deviceId] = async (context: motionSensorWebhookContext) => {
334
334
  try {
335
335
  this.webhookContext = context
336
- if (context !== undefined || context !== null) {
336
+ if (context !== undefined && context !== null) {
337
337
  this.debugLog(`received Webhook: ${JSON.stringify(context)}`)
338
338
  await this.parseStatusWebhook()
339
339
  await this.updateHomeKitCharacteristics()
@@ -187,7 +187,7 @@ export class Plug extends deviceBase {
187
187
  if ((serviceData.model === SwitchBotBLEModel.PlugMiniUS || SwitchBotBLEModel.PlugMiniJP)
188
188
  && serviceData.modelName === (SwitchBotBLEModelName.PlugMini || SwitchBotBLEModelName.PlugMini)) {
189
189
  this.serviceData = serviceData
190
- if (serviceData !== undefined || serviceData !== null) {
190
+ if (serviceData !== undefined && serviceData !== null) {
191
191
  await this.BLEparseStatus()
192
192
  await this.updateHomeKitCharacteristics()
193
193
  } else {
@@ -213,7 +213,7 @@ export class Plug extends deviceBase {
213
213
  this.platform.bleEventHandler[this.device.bleMac] = async (context: plugMiniUSServiceData | plugMiniJPServiceData) => {
214
214
  try {
215
215
  this.serviceData = context
216
- if (context !== undefined || context !== null) {
216
+ if (context !== undefined && context !== null) {
217
217
  this.debugLog(`received BLE: ${JSON.stringify(context)}`)
218
218
  await this.BLEparseStatus()
219
219
  await this.updateHomeKitCharacteristics()
@@ -258,7 +258,7 @@ export class Plug extends deviceBase {
258
258
  this.platform.webhookEventHandler[this.device.deviceId] = async (context: plugWebhookContext | plugMiniUSWebhookContext | plugMiniJPWebhookContext) => {
259
259
  try {
260
260
  this.webhookContext = context
261
- if (context !== undefined || context !== null) {
261
+ if (context !== undefined && context !== null) {
262
262
  this.debugLog(`received Webhook: ${JSON.stringify(context)}`)
263
263
  await this.parseStatusWebhook()
264
264
  await this.updateHomeKitCharacteristics()
@@ -320,10 +320,14 @@ export class Plug extends deviceBase {
320
320
  return await this.retryBLE({
321
321
  max: this.maxRetryBLE(),
322
322
  fn: async () => {
323
- if (this.Outlet.On) {
324
- return await deviceList[0].turnOn()
323
+ if (deviceList.length > 0) {
324
+ if (this.Outlet.On) {
325
+ return await deviceList[0].turnOn()
326
+ } else {
327
+ return await deviceList[0].turnOff()
328
+ }
325
329
  } else {
326
- return await deviceList[0].turnOff()
330
+ throw new Error('No devices found during discovery.')
327
331
  }
328
332
  },
329
333
  })
@@ -315,7 +315,7 @@ export class RelaySwitch extends deviceBase {
315
315
  // Update HomeKit
316
316
  if ((serviceData.model === SwitchBotBLEModel.RelaySwitch1PM && serviceData.modelName === SwitchBotBLEModelName.RelaySwitch1PM) ?? (serviceData.model === SwitchBotBLEModel.RelaySwitch1 && serviceData.modelName === SwitchBotBLEModelName.RelaySwitch1)) {
317
317
  this.serviceData = serviceData
318
- if (serviceData !== undefined || serviceData !== null) {
318
+ if (serviceData !== undefined && serviceData !== null) {
319
319
  await this.BLEparseStatus()
320
320
  await this.updateHomeKitCharacteristics()
321
321
  } else {
@@ -341,7 +341,7 @@ export class RelaySwitch extends deviceBase {
341
341
  this.platform.bleEventHandler[this.device.bleMac] = async (context: relaySwitch1ServiceData | relaySwitch1PMServiceData) => {
342
342
  try {
343
343
  this.serviceData = context
344
- if (context !== undefined || context !== null) {
344
+ if (context !== undefined && context !== null) {
345
345
  this.debugLog(`received BLE: ${JSON.stringify(context)}`)
346
346
  await this.BLEparseStatus()
347
347
  await this.updateHomeKitCharacteristics()
@@ -386,7 +386,7 @@ export class RelaySwitch extends deviceBase {
386
386
  this.platform.webhookEventHandler[this.device.deviceId] = async (context: relaySwitch1Context | relaySwitch1PMContext) => {
387
387
  try {
388
388
  this.webhookContext = context
389
- if (context !== undefined || context !== null) {
389
+ if (context !== undefined && context !== null) {
390
390
  this.debugLog(`received Webhook: ${JSON.stringify(context)}`)
391
391
  await this.parseStatusWebhook()
392
392
  await this.updateHomeKitCharacteristics()
@@ -275,7 +275,7 @@ export class RobotVacuumCleaner extends deviceBase {
275
275
  // Update HomeKit
276
276
  if (serviceData.model === SwitchBotBLEModel.Unknown && serviceData.modelName === SwitchBotBLEModelName.Unknown) {
277
277
  this.serviceData = serviceData
278
- if (serviceData !== undefined || serviceData !== null) {
278
+ if (serviceData !== undefined && serviceData !== null) {
279
279
  await this.BLEparseStatus()
280
280
  await this.updateHomeKitCharacteristics()
281
281
  } else {
@@ -301,7 +301,7 @@ export class RobotVacuumCleaner extends deviceBase {
301
301
  this.platform.bleEventHandler[this.device.bleMac] = async (context: robotVacuumCleanerServiceData) => {
302
302
  try {
303
303
  this.serviceData = context
304
- if (context !== undefined || context !== null) {
304
+ if (context !== undefined && context !== null) {
305
305
  this.debugLog(`received BLE: ${JSON.stringify(context)}`)
306
306
  await this.BLEparseStatus()
307
307
  await this.updateHomeKitCharacteristics()
@@ -346,7 +346,7 @@ export class RobotVacuumCleaner extends deviceBase {
346
346
  this.platform.webhookEventHandler[this.device.deviceId] = async (context: robotVacuumCleanerS1WebhookContext | robotVacuumCleanerS1PlusWebhookContext | floorCleaningRobotS10WebhookContext) => {
347
347
  try {
348
348
  this.webhookContext = context
349
- if (context !== undefined || context !== null) {
349
+ if (context !== undefined && context !== null) {
350
350
  this.debugLog(`received Webhook: ${JSON.stringify(context)}`)
351
351
  await this.parseStatusWebhook()
352
352
  await this.updateHomeKitCharacteristics()
@@ -400,14 +400,20 @@ export class RobotVacuumCleaner extends deviceBase {
400
400
  switchBotBLE
401
401
  .discover({ model: this.device.bleModel, id: this.device.bleMac })
402
402
  .then(async (device_list: SwitchbotDevice[]) => {
403
+ const deviceList = device_list as any[]
403
404
  this.infoLog(`On: ${this.LightBulb.On}`)
405
+ this.warnLog(`device_list: ${JSON.stringify(device_list)}`)
404
406
  return await this.retryBLE({
405
407
  max: this.maxRetryBLE(),
406
408
  fn: async () => {
407
- if (this.LightBulb.On) {
408
- return await (device_list[0] as any).turnOn()
409
+ if (deviceList && Array.isArray(deviceList) && deviceList.length > 0) {
410
+ if (this.LightBulb.On) {
411
+ return await (deviceList[0] as any).turnOn()
412
+ } else {
413
+ return await (deviceList[0] as any).turnOff()
414
+ }
409
415
  } else {
410
- return await (device_list[0] as any).turnOff()
416
+ throw new Error('No devices found during discovery.')
411
417
  }
412
418
  },
413
419
  })
@@ -269,7 +269,7 @@ export class WaterDetector extends deviceBase {
269
269
  // Update HomeKit
270
270
  if (serviceData.model === SwitchBotBLEModel.Leak && serviceData.modelName === SwitchBotBLEModelName.Leak) {
271
271
  this.serviceData = serviceData
272
- if (serviceData !== undefined || serviceData !== null) {
272
+ if (serviceData !== undefined && serviceData !== null) {
273
273
  await this.BLEparseStatus()
274
274
  await this.updateHomeKitCharacteristics()
275
275
  } else {
@@ -295,7 +295,7 @@ export class WaterDetector extends deviceBase {
295
295
  this.platform.bleEventHandler[this.device.bleMac] = async (context: waterLeakDetectorServiceData) => {
296
296
  try {
297
297
  this.serviceData = context
298
- if (context !== undefined || context !== null) {
298
+ if (context !== undefined && context !== null) {
299
299
  this.debugLog(`received BLE: ${JSON.stringify(context)}`)
300
300
  await this.BLEparseStatus()
301
301
  await this.updateHomeKitCharacteristics()
@@ -340,7 +340,7 @@ export class WaterDetector extends deviceBase {
340
340
  this.platform.webhookEventHandler[this.device.deviceId] = async (context: waterLeakDetectorWebhookContext) => {
341
341
  try {
342
342
  this.webhookContext = context
343
- if (context !== undefined || context !== null) {
343
+ if (context !== undefined && context !== null) {
344
344
  this.debugLog(`received Webhook: ${JSON.stringify(context)}`)
345
345
  await this.parseStatusWebhook()
346
346
  await this.updateHomeKitCharacteristics()
@@ -10,6 +10,8 @@
10
10
 
11
11
  import type { API, EndpointType, Logger, MatterAccessory } from 'homebridge'
12
12
 
13
+ import { deviceLoggingEnabled, deviceLoggingIsDebug, logDeviceStatusCode, rgb2hs } from '../utils.js'
14
+
13
15
  export interface BaseMatterAccessoryConfig {
14
16
  uuid: string
15
17
  displayName: string
@@ -86,26 +88,195 @@ export abstract class BaseMatterAccessory implements MatterAccessory {
86
88
  */
87
89
  protected async updateState(cluster: string, attributes: Record<string, unknown>): Promise<void> {
88
90
  await this.api.matter.updateAccessoryState(this.uuid, cluster, attributes)
89
- this.log.debug(`[${this.displayName}] Updated ${cluster} state:`, attributes)
91
+ this.logDebug(`Updated ${cluster} state:`, attributes)
90
92
  }
91
93
 
92
94
  /**
93
95
  * Log helper methods
94
96
  */
97
+ // Generic logging delegation: prefer platform-provided log helpers in
98
+ // `this.context` (infoLog/debugLog/warnLog/errorLog) and fall back to the
99
+ // local `this.log` methods when not available.
100
+ protected logWith(level: 'info' | 'error' | 'debug' | 'warn', message: string, ...args: unknown[]): void {
101
+ const ctx: any = this.context as any
102
+ const map: Record<string, string> = {
103
+ info: 'infoLog',
104
+ error: 'errorLog',
105
+ debug: 'debugLog',
106
+ warn: 'warnLog',
107
+ }
108
+ const fn = ctx?.[map[level]]
109
+ if (typeof fn === 'function') {
110
+ fn(`[${this.displayName}] ${message}`, ...args)
111
+ return
112
+ }
113
+ const local = (this.log as any)[level]
114
+ if (typeof local === 'function') {
115
+ local.call(this.log, `[${this.displayName}] ${message}`, ...args)
116
+ }
117
+ }
118
+
95
119
  protected logInfo(message: string, ...args: unknown[]): void {
96
- this.log.info(`[${this.displayName}] ${message}`, ...args)
120
+ this.logWith('info', message, ...args)
97
121
  }
98
122
 
99
123
  protected logError(message: string, ...args: unknown[]): void {
100
- this.log.error(`[${this.displayName}] ${message}`, ...args)
124
+ this.logWith('error', message, ...args)
101
125
  }
102
126
 
103
127
  protected logDebug(message: string, ...args: unknown[]): void {
104
- this.log.debug(`[${this.displayName}] ${message}`, ...args)
128
+ this.logWith('debug', message, ...args)
105
129
  }
106
130
 
107
131
  protected logWarn(message: string, ...args: unknown[]): void {
108
- this.log.warn(`[${this.displayName}] ${message}`, ...args)
132
+ this.logWith('warn', message, ...args)
133
+ }
134
+
135
+ /**
136
+ * Logging helpers parity: allow Matter accessories to ask whether device-level
137
+ * logging is enabled or in debug mode. These mirror the helpers used by the
138
+ * HAP/IR device bases so behavior is consistent across platforms.
139
+ */
140
+ public async loggingIsDebug(): Promise<boolean> {
141
+ const ctx: any = this.context as any
142
+ return deviceLoggingIsDebug(ctx?.deviceLogging)
143
+ }
144
+
145
+ public async enablingDeviceLogging(): Promise<boolean> {
146
+ const ctx: any = this.context as any
147
+ return deviceLoggingEnabled(ctx?.deviceLogging, ctx?.platformLogging)
148
+ }
149
+
150
+ /**
151
+ * Status code logging using shared helper
152
+ */
153
+ public async statusCode(statusCode: number, deviceId?: string, hubDeviceId?: string): Promise<void> {
154
+ await logDeviceStatusCode(
155
+ statusCode,
156
+ {
157
+ debugLog: this.logDebug.bind(this),
158
+ errorLog: this.logError.bind(this),
159
+ infoLog: this.logInfo.bind(this),
160
+ },
161
+ deviceId ?? (this.context as any)?.deviceId,
162
+ hubDeviceId ?? (this.context as any)?.hubDeviceId,
163
+ )
164
+ }
165
+
166
+ /**
167
+ * Convenience helpers that delegate OpenAPI/BLE commands to platform-provided
168
+ * functions that are injected into the accessory `context` by
169
+ * `platform-matter` when the accessory is created from a discovered device.
170
+ *
171
+ * These methods are intentionally thin wrappers — the platform controls
172
+ * retries, discovery and client lifecycle via the helper functions.
173
+ */
174
+ protected async sendOpenAPICommand(command: string, parameter = 'default'): Promise<any> {
175
+ const ctx: any = this.context as any
176
+ const fn = ctx?.sendOpenAPI
177
+ if (typeof fn === 'function') {
178
+ return fn(command, parameter)
179
+ }
180
+ throw new Error('OpenAPI helper not available')
181
+ }
182
+
183
+ protected async sendBLECommand(methodName: string, ...args: any[]): Promise<any> {
184
+ const ctx: any = this.context as any
185
+ const fn = ctx?.sendBLE
186
+ if (typeof fn === 'function') {
187
+ return fn(methodName, ...args)
188
+ }
189
+ throw new Error('BLE helper not available')
190
+ }
191
+
192
+ public async sendOnCommand(deviceId?: string): Promise<void> {
193
+ const ctx: any = this.context as any
194
+ const id = deviceId ?? ctx?.deviceId
195
+ try {
196
+ if (ctx?.connectionType === 'BLE') {
197
+ await this.sendBLECommand('turnOn')
198
+ } else {
199
+ await this.sendOpenAPICommand('turnOn')
200
+ }
201
+ // update our matter state
202
+ await this.updateState(this.api.matter.clusterNames.OnOff, { onOff: true })
203
+ this.logInfo(`sendOnCommand successful for ${id}`)
204
+ } catch (e: any) {
205
+ this.logError(`sendOnCommand failed for ${id}: ${String(e?.message ?? e)}`)
206
+ throw e
207
+ }
208
+ }
209
+
210
+ public async sendOffCommand(deviceId?: string): Promise<void> {
211
+ const ctx: any = this.context as any
212
+ const id = deviceId ?? ctx?.deviceId
213
+ try {
214
+ if (ctx?.connectionType === 'BLE') {
215
+ await this.sendBLECommand('turnOff')
216
+ } else {
217
+ await this.sendOpenAPICommand('turnOff')
218
+ }
219
+ await this.updateState(this.api.matter.clusterNames.OnOff, { onOff: false })
220
+ this.logInfo(`sendOffCommand successful for ${id}`)
221
+ } catch (e: any) {
222
+ this.logError(`sendOffCommand failed for ${id}: ${String(e?.message ?? e)}`)
223
+ throw e
224
+ }
225
+ }
226
+
227
+ public async sendSetBrightness(percent: number, deviceId?: string): Promise<void> {
228
+ const ctx: any = this.context as any
229
+ const id = deviceId ?? ctx?.deviceId
230
+ try {
231
+ if (ctx?.connectionType === 'BLE') {
232
+ await this.sendBLECommand('setBrightness', percent)
233
+ } else {
234
+ await this.sendOpenAPICommand('setBrightness', String(percent))
235
+ }
236
+ const level = Math.round((percent / 100) * 254)
237
+ await this.updateState(this.api.matter.clusterNames.LevelControl, { currentLevel: level })
238
+ this.logInfo(`sendSetBrightness successful for ${id}: ${percent}%`)
239
+ } catch (e: any) {
240
+ this.logError(`sendSetBrightness failed for ${id}: ${String(e?.message ?? e)}`)
241
+ throw e
242
+ }
243
+ }
244
+
245
+ public async sendSetColor(r: number, g: number, b: number, deviceId?: string): Promise<void> {
246
+ const ctx: any = this.context as any
247
+ const id = deviceId ?? ctx?.deviceId
248
+ try {
249
+ if (ctx?.connectionType === 'BLE') {
250
+ await this.sendBLECommand('setRGB', r, g, b)
251
+ } else {
252
+ await this.sendOpenAPICommand('setColor', `${r}:${g}:${b}`)
253
+ }
254
+ // Convert to hue/sat for matter state update
255
+ const [h, s] = rgb2hs(r, g, b)
256
+ await this.updateState(this.api.matter.clusterNames.ColorControl, { currentHue: Math.round((h / 360) * 254), currentSaturation: Math.round((s / 100) * 254) })
257
+ this.logInfo(`sendSetColor successful for ${id}: ${r},${g},${b}`)
258
+ } catch (e: any) {
259
+ this.logError(`sendSetColor failed for ${id}: ${String(e?.message ?? e)}`)
260
+ throw e
261
+ }
262
+ }
263
+
264
+ public async sendSetColorTemperature(kelvin: number, deviceId?: string): Promise<void> {
265
+ const ctx: any = this.context as any
266
+ const id = deviceId ?? ctx?.deviceId
267
+ try {
268
+ if (ctx?.connectionType === 'BLE') {
269
+ await this.sendBLECommand('setColorTemperature', kelvin)
270
+ } else {
271
+ await this.sendOpenAPICommand('setColorTemperature', `${kelvin}`)
272
+ }
273
+ const mireds = Math.round(1000000 / kelvin)
274
+ await this.updateState(this.api.matter.clusterNames.ColorControl, { colorTemperatureMireds: mireds })
275
+ this.logInfo(`sendSetColorTemperature successful for ${id}: ${kelvin}K`)
276
+ } catch (e: any) {
277
+ this.logError(`sendSetColorTemperature failed for ${id}: ${String(e?.message ?? e)}`)
278
+ throw e
279
+ }
109
280
  }
110
281
 
111
282
  /**