@switchbot/homebridge-switchbot 5.0.0-beta.70 → 5.0.0-beta.72

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 (534) hide show
  1. package/.github/ISSUE_TEMPLATE/e2e-verification.md +36 -0
  2. package/.github/workflows/ci.yml +61 -0
  3. package/.github/workflows/manual-e2e.yml +103 -0
  4. package/CHANGELOG.md +20 -0
  5. package/E2E-VERIFICATION.md +121 -0
  6. package/MIGRATION.md +44 -0
  7. package/README.md +11 -0
  8. package/config.schema.json +99 -1940
  9. package/dist/deviceFactory.d.ts +13 -0
  10. package/dist/deviceFactory.d.ts.map +1 -0
  11. package/dist/deviceFactory.js +81 -0
  12. package/dist/deviceFactory.js.map +1 -0
  13. package/dist/devices/deviceBase.d.ts +50 -0
  14. package/dist/devices/deviceBase.d.ts.map +1 -0
  15. package/dist/devices/deviceBase.js +119 -0
  16. package/dist/devices/deviceBase.js.map +1 -0
  17. package/dist/devices/genericDevice.d.ts +283 -0
  18. package/dist/devices/genericDevice.d.ts.map +1 -0
  19. package/dist/devices/genericDevice.js +1035 -0
  20. package/dist/devices/genericDevice.js.map +1 -0
  21. package/dist/homebridge-ui/public/index.html +72 -440
  22. package/dist/homebridge-ui/server.d.ts +3 -1
  23. package/dist/homebridge-ui/server.d.ts.map +1 -1
  24. package/dist/homebridge-ui/server.js +47 -10
  25. package/dist/homebridge-ui/server.js.map +1 -1
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +1 -3
  28. package/dist/index.js.map +1 -1
  29. package/dist/platform.d.ts +27 -0
  30. package/dist/platform.d.ts.map +1 -0
  31. package/dist/platform.js +404 -0
  32. package/dist/platform.js.map +1 -0
  33. package/dist/settings.d.ts +10 -317
  34. package/dist/settings.d.ts.map +1 -1
  35. package/dist/settings.js +5 -30
  36. package/dist/settings.js.map +1 -1
  37. package/dist/switchbotClient.d.ts +32 -0
  38. package/dist/switchbotClient.d.ts.map +1 -0
  39. package/dist/switchbotClient.js +259 -0
  40. package/dist/switchbotClient.js.map +1 -0
  41. package/dist/utils.d.ts +36 -248
  42. package/dist/utils.d.ts.map +1 -1
  43. package/dist/utils.js +38 -1367
  44. package/dist/utils.js.map +1 -1
  45. package/docs/assets/icons.js +1 -1
  46. package/docs/assets/icons.svg +1 -1
  47. package/docs/assets/style.css +3 -3
  48. package/docs/index.html +50 -15
  49. package/docs/variables/default.html +1 -1
  50. package/package.json +19 -18
  51. package/scripts/e2e/README.md +25 -0
  52. package/scripts/e2e/curtain-e2e.sh +70 -0
  53. package/scripts/e2e/fan-e2e.sh +75 -0
  54. package/scripts/e2e/light-advanced-e2e.sh +97 -0
  55. package/scripts/e2e/light-e2e.sh +75 -0
  56. package/scripts/e2e/list-accessories.sh +19 -0
  57. package/scripts/e2e/lock-e2e.sh +65 -0
  58. package/scripts/generate-matter-maps.js +60 -0
  59. package/scripts/run-e2e-local.sh +14 -0
  60. package/src/deviceFactory.ts +122 -0
  61. package/src/devices/deviceBase.ts +141 -0
  62. package/src/devices/genericDevice.ts +965 -0
  63. package/src/homebridge-ui/public/index.html +72 -440
  64. package/src/homebridge-ui/server.ts +52 -10
  65. package/src/index.ts +1 -3
  66. package/src/platform.ts +395 -0
  67. package/src/settings.ts +12 -352
  68. package/src/switchbotClient.ts +266 -0
  69. package/src/utils.ts +47 -1456
  70. package/test/accessory-restore.spec.ts +73 -0
  71. package/test/device-mapping.spec.ts +37 -0
  72. package/test/deviceFactory.spec.ts +18 -0
  73. package/test/e2e/run-e2e.spec.ts +50 -0
  74. package/test/fan-swing.spec.ts +29 -0
  75. package/test/helpers/matter-harness.ts +53 -0
  76. package/test/lock-users.spec.ts +44 -0
  77. package/test/matter-childbridge.spec.ts +55 -0
  78. package/test/matter-descriptors.spec.ts +97 -0
  79. package/test/matter-device-state.spec.ts +101 -0
  80. package/test/matter-integration.spec.ts +70 -0
  81. package/test/platform.integration.spec.ts +55 -0
  82. package/test/switchbot-client-debounce.spec.ts +131 -0
  83. package/test/switchbot-client-openapi.spec.ts +56 -0
  84. package/test/switchbotClient.spec.ts +10 -0
  85. package/test/utils.spec.ts +20 -0
  86. package/vitest.config.ts +7 -0
  87. package/coverage/base.css +0 -224
  88. package/coverage/block-navigation.js +0 -87
  89. package/coverage/clover.xml +0 -15847
  90. package/coverage/coverage-final.json +0 -42
  91. package/coverage/docs/assets/dmt/dmt-component-data.js.html +0 -85
  92. package/coverage/docs/assets/dmt/dmt-components.js.html +0 -286
  93. package/coverage/docs/assets/dmt/index.html +0 -131
  94. package/coverage/docs/assets/hierarchy.js.html +0 -85
  95. package/coverage/docs/assets/icons.js.html +0 -136
  96. package/coverage/docs/assets/index.html +0 -146
  97. package/coverage/docs/assets/main.js.html +0 -265
  98. package/coverage/favicon.png +0 -0
  99. package/coverage/index.html +0 -191
  100. package/coverage/prettify.css +0 -1
  101. package/coverage/prettify.js +0 -2
  102. package/coverage/sort-arrow-sprite.png +0 -0
  103. package/coverage/sorter.js +0 -196
  104. package/coverage/src/device/blindtilt.ts.html +0 -3238
  105. package/coverage/src/device/bot.ts.html +0 -2803
  106. package/coverage/src/device/ceilinglight.ts.html +0 -2338
  107. package/coverage/src/device/colorbulb.ts.html +0 -2824
  108. package/coverage/src/device/contact.ts.html +0 -1465
  109. package/coverage/src/device/curtain.ts.html +0 -2869
  110. package/coverage/src/device/device.ts.html +0 -2500
  111. package/coverage/src/device/fan.ts.html +0 -2242
  112. package/coverage/src/device/hub.ts.html +0 -1408
  113. package/coverage/src/device/humidifier.ts.html +0 -2116
  114. package/coverage/src/device/index.html +0 -416
  115. package/coverage/src/device/iosensor.ts.html +0 -1375
  116. package/coverage/src/device/lightstrip.ts.html +0 -2617
  117. package/coverage/src/device/lock.ts.html +0 -1963
  118. package/coverage/src/device/meter.ts.html +0 -1372
  119. package/coverage/src/device/meterplus.ts.html +0 -1384
  120. package/coverage/src/device/meterpro.ts.html +0 -1618
  121. package/coverage/src/device/motion.ts.html +0 -1264
  122. package/coverage/src/device/plug.ts.html +0 -1372
  123. package/coverage/src/device/relayswitch.ts.html +0 -2284
  124. package/coverage/src/device/robotvacuumcleaner.ts.html +0 -1810
  125. package/coverage/src/device/waterdetector.ts.html +0 -1294
  126. package/coverage/src/homebridge-ui/index.html +0 -116
  127. package/coverage/src/homebridge-ui/server.ts.html +0 -229
  128. package/coverage/src/index.html +0 -161
  129. package/coverage/src/index.ts.html +0 -124
  130. package/coverage/src/irdevice/airconditioner.ts.html +0 -1687
  131. package/coverage/src/irdevice/airpurifier.ts.html +0 -844
  132. package/coverage/src/irdevice/camera.ts.html +0 -475
  133. package/coverage/src/irdevice/fan.ts.html +0 -766
  134. package/coverage/src/irdevice/index.html +0 -251
  135. package/coverage/src/irdevice/irdevice.ts.html +0 -1117
  136. package/coverage/src/irdevice/light.ts.html +0 -826
  137. package/coverage/src/irdevice/other.ts.html +0 -2458
  138. package/coverage/src/irdevice/tv.ts.html +0 -1222
  139. package/coverage/src/irdevice/vacuumcleaner.ts.html +0 -466
  140. package/coverage/src/irdevice/waterheater.ts.html +0 -469
  141. package/coverage/src/platform.ts.html +0 -8776
  142. package/coverage/src/settings.ts.html +0 -934
  143. package/coverage/src/utils.ts.html +0 -2092
  144. package/dist/devices-hap/airpurifier.d.ts +0 -54
  145. package/dist/devices-hap/airpurifier.d.ts.map +0 -1
  146. package/dist/devices-hap/airpurifier.js +0 -533
  147. package/dist/devices-hap/airpurifier.js.map +0 -1
  148. package/dist/devices-hap/blindtilt.d.ts +0 -90
  149. package/dist/devices-hap/blindtilt.d.ts.map +0 -1
  150. package/dist/devices-hap/blindtilt.js +0 -974
  151. package/dist/devices-hap/blindtilt.js.map +0 -1
  152. package/dist/devices-hap/bot.d.ts +0 -102
  153. package/dist/devices-hap/bot.d.ts.map +0 -1
  154. package/dist/devices-hap/bot.js +0 -822
  155. package/dist/devices-hap/bot.js.map +0 -1
  156. package/dist/devices-hap/ceilinglight.d.ts +0 -85
  157. package/dist/devices-hap/ceilinglight.d.ts.map +0 -1
  158. package/dist/devices-hap/ceilinglight.js +0 -707
  159. package/dist/devices-hap/ceilinglight.js.map +0 -1
  160. package/dist/devices-hap/colorbulb.d.ts +0 -88
  161. package/dist/devices-hap/colorbulb.d.ts.map +0 -1
  162. package/dist/devices-hap/colorbulb.js +0 -921
  163. package/dist/devices-hap/colorbulb.js.map +0 -1
  164. package/dist/devices-hap/contact.d.ts +0 -44
  165. package/dist/devices-hap/contact.d.ts.map +0 -1
  166. package/dist/devices-hap/contact.js +0 -409
  167. package/dist/devices-hap/contact.js.map +0 -1
  168. package/dist/devices-hap/curtain.d.ts +0 -73
  169. package/dist/devices-hap/curtain.d.ts.map +0 -1
  170. package/dist/devices-hap/curtain.js +0 -869
  171. package/dist/devices-hap/curtain.js.map +0 -1
  172. package/dist/devices-hap/device.d.ts +0 -108
  173. package/dist/devices-hap/device.d.ts.map +0 -1
  174. package/dist/devices-hap/device.js +0 -821
  175. package/dist/devices-hap/device.js.map +0 -1
  176. package/dist/devices-hap/fan.d.ts +0 -69
  177. package/dist/devices-hap/fan.d.ts.map +0 -1
  178. package/dist/devices-hap/fan.js +0 -655
  179. package/dist/devices-hap/fan.js.map +0 -1
  180. package/dist/devices-hap/hub.d.ts +0 -37
  181. package/dist/devices-hap/hub.d.ts.map +0 -1
  182. package/dist/devices-hap/hub.js +0 -393
  183. package/dist/devices-hap/hub.js.map +0 -1
  184. package/dist/devices-hap/humidifier.d.ts +0 -73
  185. package/dist/devices-hap/humidifier.d.ts.map +0 -1
  186. package/dist/devices-hap/humidifier.js +0 -716
  187. package/dist/devices-hap/humidifier.js.map +0 -1
  188. package/dist/devices-hap/iosensor.d.ts +0 -42
  189. package/dist/devices-hap/iosensor.d.ts.map +0 -1
  190. package/dist/devices-hap/iosensor.js +0 -397
  191. package/dist/devices-hap/iosensor.js.map +0 -1
  192. package/dist/devices-hap/lightstrip.d.ts +0 -79
  193. package/dist/devices-hap/lightstrip.d.ts.map +0 -1
  194. package/dist/devices-hap/lightstrip.js +0 -827
  195. package/dist/devices-hap/lightstrip.js.map +0 -1
  196. package/dist/devices-hap/lock.d.ts +0 -53
  197. package/dist/devices-hap/lock.d.ts.map +0 -1
  198. package/dist/devices-hap/lock.js +0 -569
  199. package/dist/devices-hap/lock.js.map +0 -1
  200. package/dist/devices-hap/meter.d.ts +0 -37
  201. package/dist/devices-hap/meter.d.ts.map +0 -1
  202. package/dist/devices-hap/meter.js +0 -380
  203. package/dist/devices-hap/meter.js.map +0 -1
  204. package/dist/devices-hap/meterplus.d.ts +0 -42
  205. package/dist/devices-hap/meterplus.d.ts.map +0 -1
  206. package/dist/devices-hap/meterplus.js +0 -385
  207. package/dist/devices-hap/meterplus.js.map +0 -1
  208. package/dist/devices-hap/meterpro.d.ts +0 -43
  209. package/dist/devices-hap/meterpro.d.ts.map +0 -1
  210. package/dist/devices-hap/meterpro.js +0 -469
  211. package/dist/devices-hap/meterpro.js.map +0 -1
  212. package/dist/devices-hap/motion.d.ts +0 -42
  213. package/dist/devices-hap/motion.d.ts.map +0 -1
  214. package/dist/devices-hap/motion.js +0 -345
  215. package/dist/devices-hap/motion.js.map +0 -1
  216. package/dist/devices-hap/plug.d.ts +0 -49
  217. package/dist/devices-hap/plug.d.ts.map +0 -1
  218. package/dist/devices-hap/plug.js +0 -400
  219. package/dist/devices-hap/plug.js.map +0 -1
  220. package/dist/devices-hap/relayswitch.d.ts +0 -96
  221. package/dist/devices-hap/relayswitch.d.ts.map +0 -1
  222. package/dist/devices-hap/relayswitch.js +0 -642
  223. package/dist/devices-hap/relayswitch.js.map +0 -1
  224. package/dist/devices-hap/robotvacuumcleaner.d.ts +0 -54
  225. package/dist/devices-hap/robotvacuumcleaner.d.ts.map +0 -1
  226. package/dist/devices-hap/robotvacuumcleaner.js +0 -530
  227. package/dist/devices-hap/robotvacuumcleaner.js.map +0 -1
  228. package/dist/devices-hap/waterdetector.d.ts +0 -41
  229. package/dist/devices-hap/waterdetector.d.ts.map +0 -1
  230. package/dist/devices-hap/waterdetector.js +0 -356
  231. package/dist/devices-hap/waterdetector.js.map +0 -1
  232. package/dist/devices-matter/BaseMatterAccessory.d.ts +0 -90
  233. package/dist/devices-matter/BaseMatterAccessory.d.ts.map +0 -1
  234. package/dist/devices-matter/BaseMatterAccessory.js +0 -264
  235. package/dist/devices-matter/BaseMatterAccessory.js.map +0 -1
  236. package/dist/devices-matter/ColorLightAccessory.d.ts +0 -20
  237. package/dist/devices-matter/ColorLightAccessory.d.ts.map +0 -1
  238. package/dist/devices-matter/ColorLightAccessory.js +0 -95
  239. package/dist/devices-matter/ColorLightAccessory.js.map +0 -1
  240. package/dist/devices-matter/ColorTemperatureLightAccessory.d.ts +0 -18
  241. package/dist/devices-matter/ColorTemperatureLightAccessory.d.ts.map +0 -1
  242. package/dist/devices-matter/ColorTemperatureLightAccessory.js +0 -76
  243. package/dist/devices-matter/ColorTemperatureLightAccessory.js.map +0 -1
  244. package/dist/devices-matter/ContactSensorAccessory.d.ts +0 -12
  245. package/dist/devices-matter/ContactSensorAccessory.d.ts.map +0 -1
  246. package/dist/devices-matter/ContactSensorAccessory.js +0 -34
  247. package/dist/devices-matter/ContactSensorAccessory.js.map +0 -1
  248. package/dist/devices-matter/DimmableLightAccessory.d.ts +0 -58
  249. package/dist/devices-matter/DimmableLightAccessory.d.ts.map +0 -1
  250. package/dist/devices-matter/DimmableLightAccessory.js +0 -167
  251. package/dist/devices-matter/DimmableLightAccessory.js.map +0 -1
  252. package/dist/devices-matter/DoorLockAccessory.d.ts +0 -14
  253. package/dist/devices-matter/DoorLockAccessory.d.ts.map +0 -1
  254. package/dist/devices-matter/DoorLockAccessory.js +0 -50
  255. package/dist/devices-matter/DoorLockAccessory.js.map +0 -1
  256. package/dist/devices-matter/ExtendedColorLightAccessory.d.ts +0 -21
  257. package/dist/devices-matter/ExtendedColorLightAccessory.d.ts.map +0 -1
  258. package/dist/devices-matter/ExtendedColorLightAccessory.js +0 -106
  259. package/dist/devices-matter/ExtendedColorLightAccessory.js.map +0 -1
  260. package/dist/devices-matter/FanAccessory.d.ts +0 -16
  261. package/dist/devices-matter/FanAccessory.d.ts.map +0 -1
  262. package/dist/devices-matter/FanAccessory.js +0 -81
  263. package/dist/devices-matter/FanAccessory.js.map +0 -1
  264. package/dist/devices-matter/HumiditySensorAccessory.d.ts +0 -12
  265. package/dist/devices-matter/HumiditySensorAccessory.d.ts.map +0 -1
  266. package/dist/devices-matter/HumiditySensorAccessory.js +0 -34
  267. package/dist/devices-matter/HumiditySensorAccessory.js.map +0 -1
  268. package/dist/devices-matter/LeakSensorAccessory.d.ts +0 -12
  269. package/dist/devices-matter/LeakSensorAccessory.d.ts.map +0 -1
  270. package/dist/devices-matter/LeakSensorAccessory.js +0 -33
  271. package/dist/devices-matter/LeakSensorAccessory.js.map +0 -1
  272. package/dist/devices-matter/LightSensorAccessory.d.ts +0 -12
  273. package/dist/devices-matter/LightSensorAccessory.d.ts.map +0 -1
  274. package/dist/devices-matter/LightSensorAccessory.js +0 -34
  275. package/dist/devices-matter/LightSensorAccessory.js.map +0 -1
  276. package/dist/devices-matter/OccupancySensorAccessory.d.ts +0 -12
  277. package/dist/devices-matter/OccupancySensorAccessory.d.ts.map +0 -1
  278. package/dist/devices-matter/OccupancySensorAccessory.js +0 -39
  279. package/dist/devices-matter/OccupancySensorAccessory.js.map +0 -1
  280. package/dist/devices-matter/OnOffLightAccessory.d.ts +0 -38
  281. package/dist/devices-matter/OnOffLightAccessory.d.ts.map +0 -1
  282. package/dist/devices-matter/OnOffLightAccessory.js +0 -110
  283. package/dist/devices-matter/OnOffLightAccessory.js.map +0 -1
  284. package/dist/devices-matter/OnOffOutletAccessory.d.ts +0 -14
  285. package/dist/devices-matter/OnOffOutletAccessory.d.ts.map +0 -1
  286. package/dist/devices-matter/OnOffOutletAccessory.js +0 -43
  287. package/dist/devices-matter/OnOffOutletAccessory.js.map +0 -1
  288. package/dist/devices-matter/OnOffSwitchAccessory.d.ts +0 -14
  289. package/dist/devices-matter/OnOffSwitchAccessory.d.ts.map +0 -1
  290. package/dist/devices-matter/OnOffSwitchAccessory.js +0 -42
  291. package/dist/devices-matter/OnOffSwitchAccessory.js.map +0 -1
  292. package/dist/devices-matter/RoboticVacuumAccessory.d.ts +0 -61
  293. package/dist/devices-matter/RoboticVacuumAccessory.d.ts.map +0 -1
  294. package/dist/devices-matter/RoboticVacuumAccessory.js +0 -544
  295. package/dist/devices-matter/RoboticVacuumAccessory.js.map +0 -1
  296. package/dist/devices-matter/SmokeCOAlarmAccessory.d.ts +0 -11
  297. package/dist/devices-matter/SmokeCOAlarmAccessory.d.ts.map +0 -1
  298. package/dist/devices-matter/SmokeCOAlarmAccessory.js +0 -49
  299. package/dist/devices-matter/SmokeCOAlarmAccessory.js.map +0 -1
  300. package/dist/devices-matter/TemperatureSensorAccessory.d.ts +0 -12
  301. package/dist/devices-matter/TemperatureSensorAccessory.d.ts.map +0 -1
  302. package/dist/devices-matter/TemperatureSensorAccessory.js +0 -36
  303. package/dist/devices-matter/TemperatureSensorAccessory.js.map +0 -1
  304. package/dist/devices-matter/ThermostatAccessory.d.ts +0 -19
  305. package/dist/devices-matter/ThermostatAccessory.d.ts.map +0 -1
  306. package/dist/devices-matter/ThermostatAccessory.js +0 -95
  307. package/dist/devices-matter/ThermostatAccessory.js.map +0 -1
  308. package/dist/devices-matter/VenetianBlindAccessory.d.ts +0 -19
  309. package/dist/devices-matter/VenetianBlindAccessory.d.ts.map +0 -1
  310. package/dist/devices-matter/VenetianBlindAccessory.js +0 -99
  311. package/dist/devices-matter/VenetianBlindAccessory.js.map +0 -1
  312. package/dist/devices-matter/WindowBlindAccessory.d.ts +0 -17
  313. package/dist/devices-matter/WindowBlindAccessory.d.ts.map +0 -1
  314. package/dist/devices-matter/WindowBlindAccessory.js +0 -131
  315. package/dist/devices-matter/WindowBlindAccessory.js.map +0 -1
  316. package/dist/devices-matter/custom/PowerStripAccessory.d.ts +0 -97
  317. package/dist/devices-matter/custom/PowerStripAccessory.d.ts.map +0 -1
  318. package/dist/devices-matter/custom/PowerStripAccessory.js +0 -265
  319. package/dist/devices-matter/custom/PowerStripAccessory.js.map +0 -1
  320. package/dist/devices-matter/custom/index.d.ts +0 -8
  321. package/dist/devices-matter/custom/index.d.ts.map +0 -1
  322. package/dist/devices-matter/custom/index.js +0 -8
  323. package/dist/devices-matter/custom/index.js.map +0 -1
  324. package/dist/devices-matter/index.d.ts +0 -29
  325. package/dist/devices-matter/index.d.ts.map +0 -1
  326. package/dist/devices-matter/index.js +0 -28
  327. package/dist/devices-matter/index.js.map +0 -1
  328. package/dist/irdevice/airconditioner.d.ts +0 -61
  329. package/dist/irdevice/airconditioner.d.ts.map +0 -1
  330. package/dist/irdevice/airconditioner.js +0 -472
  331. package/dist/irdevice/airconditioner.js.map +0 -1
  332. package/dist/irdevice/airpurifier.d.ts +0 -50
  333. package/dist/irdevice/airpurifier.d.ts.map +0 -1
  334. package/dist/irdevice/airpurifier.js +0 -213
  335. package/dist/irdevice/airpurifier.js.map +0 -1
  336. package/dist/irdevice/camera.d.ts +0 -32
  337. package/dist/irdevice/camera.d.ts.map +0 -1
  338. package/dist/irdevice/camera.js +0 -107
  339. package/dist/irdevice/camera.js.map +0 -1
  340. package/dist/irdevice/fan.d.ts +0 -36
  341. package/dist/irdevice/fan.d.ts.map +0 -1
  342. package/dist/irdevice/fan.js +0 -200
  343. package/dist/irdevice/fan.js.map +0 -1
  344. package/dist/irdevice/irdevice.d.ts +0 -69
  345. package/dist/irdevice/irdevice.d.ts.map +0 -1
  346. package/dist/irdevice/irdevice.js +0 -339
  347. package/dist/irdevice/irdevice.js.map +0 -1
  348. package/dist/irdevice/light.d.ts +0 -36
  349. package/dist/irdevice/light.d.ts.map +0 -1
  350. package/dist/irdevice/light.js +0 -206
  351. package/dist/irdevice/light.js.map +0 -1
  352. package/dist/irdevice/other.d.ts +0 -57
  353. package/dist/irdevice/other.d.ts.map +0 -1
  354. package/dist/irdevice/other.js +0 -778
  355. package/dist/irdevice/other.js.map +0 -1
  356. package/dist/irdevice/tv.d.ts +0 -45
  357. package/dist/irdevice/tv.d.ts.map +0 -1
  358. package/dist/irdevice/tv.js +0 -327
  359. package/dist/irdevice/tv.js.map +0 -1
  360. package/dist/irdevice/vacuumcleaner.d.ts +0 -28
  361. package/dist/irdevice/vacuumcleaner.d.ts.map +0 -1
  362. package/dist/irdevice/vacuumcleaner.js +0 -104
  363. package/dist/irdevice/vacuumcleaner.js.map +0 -1
  364. package/dist/irdevice/waterheater.d.ts +0 -30
  365. package/dist/irdevice/waterheater.d.ts.map +0 -1
  366. package/dist/irdevice/waterheater.js +0 -105
  367. package/dist/irdevice/waterheater.js.map +0 -1
  368. package/dist/platform-hap.d.ts +0 -160
  369. package/dist/platform-hap.d.ts.map +0 -1
  370. package/dist/platform-hap.js +0 -3041
  371. package/dist/platform-hap.js.map +0 -1
  372. package/dist/platform-matter.d.ts +0 -188
  373. package/dist/platform-matter.d.ts.map +0 -1
  374. package/dist/platform-matter.js +0 -2545
  375. package/dist/platform-matter.js.map +0 -1
  376. package/dist/test/apiRequestTracker.test.d.ts +0 -2
  377. package/dist/test/apiRequestTracker.test.d.ts.map +0 -1
  378. package/dist/test/apiRequestTracker.test.js +0 -392
  379. package/dist/test/apiRequestTracker.test.js.map +0 -1
  380. package/dist/test/hap/device-webhook-context.test.d.ts +0 -2
  381. package/dist/test/hap/device-webhook-context.test.d.ts.map +0 -1
  382. package/dist/test/hap/device-webhook-context.test.js +0 -128
  383. package/dist/test/hap/device-webhook-context.test.js.map +0 -1
  384. package/dist/test/hap/platform-hap.logging.test.d.ts +0 -2
  385. package/dist/test/hap/platform-hap.logging.test.d.ts.map +0 -1
  386. package/dist/test/hap/platform-hap.logging.test.js +0 -33
  387. package/dist/test/hap/platform-hap.logging.test.js.map +0 -1
  388. package/dist/test/hap/platform-hap.test.d.ts +0 -2
  389. package/dist/test/hap/platform-hap.test.d.ts.map +0 -1
  390. package/dist/test/hap/platform-hap.test.js +0 -62
  391. package/dist/test/hap/platform-hap.test.js.map +0 -1
  392. package/dist/test/helpers/platform-fixtures.d.ts +0 -9
  393. package/dist/test/helpers/platform-fixtures.d.ts.map +0 -1
  394. package/dist/test/helpers/platform-fixtures.js +0 -30
  395. package/dist/test/helpers/platform-fixtures.js.map +0 -1
  396. package/dist/test/homebridge-ui/server.test.d.ts +0 -2
  397. package/dist/test/homebridge-ui/server.test.d.ts.map +0 -1
  398. package/dist/test/homebridge-ui/server.test.js +0 -445
  399. package/dist/test/homebridge-ui/server.test.js.map +0 -1
  400. package/dist/test/index.test.d.ts +0 -2
  401. package/dist/test/index.test.d.ts.map +0 -1
  402. package/dist/test/index.test.js +0 -19
  403. package/dist/test/index.test.js.map +0 -1
  404. package/dist/test/matter/devices-matter/baseMatterAccessory.test.d.ts +0 -2
  405. package/dist/test/matter/devices-matter/baseMatterAccessory.test.d.ts.map +0 -1
  406. package/dist/test/matter/devices-matter/baseMatterAccessory.test.js +0 -71
  407. package/dist/test/matter/devices-matter/baseMatterAccessory.test.js.map +0 -1
  408. package/dist/test/matter/platform-matter.additional.test.d.ts +0 -2
  409. package/dist/test/matter/platform-matter.additional.test.d.ts.map +0 -1
  410. package/dist/test/matter/platform-matter.additional.test.js +0 -35
  411. package/dist/test/matter/platform-matter.additional.test.js.map +0 -1
  412. package/dist/test/matter/platform-matter.bleparse.test.d.ts +0 -2
  413. package/dist/test/matter/platform-matter.bleparse.test.d.ts.map +0 -1
  414. package/dist/test/matter/platform-matter.bleparse.test.js +0 -43
  415. package/dist/test/matter/platform-matter.bleparse.test.js.map +0 -1
  416. package/dist/test/matter/platform-matter.cleanup.test.d.ts +0 -2
  417. package/dist/test/matter/platform-matter.cleanup.test.d.ts.map +0 -1
  418. package/dist/test/matter/platform-matter.cleanup.test.js +0 -70
  419. package/dist/test/matter/platform-matter.cleanup.test.js.map +0 -1
  420. package/dist/test/matter/platform-matter.keepstale.test.d.ts +0 -2
  421. package/dist/test/matter/platform-matter.keepstale.test.d.ts.map +0 -1
  422. package/dist/test/matter/platform-matter.keepstale.test.js +0 -27
  423. package/dist/test/matter/platform-matter.keepstale.test.js.map +0 -1
  424. package/dist/test/matter/platform-matter.logging.test.d.ts +0 -2
  425. package/dist/test/matter/platform-matter.logging.test.d.ts.map +0 -1
  426. package/dist/test/matter/platform-matter.logging.test.js +0 -29
  427. package/dist/test/matter/platform-matter.logging.test.js.map +0 -1
  428. package/dist/test/matter/platform-matter.mapping.test.d.ts +0 -2
  429. package/dist/test/matter/platform-matter.mapping.test.d.ts.map +0 -1
  430. package/dist/test/matter/platform-matter.mapping.test.js +0 -43
  431. package/dist/test/matter/platform-matter.mapping.test.js.map +0 -1
  432. package/dist/test/matter/platform-matter.openapi-mapping.test.d.ts +0 -2
  433. package/dist/test/matter/platform-matter.openapi-mapping.test.d.ts.map +0 -1
  434. package/dist/test/matter/platform-matter.openapi-mapping.test.js +0 -84
  435. package/dist/test/matter/platform-matter.openapi-mapping.test.js.map +0 -1
  436. package/dist/test/matter/platform-matter.test.d.ts +0 -2
  437. package/dist/test/matter/platform-matter.test.d.ts.map +0 -1
  438. package/dist/test/matter/platform-matter.test.js +0 -117
  439. package/dist/test/matter/platform-matter.test.js.map +0 -1
  440. package/dist/test/matter/platform-matter.unregister.test.d.ts +0 -2
  441. package/dist/test/matter/platform-matter.unregister.test.d.ts.map +0 -1
  442. package/dist/test/matter/platform-matter.unregister.test.js +0 -30
  443. package/dist/test/matter/platform-matter.unregister.test.js.map +0 -1
  444. package/dist/test/matter/platform-matter.webhook.test.d.ts +0 -2
  445. package/dist/test/matter/platform-matter.webhook.test.d.ts.map +0 -1
  446. package/dist/test/matter/platform-matter.webhook.test.js +0 -46
  447. package/dist/test/matter/platform-matter.webhook.test.js.map +0 -1
  448. package/dist/test/utils.test.d.ts +0 -2
  449. package/dist/test/utils.test.d.ts.map +0 -1
  450. package/dist/test/utils.test.js +0 -95
  451. package/dist/test/utils.test.js.map +0 -1
  452. package/dist/test/verifyconfig.test.d.ts +0 -2
  453. package/dist/test/verifyconfig.test.d.ts.map +0 -1
  454. package/dist/test/verifyconfig.test.js +0 -167
  455. package/dist/test/verifyconfig.test.js.map +0 -1
  456. package/src/custom.d.ts +0 -7
  457. package/src/devices-hap/airpurifier.ts +0 -568
  458. package/src/devices-hap/blindtilt.ts +0 -1049
  459. package/src/devices-hap/bot.ts +0 -910
  460. package/src/devices-hap/ceilinglight.ts +0 -747
  461. package/src/devices-hap/colorbulb.ts +0 -940
  462. package/src/devices-hap/contact.ts +0 -457
  463. package/src/devices-hap/curtain.ts +0 -944
  464. package/src/devices-hap/device.ts +0 -890
  465. package/src/devices-hap/fan.ts +0 -716
  466. package/src/devices-hap/hub.ts +0 -440
  467. package/src/devices-hap/humidifier.ts +0 -762
  468. package/src/devices-hap/iosensor.ts +0 -442
  469. package/src/devices-hap/lightstrip.ts +0 -863
  470. package/src/devices-hap/lock.ts +0 -627
  471. package/src/devices-hap/meter.ts +0 -427
  472. package/src/devices-hap/meterplus.ts +0 -431
  473. package/src/devices-hap/meterpro.ts +0 -523
  474. package/src/devices-hap/motion.ts +0 -390
  475. package/src/devices-hap/plug.ts +0 -427
  476. package/src/devices-hap/relayswitch.ts +0 -727
  477. package/src/devices-hap/robotvacuumcleaner.ts +0 -574
  478. package/src/devices-hap/waterdetector.ts +0 -400
  479. package/src/devices-matter/BaseMatterAccessory.ts +0 -302
  480. package/src/devices-matter/ColorLightAccessory.ts +0 -110
  481. package/src/devices-matter/ColorTemperatureLightAccessory.ts +0 -90
  482. package/src/devices-matter/ContactSensorAccessory.ts +0 -41
  483. package/src/devices-matter/DimmableLightAccessory.ts +0 -192
  484. package/src/devices-matter/DoorLockAccessory.ts +0 -60
  485. package/src/devices-matter/ExtendedColorLightAccessory.ts +0 -122
  486. package/src/devices-matter/FanAccessory.ts +0 -95
  487. package/src/devices-matter/HumiditySensorAccessory.ts +0 -41
  488. package/src/devices-matter/LeakSensorAccessory.ts +0 -40
  489. package/src/devices-matter/LightSensorAccessory.ts +0 -41
  490. package/src/devices-matter/OccupancySensorAccessory.ts +0 -48
  491. package/src/devices-matter/OnOffLightAccessory.ts +0 -125
  492. package/src/devices-matter/OnOffOutletAccessory.ts +0 -51
  493. package/src/devices-matter/OnOffSwitchAccessory.ts +0 -51
  494. package/src/devices-matter/RoboticVacuumAccessory.ts +0 -621
  495. package/src/devices-matter/SmokeCOAlarmAccessory.ts +0 -59
  496. package/src/devices-matter/TemperatureSensorAccessory.ts +0 -43
  497. package/src/devices-matter/ThermostatAccessory.ts +0 -110
  498. package/src/devices-matter/VenetianBlindAccessory.ts +0 -115
  499. package/src/devices-matter/WindowBlindAccessory.ts +0 -135
  500. package/src/devices-matter/custom/PowerStripAccessory.ts +0 -309
  501. package/src/devices-matter/custom/index.ts +0 -8
  502. package/src/devices-matter/index.ts +0 -29
  503. package/src/irdevice/airconditioner.ts +0 -533
  504. package/src/irdevice/airpurifier.ts +0 -252
  505. package/src/irdevice/camera.ts +0 -129
  506. package/src/irdevice/fan.ts +0 -226
  507. package/src/irdevice/irdevice.ts +0 -383
  508. package/src/irdevice/light.ts +0 -246
  509. package/src/irdevice/other.ts +0 -790
  510. package/src/irdevice/tv.ts +0 -378
  511. package/src/irdevice/vacuumcleaner.ts +0 -126
  512. package/src/irdevice/waterheater.ts +0 -127
  513. package/src/platform-hap.ts +0 -3193
  514. package/src/platform-matter.ts +0 -2703
  515. package/src/test/apiRequestTracker.test.ts +0 -417
  516. package/src/test/hap/device-webhook-context.test.ts +0 -136
  517. package/src/test/hap/platform-hap.logging.test.ts +0 -36
  518. package/src/test/hap/platform-hap.test.ts +0 -70
  519. package/src/test/helpers/platform-fixtures.ts +0 -33
  520. package/src/test/homebridge-ui/server.test.ts +0 -486
  521. package/src/test/index.test.ts +0 -24
  522. package/src/test/matter/devices-matter/baseMatterAccessory.test.ts +0 -88
  523. package/src/test/matter/platform-matter.additional.test.ts +0 -44
  524. package/src/test/matter/platform-matter.bleparse.test.ts +0 -47
  525. package/src/test/matter/platform-matter.cleanup.test.ts +0 -86
  526. package/src/test/matter/platform-matter.keepstale.test.ts +0 -37
  527. package/src/test/matter/platform-matter.logging.test.ts +0 -33
  528. package/src/test/matter/platform-matter.mapping.test.ts +0 -57
  529. package/src/test/matter/platform-matter.openapi-mapping.test.ts +0 -109
  530. package/src/test/matter/platform-matter.test.ts +0 -144
  531. package/src/test/matter/platform-matter.unregister.test.ts +0 -39
  532. package/src/test/matter/platform-matter.webhook.test.ts +0 -54
  533. package/src/test/utils.test.ts +0 -96
  534. package/src/test/verifyconfig.test.ts +0 -198
@@ -1,3193 +0,0 @@
1
- /* Copyright(C) 2017-2024, donavanbecker (https://github.com/donavanbecker). All rights reserved.
2
- *
3
- * platform.ts: @switchbot/homebridge-switchbot platform class.
4
- */
5
- import type { Server } from 'node:http'
6
-
7
- import type { API, DynamicPlatformPlugin, Logging, PlatformAccessory } from 'homebridge'
8
- import type { MqttClient } from 'mqtt'
9
- /*
10
- * For Testing Locally:
11
- * import type { blindTilt, curtain, curtain3, device, irdevice } from '/Users/Shared/GitHub/OpenWonderLabs/node-switchbot/dist/index.js';
12
- * import { LogLevel, SwitchBotBLE, SwitchBotModel, SwitchBotOpenAPI } from '/Users/Shared/GitHub/OpenWonderLabs/node-switchbot/dist/index.js';
13
- */
14
- import type { blindTilt, bodyChange, curtain, curtain3, device, deviceStatusRequest, irdevice } from 'node-switchbot'
15
-
16
- import type { blindTiltConfig, curtainConfig, devicesConfig, irDevicesConfig, options, SwitchBotPlatformConfig } from './settings.js'
17
-
18
- import { readFileSync } from 'node:fs'
19
- import { argv } from 'node:process'
20
-
21
- import asyncmqtt from 'async-mqtt'
22
- import fakegato from 'fakegato-history'
23
- import { EveHomeKitTypes } from 'homebridge-lib/EveHomeKitTypes'
24
- import { LogLevel, SwitchBotBLE, SwitchBotModel, SwitchBotOpenAPI } from 'node-switchbot'
25
- import { queueScheduler } from 'rxjs'
26
-
27
- import { AirPurifier } from './devices-hap/airpurifier.js'
28
- import { BlindTilt } from './devices-hap/blindtilt.js'
29
- import { Bot } from './devices-hap/bot.js'
30
- import { CeilingLight } from './devices-hap/ceilinglight.js'
31
- import { ColorBulb } from './devices-hap/colorbulb.js'
32
- import { Contact } from './devices-hap/contact.js'
33
- import { Curtain } from './devices-hap/curtain.js'
34
- import { Fan } from './devices-hap/fan.js'
35
- import { Hub } from './devices-hap/hub.js'
36
- import { Humidifier } from './devices-hap/humidifier.js'
37
- import { IOSensor } from './devices-hap/iosensor.js'
38
- import { StripLight } from './devices-hap/lightstrip.js'
39
- import { Lock } from './devices-hap/lock.js'
40
- import { Meter } from './devices-hap/meter.js'
41
- import { MeterPlus } from './devices-hap/meterplus.js'
42
- import { MeterPro } from './devices-hap/meterpro.js'
43
- import { Motion } from './devices-hap/motion.js'
44
- import { Plug } from './devices-hap/plug.js'
45
- import { RelaySwitch } from './devices-hap/relayswitch.js'
46
- import { RobotVacuumCleaner } from './devices-hap/robotvacuumcleaner.js'
47
- import { WaterDetector } from './devices-hap/waterdetector.js'
48
- import { AirConditioner } from './irdevice/airconditioner.js'
49
- import { AirPurifierIR } from './irdevice/airpurifier.js'
50
- import { Camera } from './irdevice/camera.js'
51
- import { IRFan } from './irdevice/fan.js'
52
- import { Light } from './irdevice/light.js'
53
- import { Others } from './irdevice/other.js'
54
- import { TV } from './irdevice/tv.js'
55
- import { VacuumCleaner } from './irdevice/vacuumcleaner.js'
56
- import { WaterHeater } from './irdevice/waterheater.js'
57
- import { PLATFORM_NAME, PLUGIN_NAME } from './settings.js'
58
- import { ApiRequestTracker, applyDeviceTypeTemplates, createPlatformLogger, formatDeviceIdAsMac, isBlindTiltDevice, isCurtainDevice, isSuccessfulStatusCode, logStatusCode, mergeByDeviceId, safeStringify, sleep } from './utils.js'
59
-
60
- /**
61
- * HomebridgePlatform
62
- * This class is the main constructor for your plugin, this is where you should
63
- * parse the user config and discover/register accessories with Homebridge.
64
- */
65
- export class SwitchBotHAPPlatform implements DynamicPlatformPlugin {
66
- // Platform properties
67
- public accessories: PlatformAccessory[] = []
68
- public readonly api: API
69
- public readonly log: Logging
70
-
71
- // Logging helper functions (attached from utils.createPlatformLogger in constructor)
72
- infoLog!: (...log: any[]) => Promise<void>
73
- successLog!: (...log: any[]) => Promise<void>
74
- debugSuccessLog!: (...log: any[]) => Promise<void>
75
- warnLog!: (...log: any[]) => Promise<void>
76
- debugWarnLog!: (...log: any[]) => Promise<void>
77
- errorLog!: (...log: any[]) => Promise<void>
78
- debugErrorLog!: (...log: any[]) => Promise<void>
79
- debugLog!: (...log: any[]) => Promise<void>
80
- loggingIsDebug!: () => Promise<boolean>
81
- enablingPlatformLogging!: () => Promise<boolean>
82
-
83
- // Configuration properties
84
- platformConfig!: SwitchBotPlatformConfig
85
- platformLogging!: options['logging']
86
- platformRefreshRate!: options['refreshRate']
87
- platformPushRate!: options['pushRate']
88
- platformUpdateRate!: options['updateRate']
89
- platformMaxRetries!: options['maxRetries']
90
- platformDelayBetweenRetries!: options['delayBetweenRetries']
91
- config!: SwitchBotPlatformConfig
92
- debugMode!: boolean
93
- version!: string
94
-
95
- // MQTT and Webhook properties
96
- mqttClient: MqttClient | null = null
97
- webhookEventListener: Server | null = null
98
-
99
- // SwitchBot APIs
100
- switchBotAPI!: SwitchBotOpenAPI
101
- switchBotBLE!: SwitchBotBLE
102
-
103
- // API request tracking
104
- private apiTracker?: ApiRequestTracker
105
-
106
- // External APIs
107
- public readonly eve: any
108
- public readonly fakegatoAPI: any
109
-
110
- // Event Handlers
111
- public readonly webhookEventHandler: { [x: string]: (context: any) => void } = {}
112
- public readonly bleEventHandler: { [x: string]: (context: any) => void } = {}
113
-
114
- constructor(
115
- log: Logging,
116
- config: SwitchBotPlatformConfig,
117
- api: API,
118
- ) {
119
- this.api = api
120
- this.log = log
121
-
122
- // Attach shared platform logging helpers (moved to utils for reuse)
123
- const _pl = createPlatformLogger(async () => this.platformLogging, this.log)
124
- this.infoLog = _pl.infoLog
125
- this.successLog = _pl.successLog
126
- this.debugSuccessLog = _pl.debugSuccessLog
127
- this.warnLog = _pl.warnLog
128
- this.debugWarnLog = _pl.debugWarnLog
129
- this.errorLog = _pl.errorLog
130
- this.debugErrorLog = _pl.debugErrorLog
131
- this.debugLog = _pl.debugLog
132
- this.loggingIsDebug = _pl.loggingIsDebug
133
- this.enablingPlatformLogging = _pl.enablingPlatformLogging
134
-
135
- // only load if configured
136
- if (!config) {
137
- this.errorLog('No configuration found for the plugin, please check your config.')
138
- return
139
- }
140
-
141
- // Plugin options into our config variables.
142
- this.config = {
143
- platform: 'SwitchBotPlatform',
144
- name: config.name,
145
- credentials: config.credentials as object,
146
- options: config.options as object,
147
- devices: config.devices as { deviceId: string }[],
148
- }
149
-
150
- // Determine platform logging preference (match HAP behaviour as closely as
151
- // possible using config values. We default to 'standard' when unspecified.)
152
- this.platformLogging = (this.config.options?.logging === 'debug' || this.config.options?.logging === 'standard' || this.config.options?.logging === 'none')
153
- ? this.config.options.logging
154
- : 'standard'
155
-
156
- // Unconditional diagnostic using the raw Homebridge `log` so it always
157
- // appears regardless of the platform logging helpers' gating logic.
158
- try {
159
- this.log.debug?.(`[SwitchBot HAP] effective platformLogging=${String(this.platformLogging)}`)
160
- } catch (e: any) {
161
- // swallow any logging errors — diagnostics are best-effort
162
- }
163
-
164
- // Note: deviceConfig and irdeviceConfig have been removed from the platform.
165
- // All device-specific configuration should be done via options.devices and options.irdevices arrays.
166
-
167
- // Plugin Configuration
168
- this.getPlatformLogSettings()
169
- this.getPlatformRateSettings()
170
- this.getPlatformConfigSettings()
171
- this.getVersion()
172
-
173
- // Finish initializing the platform
174
- this.debugLog(`Finished initializing platform: ${config.name}`)
175
-
176
- // verify the config
177
- try {
178
- this.verifyConfig()
179
- this.debugLog('Config OK')
180
- } catch (e: any) {
181
- this.errorLog(`Verify Config, Error Message: ${e.message ?? e}, Submit Bugs Here: ` + 'https://tinyurl.com/SwitchBotBug')
182
- this.debugErrorLog(`Verify Config, Error: ${e.message ?? e}`)
183
- return
184
- }
185
-
186
- // SwitchBot OpenAPI
187
- if (this.config.credentials?.token && this.config.credentials?.secret) {
188
- this.switchBotAPI = new SwitchBotOpenAPI(this.config.credentials.token, this.config.credentials.secret, this.config.options?.hostname)
189
- } else {
190
- this.debugErrorLog('Missing SwitchBot API credentials (token or secret).')
191
- }
192
- // Listen for log events
193
- if (!this.config.options?.disableLogsforOpenAPI && this.switchBotAPI) {
194
- this.switchBotAPI.on('log', (log) => {
195
- switch (log.level) {
196
- case LogLevel.SUCCESS:
197
- this.successLog(log.message)
198
- break
199
- case LogLevel.DEBUGSUCCESS:
200
- this.debugSuccessLog(log.message)
201
- break
202
- case LogLevel.WARN:
203
- this.warnLog(log.message)
204
- break
205
- case LogLevel.DEBUGWARN:
206
- this.debugWarnLog(log.message)
207
- break
208
- case LogLevel.ERROR:
209
- this.errorLog(log.message)
210
- break
211
- case LogLevel.DEBUGERROR:
212
- this.debugErrorLog(log.message)
213
- break
214
- case LogLevel.DEBUG:
215
- this.debugLog(log.message)
216
- break
217
- case LogLevel.INFO:
218
- default:
219
- this.infoLog(log.message)
220
- }
221
- })
222
- } else {
223
- this.debugErrorLog(`SwitchBot OpenAPI logs are disabled, enable it by setting disableLogsforOpenAPI to false.`)
224
- this.debugLog(`SwitchBot OpenAPI: ${JSON.stringify(this.switchBotAPI)}, disableLogsforOpenAPI: ${this.config.options?.disableLogsforOpenAPI}`)
225
- }
226
- // import fakegato-history module and EVE characteristics
227
- this.fakegatoAPI = fakegato(api)
228
- this.eve = new EveHomeKitTypes(api)
229
-
230
- // When this event is fired it means Homebridge has restored all cached accessories from disk.
231
- // Dynamic Platform plugins should only register new accessories after this event was fired,
232
- // in order to ensure they weren't added to homebridge already. This event can also be used
233
- // to start discovery of new accessories.
234
- this.api.on('didFinishLaunching', async () => {
235
- this.debugLog('Executed didFinishLaunching callback')
236
-
237
- // Initialize API request tracking
238
- if (this.switchBotAPI) {
239
- try {
240
- const dailyApiLimit = this.config.options?.dailyApiLimit ?? 10000
241
- const dailyApiReserveForCommands = this.config.options?.dailyApiReserveForCommands ?? 1000
242
- const webhookOnlyOnReserve = this.config.options?.webhookOnlyOnReserve ?? false
243
- this.apiTracker = new ApiRequestTracker(this.api, this.log, 'SwitchBot HAP', {
244
- dailyLimit: dailyApiLimit,
245
- reserveForCommands: dailyApiReserveForCommands,
246
- pausePollingAtReserve: webhookOnlyOnReserve,
247
- resetAtLocalMidnight: this.config.options?.dailyApiResetAtLocalMidnight ?? false,
248
- })
249
- this.apiTracker.startHourlyLogging()
250
- this.debugLog('API request tracking initialized for OpenAPI usage')
251
- } catch (e: any) {
252
- this.errorLog(`Failed to initialize API request tracking: ${e.message ?? e}`)
253
- }
254
- }
255
-
256
- // run the method to discover / register your devices as accessories
257
- try {
258
- // Does the user have a version of Homebridge that is compatible with matter?
259
- if (!this.api.isMatterAvailable?.()) {
260
- this.debugLog(`Matter is not available in this version of Homebridge. Please update Homebridge to use this plugin, ${this.api.isMatterAvailable?.() ? '' : ' (Matter is not available in this version of Homebridge)'}`)
261
- }
262
- if (!this.api.isMatterEnabled?.()) {
263
- this.debugLog(`Matter is not enabled in Homebridge. Please enable Matter in the Homebridge settings to use this plugin, ${this.api.isMatterEnabled?.() ? '' : ' (Matter is not enabled in Homebridge)'}`)
264
- }
265
- if (!this.api.isMatterAvailable?.() && !this.api.isMatterEnabled?.()) {
266
- await this.discoverDevices()
267
- } else {
268
- this.infoLog('Matter is enabled in Homebridge. SwitchBot Matter devices will be handled by the Matter platform.')
269
- }
270
- } catch (e: any) {
271
- this.errorLog(`Failed to Discover, Error Message: ${e.message ?? e}, Submit Bugs Here: ` + 'https://tinyurl.com/SwitchBotBug')
272
- this.debugErrorLog(`Failed to Discover, Error: ${e.message ?? e}`)
273
- }
274
- })
275
-
276
- try {
277
- this.setupMqtt()
278
- } catch (e: any) {
279
- this.errorLog(`Setup MQTT, Error Message: ${e.message ?? e}, Submit Bugs Here: ` + 'https://tinyurl.com/SwitchBotBug')
280
- }
281
- try {
282
- this.setupwebhook()
283
- } catch (e: any) {
284
- this.errorLog(`Setup Webhook, Error Message: ${e.message ?? e}, Submit Bugs Here: ` + 'https://tinyurl.com/SwitchBotBug')
285
- }
286
- try {
287
- this.setupBlE()
288
- } catch (e: any) {
289
- this.errorLog(`Setup Platform BLE, Error Message: ${e.message ?? e}, Submit Bugs Here: ` + 'https://tinyurl.com/SwitchBotBug')
290
- }
291
- }
292
-
293
- async setupMqtt(): Promise<void> {
294
- if (this.config.options?.mqttURL) {
295
- try {
296
- const { connectAsync } = asyncmqtt
297
- this.mqttClient = await connectAsync(this.config.options?.mqttURL, this.config.options.mqttOptions || {})
298
- this.debugLog('MQTT connection has been established successfully.')
299
- this.mqttClient.on('error', async (e: Error) => {
300
- this.errorLog(`Failed to publish MQTT messages. ${e.message ?? e}`)
301
- })
302
- if (!this.config.options?.webhookURL) {
303
- // receive webhook events via MQTT
304
- this.infoLog(`Webhook is configured to be received through ${this.config.options.mqttURL}/homebridge-switchbot/webhook.`)
305
- this.mqttClient.subscribe('homebridge-switchbot/webhook/+')
306
- this.mqttClient.on('message', async (topic: string, message) => {
307
- try {
308
- this.debugLog(`Received Webhook via MQTT: ${topic}=${message}`)
309
- const context = JSON.parse(message.toString())
310
- this.webhookEventHandler[context.deviceMac]?.(context)
311
- } catch (e: any) {
312
- this.errorLog(`Failed to handle webhook event. Error: ${e.message ?? e}`)
313
- }
314
- })
315
- }
316
- } catch (e: any) {
317
- this.mqttClient = null
318
- this.errorLog(`Failed to establish MQTT connection. ${e.message ?? e}`)
319
- }
320
- }
321
- }
322
-
323
- async setupwebhook() {
324
- // webhook configuration
325
- if (this.config.options?.webhookURL) {
326
- const url = this.config.options?.webhookURL
327
- try {
328
- this.switchBotAPI.setupWebhook(url)
329
- // Listen for webhook events
330
- this.switchBotAPI.on('webhookEvent', (body) => {
331
- if (this.config.options?.mqttURL) {
332
- const mac = body.context.deviceMac?.toLowerCase().match(/[\s\S]{1,2}/g)?.join(':')
333
- const options = this.config.options?.mqttPubOptions || {}
334
- this.mqttClient?.publish(`homebridge-switchbot/webhook/${mac}`, `${JSON.stringify(body.context)}`, options)
335
- }
336
- this.webhookEventHandler[body.context.deviceMac]?.(body.context)
337
- })
338
- } catch (e: any) {
339
- this.errorLog(`Failed to setup webhook. Error: ${e.message ?? e}`)
340
- }
341
-
342
- this.api.on('shutdown', async () => {
343
- try {
344
- this.switchBotAPI.deleteWebhook(url)
345
- } catch (e: any) {
346
- this.errorLog(`Failed to delete webhook. Error: ${e.message ?? e}`)
347
- }
348
- })
349
- }
350
- }
351
-
352
- async setupBlE() {
353
- this.switchBotBLE = new SwitchBotBLE()
354
- // Listen for log events
355
- if (!this.config.options?.disableLogsforBLE) {
356
- this.switchBotBLE.on('log', (log) => {
357
- switch (log.level) {
358
- case LogLevel.SUCCESS:
359
- this.successLog(log.message)
360
- break
361
- case LogLevel.DEBUGSUCCESS:
362
- this.debugSuccessLog(log.message)
363
- break
364
- case LogLevel.WARN:
365
- this.warnLog(log.message)
366
- break
367
- case LogLevel.DEBUGWARN:
368
- this.debugWarnLog(log.message)
369
- break
370
- case LogLevel.ERROR:
371
- this.errorLog(log.message)
372
- break
373
- case LogLevel.DEBUGERROR:
374
- this.debugErrorLog(log.message)
375
- break
376
- case LogLevel.DEBUG:
377
- this.debugLog(log.message)
378
- break
379
- case LogLevel.INFO:
380
- default:
381
- this.infoLog(log.message)
382
- }
383
- })
384
- }
385
- if (this.config.options?.BLE) {
386
- this.debugLog('setupBLE')
387
- if (this.switchBotBLE === undefined) {
388
- this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${JSON.stringify(this.switchBotBLE)}`)
389
- } else {
390
- // Start to monitor advertisement packets
391
- (async () => {
392
- // Start to monitor advertisement packets
393
- this.debugLog('Scanning for BLE SwitchBot devices...')
394
- try {
395
- await this.switchBotBLE.startScan()
396
- } catch (e: any) {
397
- this.errorLog(`Failed to start BLE scanning. Error: ${e.message ?? e}`)
398
- }
399
- // Set an event handler to monitor advertisement packets
400
- this.switchBotBLE.onadvertisement = async (ad: any) => {
401
- try {
402
- this.bleEventHandler[ad.address]?.(ad.serviceData)
403
- } catch (e: any) {
404
- this.errorLog(`Failed to handle BLE event. Error: ${e.message ?? e}`)
405
- }
406
- }
407
- })()
408
-
409
- this.api.on('shutdown', async () => {
410
- try {
411
- // this.switchBotBLE.stopScan()
412
- this.infoLog('Stopped BLE scanning to close listening.')
413
- } catch (e: any) {
414
- this.errorLog(`Failed to stop Platform BLE scanning. Error: ${e.message ?? e}`)
415
- }
416
- })
417
- }
418
- } else {
419
- this.debugLog('Platform BLE is not enabled')
420
- }
421
- }
422
-
423
- /**
424
- * This function is invoked when homebridge restores cached accessories from disk at startup.
425
- * It should be used to setup event handlers for characteristics and update respective values.
426
- */
427
- async configureAccessory(accessory: PlatformAccessory) {
428
- const { displayName } = accessory
429
- this.debugLog(`Loading accessory from cache: ${displayName}`)
430
-
431
- // add the restored accessory to the accessories cache so we can track if it has already been registered
432
- this.accessories.push(accessory)
433
- }
434
-
435
- /**
436
- * Verify the config passed to the plugin is valid
437
- */
438
- async verifyConfig() {
439
- this.debugLog('Verifying Config')
440
- this.config = this.config || {}
441
- this.config.options = this.config.options || {}
442
-
443
- if (this.config.options) {
444
- // Device Config
445
- if (this.config.options.devices) {
446
- for (const deviceConfig of this.config.options.devices) {
447
- if (!deviceConfig.hide_device) {
448
- if (!deviceConfig.deviceId) {
449
- this.errorLog('The devices config section is missing the *Device ID* in the config. Please check your config.')
450
- }
451
- if (!deviceConfig.configDeviceType && (deviceConfig as devicesConfig).connectionType) {
452
- this.errorLog('The devices config section is missing the *Device Type* in the config. Please check your config.')
453
- }
454
- }
455
- }
456
- }
457
-
458
- // IR Device Config
459
- if (this.config.options.irdevices) {
460
- for (const irDeviceConfig of this.config.options.irdevices) {
461
- if (!irDeviceConfig.hide_device) {
462
- if (!irDeviceConfig.deviceId) {
463
- this.errorLog('The devices config section is missing the *Device ID* in the config. Please check your config.')
464
- }
465
- if (!irDeviceConfig.deviceId && !irDeviceConfig.configRemoteType) {
466
- this.errorLog('The devices config section is missing the *Device Type* in the config. Please check your config.')
467
- }
468
- }
469
- }
470
- }
471
- }
472
-
473
- if (!this.config.credentials && !this.config.options) {
474
- this.debugWarnLog('Missing Credentials')
475
- } else if (this.config.credentials && !this.config.credentials.notice) {
476
- if (!this.config.credentials?.token) {
477
- this.debugErrorLog('Missing token')
478
- this.debugWarnLog('Cloud Enabled SwitchBot Devices & IR Devices will not work')
479
- }
480
- if (this.config.credentials?.token) {
481
- if (!this.config.credentials?.secret) {
482
- this.debugErrorLog('Missing secret')
483
- this.debugWarnLog('Cloud Enabled SwitchBot Devices & IR Devices will not work')
484
- }
485
- }
486
- }
487
- }
488
-
489
- async discoverDevices() {
490
- if (!this.config.credentials?.token) {
491
- return this.handleManualConfig()
492
- }
493
-
494
- let retryCount = 0
495
- const maxRetries = this.platformMaxRetries ?? 5
496
- const delayBetweenRetries = this.platformDelayBetweenRetries || 5000
497
- let rateLimitExceeded = false
498
-
499
- this.debugWarnLog(`Retry Count: ${retryCount}`)
500
- this.debugWarnLog(`Max Retries: ${this.platformMaxRetries}`)
501
- this.debugWarnLog(`Delay Between Retries: ${this.platformDelayBetweenRetries}`)
502
-
503
- while (retryCount < maxRetries) {
504
- try {
505
- if (!this.apiTracker?.trySpend('discovery')) {
506
- rateLimitExceeded = true
507
- this.warnLog('OpenAPI daily budget reached (discovery blocked). Falling back to manual device configuration.')
508
- break
509
- }
510
- const { response, statusCode } = await this.switchBotAPI.getDevices()
511
- this.debugLog(`response: ${JSON.stringify(response)}`)
512
- if (this.isSuccessfulResponse(statusCode)) {
513
- const deviceList = Array.isArray(response.body.deviceList) ? response.body.deviceList : []
514
- const irDeviceList = Array.isArray(response.body.infraredRemoteList) ? response.body.infraredRemoteList : []
515
- await this.handleDevices(deviceList)
516
- await this.handleIRDevices(irDeviceList)
517
- // Diagnostic: warn users if their device count + refresh rate may exceed daily limits
518
- this.validateApiUsageConfig(deviceList.length, irDeviceList.length)
519
- break
520
- } else {
521
- // Check if rate limit exceeded (429)
522
- if (statusCode === 429) {
523
- rateLimitExceeded = true
524
- this.warnLog('OpenAPI rate limit (429) exceeded. Falling back to manual device configuration.')
525
- this.warnLog('Webhook functionality will still work if devices are configured manually.')
526
- break
527
- }
528
- await this.handleErrorResponse(statusCode, retryCount, maxRetries, delayBetweenRetries)
529
- retryCount++
530
- }
531
- } catch (e: any) {
532
- retryCount++
533
- this.debugErrorLog(`Failed to Discover Devices, Error Message: ${JSON.stringify(e.message)}, Submit Bugs Here: https://tinyurl.com/SwitchBotBug`)
534
- this.debugErrorLog(`Failed to Discover Devices, Error: ${e.message ?? e}`)
535
- }
536
- }
537
-
538
- // If rate limit exceeded or retries exhausted, try to load from manual config or cached accessories
539
- if (rateLimitExceeded || retryCount >= maxRetries) {
540
- const hasCachedAccessories = this.accessories.length > 0
541
- const hasManualConfig = this.config.options?.devices || this.config.options?.irdevices
542
-
543
- if (hasManualConfig || hasCachedAccessories) {
544
- if (hasCachedAccessories) {
545
- this.warnLog(`Found ${this.accessories.length} cached accessories from previous sessions.`)
546
- this.warnLog('Reinstantiating device classes to enable webhook handlers...')
547
- await this.restoreCachedAccessories()
548
- }
549
- if (hasManualConfig) {
550
- this.warnLog('Attempting to load devices from manual configuration...')
551
- await this.handleManualConfig()
552
- }
553
- if (hasCachedAccessories) {
554
- this.infoLog('Cached accessories restored. Webhook functionality is active.')
555
- this.infoLog('Device discovery will resume when API rate limit resets.')
556
- }
557
- } else {
558
- this.errorLog('OpenAPI unavailable and no cached accessories or manual device configuration found.')
559
- this.errorLog('Please configure devices manually in the plugin settings to use webhook functionality.')
560
- }
561
- }
562
- }
563
-
564
- /**
565
- * Restore cached accessories by reinstantiating their device classes
566
- * This ensures webhook handlers and other functionality are properly set up
567
- */
568
- private async restoreCachedAccessories() {
569
- this.debugLog('Restoring cached accessories and setting up webhook handlers...')
570
-
571
- for (const accessory of this.accessories) {
572
- try {
573
- const device = accessory.context.device
574
- const deviceType = accessory.context.deviceType || device?.deviceType
575
- const deviceId = accessory.context.deviceId || device?.deviceId
576
-
577
- if (!device || !deviceType || !deviceId) {
578
- this.debugWarnLog(`Skipping cached accessory ${accessory.displayName} - missing context data`)
579
- continue
580
- }
581
-
582
- this.debugLog(`Reinstantiating ${deviceType} for cached accessory: ${accessory.displayName}`)
583
-
584
- // Reinstantiate the device class based on deviceType
585
- const deviceTypeHandlers: { [key: string]: new (platform: any, accessory: PlatformAccessory, device: any) => any } = {
586
- 'Humidifier': Humidifier,
587
- 'Humidifier2': Humidifier,
588
- 'Hub 2': Hub,
589
- 'Hub 3': Hub,
590
- 'Bot': Bot,
591
- 'Relay Switch 1': RelaySwitch,
592
- 'Relay Switch 1PM': RelaySwitch,
593
- 'Meter': Meter,
594
- 'MeterPlus': MeterPlus,
595
- 'Meter Plus (JP)': MeterPlus,
596
- 'MeterPro': MeterPro,
597
- 'MeterPro(CO2)': MeterPro,
598
- 'WoIOSensor': IOSensor,
599
- 'Water Detector': WaterDetector,
600
- 'Motion Sensor': Motion,
601
- 'Contact Sensor': Contact,
602
- 'Curtain': Curtain,
603
- 'Curtain3': Curtain,
604
- 'WoRollerShade': Curtain,
605
- 'Roller Shade': Curtain,
606
- 'Blind Tilt': BlindTilt,
607
- 'Plug': Plug,
608
- 'Plug Mini (US)': Plug,
609
- 'Plug Mini (JP)': Plug,
610
- 'Smart Lock': Lock,
611
- 'Smart Lock Pro': Lock,
612
- 'Smart Lock Ultra': Lock,
613
- 'Color Bulb': ColorBulb,
614
- 'K10+': RobotVacuumCleaner,
615
- 'K10+ Pro': RobotVacuumCleaner,
616
- 'WoSweeper': RobotVacuumCleaner,
617
- 'WoSweeperMini': RobotVacuumCleaner,
618
- 'Robot Vacuum Cleaner S1': RobotVacuumCleaner,
619
- 'Robot Vacuum Cleaner S1 Plus': RobotVacuumCleaner,
620
- 'Robot Vacuum Cleaner S10': RobotVacuumCleaner,
621
- 'Ceiling Light': CeilingLight,
622
- 'Ceiling Light Pro': CeilingLight,
623
- 'Strip Light': StripLight,
624
- 'Battery Circulator Fan': Fan,
625
- 'Air Purifier PM2.5': AirPurifier,
626
- 'Air Purifier Table PM2.5': AirPurifier,
627
- 'Air Purifier VOC': AirPurifier,
628
- 'Air Purifier Table VOC': AirPurifier,
629
- }
630
-
631
- const DeviceClass = deviceTypeHandlers[deviceType]
632
- if (DeviceClass) {
633
- new DeviceClass(this, accessory, device)
634
- this.debugSuccessLog(`Successfully restored ${deviceType}: ${accessory.displayName}`)
635
- } else {
636
- this.debugLog(`No handler for device type: ${deviceType}`)
637
- }
638
- } catch (e: any) {
639
- this.errorLog(`Failed to restore cached accessory ${accessory.displayName}, Error: ${e.message ?? e}`)
640
- }
641
- }
642
-
643
- this.infoLog(`Restored ${this.accessories.length} cached accessories with webhook support`)
644
- }
645
-
646
- private async handleManualConfig() {
647
- // Handle regular devices
648
- if (this.config.options?.devices) {
649
- this.debugLog(`SwitchBot Device Manual Config Set: ${JSON.stringify(this.config.options?.devices)}`)
650
- const devices = this.config.options.devices.map((v: any) => v)
651
- for (const device of devices) {
652
- device.deviceType = device.configDeviceType !== undefined ? device.configDeviceType : 'Unknown'
653
- device.deviceName = device.configDeviceName !== undefined ? device.configDeviceName : 'Unknown'
654
- try {
655
- device.deviceId = formatDeviceIdAsMac(device.deviceId, true)
656
- this.debugLog(`deviceId: ${device.deviceId}`)
657
- if (device.deviceType) {
658
- await this.createDevice(device)
659
- }
660
- } catch (error) {
661
- this.errorLog(`failed to format device ID as MAC, Error: ${error}`)
662
- }
663
- }
664
- }
665
-
666
- // Handle IR devices
667
- if (this.config.options?.irdevices) {
668
- this.debugLog(`SwitchBot IR Device Manual Config Set: ${JSON.stringify(this.config.options?.irdevices)}`)
669
- const irdevices = this.config.options.irdevices.map((v: any) => v)
670
- for (const irdevice of irdevices) {
671
- irdevice.remoteType = irdevice.configRemoteType !== undefined ? irdevice.configRemoteType : 'Unknown'
672
- irdevice.deviceName = irdevice.configDeviceName !== undefined ? irdevice.configDeviceName : 'Unknown'
673
- try {
674
- this.debugLog(`IR deviceId: ${irdevice.deviceId}`)
675
- if (irdevice.remoteType) {
676
- await this.createIRDevice(irdevice)
677
- }
678
- } catch (error) {
679
- this.errorLog(`failed to create IR device, Error: ${error}`)
680
- }
681
- }
682
- }
683
-
684
- if (!this.config.options?.devices && !this.config.options?.irdevices) {
685
- this.errorLog('Neither SwitchBot Token or Device Config are set.')
686
- }
687
- }
688
-
689
- /**
690
- * Check if an API status code indicates success
691
- * @deprecated Use shared isSuccessfulStatusCode from utils.js instead
692
- */
693
- private isSuccessfulResponse(apiStatusCode: number): boolean {
694
- return isSuccessfulStatusCode(apiStatusCode)
695
- }
696
-
697
- private async handleDevices(deviceLists: any[]) {
698
- if (!this.config.options?.devices) {
699
- this.debugLog(`SwitchBot Device Config Not Set: ${JSON.stringify(this.config.options?.devices)}`)
700
- if (deviceLists.length === 0) {
701
- this.debugLog('SwitchBot API Has No Devices With Cloud Services Enabled')
702
- } else {
703
- for (const device of deviceLists) {
704
- if (device.deviceType) {
705
- if (device.configDeviceName) {
706
- device.deviceName = device.configDeviceName
707
- }
708
- await this.createDevice(device)
709
- }
710
- }
711
- }
712
- } else {
713
- this.debugLog(`SwitchBot Device Config Set: ${JSON.stringify(this.config.options?.devices)}`)
714
-
715
- // Check and assign configDeviceType to deviceType if deviceType is not present
716
- const devicesWithTypeAssigned = deviceLists.map((device) => {
717
- if (!device.deviceType) {
718
- device.deviceType = device.configDeviceType !== undefined ? device.configDeviceType : 'Unknown'
719
- this.warnLog(`API is displaying no deviceType: ${device.deviceType}, So using configDeviceType: ${device.configDeviceType}`)
720
- }
721
- return device
722
- })
723
-
724
- // Apply device-type templates from config entries with applyToAllDevicesOfType=true
725
- const devicesWithTemplates = applyDeviceTypeTemplates(
726
- devicesWithTypeAssigned,
727
- this.config.options.devices,
728
- 'deviceType',
729
- msg => this.debugLog(msg),
730
- )
731
-
732
- const allowConfigOnly = Boolean(this.config.options?.allowConfigOnlyDevices)
733
- const devices = mergeByDeviceId(this.config.options.devices ?? [], devicesWithTemplates ?? [], allowConfigOnly)
734
-
735
- // Apply global webhook option to devices that don't have their own webhook setting
736
- if (this.config.options?.webhook === true) {
737
- for (const device of devices) {
738
- if (device.webhook === undefined) {
739
- device.webhook = true
740
- this.debugLog(`Applying global webhook option to device: ${device.deviceName ?? device.deviceId}`)
741
- }
742
- }
743
- }
744
-
745
- this.debugLog(`SwitchBot Devices: ${JSON.stringify(devices)}`)
746
-
747
- for (const device of devices) {
748
- if (device.configDeviceName) {
749
- device.deviceName = device.configDeviceName
750
- }
751
- // Log effective webhook setting for diagnostics
752
- try {
753
- const effectiveWebhook = device.webhook !== undefined ? device.webhook : (this.config.options?.webhook === true ? true : undefined)
754
- this.debugLog(`Effective webhook for device ${device.deviceName ?? device.deviceId}: ${String(effectiveWebhook)}`)
755
- } catch (e: any) {
756
- this.debugLog(`Failed logging effective webhook for ${device.deviceName ?? device.deviceId}: ${e?.message ?? e}`)
757
- }
758
- await this.createDevice(device)
759
- }
760
- }
761
- }
762
-
763
- private async handleIRDevices(irDeviceLists: any[]) {
764
- if (!this.config.options?.irdevices) {
765
- this.debugLog(`IR Device Config Not Set: ${JSON.stringify(this.config.options?.irdevices)}`)
766
- for (const device of irDeviceLists) {
767
- if (device.remoteType) {
768
- await this.createIRDevice(device)
769
- }
770
- }
771
- } else {
772
- this.debugLog(`IR Device Config Set: ${JSON.stringify(this.config.options?.irdevices)}`)
773
-
774
- // Check and assign configRemoteType to remoteType if remoteType is not present
775
- const devicesWithTypeAssigned = irDeviceLists.map((device) => {
776
- if (!device.remoteType && device.configRemoteType) {
777
- device.remoteType = device.configRemoteType
778
- this.warnLog(`API is displaying no remoteType: ${device.remoteType}, So using configRemoteType: ${device.configRemoteType}`)
779
- } else if (!device.remoteType && !device.configDeviceName) {
780
- this.errorLog('No remoteType or configRemoteType for device. No device will be created.')
781
- return null
782
- }
783
- return device
784
- }).filter(device => device !== null) // Filter out skipped devices
785
-
786
- // Apply remote-type templates from config entries with applyToAllDevicesOfType=true
787
- const devicesWithTemplates = applyDeviceTypeTemplates(
788
- devicesWithTypeAssigned,
789
- this.config.options.irdevices,
790
- 'remoteType',
791
- msg => this.debugLog(msg),
792
- )
793
-
794
- const allowConfigOnly = Boolean(this.config.options?.allowConfigOnlyDevices)
795
- const devices = mergeByDeviceId(this.config.options.irdevices ?? [], devicesWithTemplates ?? [], allowConfigOnly)
796
-
797
- // Apply global webhook option to IR devices that don't have their own webhook setting
798
- if (this.config.options?.webhook === true) {
799
- for (const device of devices) {
800
- if (device.webhook === undefined) {
801
- device.webhook = true
802
- this.debugLog(`Applying global webhook option to IR device: ${device.deviceName ?? device.deviceId}`)
803
- }
804
- }
805
- }
806
-
807
- this.debugLog(`IR Devices: ${JSON.stringify(devices)}`)
808
- for (const device of devices) {
809
- if (device.configDeviceName) {
810
- device.deviceName = device.configDeviceName
811
- }
812
- // Log effective webhook setting for diagnostics (IR devices)
813
- try {
814
- const effectiveWebhook = device.webhook !== undefined ? device.webhook : (this.config.options?.webhook === true ? true : undefined)
815
- this.debugLog(`Effective webhook for IR device ${device.deviceName ?? device.deviceId}: ${String(effectiveWebhook)}`)
816
- } catch (e: any) {
817
- this.debugLog(`Failed logging effective webhook for IR ${device.deviceName ?? device.deviceId}: ${e?.message ?? e}`)
818
- }
819
- await this.createIRDevice(device)
820
- }
821
- }
822
- }
823
-
824
- private async handleErrorResponse(apiStatusCode: number, retryCount: number, maxRetries: number, delayBetweenRetries: number) {
825
- await this.statusCode(apiStatusCode)
826
- if (apiStatusCode === 500) {
827
- this.infoLog(`statusCode: ${apiStatusCode} Attempt ${retryCount + 1} of ${maxRetries}`)
828
- await sleep(delayBetweenRetries)
829
- }
830
- }
831
-
832
- private async createDevice(device: device & devicesConfig) {
833
- const deviceTypeHandlers: { [key: string]: (device: device & devicesConfig) => Promise<void> } = {
834
- 'Humidifier': this.createHumidifier.bind(this),
835
- 'Humidifier2': this.createHumidifier.bind(this),
836
- 'Hub 2': this.createHub2.bind(this),
837
- 'Hub 3': this.createHub2.bind(this),
838
- 'Bot': this.createBot.bind(this),
839
- 'Relay Switch 1': this.createRelaySwitch.bind(this),
840
- 'Relay Switch 1PM': this.createRelaySwitch.bind(this),
841
- 'Meter': this.createMeter.bind(this),
842
- 'MeterPlus': this.createMeterPlus.bind(this),
843
- 'Meter Plus (JP)': this.createMeterPlus.bind(this),
844
- 'MeterPro': this.createMeterPro.bind(this),
845
- 'MeterPro(CO2)': this.createMeterPro.bind(this),
846
- 'WoIOSensor': this.createIOSensor.bind(this),
847
- 'Water Detector': this.createWaterDetector.bind(this),
848
- 'Motion Sensor': this.createMotion.bind(this),
849
- 'Contact Sensor': this.createContact.bind(this),
850
- 'Curtain': this.createCurtain.bind(this),
851
- 'Curtain3': this.createCurtain.bind(this),
852
- 'WoRollerShade': this.createCurtain.bind(this),
853
- 'Roller Shade': this.createCurtain.bind(this),
854
- 'Blind Tilt': this.createBlindTilt.bind(this),
855
- 'Plug': this.createPlug.bind(this),
856
- 'Plug Mini (US)': this.createPlug.bind(this),
857
- 'Plug Mini (JP)': this.createPlug.bind(this),
858
- 'Smart Lock': this.createLock.bind(this),
859
- 'Smart Lock Pro': this.createLock.bind(this),
860
- 'Smart Lock Ultra': this.createLock.bind(this),
861
- 'Color Bulb': this.createColorBulb.bind(this),
862
- 'K10+': this.createRobotVacuumCleaner.bind(this),
863
- 'K10+ Pro': this.createRobotVacuumCleaner.bind(this),
864
- 'WoSweeper': this.createRobotVacuumCleaner.bind(this),
865
- 'WoSweeperMini': this.createRobotVacuumCleaner.bind(this),
866
- 'Robot Vacuum Cleaner S1': this.createRobotVacuumCleaner.bind(this),
867
- 'Robot Vacuum Cleaner S1 Plus': this.createRobotVacuumCleaner.bind(this),
868
- 'Robot Vacuum Cleaner S10': this.createRobotVacuumCleaner.bind(this),
869
- 'Ceiling Light': this.createCeilingLight.bind(this),
870
- 'Ceiling Light Pro': this.createCeilingLight.bind(this),
871
- 'Strip Light': this.createStripLight.bind(this),
872
- 'Battery Circulator Fan': this.createFan.bind(this),
873
- 'Air Purifier PM2.5': this.createAirPurifier.bind(this),
874
- 'Air Purifier Table PM2.5': this.createAirPurifier.bind(this),
875
- 'Air Purifier VOC': this.createAirPurifier.bind(this),
876
- 'Air Purifier Table VOC': this.createAirPurifier.bind(this),
877
- }
878
-
879
- if (deviceTypeHandlers[device.deviceType!]) {
880
- this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`)
881
- await deviceTypeHandlers[device.deviceType!](device)
882
- } else if (['Hub Mini', 'Hub Plus', 'Remote', 'Indoor Cam', 'remote with screen'].includes(device.deviceType!)) {
883
- this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}, is currently not supported, device: ${JSON.stringify(device)}`)
884
- } else {
885
- this.warnLog(`Device: ${device.deviceName} with Device Type: ${device.deviceType}, is currently not supported. Submit Feature Requests Here: https://tinyurl.com/SwitchBotFeatureRequest, device: ${JSON.stringify(device)}`)
886
- }
887
- }
888
-
889
- private async createIRDevice(device: irdevice & irDevicesConfig) {
890
- device.connectionType = device.connectionType ?? 'OpenAPI'
891
- const deviceTypeHandlers: { [key: string]: (device: irdevice & irDevicesConfig) => Promise<void> } = {
892
- 'TV': this.createTV.bind(this),
893
- 'DIY TV': this.createTV.bind(this),
894
- 'Projector': this.createTV.bind(this),
895
- 'DIY Projector': this.createTV.bind(this),
896
- 'Set Top Box': this.createTV.bind(this),
897
- 'DIY Set Top Box': this.createTV.bind(this),
898
- 'IPTV': this.createTV.bind(this),
899
- 'DIY IPTV': this.createTV.bind(this),
900
- 'DVD': this.createTV.bind(this),
901
- 'DIY DVD': this.createTV.bind(this),
902
- 'Speaker': this.createTV.bind(this),
903
- 'DIY Speaker': this.createTV.bind(this),
904
- 'Fan': this.createIRFan.bind(this),
905
- 'DIY Fan': this.createIRFan.bind(this),
906
- 'Air Conditioner': this.createAirConditioner.bind(this),
907
- 'DIY Air Conditioner': this.createAirConditioner.bind(this),
908
- 'Light': this.createLight.bind(this),
909
- 'DIY Light': this.createLight.bind(this),
910
- 'Air Purifier': this.createAirPurifierIR.bind(this),
911
- 'DIY Air Purifier': this.createAirPurifierIR.bind(this),
912
- 'Water Heater': this.createWaterHeater.bind(this),
913
- 'DIY Water Heater': this.createWaterHeater.bind(this),
914
- 'Vacuum Cleaner': this.createVacuumCleaner.bind(this),
915
- 'DIY Vacuum Cleaner': this.createVacuumCleaner.bind(this),
916
- 'Camera': this.createCamera.bind(this),
917
- 'DIY Camera': this.createCamera.bind(this),
918
- 'Others': this.createOthers.bind(this),
919
- }
920
-
921
- if (deviceTypeHandlers[device.remoteType!]) {
922
- this.debugLog(`Discovered ${device.remoteType}: ${device.deviceId}`)
923
- if (device.remoteType.startsWith('DIY') && device.external === undefined) {
924
- device.external = true
925
- }
926
- await deviceTypeHandlers[device.remoteType!](device)
927
- } else {
928
- this.warnLog(`Device: ${device.deviceName} with Device Type: ${device.remoteType}, is currently not supported. Submit Feature Requests Here: https://tinyurl.com/SwitchBotFeatureRequest, device: ${JSON.stringify(device)}`)
929
- }
930
- }
931
-
932
- private async createHumidifier(device: device & devicesConfig) {
933
- const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`)
934
-
935
- // see if an accessory with the same uuid has already been registered and restored from
936
- // the cached devices we stored in the `configureAccessory` method above
937
- const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid)
938
-
939
- if (existingAccessory) {
940
- // the accessory already exists
941
- if (await this.registerDevice(device)) {
942
- // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
943
- existingAccessory.context.device = device
944
- existingAccessory.context.deviceId = device.deviceId
945
- existingAccessory.context.deviceType = device.deviceType
946
- existingAccessory.context.model = device.deviceType === 'Humidifier2' ? SwitchBotModel.Humidifier2 : SwitchBotModel.Humidifier
947
- existingAccessory.displayName = device.configDeviceName
948
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
949
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
950
- existingAccessory.context.connectionType = await this.connectionType(device)
951
- existingAccessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
952
- this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} deviceId: ${device.deviceId}`)
953
- this.api.updatePlatformAccessories([existingAccessory])
954
- // create the accessory handler for the restored accessory
955
- // this is imported from `platformAccessory.ts`
956
- new Humidifier(this, existingAccessory, device)
957
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${existingAccessory.UUID})`)
958
- } else {
959
- this.unregisterPlatformAccessories(existingAccessory)
960
- }
961
- } else if (await this.registerDevice(device)) {
962
- // create a new accessory
963
- const accessory = new this.api.platformAccessory(device.configDeviceName
964
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
965
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName), uuid)
966
-
967
- // store a copy of the device object in the `accessory.context`
968
- // the `context` property can be used to store any data about the accessory you may need
969
- accessory.context.device = device
970
- accessory.context.deviceId = device.deviceId
971
- accessory.context.deviceType = device.deviceType
972
- accessory.context.model = device.deviceType === 'Humidifier2' ? SwitchBotModel.Humidifier2 : SwitchBotModel.Humidifier
973
- accessory.displayName = device.configDeviceName
974
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
975
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
976
- accessory.context.connectionType = await this.connectionType(device)
977
- accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
978
- const newOrExternal = !device.external ? 'Adding new' : 'Loading external'
979
- this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`)
980
- // create the accessory handler for the newly create accessory
981
- // this is imported from `platformAccessory.ts`
982
- new Humidifier(this, accessory, device)
983
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${accessory.UUID})`)
984
-
985
- // publish device externally or link the accessory to your platform
986
- this.externalOrPlatform(device, accessory)
987
- this.accessories.push(accessory)
988
- } else {
989
- this.debugLog(`Device not registered: ${device.deviceName} ${device.deviceType} deviceId: ${device.deviceId}`)
990
- }
991
- }
992
-
993
- private async createBot(device: device & devicesConfig) {
994
- const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`)
995
-
996
- // see if an accessory with the same uuid has already been registered and restored from
997
- // the cached devices we stored in the `configureAccessory` method above
998
- const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid)
999
-
1000
- if (existingAccessory) {
1001
- // the accessory already exists
1002
- if (await this.registerDevice(device)) {
1003
- // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
1004
- existingAccessory.context.device = device
1005
- existingAccessory.context.deviceId = device.deviceId
1006
- existingAccessory.context.deviceType = device.deviceType
1007
- existingAccessory.context.model = SwitchBotModel.Bot
1008
- existingAccessory.displayName = device.configDeviceName
1009
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1010
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
1011
- existingAccessory.context.connectionType = await this.connectionType(device)
1012
- existingAccessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
1013
- this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} deviceId: ${device.deviceId}`)
1014
- this.api.updatePlatformAccessories([existingAccessory])
1015
- // create the accessory handler for the restored accessory
1016
- // this is imported from `platformAccessory.ts`
1017
- new Bot(this, existingAccessory, device)
1018
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${existingAccessory.UUID})`)
1019
- } else {
1020
- this.unregisterPlatformAccessories(existingAccessory)
1021
- }
1022
- } else if (await this.registerDevice(device)) {
1023
- // create a new accessory
1024
- const accessory = new this.api.platformAccessory(device.configDeviceName
1025
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1026
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName), uuid)
1027
-
1028
- // store a copy of the device object in the `accessory.context`
1029
- // the `context` property can be used to store any data about the accessory you may need
1030
- accessory.context.device = device
1031
- accessory.context.deviceId = device.deviceId
1032
- accessory.context.deviceType = device.deviceType
1033
- accessory.context.model = SwitchBotModel.Bot
1034
- accessory.displayName = device.configDeviceName
1035
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1036
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
1037
- accessory.context.connectionType = await this.connectionType(device)
1038
- accessory.context.connectionType = await this.connectionType(device)
1039
- accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
1040
- const newOrExternal = !device.external ? 'Adding new' : 'Loading external'
1041
- this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`)
1042
- // accessory.context.version = findaccessories.accessoryAttribute.softwareRevision;
1043
- // create the accessory handler for the newly create accessory
1044
- // this is imported from `platformAccessory.ts`
1045
- new Bot(this, accessory, device)
1046
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${accessory.UUID})`)
1047
-
1048
- // publish device externally or link the accessory to your platform
1049
- this.externalOrPlatform(device, accessory)
1050
- this.accessories.push(accessory)
1051
- } else {
1052
- this.debugLog(`Device not registered: ${device.deviceName} ${device.deviceType} deviceId: ${device.deviceId}`)
1053
- }
1054
- }
1055
-
1056
- private async createRelaySwitch(device: device & devicesConfig) {
1057
- const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`)
1058
-
1059
- // see if an accessory with the same uuid has already been registered and restored from
1060
- // the cached devices we stored in the `configureAccessory` method above
1061
- const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid)
1062
-
1063
- if (existingAccessory) {
1064
- // the accessory already exists
1065
- if (await this.registerDevice(device)) {
1066
- // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
1067
- existingAccessory.context.device = device
1068
- existingAccessory.context.deviceId = device.deviceId
1069
- existingAccessory.context.deviceType = device.deviceType
1070
- existingAccessory.context.model = device.deviceType === 'Relay Switch 1' ? SwitchBotModel.RelaySwitch1 : SwitchBotModel.RelaySwitch1PM
1071
- existingAccessory.displayName = device.configDeviceName
1072
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1073
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
1074
- existingAccessory.context.connectionType = await this.connectionType(device)
1075
- existingAccessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
1076
- this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} deviceId: ${device.deviceId}`)
1077
- this.api.updatePlatformAccessories([existingAccessory])
1078
- // create the accessory handler for the restored accessory
1079
- // this is imported from `platformAccessory.ts`
1080
- new RelaySwitch(this, existingAccessory, device)
1081
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${existingAccessory.UUID})`)
1082
- } else {
1083
- this.unregisterPlatformAccessories(existingAccessory)
1084
- }
1085
- } else if (await this.registerDevice(device)) {
1086
- // create a new accessory
1087
- const accessory = new this.api.platformAccessory(device.configDeviceName
1088
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1089
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName), uuid)
1090
-
1091
- // store a copy of the device object in the `accessory.context`
1092
- // the `context` property can be used to store any data about the accessory you may need
1093
- accessory.context.device = device
1094
- accessory.context.deviceId = device.deviceId
1095
- accessory.context.deviceType = device.deviceType
1096
- accessory.context.model = device.deviceType === 'Relay Switch 1' ? SwitchBotModel.RelaySwitch1 : SwitchBotModel.RelaySwitch1PM
1097
- accessory.displayName = device.configDeviceName
1098
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1099
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
1100
- accessory.context.connectionType = await this.connectionType(device)
1101
- accessory.context.connectionType = await this.connectionType(device)
1102
- accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
1103
- const newOrExternal = !device.external ? 'Adding new' : 'Loading external'
1104
- this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`)
1105
- // accessory.context.version = findaccessories.accessoryAttribute.softwareRevision;
1106
- // create the accessory handler for the newly create accessory
1107
- // this is imported from `platformAccessory.ts`
1108
- new RelaySwitch(this, accessory, device)
1109
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${accessory.UUID})`)
1110
-
1111
- // publish device externally or link the accessory to your platform
1112
- this.externalOrPlatform(device, accessory)
1113
- this.accessories.push(accessory)
1114
- } else {
1115
- this.debugLog(`Device not registered: ${device.deviceName} ${device.deviceType} deviceId: ${device.deviceId}`)
1116
- }
1117
- }
1118
-
1119
- private async createMeter(device: device & devicesConfig) {
1120
- const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`)
1121
-
1122
- // see if an accessory with the same uuid has already been registered and restored from
1123
- // the cached devices we stored in the `configureAccessory` method above
1124
- const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid)
1125
-
1126
- if (existingAccessory) {
1127
- // the accessory already exists
1128
- if (await this.registerDevice(device)) {
1129
- // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
1130
- existingAccessory.context.device = device
1131
- existingAccessory.context.model = SwitchBotModel.Meter
1132
- existingAccessory.context.deviceId = device.deviceId
1133
- existingAccessory.context.deviceType = device.deviceType
1134
- existingAccessory.displayName = device.configDeviceName
1135
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1136
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
1137
- existingAccessory.context.connectionType = await this.connectionType(device)
1138
- existingAccessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
1139
- this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} deviceId: ${device.deviceId}`)
1140
- this.api.updatePlatformAccessories([existingAccessory])
1141
- // create the accessory handler for the restored accessory
1142
- // this is imported from `platformAccessory.ts`
1143
- new Meter(this, existingAccessory, device)
1144
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${existingAccessory.UUID})`)
1145
- } else {
1146
- this.unregisterPlatformAccessories(existingAccessory)
1147
- }
1148
- } else if (await this.registerDevice(device)) {
1149
- // create a new accessory
1150
- const accessory = new this.api.platformAccessory(device.configDeviceName
1151
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1152
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName), uuid)
1153
-
1154
- // store a copy of the device object in the `accessory.context`
1155
- // the `context` property can be used to store any data about the accessory you may need
1156
- accessory.context.device = device
1157
- accessory.context.model = SwitchBotModel.Meter
1158
- accessory.context.deviceId = device.deviceId
1159
- accessory.context.deviceType = device.deviceType
1160
- accessory.displayName = device.configDeviceName
1161
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1162
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
1163
- accessory.context.connectionType = await this.connectionType(device)
1164
- accessory.context.connectionType = await this.connectionType(device)
1165
- accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
1166
- const newOrExternal = !device.external ? 'Adding new' : 'Loading external'
1167
- this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`)
1168
- // create the accessory handler for the newly create accessory
1169
- // this is imported from `platformAccessory.ts`
1170
- new Meter(this, accessory, device)
1171
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${accessory.UUID})`)
1172
-
1173
- // publish device externally or link the accessory to your platform
1174
- this.externalOrPlatform(device, accessory)
1175
- this.accessories.push(accessory)
1176
- } else {
1177
- this.debugLog(`Device not registered: ${device.deviceName} ${device.deviceType} deviceId: ${device.deviceId}`)
1178
- }
1179
- }
1180
-
1181
- private async createMeterPlus(device: device & devicesConfig) {
1182
- const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`)
1183
-
1184
- // see if an accessory with the same uuid has already been registered and restored from
1185
- // the cached devices we stored in the `configureAccessory` method above
1186
- const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid)
1187
-
1188
- if (existingAccessory) {
1189
- // the accessory already exists
1190
- if (await this.registerDevice(device)) {
1191
- // console.log("existingAccessory", existingAccessory);
1192
- // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
1193
- existingAccessory.context.device = device
1194
- existingAccessory.context.model = SwitchBotModel.MeterPlusUS ?? SwitchBotModel.MeterPlusJP
1195
- existingAccessory.context.deviceId = device.deviceId
1196
- existingAccessory.context.deviceType = device.deviceType
1197
- existingAccessory.displayName = device.configDeviceName
1198
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1199
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
1200
- existingAccessory.context.connectionType = await this.connectionType(device)
1201
- existingAccessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
1202
- this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} deviceId: ${device.deviceId}`)
1203
- this.api.updatePlatformAccessories([existingAccessory])
1204
- // create the accessory handler for the restored accessory
1205
- // this is imported from `platformAccessory.ts`
1206
- new MeterPlus(this, existingAccessory, device)
1207
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${existingAccessory.UUID})`)
1208
- } else {
1209
- this.unregisterPlatformAccessories(existingAccessory)
1210
- }
1211
- } else if (await this.registerDevice(device)) {
1212
- // create a new accessory
1213
- const accessory = new this.api.platformAccessory(device.configDeviceName
1214
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1215
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName), uuid)
1216
-
1217
- // store a copy of the device object in the `accessory.context`
1218
- // the `context` property can be used to store any data about the accessory you may need
1219
- accessory.context.device = device
1220
- accessory.context.model = SwitchBotModel.MeterPlusUS ?? SwitchBotModel.MeterPlusJP
1221
- accessory.context.deviceId = device.deviceId
1222
- accessory.context.deviceType = device.deviceType
1223
- accessory.displayName = device.configDeviceName
1224
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1225
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
1226
- accessory.context.connectionType = await this.connectionType(device)
1227
- accessory.context.connectionType = await this.connectionType(device)
1228
- accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
1229
- const newOrExternal = !device.external ? 'Adding new' : 'Loading external'
1230
- this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`)
1231
- // create the accessory handler for the newly create accessory
1232
- // this is imported from `platformAccessory.ts`
1233
- new MeterPlus(this, accessory, device)
1234
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${accessory.UUID})`)
1235
-
1236
- // publish device externally or link the accessory to your platform
1237
- this.externalOrPlatform(device, accessory)
1238
- this.accessories.push(accessory)
1239
- } else {
1240
- this.debugLog(`Device not registered: ${device.deviceName} ${device.deviceType} deviceId: ${device.deviceId}`)
1241
- }
1242
- }
1243
-
1244
- private async createMeterPro(device: device & devicesConfig) {
1245
- const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`)
1246
-
1247
- // see if an accessory with the same uuid has already been registered and restored from
1248
- // the cached devices we stored in the `configureAccessory` method above
1249
- const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid)
1250
-
1251
- if (existingAccessory) {
1252
- // the accessory already exists
1253
- if (await this.registerDevice(device)) {
1254
- // console.log("existingAccessory", existingAccessory);
1255
- // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
1256
- existingAccessory.context.device = device
1257
- existingAccessory.context.model = SwitchBotModel.MeterPro ?? SwitchBotModel.MeterProCO2
1258
- existingAccessory.context.deviceId = device.deviceId
1259
- existingAccessory.context.deviceType = device.deviceType
1260
- existingAccessory.displayName = device.configDeviceName
1261
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1262
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
1263
- existingAccessory.context.connectionType = await this.connectionType(device)
1264
- existingAccessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
1265
- this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} deviceId: ${device.deviceId}`)
1266
- this.api.updatePlatformAccessories([existingAccessory])
1267
- // create the accessory handler for the restored accessory
1268
- // this is imported from `platformAccessory.ts`
1269
- new MeterPro(this, existingAccessory, device)
1270
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${existingAccessory.UUID})`)
1271
- } else {
1272
- this.unregisterPlatformAccessories(existingAccessory)
1273
- }
1274
- } else if (await this.registerDevice(device)) {
1275
- // create a new accessory
1276
- const accessory = new this.api.platformAccessory(device.configDeviceName
1277
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1278
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName), uuid)
1279
-
1280
- // store a copy of the device object in the `accessory.context`
1281
- // the `context` property can be used to store any data about the accessory you may need
1282
- accessory.context.device = device
1283
- accessory.context.model = SwitchBotModel.MeterPro ?? SwitchBotModel.MeterProCO2
1284
- accessory.context.deviceId = device.deviceId
1285
- accessory.context.deviceType = device.deviceType
1286
- accessory.displayName = device.configDeviceName
1287
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1288
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
1289
- accessory.context.connectionType = await this.connectionType(device)
1290
- accessory.context.connectionType = await this.connectionType(device)
1291
- accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
1292
- const newOrExternal = !device.external ? 'Adding new' : 'Loading external'
1293
- this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`)
1294
- // create the accessory handler for the newly create accessory
1295
- // this is imported from `platformAccessory.ts`
1296
- new MeterPro(this, accessory, device)
1297
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${accessory.UUID})`)
1298
-
1299
- // publish device externally or link the accessory to your platform
1300
- this.externalOrPlatform(device, accessory)
1301
- this.accessories.push(accessory)
1302
- } else {
1303
- this.debugLog(`Device not registered: ${device.deviceName} ${device.deviceType} deviceId: ${device.deviceId}`)
1304
- }
1305
- }
1306
-
1307
- private async createHub2(device: device & devicesConfig) {
1308
- const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`)
1309
-
1310
- // see if an accessory with the same uuid has already been registered and restored from
1311
- // the cached devices we stored in the `configureAccessory` method above
1312
- const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid)
1313
-
1314
- if (existingAccessory) {
1315
- // the accessory already exists
1316
- if (await this.registerDevice(device)) {
1317
- // console.log("existingAccessory", existingAccessory);
1318
- // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
1319
- existingAccessory.context.device = device
1320
- existingAccessory.context.model = SwitchBotModel.Hub2
1321
- existingAccessory.context.deviceId = device.deviceId
1322
- existingAccessory.context.deviceType = device.deviceType
1323
- existingAccessory.displayName = device.configDeviceName
1324
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1325
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
1326
- existingAccessory.context.connectionType = await this.connectionType(device)
1327
- existingAccessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
1328
- this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} deviceId: ${device.deviceId}`)
1329
- this.api.updatePlatformAccessories([existingAccessory])
1330
- // create the accessory handler for the restored accessory
1331
- // this is imported from `platformAccessory.ts`
1332
- new Hub(this, existingAccessory, device)
1333
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${existingAccessory.UUID})`)
1334
- } else {
1335
- this.unregisterPlatformAccessories(existingAccessory)
1336
- }
1337
- } else if (await this.registerDevice(device)) {
1338
- // create a new accessory
1339
- const accessory = new this.api.platformAccessory(device.configDeviceName
1340
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1341
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName), uuid)
1342
-
1343
- // store a copy of the device object in the `accessory.context`
1344
- // the `context` property can be used to store any data about the accessory you may need
1345
- accessory.context.device = device
1346
- accessory.context.model = SwitchBotModel.Hub2
1347
- accessory.context.deviceId = device.deviceId
1348
- accessory.context.deviceType = device.deviceType
1349
- accessory.displayName = device.configDeviceName
1350
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1351
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
1352
- accessory.context.connectionType = await this.connectionType(device)
1353
- accessory.context.connectionType = await this.connectionType(device)
1354
- accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
1355
- const newOrExternal = !device.external ? 'Adding new' : 'Loading external'
1356
- this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`)
1357
- // create the accessory handler for the newly create accessory
1358
- // this is imported from `platformAccessory.ts`
1359
- new Hub(this, accessory, device)
1360
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${accessory.UUID})`)
1361
-
1362
- // publish device externally or link the accessory to your platform
1363
- this.externalOrPlatform(device, accessory)
1364
- this.accessories.push(accessory)
1365
- } else {
1366
- this.debugLog(`Device not registered: ${device.deviceName} ${device.deviceType} deviceId: ${device.deviceId}`)
1367
- }
1368
- }
1369
-
1370
- private async createIOSensor(device: device & devicesConfig) {
1371
- const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`)
1372
-
1373
- // see if an accessory with the same uuid has already been registered and restored from
1374
- // the cached devices we stored in the `configureAccessory` method above
1375
- const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid)
1376
-
1377
- if (existingAccessory) {
1378
- // the accessory already exists
1379
- if (await this.registerDevice(device)) {
1380
- // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
1381
- existingAccessory.context.device = device
1382
- existingAccessory.context.model = SwitchBotModel.OutdoorMeter
1383
- existingAccessory.context.deviceId = device.deviceId
1384
- existingAccessory.context.deviceType = device.deviceType
1385
- existingAccessory.displayName = device.configDeviceName
1386
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1387
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
1388
- existingAccessory.context.connectionType = await this.connectionType(device)
1389
- existingAccessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
1390
- this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} deviceId: ${device.deviceId}`)
1391
- this.api.updatePlatformAccessories([existingAccessory])
1392
- // create the accessory handler for the restored accessory
1393
- // this is imported from `platformAccessory.ts`
1394
- new IOSensor(this, existingAccessory, device)
1395
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${existingAccessory.UUID})`)
1396
- } else {
1397
- this.unregisterPlatformAccessories(existingAccessory)
1398
- }
1399
- } else if (await this.registerDevice(device)) {
1400
- // create a new accessory
1401
- const accessory = new this.api.platformAccessory(device.configDeviceName
1402
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1403
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName), uuid)
1404
-
1405
- // store a copy of the device object in the `accessory.context`
1406
- // the `context` property can be used to store any data about the accessory you may need
1407
- accessory.context.device = device
1408
- accessory.context.model = SwitchBotModel.OutdoorMeter
1409
- accessory.context.deviceId = device.deviceId
1410
- accessory.context.deviceType = device.deviceType
1411
- accessory.displayName = device.configDeviceName
1412
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1413
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
1414
- accessory.context.connectionType = await this.connectionType(device)
1415
- accessory.context.connectionType = await this.connectionType(device)
1416
- accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
1417
- const newOrExternal = !device.external ? 'Adding new' : 'Loading external'
1418
- this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`)
1419
- // create the accessory handler for the newly create accessory
1420
- // this is imported from `platformAccessory.ts`
1421
- new IOSensor(this, accessory, device)
1422
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${accessory.UUID})`)
1423
-
1424
- // publish device externally or link the accessory to your platform
1425
- this.externalOrPlatform(device, accessory)
1426
- this.accessories.push(accessory)
1427
- } else {
1428
- this.debugLog(`Device not registered: ${device.deviceName} ${device.deviceType} deviceId: ${device.deviceId}`)
1429
- }
1430
- }
1431
-
1432
- private async createWaterDetector(device: device & devicesConfig) {
1433
- const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`)
1434
-
1435
- // see if an accessory with the same uuid has already been registered and restored from
1436
- // the cached devices we stored in the `configureAccessory` method above
1437
- const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid)
1438
-
1439
- if (existingAccessory) {
1440
- // the accessory already exists
1441
- if (await this.registerDevice(device)) {
1442
- // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
1443
- existingAccessory.context.device = device
1444
- existingAccessory.context.deviceId = device.deviceId
1445
- existingAccessory.context.deviceType = device.deviceType
1446
- existingAccessory.context.model = SwitchBotModel.WaterDetector
1447
- existingAccessory.displayName = device.configDeviceName
1448
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1449
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
1450
- existingAccessory.context.connectionType = await this.connectionType(device)
1451
- existingAccessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
1452
- this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} deviceId: ${device.deviceId}`)
1453
- this.api.updatePlatformAccessories([existingAccessory])
1454
- // create the accessory handler for the restored accessory
1455
- // this is imported from `platformAccessory.ts`
1456
- new WaterDetector(this, existingAccessory, device)
1457
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${existingAccessory.UUID})`)
1458
- } else {
1459
- this.unregisterPlatformAccessories(existingAccessory)
1460
- }
1461
- } else if (await this.registerDevice(device)) {
1462
- // create a new accessory
1463
- const accessory = new this.api.platformAccessory(device.configDeviceName
1464
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1465
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName), uuid)
1466
-
1467
- // store a copy of the device object in the `accessory.context`
1468
- // the `context` property can be used to store any data about the accessory you may need
1469
- accessory.context.device = device
1470
- accessory.context.deviceId = device.deviceId
1471
- accessory.context.deviceType = device.deviceType
1472
- accessory.context.model = SwitchBotModel.WaterDetector
1473
- accessory.displayName = device.configDeviceName
1474
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1475
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
1476
- accessory.context.connectionType = await this.connectionType(device)
1477
- accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
1478
- accessory.context.connectionType = await this.connectionType(device)
1479
- const newOrExternal = !device.external ? 'Adding new' : 'Loading external'
1480
- this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`)
1481
- // create the accessory handler for the newly create accessory
1482
- // this is imported from `platformAccessory.ts`
1483
- new WaterDetector(this, accessory, device)
1484
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${accessory.UUID})`)
1485
-
1486
- // publish device externally or link the accessory to your platform
1487
- this.externalOrPlatform(device, accessory)
1488
- this.accessories.push(accessory)
1489
- } else {
1490
- this.debugLog(`Device not registered: ${device.deviceName} ${device.deviceType} deviceId: ${device.deviceId}`)
1491
- }
1492
- }
1493
-
1494
- private async createMotion(device: device & devicesConfig) {
1495
- const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`)
1496
-
1497
- // see if an accessory with the same uuid has already been registered and restored from
1498
- // the cached devices we stored in the `configureAccessory` method above
1499
- const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid)
1500
-
1501
- if (existingAccessory) {
1502
- // the accessory already exists
1503
- if (await this.registerDevice(device)) {
1504
- // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
1505
- existingAccessory.context.device = device
1506
- existingAccessory.context.deviceId = device.deviceId
1507
- existingAccessory.context.deviceType = device.deviceType
1508
- existingAccessory.context.model = SwitchBotModel.MotionSensor
1509
- existingAccessory.displayName = device.configDeviceName
1510
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1511
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
1512
- existingAccessory.context.connectionType = await this.connectionType(device)
1513
- existingAccessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
1514
- this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} deviceId: ${device.deviceId}`)
1515
- this.api.updatePlatformAccessories([existingAccessory])
1516
- // create the accessory handler for the restored accessory
1517
- // this is imported from `platformAccessory.ts`
1518
- new Motion(this, existingAccessory, device)
1519
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${existingAccessory.UUID})`)
1520
- } else {
1521
- this.unregisterPlatformAccessories(existingAccessory)
1522
- }
1523
- } else if (await this.registerDevice(device)) {
1524
- // create a new accessory
1525
- const accessory = new this.api.platformAccessory(device.configDeviceName
1526
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1527
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName), uuid)
1528
-
1529
- // store a copy of the device object in the `accessory.context`
1530
- // the `context` property can be used to store any data about the accessory you may need
1531
- accessory.context.device = device
1532
- accessory.context.deviceId = device.deviceId
1533
- accessory.context.deviceType = device.deviceType
1534
- accessory.context.model = SwitchBotModel.MotionSensor
1535
- accessory.displayName = device.configDeviceName
1536
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1537
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
1538
- accessory.context.connectionType = await this.connectionType(device)
1539
- accessory.context.connectionType = await this.connectionType(device)
1540
- accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
1541
- const newOrExternal = !device.external ? 'Adding new' : 'Loading external'
1542
- this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`)
1543
- // create the accessory handler for the newly create accessory
1544
- // this is imported from `platformAccessory.ts`
1545
- new Motion(this, accessory, device)
1546
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${accessory.UUID})`)
1547
-
1548
- // publish device externally or link the accessory to your platform
1549
- this.externalOrPlatform(device, accessory)
1550
- this.accessories.push(accessory)
1551
- } else {
1552
- this.debugLog(`Device not registered: ${device.deviceName} ${device.deviceType} deviceId: ${device.deviceId}`)
1553
- }
1554
- }
1555
-
1556
- private async createContact(device: device & devicesConfig) {
1557
- const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`)
1558
-
1559
- // see if an accessory with the same uuid has already been registered and restored from
1560
- // the cached devices we stored in the `configureAccessory` method above
1561
- const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid)
1562
-
1563
- if (existingAccessory) {
1564
- // the accessory already exists
1565
- if (await this.registerDevice(device)) {
1566
- // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
1567
- existingAccessory.context.device = device
1568
- existingAccessory.context.deviceId = device.deviceId
1569
- existingAccessory.context.deviceType = device.deviceType
1570
- existingAccessory.context.model = SwitchBotModel.ContactSensor
1571
- existingAccessory.displayName = device.configDeviceName
1572
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1573
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
1574
- existingAccessory.context.connectionType = await this.connectionType(device)
1575
- existingAccessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
1576
- this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} deviceId: ${device.deviceId}`)
1577
- this.api.updatePlatformAccessories([existingAccessory])
1578
- // create the accessory handler for the restored accessory
1579
- // this is imported from `platformAccessory.ts`
1580
- new Contact(this, existingAccessory, device)
1581
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${existingAccessory.UUID})`)
1582
- } else {
1583
- this.unregisterPlatformAccessories(existingAccessory)
1584
- }
1585
- } else if (await this.registerDevice(device)) {
1586
- // create a new accessory
1587
- const accessory = new this.api.platformAccessory(device.configDeviceName
1588
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1589
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName), uuid)
1590
-
1591
- // store a copy of the device object in the `accessory.context`
1592
- // the `context` property can be used to store any data about the accessory you may need
1593
- accessory.context.device = device
1594
- accessory.context.deviceId = device.deviceId
1595
- accessory.context.deviceType = device.deviceType
1596
- accessory.context.model = SwitchBotModel.ContactSensor
1597
- accessory.displayName = device.configDeviceName
1598
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1599
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
1600
- accessory.context.connectionType = await this.connectionType(device)
1601
- accessory.context.connectionType = await this.connectionType(device)
1602
- accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
1603
- const newOrExternal = !device.external ? 'Adding new' : 'Loading external'
1604
- this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`)
1605
- // create the accessory handler for the newly create accessory
1606
- // this is imported from `platformAccessory.ts`
1607
- new Contact(this, accessory, device)
1608
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${accessory.UUID})`)
1609
-
1610
- // publish device externally or link the accessory to your platform
1611
- this.externalOrPlatform(device, accessory)
1612
- this.accessories.push(accessory)
1613
- } else {
1614
- this.debugLog(`Device not registered: ${device.deviceName} ${device.deviceType} deviceId: ${device.deviceId}`)
1615
- }
1616
- }
1617
-
1618
- private async createBlindTilt(device: device & devicesConfig) {
1619
- const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`)
1620
-
1621
- // see if an accessory with the same uuid has already been registered and restored from
1622
- // the cached devices we stored in the `configureAccessory` method above
1623
- const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid)
1624
-
1625
- if (existingAccessory) {
1626
- // the accessory already exists
1627
- if (await this.registerDevice(device)) {
1628
- // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
1629
- existingAccessory.context.device = device
1630
- existingAccessory.context.deviceId = device.deviceId
1631
- existingAccessory.context.deviceType = device.deviceType
1632
- existingAccessory.context.model = SwitchBotModel.BlindTilt
1633
- existingAccessory.displayName = device.configDeviceName
1634
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1635
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
1636
- existingAccessory.context.connectionType = await this.connectionType(device)
1637
- existingAccessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
1638
- this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} deviceId: ${device.deviceId}`)
1639
- this.api.updatePlatformAccessories([existingAccessory])
1640
- // create the accessory handler for the restored accessory
1641
- // this is imported from `platformAccessory.ts`
1642
- new BlindTilt(this, existingAccessory, device as blindTiltConfig)
1643
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${existingAccessory.UUID})`)
1644
- } else {
1645
- this.unregisterPlatformAccessories(existingAccessory)
1646
- }
1647
- } else if (await this.registerDevice(device)) {
1648
- if (isBlindTiltDevice(device)) {
1649
- if (device.group && !(device as blindTiltConfig | curtainConfig).disable_group) {
1650
- this.debugLog(
1651
- 'Your Curtains are grouped, '
1652
- + `, Secondary curtain automatically hidden. Main Curtain: ${device.deviceName}, deviceId: ${device.deviceId}`,
1653
- )
1654
- } else {
1655
- if (device.master) {
1656
- this.warnLog(`Main Curtain: ${device.deviceName}, deviceId: ${device.deviceId}`)
1657
- } else {
1658
- this.errorLog(`Secondary Curtain: ${device.deviceName}, deviceId: ${device.deviceId}`)
1659
- }
1660
- }
1661
- }
1662
-
1663
- // create a new accessory
1664
- const accessory = new this.api.platformAccessory(device.configDeviceName
1665
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1666
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName), uuid)
1667
-
1668
- // store a copy of the device object in the `accessory.context`
1669
- // the `context` property can be used to store any data about the accessory you may need
1670
- accessory.context.device = device
1671
- accessory.context.deviceId = device.deviceId
1672
- accessory.context.deviceType = device.deviceType
1673
- accessory.context.model = SwitchBotModel.BlindTilt
1674
- accessory.displayName = device.configDeviceName
1675
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1676
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
1677
- accessory.context.connectionType = await this.connectionType(device)
1678
- accessory.context.connectionType = await this.connectionType(device)
1679
- accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
1680
- const newOrExternal = !device.external ? 'Adding new' : 'Loading external'
1681
- this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`)
1682
- // create the accessory handler for the newly create accessory
1683
- // this is imported from `platformAccessory.ts`
1684
- new BlindTilt(this, accessory, device as blindTiltConfig)
1685
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${accessory.UUID})`)
1686
-
1687
- // publish device externally or link the accessory to your platform
1688
- this.externalOrPlatform(device, accessory)
1689
- this.accessories.push(accessory)
1690
- } else {
1691
- this.debugLog(`Device not registered: ${device.deviceName} ${device.deviceType} deviceId: ${device.deviceId}`)
1692
- }
1693
- }
1694
-
1695
- private async createCurtain(device: device & devicesConfig) {
1696
- const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`)
1697
-
1698
- // see if an accessory with the same uuid has already been registered and restored from
1699
- // the cached devices we stored in the `configureAccessory` method above
1700
- const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid)
1701
-
1702
- if (existingAccessory) {
1703
- // the accessory already exists
1704
- if (await this.registerDevice(device)) {
1705
- // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
1706
- existingAccessory.context.device = device
1707
- existingAccessory.context.deviceId = device.deviceId
1708
- existingAccessory.context.deviceType = device.deviceType
1709
- existingAccessory.context.model = device.deviceType === 'Curtain3' ? SwitchBotModel.Curtain3 : SwitchBotModel.Curtain
1710
- existingAccessory.displayName = device.configDeviceName
1711
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1712
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
1713
- existingAccessory.context.connectionType = await this.connectionType(device)
1714
- existingAccessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
1715
- this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} deviceId: ${device.deviceId}`)
1716
- this.api.updatePlatformAccessories([existingAccessory])
1717
- // create the accessory handler for the restored accessory
1718
- // this is imported from `platformAccessory.ts`
1719
- new Curtain(this, existingAccessory, device as curtainConfig)
1720
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${existingAccessory.UUID})`)
1721
- } else {
1722
- this.unregisterPlatformAccessories(existingAccessory)
1723
- }
1724
- } else if (await this.registerDevice(device)) {
1725
- if (isCurtainDevice(device)) {
1726
- if (device.group && !(device as blindTiltConfig | curtainConfig).disable_group) {
1727
- this.debugLog(
1728
- 'Your Curtains are grouped, '
1729
- + `, Secondary curtain automatically hidden. Main Curtain: ${device.deviceName}, deviceId: ${device.deviceId}`,
1730
- )
1731
- } else {
1732
- if (device.master) {
1733
- this.warnLog(`Main Curtain: ${device.deviceName}, deviceId: ${device.deviceId}`)
1734
- } else {
1735
- this.errorLog(`Secondary Curtain: ${device.deviceName}, deviceId: ${device.deviceId}`)
1736
- }
1737
- }
1738
- }
1739
-
1740
- // create a new accessory
1741
- const accessory = new this.api.platformAccessory(device.configDeviceName
1742
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1743
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName), uuid)
1744
-
1745
- // store a copy of the device object in the `accessory.context`
1746
- // the `context` property can be used to store any data about the accessory you may need
1747
- accessory.context.device = device
1748
- accessory.context.deviceId = device.deviceId
1749
- accessory.context.deviceType = device.deviceType
1750
- accessory.context.model = device.deviceType === 'Curtain3' ? SwitchBotModel.Curtain3 : SwitchBotModel.Curtain
1751
- accessory.displayName = device.configDeviceName
1752
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1753
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
1754
- accessory.context.connectionType = await this.connectionType(device)
1755
- accessory.context.connectionType = await this.connectionType(device)
1756
- accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
1757
- const newOrExternal = !device.external ? 'Adding new' : 'Loading external'
1758
- this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`)
1759
- // create the accessory handler for the newly create accessory
1760
- // this is imported from `platformAccessory.ts`
1761
- new Curtain(this, accessory, device as curtainConfig)
1762
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${accessory.UUID})`)
1763
-
1764
- // publish device externally or link the accessory to your platform
1765
- this.externalOrPlatform(device, accessory)
1766
- this.accessories.push(accessory)
1767
- } else {
1768
- this.debugLog(`Device not registered: ${device.deviceName} ${device.deviceType} deviceId: ${device.deviceId}`)
1769
- }
1770
- }
1771
-
1772
- private async createPlug(device: device & devicesConfig) {
1773
- const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`)
1774
-
1775
- // see if an accessory with the same uuid has already been registered and restored from
1776
- // the cached devices we stored in the `configureAccessory` method above
1777
- const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid)
1778
-
1779
- if (existingAccessory) {
1780
- // the accessory already exists
1781
- if (await this.registerDevice(device)) {
1782
- // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
1783
- existingAccessory.context.device = device
1784
- existingAccessory.context.deviceId = device.deviceId
1785
- existingAccessory.context.deviceType = device.deviceType
1786
- existingAccessory.context.model = device.deviceType === 'Plug Mini (US)'
1787
- ? SwitchBotModel.PlugMiniUS
1788
- : device.deviceType === 'Plug Mini (JP)'
1789
- ? SwitchBotModel.PlugMiniJP
1790
- : SwitchBotModel.Plug
1791
- existingAccessory.displayName = device.configDeviceName
1792
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1793
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
1794
- existingAccessory.context.connectionType = await this.connectionType(device)
1795
- existingAccessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
1796
- this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} deviceId: ${device.deviceId}`)
1797
- this.api.updatePlatformAccessories([existingAccessory])
1798
- // create the accessory handler for the restored accessory
1799
- // this is imported from `platformAccessory.ts`
1800
- new Plug(this, existingAccessory, device)
1801
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${existingAccessory.UUID})`)
1802
- } else {
1803
- this.unregisterPlatformAccessories(existingAccessory)
1804
- }
1805
- } else if (await this.registerDevice(device)) {
1806
- // create a new accessory
1807
- const accessory = new this.api.platformAccessory(device.configDeviceName
1808
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1809
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName), uuid)
1810
-
1811
- // store a copy of the device object in the `accessory.context`
1812
- // the `context` property can be used to store any data about the accessory you may need
1813
- accessory.context.device = device
1814
- accessory.context.deviceId = device.deviceId
1815
- accessory.context.deviceType = device.deviceType
1816
- accessory.context.model = device.deviceType === 'Plug Mini (US)'
1817
- ? SwitchBotModel.PlugMiniUS
1818
- : device.deviceType === 'Plug Mini (JP)'
1819
- ? SwitchBotModel.PlugMiniJP
1820
- : SwitchBotModel.Plug
1821
- accessory.displayName = device.configDeviceName
1822
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1823
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
1824
- accessory.context.connectionType = await this.connectionType(device)
1825
- accessory.context.connectionType = await this.connectionType(device)
1826
- accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
1827
- const newOrExternal = !device.external ? 'Adding new' : 'Loading external'
1828
- this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`)
1829
- // create the accessory handler for the newly create accessory
1830
- // this is imported from `platformAccessory.ts`
1831
- new Plug(this, accessory, device)
1832
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${accessory.UUID})`)
1833
-
1834
- // publish device externally or link the accessory to your platform
1835
- this.externalOrPlatform(device, accessory)
1836
- this.accessories.push(accessory)
1837
- } else {
1838
- this.debugLog(`Device not registered: ${device.deviceName} ${device.deviceType} deviceId: ${device.deviceId}`)
1839
- }
1840
- }
1841
-
1842
- private async createLock(device: device & devicesConfig) {
1843
- const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`)
1844
-
1845
- // see if an accessory with the same uuid has already been registered and restored from
1846
- // the cached devices we stored in the `configureAccessory` method above
1847
- const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid)
1848
-
1849
- if (existingAccessory) {
1850
- // the accessory already exists
1851
- if (await this.registerDevice(device)) {
1852
- // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
1853
- existingAccessory.context.device = device
1854
- existingAccessory.context.deviceId = device.deviceId
1855
- existingAccessory.context.deviceType = device.deviceType
1856
- existingAccessory.context.model = (device.deviceType === 'Smart Lock Pro' || device.deviceType === 'Smart Lock Ultra') ? SwitchBotModel.LockPro : SwitchBotModel.Lock
1857
- existingAccessory.displayName = device.configDeviceName
1858
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1859
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
1860
- existingAccessory.context.connectionType = await this.connectionType(device)
1861
- existingAccessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
1862
- this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} deviceId: ${device.deviceId}`)
1863
- this.api.updatePlatformAccessories([existingAccessory])
1864
- // create the accessory handler for the restored accessory
1865
- // this is imported from `platformAccessory.ts`
1866
- new Lock(this, existingAccessory, device)
1867
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${existingAccessory.UUID})`)
1868
- } else {
1869
- this.unregisterPlatformAccessories(existingAccessory)
1870
- }
1871
- } else if (await this.registerDevice(device)) {
1872
- // create a new accessory
1873
- const accessory = new this.api.platformAccessory(device.configDeviceName
1874
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1875
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName), uuid)
1876
-
1877
- // store a copy of the device object in the `accessory.context`
1878
- // the `context` property can be used to store any data about the accessory you may need
1879
- accessory.context.device = device
1880
- accessory.context.deviceId = device.deviceId
1881
- accessory.context.deviceType = device.deviceType
1882
- accessory.context.model = (device.deviceType === 'Smart Lock Pro' || device.deviceType === 'Smart Lock Ultra') ? SwitchBotModel.LockPro : SwitchBotModel.Lock
1883
- accessory.displayName = device.configDeviceName
1884
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1885
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
1886
- accessory.context.connectionType = await this.connectionType(device)
1887
- accessory.context.connectionType = await this.connectionType(device)
1888
- accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
1889
- const newOrExternal = !device.external ? 'Adding new' : 'Loading external'
1890
- this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`)
1891
- // create the accessory handler for the newly create accessory
1892
- // this is imported from `platformAccessory.ts`
1893
- new Lock(this, accessory, device)
1894
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${accessory.UUID})`)
1895
-
1896
- // publish device externally or link the accessory to your platform
1897
- this.externalOrPlatform(device, accessory)
1898
- this.accessories.push(accessory)
1899
- } else {
1900
- this.debugLog(`Device not registered: ${device.deviceName} ${device.deviceType} deviceId: ${device.deviceId}`)
1901
- }
1902
- }
1903
-
1904
- private async createColorBulb(device: device & devicesConfig) {
1905
- const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`)
1906
-
1907
- // see if an accessory with the same uuid has already been registered and restored from
1908
- // the cached devices we stored in the `configureAccessory` method above
1909
- const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid)
1910
-
1911
- if (existingAccessory) {
1912
- // the accessory already exists
1913
- if (await this.registerDevice(device)) {
1914
- // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
1915
- existingAccessory.context.device = device
1916
- existingAccessory.context.deviceId = device.deviceId
1917
- existingAccessory.context.deviceType = device.deviceType
1918
- existingAccessory.context.model = SwitchBotModel.ColorBulb
1919
- existingAccessory.displayName = device.configDeviceName
1920
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1921
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
1922
- existingAccessory.context.connectionType = await this.connectionType(device)
1923
- existingAccessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
1924
- this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} deviceId: ${device.deviceId}`)
1925
- this.api.updatePlatformAccessories([existingAccessory])
1926
- // create the accessory handler for the restored accessory
1927
- // this is imported from `platformAccessory.ts`
1928
- new ColorBulb(this, existingAccessory, device)
1929
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${existingAccessory.UUID})`)
1930
- } else {
1931
- this.unregisterPlatformAccessories(existingAccessory)
1932
- }
1933
- } else if (await this.registerDevice(device)) {
1934
- // create a new accessory
1935
- const accessory = new this.api.platformAccessory(device.configDeviceName
1936
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1937
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName), uuid)
1938
-
1939
- // store a copy of the device object in the `accessory.context`
1940
- // the `context` property can be used to store any data about the accessory you may need
1941
- accessory.context.device = device
1942
- accessory.context.deviceId = device.deviceId
1943
- accessory.context.deviceType = device.deviceType
1944
- accessory.context.model = SwitchBotModel.ColorBulb
1945
- accessory.displayName = device.configDeviceName
1946
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1947
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
1948
- accessory.context.connectionType = await this.connectionType(device)
1949
- accessory.context.connectionType = await this.connectionType(device)
1950
- accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
1951
- const newOrExternal = !device.external ? 'Adding new' : 'Loading external'
1952
- this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`)
1953
- // create the accessory handler for the newly create accessory
1954
- // this is imported from `platformAccessory.ts`
1955
- new ColorBulb(this, accessory, device)
1956
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${accessory.UUID})`)
1957
-
1958
- // publish device externally or link the accessory to your platform
1959
- this.externalOrPlatform(device, accessory)
1960
- this.accessories.push(accessory)
1961
- } else {
1962
- this.debugLog(`Device not registered: ${device.deviceName} ${device.deviceType} deviceId: ${device.deviceId}`)
1963
- }
1964
- }
1965
-
1966
- private async createCeilingLight(device: device & devicesConfig) {
1967
- const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`)
1968
-
1969
- // see if an accessory with the same uuid has already been registered and restored from
1970
- // the cached devices we stored in the `configureAccessory` method above
1971
- const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid)
1972
-
1973
- if (existingAccessory) {
1974
- // the accessory already exists
1975
- if (await this.registerDevice(device)) {
1976
- // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
1977
- existingAccessory.context.device = device
1978
- existingAccessory.context.deviceId = device.deviceId
1979
- existingAccessory.context.deviceType = device.deviceType
1980
- existingAccessory.context.model = device.deviceType === 'Ceiling Light Pro' ? SwitchBotModel.CeilingLightPro : SwitchBotModel.CeilingLight
1981
- existingAccessory.displayName = device.configDeviceName
1982
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1983
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
1984
- existingAccessory.context.connectionType = await this.connectionType(device)
1985
- existingAccessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
1986
- this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} deviceId: ${device.deviceId}`)
1987
- this.api.updatePlatformAccessories([existingAccessory])
1988
- // create the accessory handler for the restored accessory
1989
- // this is imported from `platformAccessory.ts`
1990
- new CeilingLight(this, existingAccessory, device)
1991
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${existingAccessory.UUID})`)
1992
- } else {
1993
- this.unregisterPlatformAccessories(existingAccessory)
1994
- }
1995
- } else if (await this.registerDevice(device)) {
1996
- // create a new accessory
1997
- const accessory = new this.api.platformAccessory(device.configDeviceName
1998
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
1999
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName), uuid)
2000
-
2001
- // store a copy of the device object in the `accessory.context`
2002
- // the `context` property can be used to store any data about the accessory you may need
2003
- accessory.context.device = device
2004
- accessory.context.deviceId = device.deviceId
2005
- accessory.context.deviceType = device.deviceType
2006
- accessory.context.model = device.deviceType === 'Ceiling Light Pro' ? SwitchBotModel.CeilingLightPro : SwitchBotModel.CeilingLight
2007
- accessory.displayName = device.configDeviceName
2008
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2009
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
2010
- accessory.context.connectionType = await this.connectionType(device)
2011
- accessory.context.connectionType = await this.connectionType(device)
2012
- accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
2013
- const newOrExternal = !device.external ? 'Adding new' : 'Loading external'
2014
- this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`)
2015
- // create the accessory handler for the newly create accessory
2016
- // this is imported from `platformAccessory.ts`
2017
- new CeilingLight(this, accessory, device)
2018
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${accessory.UUID})`)
2019
-
2020
- // publish device externally or link the accessory to your platform
2021
- this.externalOrPlatform(device, accessory)
2022
- this.accessories.push(accessory)
2023
- } else {
2024
- this.debugLog(`Device not registered: ${device.deviceName} ${device.deviceType} deviceId: ${device.deviceId}`)
2025
- }
2026
- }
2027
-
2028
- private async createStripLight(device: device & devicesConfig) {
2029
- const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`)
2030
-
2031
- // see if an accessory with the same uuid has already been registered and restored from
2032
- // the cached devices we stored in the `configureAccessory` method above
2033
- const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid)
2034
-
2035
- if (existingAccessory) {
2036
- // the accessory already exists
2037
- if (await this.registerDevice(device)) {
2038
- // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
2039
- existingAccessory.context.device = device
2040
- existingAccessory.context.deviceId = device.deviceId
2041
- existingAccessory.context.deviceType = device.deviceType
2042
- existingAccessory.context.model = SwitchBotModel.StripLight
2043
- existingAccessory.displayName = device.configDeviceName
2044
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2045
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
2046
- existingAccessory.context.connectionType = await this.connectionType(device)
2047
- existingAccessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
2048
- this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} deviceId: ${device.deviceId}`)
2049
- this.api.updatePlatformAccessories([existingAccessory])
2050
- // create the accessory handler for the restored accessory
2051
- // this is imported from `platformAccessory.ts`
2052
- new StripLight(this, existingAccessory, device)
2053
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${existingAccessory.UUID})`)
2054
- } else {
2055
- this.unregisterPlatformAccessories(existingAccessory)
2056
- }
2057
- } else if (await this.registerDevice(device)) {
2058
- // create a new accessory
2059
- const accessory = new this.api.platformAccessory(device.configDeviceName
2060
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2061
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName), uuid)
2062
-
2063
- // store a copy of the device object in the `accessory.context`
2064
- // the `context` property can be used to store any data about the accessory you may need
2065
- accessory.context.device = device
2066
- accessory.context.deviceId = device.deviceId
2067
- accessory.context.deviceType = device.deviceType
2068
- accessory.context.model = SwitchBotModel.StripLight
2069
- accessory.displayName = device.configDeviceName
2070
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2071
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
2072
- accessory.context.connectionType = await this.connectionType(device)
2073
- accessory.context.connectionType = await this.connectionType(device)
2074
- accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
2075
- const newOrExternal = !device.external ? 'Adding new' : 'Loading external'
2076
- this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`)
2077
- // create the accessory handler for the newly create accessory
2078
- // this is imported from `platformAccessory.ts`
2079
- new StripLight(this, accessory, device)
2080
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${accessory.UUID})`)
2081
-
2082
- // publish device externally or link the accessory to your platform
2083
- this.externalOrPlatform(device, accessory)
2084
- this.accessories.push(accessory)
2085
- } else {
2086
- this.debugLog(`Device not registered: ${device.deviceName} ${device.deviceType} deviceId: ${device.deviceId}`)
2087
- }
2088
- }
2089
-
2090
- private async createFan(device: device & devicesConfig) {
2091
- const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`)
2092
-
2093
- // see if an accessory with the same uuid has already been registered and restored from
2094
- // the cached devices we stored in the `configureAccessory` method above
2095
- const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid)
2096
-
2097
- if (existingAccessory) {
2098
- // the accessory already exists
2099
- if (await this.registerDevice(device)) {
2100
- // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
2101
- existingAccessory.context.device = device
2102
- existingAccessory.context.deviceId = device.deviceId
2103
- existingAccessory.context.deviceType = device.deviceType
2104
- existingAccessory.context.model = SwitchBotModel.BatteryCirculatorFan
2105
- existingAccessory.displayName = device.configDeviceName
2106
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2107
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
2108
- existingAccessory.context.connectionType = await this.connectionType(device)
2109
- existingAccessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
2110
- this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} deviceId: ${device.deviceId}`)
2111
- this.api.updatePlatformAccessories([existingAccessory])
2112
- // create the accessory handler for the restored accessory
2113
- // this is imported from `platformAccessory.ts`
2114
- new Fan(this, existingAccessory, device)
2115
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${existingAccessory.UUID})`)
2116
- } else {
2117
- this.unregisterPlatformAccessories(existingAccessory)
2118
- }
2119
- } else if (await this.registerDevice(device)) {
2120
- // create a new accessory
2121
- const accessory = new this.api.platformAccessory(device.configDeviceName
2122
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2123
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName), uuid)
2124
-
2125
- // store a copy of the device object in the `accessory.context`
2126
- // the `context` property can be used to store any data about the accessory you may need
2127
- accessory.context.device = device
2128
- accessory.context.deviceId = device.deviceId
2129
- accessory.context.deviceType = device.deviceType
2130
- accessory.context.model = SwitchBotModel.BatteryCirculatorFan
2131
- accessory.displayName = device.configDeviceName
2132
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2133
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
2134
- accessory.context.connectionType = await this.connectionType(device)
2135
- accessory.context.connectionType = await this.connectionType(device)
2136
- accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
2137
- const newOrExternal = !device.external ? 'Adding new' : 'Loading external'
2138
- this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`)
2139
- // create the accessory handler for the newly create accessory
2140
- // this is imported from `platformAccessory.ts`
2141
- new Fan(this, accessory, device)
2142
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${accessory.UUID})`)
2143
-
2144
- // publish device externally or link the accessory to your platform
2145
- this.externalOrPlatform(device, accessory)
2146
- this.accessories.push(accessory)
2147
- } else {
2148
- this.debugLog(`Device not registered: ${device.deviceName} ${device.deviceType} deviceId: ${device.deviceId}`)
2149
- }
2150
- }
2151
-
2152
- private async createAirPurifier(device: device & devicesConfig) {
2153
- const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`)
2154
-
2155
- // see if an accessory with the same uuid has already been registered and restored from
2156
- // the cached devices we stored in the `configureAccessory` method above
2157
- const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid)
2158
-
2159
- if (existingAccessory) {
2160
- // the accessory already exists
2161
- if (await this.registerDevice(device)) {
2162
- // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
2163
- existingAccessory.context.device = device
2164
- existingAccessory.context.deviceId = device.deviceId
2165
- existingAccessory.context.deviceType = device.deviceType
2166
- existingAccessory.context.model = SwitchBotModel.BatteryCirculatorFan
2167
- existingAccessory.displayName = device.configDeviceName
2168
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2169
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
2170
- existingAccessory.context.connectionType = await this.connectionType(device)
2171
- existingAccessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
2172
- this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} deviceId: ${device.deviceId}`)
2173
- this.api.updatePlatformAccessories([existingAccessory])
2174
- // create the accessory handler for the restored accessory
2175
- // this is imported from `platformAccessory.ts`
2176
- new AirPurifier(this, existingAccessory, device)
2177
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${existingAccessory.UUID})`)
2178
- } else {
2179
- this.unregisterPlatformAccessories(existingAccessory)
2180
- }
2181
- } else if (await this.registerDevice(device)) {
2182
- // create a new accessory
2183
- const accessory = new this.api.platformAccessory(device.configDeviceName
2184
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2185
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName), uuid)
2186
-
2187
- // store a copy of the device object in the `accessory.context`
2188
- // the `context` property can be used to store any data about the accessory you may need
2189
- accessory.context.device = device
2190
- accessory.context.deviceId = device.deviceId
2191
- accessory.context.deviceType = device.deviceType
2192
- accessory.context.model = SwitchBotModel.BatteryCirculatorFan
2193
- accessory.displayName = device.configDeviceName
2194
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2195
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
2196
- accessory.context.connectionType = await this.connectionType(device)
2197
- accessory.context.connectionType = await this.connectionType(device)
2198
- accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
2199
- const newOrExternal = !device.external ? 'Adding new' : 'Loading external'
2200
- this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`)
2201
- // create the accessory handler for the newly create accessory
2202
- // this is imported from `platformAccessory.ts`
2203
- new AirPurifier(this, accessory, device)
2204
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${accessory.UUID})`)
2205
-
2206
- // publish device externally or link the accessory to your platform
2207
- this.externalOrPlatform(device, accessory)
2208
- this.accessories.push(accessory)
2209
- } else {
2210
- this.debugLog(`Device not registered: ${device.deviceName} ${device.deviceType} deviceId: ${device.deviceId}`)
2211
- }
2212
- }
2213
-
2214
- private async createRobotVacuumCleaner(device: device & devicesConfig) {
2215
- const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`)
2216
-
2217
- // see if an accessory with the same uuid has already been registered and restored from
2218
- // the cached devices we stored in the `configureAccessory` method above
2219
- const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid)
2220
-
2221
- if (existingAccessory) {
2222
- // the accessory already exists
2223
- if (await this.registerDevice(device)) {
2224
- // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
2225
- existingAccessory.context.device = device
2226
- existingAccessory.context.deviceId = device.deviceId
2227
- existingAccessory.context.deviceType = device.deviceType
2228
- existingAccessory.context.model = device.deviceType === 'Robot Vacuum Cleaner S1'
2229
- ? SwitchBotModel.RobotVacuumCleanerS1
2230
- : device.deviceType === 'Robot Vacuum Cleaner S1 Plus'
2231
- ? SwitchBotModel.RobotVacuumCleanerS1Plus
2232
- : device.deviceType === 'Robot Vacuum Cleaner S10'
2233
- ? SwitchBotModel.RobotVacuumCleanerS10
2234
- : device.deviceType === 'WoSweeper'
2235
- ? SwitchBotModel.WoSweeper
2236
- : device.deviceType === 'WoSweeperMini'
2237
- ? SwitchBotModel.WoSweeperMini
2238
- : SwitchBotModel.Unknown
2239
- existingAccessory.displayName = device.configDeviceName
2240
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2241
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
2242
- existingAccessory.context.connectionType = await this.connectionType(device)
2243
- existingAccessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
2244
- this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} deviceId: ${device.deviceId}`)
2245
- this.api.updatePlatformAccessories([existingAccessory])
2246
- // create the accessory handler for the restored accessory
2247
- // this is imported from `platformAccessory.ts`
2248
- new RobotVacuumCleaner(this, existingAccessory, device)
2249
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${existingAccessory.UUID})`)
2250
- } else {
2251
- this.unregisterPlatformAccessories(existingAccessory)
2252
- }
2253
- } else if (await this.registerDevice(device)) {
2254
- // create a new accessory
2255
- const accessory = new this.api.platformAccessory(device.configDeviceName
2256
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2257
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName), uuid)
2258
-
2259
- // store a copy of the device object in the `accessory.context`
2260
- // the `context` property can be used to store any data about the accessory you may need
2261
- accessory.context.device = device
2262
- accessory.context.deviceId = device.deviceId
2263
- accessory.context.deviceType = device.deviceType
2264
- accessory.context.model = device.deviceType === 'Robot Vacuum Cleaner S1'
2265
- ? SwitchBotModel.RobotVacuumCleanerS1
2266
- : device.deviceType === 'Robot Vacuum Cleaner S1 Plus'
2267
- ? SwitchBotModel.RobotVacuumCleanerS1Plus
2268
- : device.deviceType === 'Robot Vacuum Cleaner S10'
2269
- ? SwitchBotModel.RobotVacuumCleanerS10
2270
- : device.deviceType === 'WoSweeper'
2271
- ? SwitchBotModel.WoSweeper
2272
- : device.deviceType === 'WoSweeperMini'
2273
- ? SwitchBotModel.WoSweeperMini
2274
- : SwitchBotModel.Unknown
2275
- accessory.displayName = device.configDeviceName
2276
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2277
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
2278
- accessory.context.connectionType = await this.connectionType(device)
2279
- accessory.context.connectionType = await this.connectionType(device)
2280
- accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
2281
- const newOrExternal = !device.external ? 'Adding new' : 'Loading external'
2282
- this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`)
2283
- // create the accessory handler for the newly create accessory
2284
- // this is imported from `platformAccessory.ts`
2285
- new RobotVacuumCleaner(this, accessory, device)
2286
- this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${accessory.UUID})`)
2287
-
2288
- // publish device externally or link the accessory to your platform
2289
- this.externalOrPlatform(device, accessory)
2290
- this.accessories.push(accessory)
2291
- } else {
2292
- this.debugLog(`Device not registered: ${device.deviceName} ${device.deviceType} deviceId: ${device.deviceId}`)
2293
- }
2294
- }
2295
-
2296
- private async createTV(device: irdevice & irDevicesConfig) {
2297
- const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`)
2298
-
2299
- // see if an accessory with the same uuid has already been registered and restored from
2300
- // the cached devices we stored in the `configureAccessory` method above
2301
- const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid)
2302
-
2303
- if (!device.hide_device && existingAccessory) {
2304
- // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
2305
- existingAccessory.context.device = device
2306
- existingAccessory.context.deviceId = device.deviceId
2307
- existingAccessory.context.deviceType = `IR: ${device.remoteType}`
2308
- existingAccessory.context.model = device.remoteType
2309
- existingAccessory.displayName = device.configDeviceName
2310
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2311
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
2312
- this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} deviceId: ${device.deviceId}`)
2313
- existingAccessory.context.connectionType = device.connectionType
2314
- this.api.updatePlatformAccessories([existingAccessory])
2315
- // create the accessory handler for the restored accessory
2316
- // this is imported from `platformAccessory.ts`
2317
- new TV(this, existingAccessory, device)
2318
- this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${existingAccessory.UUID})`)
2319
- } else if (!device.hide_device && device.hubDeviceId) {
2320
- // create a new accessory
2321
- const accessory = new this.api.platformAccessory(device.configDeviceName
2322
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2323
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName), uuid)
2324
-
2325
- // store a copy of the device object in the `accessory.context`
2326
- // the `context` property can be used to store any data about the accessory you may need
2327
- accessory.context.device = device
2328
- accessory.context.deviceId = device.deviceId
2329
- accessory.context.deviceType = `IR: ${device.remoteType}`
2330
- accessory.context.model = device.remoteType
2331
- accessory.displayName = device.configDeviceName
2332
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2333
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
2334
- accessory.context.connectionType = await this.connectionType(device)
2335
- accessory.context.version = device.firmware ?? this.version ?? '0.0.0'
2336
- const newOrExternal = !device.external ? 'Adding new' : 'Loading external'
2337
- this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`)
2338
- // create the accessory handler for the newly create accessory
2339
- // this is imported from `platformAccessory.ts`
2340
- new TV(this, accessory, device)
2341
- this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`)
2342
-
2343
- this.externalOrPlatform(device, accessory)
2344
- this.accessories.push(accessory)
2345
- } else {
2346
- this.debugLog(`Device not registered: ${device.deviceName} ${device.remoteType} deviceId: ${device.deviceId}`)
2347
- }
2348
- }
2349
-
2350
- private async createIRFan(device: irdevice & irDevicesConfig) {
2351
- const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`)
2352
-
2353
- // see if an accessory with the same uuid has already been registered and restored from
2354
- // the cached devices we stored in the `configureAccessory` method above
2355
- const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid)
2356
-
2357
- if (existingAccessory) {
2358
- // the accessory already exists
2359
- if (!device.hide_device && device.hubDeviceId) {
2360
- // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
2361
- existingAccessory.context.device = device
2362
- existingAccessory.context.deviceId = device.deviceId
2363
- existingAccessory.context.deviceType = `IR: ${device.remoteType}`
2364
- existingAccessory.context.model = device.remoteType
2365
- existingAccessory.displayName = device.configDeviceName
2366
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2367
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
2368
- this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} deviceId: ${device.deviceId}`)
2369
- existingAccessory.context.connectionType = device.connectionType
2370
- this.api.updatePlatformAccessories([existingAccessory])
2371
- // create the accessory handler for the restored accessory
2372
- // this is imported from `platformAccessory.ts`
2373
- new IRFan(this, existingAccessory, device)
2374
- this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${existingAccessory.UUID})`)
2375
- } else {
2376
- this.unregisterPlatformAccessories(existingAccessory)
2377
- }
2378
- } else if (!device.hide_device && device.hubDeviceId) {
2379
- // create a new accessory
2380
- const accessory = new this.api.platformAccessory(device.configDeviceName
2381
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2382
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName), uuid)
2383
-
2384
- // store a copy of the device object in the `accessory.context`
2385
- // the `context` property can be used to store any data about the accessory you may need
2386
- accessory.context.device = device
2387
- accessory.context.deviceId = device.deviceId
2388
- accessory.context.deviceType = `IR: ${device.remoteType}`
2389
- accessory.context.model = device.remoteType
2390
- accessory.displayName = device.configDeviceName
2391
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2392
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
2393
- accessory.context.connectionType = await this.connectionType(device)
2394
- accessory.context.version = device.firmware ?? this.version ?? '0.0.0'
2395
- const newOrExternal = !device.external ? 'Adding new' : 'Loading external'
2396
- this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`)
2397
- // create the accessory handler for the newly create accessory
2398
- // this is imported from `platformAccessory.ts`
2399
- new IRFan(this, accessory, device)
2400
- this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`)
2401
-
2402
- // publish device externally or link the accessory to your platform
2403
- this.externalOrPlatform(device, accessory)
2404
- this.accessories.push(accessory)
2405
- } else {
2406
- this.debugLog(`Device not registered: ${device.deviceName} ${device.remoteType} deviceId: ${device.deviceId}`)
2407
- }
2408
- }
2409
-
2410
- private async createLight(device: irdevice & irDevicesConfig) {
2411
- const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`)
2412
-
2413
- // see if an accessory with the same uuid has already been registered and restored from
2414
- // the cached devices we stored in the `configureAccessory` method above
2415
- const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid)
2416
-
2417
- if (existingAccessory) {
2418
- // the accessory already exists
2419
- if (!device.hide_device && device.hubDeviceId) {
2420
- // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
2421
- existingAccessory.context.device = device
2422
- existingAccessory.context.deviceId = device.deviceId
2423
- existingAccessory.context.deviceType = `IR: ${device.remoteType}`
2424
- existingAccessory.context.model = device.remoteType
2425
- existingAccessory.displayName = device.configDeviceName
2426
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2427
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
2428
- this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} deviceId: ${device.deviceId}`)
2429
- existingAccessory.context.connectionType = device.connectionType
2430
- this.api.updatePlatformAccessories([existingAccessory])
2431
- // create the accessory handler for the restored accessory
2432
- // this is imported from `platformAccessory.ts`
2433
- new Light(this, existingAccessory, device)
2434
- this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${existingAccessory.UUID})`)
2435
- } else {
2436
- this.unregisterPlatformAccessories(existingAccessory)
2437
- }
2438
- } else if (!device.hide_device && device.hubDeviceId) {
2439
- // create a new accessory
2440
- const accessory = new this.api.platformAccessory(device.configDeviceName
2441
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2442
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName), uuid)
2443
-
2444
- // store a copy of the device object in the `accessory.context`
2445
- // the `context` property can be used to store any data about the accessory you may need
2446
- accessory.context.device = device
2447
- accessory.context.deviceId = device.deviceId
2448
- accessory.context.deviceType = `IR: ${device.remoteType}`
2449
- accessory.context.model = device.remoteType
2450
- accessory.displayName = device.configDeviceName
2451
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2452
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
2453
- accessory.context.connectionType = await this.connectionType(device)
2454
- accessory.context.version = device.firmware ?? this.version ?? '0.0.0'
2455
- const newOrExternal = !device.external ? 'Adding new' : 'Loading external'
2456
- this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`)
2457
- // create the accessory handler for the newly create accessory
2458
- // this is imported from `platformAccessory.ts`
2459
- new Light(this, accessory, device)
2460
- this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`)
2461
-
2462
- // publish device externally or link the accessory to your platform
2463
- this.externalOrPlatform(device, accessory)
2464
- this.accessories.push(accessory)
2465
- } else {
2466
- this.debugLog(`Device not registered: ${device.deviceName} ${device.remoteType} deviceId: ${device.deviceId}`)
2467
- }
2468
- }
2469
-
2470
- private async createAirConditioner(device: irdevice & irDevicesConfig) {
2471
- const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`)
2472
-
2473
- // see if an accessory with the same uuid has already been registered and restored from
2474
- // the cached devices we stored in the `configureAccessory` method above
2475
- const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid)
2476
-
2477
- if (existingAccessory) {
2478
- // the accessory already exists
2479
- if (!device.hide_device && device.hubDeviceId) {
2480
- // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
2481
- existingAccessory.context.device = device
2482
- existingAccessory.context.deviceId = device.deviceId
2483
- existingAccessory.context.deviceType = `IR: ${device.remoteType}`
2484
- existingAccessory.context.model = device.remoteType
2485
- existingAccessory.displayName = device.configDeviceName
2486
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2487
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
2488
- this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} deviceId: ${device.deviceId}`)
2489
- existingAccessory.context.connectionType = device.connectionType
2490
- this.api.updatePlatformAccessories([existingAccessory])
2491
- // create the accessory handler for the restored accessory
2492
- // this is imported from `platformAccessory.ts`
2493
- new AirConditioner(this, existingAccessory, device)
2494
- this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${existingAccessory.UUID})`)
2495
- } else {
2496
- this.unregisterPlatformAccessories(existingAccessory)
2497
- }
2498
- } else if (!device.hide_device && device.hubDeviceId) {
2499
- // create a new accessory
2500
- const accessory = new this.api.platformAccessory(device.configDeviceName
2501
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2502
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName), uuid)
2503
-
2504
- // store a copy of the device object in the `accessory.context`
2505
- // the `context` property can be used to store any data about the accessory you may need
2506
- accessory.context.device = device
2507
- accessory.context.deviceId = device.deviceId
2508
- accessory.context.deviceType = `IR: ${device.remoteType}`
2509
- accessory.context.model = device.remoteType
2510
- accessory.displayName = device.configDeviceName
2511
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2512
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
2513
- accessory.context.connectionType = await this.connectionType(device)
2514
- accessory.context.version = device.firmware ?? this.version ?? '0.0.0'
2515
- const newOrExternal = !device.external ? 'Adding new' : 'Loading external'
2516
- this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`)
2517
- // create the accessory handler for the newly create accessory
2518
- // this is imported from `platformAccessory.ts`
2519
- new AirConditioner(this, accessory, device)
2520
- this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`)
2521
-
2522
- // publish device externally or link the accessory to your platform
2523
- this.externalOrPlatform(device, accessory)
2524
- this.accessories.push(accessory)
2525
- } else {
2526
- this.debugLog(`Device not registered: ${device.deviceName} ${device.remoteType} deviceId: ${device.deviceId}`)
2527
- }
2528
- }
2529
-
2530
- private async createAirPurifierIR(device: irdevice & irDevicesConfig) {
2531
- const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`)
2532
-
2533
- // see if an accessory with the same uuid has already been registered and restored from
2534
- // the cached devices we stored in the `configureAccessory` method above
2535
- const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid)
2536
-
2537
- if (existingAccessory) {
2538
- // the accessory already exists
2539
- if (!device.hide_device && device.hubDeviceId) {
2540
- // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
2541
- existingAccessory.context.device = device
2542
- existingAccessory.context.deviceId = device.deviceId
2543
- existingAccessory.context.deviceType = `IR: ${device.remoteType}`
2544
- existingAccessory.context.model = device.remoteType
2545
- existingAccessory.displayName = device.configDeviceName
2546
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2547
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
2548
- this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} deviceId: ${device.deviceId}`)
2549
- existingAccessory.context.connectionType = device.connectionType
2550
- this.api.updatePlatformAccessories([existingAccessory])
2551
- // create the accessory handler for the restored accessory
2552
- // this is imported from `platformAccessory.ts`
2553
- new AirPurifierIR(this, existingAccessory, device)
2554
- this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${existingAccessory.UUID})`)
2555
- } else {
2556
- this.unregisterPlatformAccessories(existingAccessory)
2557
- }
2558
- } else if (!device.hide_device && device.hubDeviceId) {
2559
- // create a new accessory
2560
- const accessory = new this.api.platformAccessory(device.configDeviceName
2561
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2562
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName), uuid)
2563
-
2564
- // store a copy of the device object in the `accessory.context`
2565
- // the `context` property can be used to store any data about the accessory you may need
2566
- accessory.context.device = device
2567
- accessory.context.deviceId = device.deviceId
2568
- accessory.context.deviceType = `IR: ${device.remoteType}`
2569
- accessory.context.model = device.remoteType
2570
- accessory.displayName = device.configDeviceName
2571
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2572
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
2573
- accessory.context.connectionType = await this.connectionType(device)
2574
- accessory.context.version = device.firmware ?? this.version ?? '0.0.0'
2575
- const newOrExternal = !device.external ? 'Adding new' : 'Loading external'
2576
- this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`)
2577
- // create the accessory handler for the newly create accessory
2578
- // this is imported from `platformAccessory.ts`
2579
- new AirPurifierIR(this, accessory, device)
2580
- this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`)
2581
-
2582
- // publish device externally or link the accessory to your platform
2583
- this.externalOrPlatform(device, accessory)
2584
- this.accessories.push(accessory)
2585
- } else {
2586
- this.debugLog(`Device not registered: ${device.deviceName} ${device.remoteType} deviceId: ${device.deviceId}`)
2587
- }
2588
- }
2589
-
2590
- private async createWaterHeater(device: irdevice & irDevicesConfig) {
2591
- const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`)
2592
-
2593
- // see if an accessory with the same uuid has already been registered and restored from
2594
- // the cached devices we stored in the `configureAccessory` method above
2595
- const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid)
2596
-
2597
- if (existingAccessory) {
2598
- // the accessory already exists
2599
- if (!device.hide_device && device.hubDeviceId) {
2600
- // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
2601
- existingAccessory.context.device = device
2602
- existingAccessory.context.deviceId = device.deviceId
2603
- existingAccessory.context.deviceType = `IR: ${device.remoteType}`
2604
- existingAccessory.context.model = device.remoteType
2605
- existingAccessory.displayName = device.configDeviceName
2606
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2607
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
2608
- this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} deviceId: ${device.deviceId}`)
2609
- existingAccessory.context.connectionType = device.connectionType
2610
- this.api.updatePlatformAccessories([existingAccessory])
2611
- // create the accessory handler for the restored accessory
2612
- // this is imported from `platformAccessory.ts`
2613
- new WaterHeater(this, existingAccessory, device)
2614
- this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${existingAccessory.UUID})`)
2615
- } else {
2616
- this.unregisterPlatformAccessories(existingAccessory)
2617
- }
2618
- } else if (!device.hide_device && device.hubDeviceId) {
2619
- // create a new accessory
2620
- const accessory = new this.api.platformAccessory(device.configDeviceName
2621
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2622
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName), uuid)
2623
-
2624
- // store a copy of the device object in the `accessory.context`
2625
- // the `context` property can be used to store any data about the accessory you may need
2626
- accessory.context.device = device
2627
- accessory.context.deviceId = device.deviceId
2628
- accessory.context.deviceType = `IR: ${device.remoteType}`
2629
- accessory.context.model = device.remoteType
2630
- accessory.displayName = device.configDeviceName
2631
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2632
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
2633
- accessory.context.connectionType = await this.connectionType(device)
2634
- accessory.context.version = device.firmware ?? this.version ?? '0.0.0'
2635
- const newOrExternal = !device.external ? 'Adding new' : 'Loading external'
2636
- this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`)
2637
- // create the accessory handler for the newly create accessory
2638
- // this is imported from `platformAccessory.ts`
2639
- new WaterHeater(this, accessory, device)
2640
- this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`)
2641
-
2642
- // publish device externally or link the accessory to your platform
2643
- this.externalOrPlatform(device, accessory)
2644
- this.accessories.push(accessory)
2645
- } else {
2646
- this.debugLog(`Device not registered: ${device.deviceName} ${device.remoteType} deviceId: ${device.deviceId}`)
2647
- }
2648
- }
2649
-
2650
- private async createVacuumCleaner(device: irdevice & irDevicesConfig) {
2651
- const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`)
2652
-
2653
- // see if an accessory with the same uuid has already been registered and restored from
2654
- // the cached devices we stored in the `configureAccessory` method above
2655
- const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid)
2656
-
2657
- if (existingAccessory) {
2658
- // the accessory already exists
2659
- if (!device.hide_device && device.hubDeviceId) {
2660
- // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
2661
- existingAccessory.context.device = device
2662
- existingAccessory.context.deviceId = device.deviceId
2663
- existingAccessory.context.deviceType = `IR: ${device.remoteType}`
2664
- existingAccessory.context.model = device.remoteType
2665
- existingAccessory.displayName = device.configDeviceName
2666
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2667
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
2668
- this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} deviceId: ${device.deviceId}`)
2669
- existingAccessory.context.connectionType = device.connectionType
2670
- this.api.updatePlatformAccessories([existingAccessory])
2671
- // create the accessory handler for the restored accessory
2672
- // this is imported from `platformAccessory.ts`
2673
- new VacuumCleaner(this, existingAccessory, device)
2674
- this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${existingAccessory.UUID})`)
2675
- } else {
2676
- this.unregisterPlatformAccessories(existingAccessory)
2677
- }
2678
- } else if (!device.hide_device && device.hubDeviceId) {
2679
- // create a new accessory
2680
- const accessory = new this.api.platformAccessory(device.configDeviceName
2681
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2682
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName), uuid)
2683
-
2684
- // store a copy of the device object in the `accessory.context`
2685
- // the `context` property can be used to store any data about the accessory you may need
2686
- accessory.context.device = device
2687
- accessory.context.deviceId = device.deviceId
2688
- accessory.context.deviceType = `IR: ${device.remoteType}`
2689
- accessory.context.model = device.remoteType
2690
- accessory.displayName = device.configDeviceName
2691
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2692
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
2693
- accessory.context.connectionType = await this.connectionType(device)
2694
- accessory.context.version = device.firmware ?? this.version ?? '0.0.0'
2695
- const newOrExternal = !device.external ? 'Adding new' : 'Loading external'
2696
- this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`)
2697
- // create the accessory handler for the newly create accessory
2698
- // this is imported from `platformAccessory.ts`
2699
- new VacuumCleaner(this, accessory, device)
2700
- this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`)
2701
-
2702
- // publish device externally or link the accessory to your platform
2703
- this.externalOrPlatform(device, accessory)
2704
- this.accessories.push(accessory)
2705
- } else {
2706
- this.debugLog(`Device not registered: ${device.deviceName} ${device.remoteType} deviceId: ${device.deviceId}`)
2707
- }
2708
- }
2709
-
2710
- private async createCamera(device: irdevice & irDevicesConfig) {
2711
- const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`)
2712
-
2713
- // see if an accessory with the same uuid has already been registered and restored from
2714
- // the cached devices we stored in the `configureAccessory` method above
2715
- const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid)
2716
-
2717
- if (existingAccessory) {
2718
- // the accessory already exists
2719
- if (!device.hide_device && device.hubDeviceId) {
2720
- // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
2721
- existingAccessory.context.device = device
2722
- existingAccessory.context.deviceId = device.deviceId
2723
- existingAccessory.context.deviceType = `IR: ${device.remoteType}`
2724
- existingAccessory.context.model = device.remoteType
2725
- existingAccessory.displayName = device.configDeviceName
2726
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2727
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
2728
- this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} deviceId: ${device.deviceId}`)
2729
- existingAccessory.context.connectionType = device.connectionType
2730
- this.api.updatePlatformAccessories([existingAccessory])
2731
- // create the accessory handler for the restored accessory
2732
- // this is imported from `platformAccessory.ts`
2733
- new Camera(this, existingAccessory, device)
2734
- this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${existingAccessory.UUID})`)
2735
- } else {
2736
- this.unregisterPlatformAccessories(existingAccessory)
2737
- }
2738
- } else if (!device.hide_device && device.hubDeviceId) {
2739
- // create a new accessory
2740
- const accessory = new this.api.platformAccessory(device.configDeviceName
2741
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2742
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName), uuid)
2743
-
2744
- // store a copy of the device object in the `accessory.context`
2745
- // the `context` property can be used to store any data about the accessory you may need
2746
- accessory.context.device = device
2747
- accessory.context.deviceId = device.deviceId
2748
- accessory.context.deviceType = `IR: ${device.remoteType}`
2749
- accessory.context.model = device.remoteType
2750
- accessory.displayName = device.configDeviceName
2751
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2752
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
2753
- accessory.context.connectionType = await this.connectionType(device)
2754
- accessory.context.version = device.firmware ?? this.version ?? '0.0.0'
2755
- const newOrExternal = !device.external ? 'Adding new' : 'Loading external'
2756
- this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`)
2757
- // create the accessory handler for the newly create accessory
2758
- // this is imported from `platformAccessory.ts`
2759
- new Camera(this, accessory, device)
2760
- this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`)
2761
-
2762
- // publish device externally or link the accessory to your platform
2763
- this.externalOrPlatform(device, accessory)
2764
- this.accessories.push(accessory)
2765
- } else {
2766
- this.debugLog(`Device not registered: ${device.deviceName} ${device.remoteType} deviceId: ${device.deviceId}`)
2767
- }
2768
- }
2769
-
2770
- private async createOthers(device: irdevice & irDevicesConfig) {
2771
- const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`)
2772
-
2773
- // see if an accessory with the same uuid has already been registered and restored from
2774
- // the cached devices we stored in the `configureAccessory` method above
2775
- const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid)
2776
-
2777
- if (existingAccessory) {
2778
- // the accessory already exists
2779
- if (!device.hide_device && device.hubDeviceId) {
2780
- // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
2781
- existingAccessory.context.device = device
2782
- existingAccessory.context.deviceId = device.deviceId
2783
- existingAccessory.context.deviceType = `IR: ${device.remoteType}`
2784
- existingAccessory.context.model = device.remoteType
2785
- existingAccessory.displayName = device.configDeviceName
2786
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2787
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
2788
- this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} deviceId: ${device.deviceId}`)
2789
- existingAccessory.context.connectionType = device.connectionType
2790
- this.api.updatePlatformAccessories([existingAccessory])
2791
- // create the accessory handler for the restored accessory
2792
- // this is imported from `platformAccessory.ts`
2793
- new Others(this, existingAccessory, device)
2794
- this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${existingAccessory.UUID})`)
2795
- } else {
2796
- this.unregisterPlatformAccessories(existingAccessory)
2797
- }
2798
- } else if (!device.hide_device && device.hubDeviceId) {
2799
- // create a new accessory
2800
- const accessory = new this.api.platformAccessory(device.configDeviceName
2801
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2802
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName), uuid)
2803
-
2804
- // store a copy of the device object in the `accessory.context`
2805
- // the `context` property can be used to store any data about the accessory you may need
2806
- accessory.context.device = device
2807
- accessory.context.deviceId = device.deviceId
2808
- accessory.context.deviceType = `IR: ${device.remoteType}`
2809
- accessory.context.model = device.remoteType
2810
- accessory.displayName = device.configDeviceName
2811
- ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
2812
- : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
2813
- accessory.context.connectionType = await this.connectionType(device)
2814
- accessory.context.version = device.firmware ?? this.version ?? '0.0.0'
2815
- const newOrExternal = !device.external ? 'Adding new' : 'Loading external'
2816
- this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`)
2817
- // create the accessory handler for the newly create accessory
2818
- // this is imported from `platformAccessory.ts`
2819
- new Others(this, accessory, device)
2820
- this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`)
2821
-
2822
- // publish device externally or link the accessory to your platform
2823
- this.externalOrPlatform(device, accessory)
2824
- this.accessories.push(accessory)
2825
- } else {
2826
- this.debugLog(`Device not registered: ${device.deviceName} ${device.remoteType} deviceId: ${device.deviceId}`)
2827
- }
2828
- }
2829
-
2830
- async registerCurtains(device: device & devicesConfig): Promise<boolean> {
2831
- let registerWindowCovering: boolean
2832
- if (isCurtainDevice(device)) {
2833
- this.debugWarnLog(`deviceName: ${device.deviceName} deviceId: ${device.deviceId}, curtainDevicesIds: ${device.curtainDevicesIds},x master: ${device.master}, group: ${device.group}, disable_group: ${(device as blindTiltConfig | curtainConfig).disable_group}, connectionType: ${device.connectionType}`)
2834
- registerWindowCovering = await this.registerWindowCovering(device)
2835
- } else if (isBlindTiltDevice(device)) {
2836
- this.debugWarnLog(`deviceName: ${device.deviceName} deviceId: ${device.deviceId}, blindTiltDevicesIds: ${device.blindTiltDevicesIds}, master: ${device.master}, group: ${device.group}, disable_group: ${(device as blindTiltConfig | curtainConfig).disable_group}, connectionType: ${device.connectionType}`)
2837
- registerWindowCovering = await this.registerWindowCovering(device)
2838
- } else {
2839
- registerWindowCovering = false
2840
- }
2841
- return registerWindowCovering
2842
- }
2843
-
2844
- async registerWindowCovering(device: (curtain | curtain3 | blindTilt) & devicesConfig) {
2845
- this.debugLog(`master: ${device.master}`)
2846
- let registerCurtain: boolean
2847
- if (device.master && device.group) {
2848
- // OpenAPI: Master Curtains/Blind Tilt in Group
2849
- registerCurtain = true
2850
- this.debugLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] device.master: ${device.master}, device.group: ${device.group} connectionType; ${device.connectionType}`)
2851
- this.debugWarnLog(`Device: ${device.deviceName} registerCurtains: ${registerCurtain}`)
2852
- } else if (!device.master && (device as blindTiltConfig | curtainConfig).disable_group) {
2853
- registerCurtain = true
2854
- this.debugLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] device.master: ${device.master}, disable_group: ${(device as blindTiltConfig | curtainConfig).disable_group}, connectionType; ${device.connectionType}`)
2855
- this.debugWarnLog(`Device: ${device.deviceName} registerCurtains: ${registerCurtain}`)
2856
- } else if (device.master && !device.group) {
2857
- // OpenAPI: Master Curtains/Blind Tilts not in Group
2858
- registerCurtain = true
2859
- this.debugLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] device.master: ${device.master}, device.group: ${device.group} connectionType; ${device.connectionType}`)
2860
- this.debugWarnLog(`Device: ${device.deviceName} registerCurtains: ${registerCurtain}`)
2861
- } else if (device.connectionType === 'BLE') {
2862
- // BLE: Curtains/Blind Tilt
2863
- registerCurtain = true
2864
- this.debugLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] connectionType: ${device.connectionType}, group: ${device.group}`)
2865
- this.debugWarnLog(`Device: ${device.deviceName} registerCurtains: ${registerCurtain}`)
2866
- } else {
2867
- registerCurtain = false
2868
- this.debugErrorLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] disable_group: ${(device as blindTiltConfig | curtainConfig).disable_group}, device.master: ${device.master}, device.group: ${device.group}`)
2869
- this.debugWarnLog(`Device: ${device.deviceName} registerCurtains: ${registerCurtain}, device.connectionType: ${device.connectionType}`)
2870
- }
2871
- return registerCurtain
2872
- }
2873
-
2874
- async connectionType(device: (device & devicesConfig) | (irdevice & irDevicesConfig)): Promise<any> {
2875
- let connectionType: string
2876
- if (!device.connectionType && this.config.credentials?.token && this.config.credentials.secret) {
2877
- connectionType = 'OpenAPI'
2878
- } else {
2879
- connectionType = device.connectionType!
2880
- }
2881
- return connectionType
2882
- }
2883
-
2884
- async registerDevice(device: device & devicesConfig) {
2885
- device.connectionType = await this.connectionType(device)
2886
- let registerDevice: boolean
2887
-
2888
- const shouldRegister = !device.hide_device && (device.connectionType === 'BLE/OpenAPI' || (device.deviceId && device.configDeviceType && device.configDeviceName && device.connectionType === 'BLE') || device.connectionType === 'OpenAPI' || device.connectionType === 'Disabled')
2889
-
2890
- if (shouldRegister) {
2891
- registerDevice = await this.handleDeviceRegistration(device)
2892
- } else {
2893
- registerDevice = false
2894
- this.debugErrorLog(`Device: ${device.deviceName} connectionType: ${device.connectionType}, hide_device: ${device.hide_device}, will not display in HomeKit`)
2895
- }
2896
-
2897
- return registerDevice
2898
- }
2899
-
2900
- async handleDeviceRegistration(device: device & devicesConfig): Promise<boolean> {
2901
- let registerDevice: boolean
2902
-
2903
- switch (device.deviceType) {
2904
- case 'Curtain':
2905
- case 'Curtain3':
2906
- case 'Blind Tilt':
2907
- registerDevice = await this.registerCurtains(device)
2908
- this.debugWarnLog(`Device: ${device.deviceName} ${device.deviceType} registerDevice: ${registerDevice}`)
2909
- break
2910
- default:
2911
- registerDevice = true
2912
- this.debugWarnLog(`Device: ${device.deviceName} registerDevice: ${registerDevice}`)
2913
- }
2914
-
2915
- if (registerDevice) {
2916
- this.debugWarnLog(`Device: ${device.deviceName} connectionType: ${device.connectionType}, will display in HomeKit`)
2917
- } else {
2918
- this.debugErrorLog(`Device: ${device.deviceName} connectionType: ${device.connectionType}, will not display in HomeKit`)
2919
- }
2920
-
2921
- return registerDevice
2922
- }
2923
-
2924
- public async externalOrPlatform(device: (device & devicesConfig) | (irdevice & irDevicesConfig), accessory: PlatformAccessory) {
2925
- const { displayName } = accessory
2926
- const isExternal = device.external ?? false
2927
-
2928
- if (isExternal) {
2929
- this.debugWarnLog(`${displayName} External Accessory Mode`)
2930
- this.api.publishExternalAccessories(PLUGIN_NAME, [accessory])
2931
- } else {
2932
- this.debugLog(`${displayName} External Accessory Mode: ${isExternal}`)
2933
- this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory])
2934
- }
2935
- }
2936
-
2937
- public unregisterPlatformAccessories(existingAccessory: PlatformAccessory) {
2938
- const { displayName } = existingAccessory
2939
- // remove platform accessories when no longer present
2940
- this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [existingAccessory])
2941
- this.warnLog(`Removing existing accessory from cache: ${displayName}`)
2942
- }
2943
-
2944
- /**
2945
- * Handles the status codes returned by the device and logs appropriate messages.
2946
- *
2947
- * @param statusCode - The status code returned by the device.
2948
- * @returns A promise that resolves when the logging is complete.
2949
- * @deprecated Use shared logStatusCode from utils.js instead
2950
- */
2951
- async statusCode(statusCode: number): Promise<void> {
2952
- await logStatusCode(statusCode, {
2953
- debugLog: this.debugLog.bind(this),
2954
- errorLog: this.errorLog.bind(this),
2955
- })
2956
- }
2957
-
2958
- async retryRequest(device: (device & devicesConfig) | (irdevice & irDevicesConfig), deviceMaxRetries: number, deviceDelayBetweenRetries: number): Promise<{ response: any, statusCode: deviceStatusRequest['statusCode'] }> {
2959
- // Check API budget BEFORE attempting any retries - don't waste cycles on blocked requests
2960
- if (!this.apiTracker?.trySpend('poll')) {
2961
- // Don't log on every blocked request - the ApiRequestTracker handles periodic warnings
2962
- return {
2963
- response: {
2964
- deviceId: '',
2965
- deviceType: '',
2966
- hubDeviceId: '',
2967
- version: 0,
2968
- deviceName: '',
2969
- },
2970
- statusCode: 429,
2971
- }
2972
- }
2973
-
2974
- let retryCount = 0
2975
- const maxRetries = deviceMaxRetries
2976
- const delayBetweenRetries = deviceDelayBetweenRetries
2977
- while (retryCount < maxRetries) {
2978
- try {
2979
- const { response, statusCode } = await this.switchBotAPI.getDeviceStatus(device.deviceId, this.config.credentials?.token, this.config.credentials?.secret)
2980
- this.debugLog(`response: ${JSON.stringify(response)}`)
2981
- return { response, statusCode }
2982
- } catch (error: any) {
2983
- this.errorLog(`Error making request: ${error.message}`)
2984
- }
2985
- retryCount++
2986
- this.debugLog(`Retry attempt ${retryCount} of ${maxRetries}`)
2987
- await sleep(delayBetweenRetries)
2988
- }
2989
- return { response: {
2990
- deviceId: '',
2991
- deviceType: '',
2992
- hubDeviceId: '',
2993
- version: 0,
2994
- deviceName: '',
2995
- }, statusCode: 500 }
2996
- }
2997
-
2998
- async retryCommand(device: (device & devicesConfig) | (irdevice & irDevicesConfig), bodyChange: bodyChange, deviceMaxRetries?: number, deviceDelayBetweenRetries?: number): Promise<{ response: any, statusCode: number }> {
2999
- let retryCount = 0
3000
- const maxRetries = deviceMaxRetries ?? 1
3001
- const delayBetweenRetries = deviceDelayBetweenRetries ?? 1000
3002
- while (retryCount < maxRetries) {
3003
- try {
3004
- if (!this.apiTracker?.trySpend('command')) {
3005
- return { response: {}, statusCode: 429 }
3006
- }
3007
- const { response, statusCode } = await this.switchBotAPI.controlDevice(
3008
- device.deviceId,
3009
- bodyChange.command,
3010
- bodyChange.parameter,
3011
- bodyChange.commandType as import('node-switchbot').commandType,
3012
- this.config.credentials?.token,
3013
- this.config.credentials?.secret,
3014
- )
3015
- this.debugLog(`response: ${JSON.stringify(response)}`)
3016
- return { response, statusCode }
3017
- } catch (error: any) {
3018
- this.errorLog(`Error making request: ${error.message}`)
3019
- }
3020
- retryCount++
3021
- this.debugLog(`Retry attempt ${retryCount} of ${maxRetries}`)
3022
- await sleep(delayBetweenRetries)
3023
- }
3024
- return { response: {}, statusCode: 500 }
3025
- }
3026
-
3027
- // BLE Connection
3028
- async connectBLE(accessory: PlatformAccessory, device: device & devicesConfig): Promise<any> {
3029
- try {
3030
- queueScheduler.schedule(async () => this.switchBotBLE)
3031
- this.debugLog(`${device.deviceType}: ${accessory.displayName} 'node-switchbot' found: ${safeStringify(this.switchBotBLE)}`)
3032
- return this.switchBotBLE
3033
- } catch (e: any) {
3034
- this.errorLog(`${device.deviceType}: ${accessory.displayName} 'node-switchbot' not found, Error: ${e.message ?? e}`)
3035
- return false
3036
- }
3037
- }
3038
-
3039
- async getPlatformConfigSettings() {
3040
- if (this.config.options) {
3041
- const platformConfig: SwitchBotPlatformConfig = {
3042
- platform: 'Resideo',
3043
- }
3044
- platformConfig.logging = this.config.options.logging ? this.config.options.logging : undefined
3045
- platformConfig.refreshRate = this.config.options.refreshRate ? this.config.options.refreshRate : undefined
3046
- platformConfig.updateRate = this.config.options.updateRate ? this.config.options.updateRate : undefined
3047
- platformConfig.pushRate = this.config.options.pushRate ? this.config.options.pushRate : undefined
3048
- platformConfig.maxRetries = this.config.options.maxRetries ? this.config.options.maxRetries : undefined
3049
- platformConfig.delayBetweenRetries = this.config.options.delayBetweenRetries ? this.config.options.delayBetweenRetries : undefined
3050
- if (Object.entries(platformConfig).length !== 0) {
3051
- await this.debugLog(`Platform Config: ${JSON.stringify(platformConfig)}`)
3052
- }
3053
- this.platformConfig = platformConfig
3054
- }
3055
- }
3056
-
3057
- async getPlatformRateSettings() {
3058
- // RefreshRate
3059
- this.platformRefreshRate = this.config.options?.refreshRate ? this.config.options.refreshRate : undefined
3060
- const refreshRate = this.config.options?.refreshRate ? 'Using Platform Config refreshRate' : 'Platform Config refreshRate Not Set'
3061
- await this.debugLog(`${refreshRate}: ${this.platformRefreshRate}`)
3062
- // UpdateRate
3063
- this.platformUpdateRate = this.config.options?.updateRate ? this.config.options.updateRate : undefined
3064
- const updateRate = this.config.options?.updateRate ? 'Using Platform Config updateRate' : 'Platform Config updateRate Not Set'
3065
- await this.debugLog(`${updateRate}: ${this.platformUpdateRate}`)
3066
- // PushRate
3067
- this.platformPushRate = this.config.options?.pushRate ? this.config.options.pushRate : undefined
3068
- const pushRate = this.config.options?.pushRate ? 'Using Platform Config pushRate' : 'Platform Config pushRate Not Set'
3069
- await this.debugLog(`${pushRate}: ${this.platformPushRate}`)
3070
- // MaxRetries
3071
- this.platformMaxRetries = this.config.options?.maxRetries ? this.config.options.maxRetries : undefined
3072
- const maxRetries = this.config.options?.maxRetries ? 'Using Platform Config maxRetries' : 'Platform Config maxRetries Not Set'
3073
- await this.debugLog(`${maxRetries}: ${this.platformMaxRetries}`)
3074
- // DelayBetweenRetries
3075
- this.platformDelayBetweenRetries = this.config.options?.delayBetweenRetries ? this.config.options.delayBetweenRetries : undefined
3076
- const delayBetweenRetries = this.config.options?.delayBetweenRetries ? 'Using Platform Config delayBetweenRetries' : 'Platform Config delayBetweenRetries Not Set'
3077
- await this.debugLog(`${delayBetweenRetries}: ${this.platformDelayBetweenRetries}`)
3078
- }
3079
-
3080
- async getPlatformLogSettings() {
3081
- this.debugMode = argv.includes('-D') ?? argv.includes('--debug')
3082
- this.platformLogging = (this.config.options?.logging === 'debug' || this.config.options?.logging === 'standard'
3083
- || this.config.options?.logging === 'none')
3084
- ? this.config.options.logging
3085
- : this.debugMode ? 'debugMode' : 'standard'
3086
- const logging = this.config.options?.logging ? 'Platform Config' : this.debugMode ? 'debugMode' : 'Default'
3087
- await this.debugLog(`Using ${logging} Logging: ${this.platformLogging}`)
3088
- }
3089
-
3090
- /**
3091
- * Asynchronously retrieves the version of the plugin from the package.json file.
3092
- *
3093
- * This method reads the package.json file located in the parent directory,
3094
- * parses its content to extract the version, and logs the version using the debug logger.
3095
- * The extracted version is then assigned to the `version` property of the class.
3096
- *
3097
- * @returns {Promise<void>} A promise that resolves when the version has been retrieved and logged.
3098
- */
3099
- async getVersion(): Promise<void> {
3100
- const { version } = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf-8'))
3101
- this.debugLog(`Plugin Version: ${version}`)
3102
- this.version = version
3103
- }
3104
-
3105
- /**
3106
- * Validate that the user's configuration won't exceed API limits
3107
- * Warn if device count × polling frequency will hit daily limits
3108
- */
3109
- private validateApiUsageConfig(deviceCount: number, irDeviceCount: number): void {
3110
- try {
3111
- const totalDevices = deviceCount + irDeviceCount
3112
- if (totalDevices === 0) {
3113
- return
3114
- }
3115
-
3116
- const refreshRate = this.platformRefreshRate ?? 300 // seconds
3117
- const dailyLimit = this.config.options?.dailyApiLimit ?? 10000
3118
- const reserveForCommands = this.config.options?.dailyApiReserveForCommands ?? 1000
3119
-
3120
- // Calculate polls per day (86400 seconds in a day)
3121
- const pollsPerDevicePerDay = Math.floor(86400 / refreshRate)
3122
- const totalPollsPerDay = pollsPerDevicePerDay * totalDevices
3123
-
3124
- // Add discovery calls (typically 1-2 per day)
3125
- const estimatedDiscoveryCalls = 2
3126
- const totalEstimatedCalls = totalPollsPerDay + estimatedDiscoveryCalls
3127
-
3128
- const usableLimit = dailyLimit - reserveForCommands
3129
- const percentOfLimit = Math.round((totalEstimatedCalls / usableLimit) * 100)
3130
-
3131
- this.debugLog(`[API Usage Diagnostic] ${totalDevices} devices × ${pollsPerDevicePerDay} polls/day = ${totalPollsPerDay} estimated daily polls`)
3132
- this.debugLog(`[API Usage Diagnostic] With ${reserveForCommands} reserved for commands, usable limit is ${usableLimit}`)
3133
-
3134
- if (totalEstimatedCalls > dailyLimit) {
3135
- this.errorLog(`⚠️ API LIMIT WARNING: Your configuration will exceed the daily API limit!`)
3136
- this.errorLog(` Devices: ${totalDevices} | Refresh rate: ${refreshRate}s | Estimated daily polls: ${totalEstimatedCalls}`)
3137
- this.errorLog(` Daily limit: ${dailyLimit} | You will use ${percentOfLimit}% of available budget`)
3138
- this.errorLog(` SOLUTION: Increase refreshRate to ${Math.ceil((totalDevices * 86400) / usableLimit)} seconds or higher`)
3139
- this.errorLog(` OR: Enable webhooks and set 'webhookOnlyOnReserve: true' to reduce polling`)
3140
- } else if (totalEstimatedCalls > usableLimit) {
3141
- this.warnLog(`⚠️ API USAGE WARNING: Configuration may exceed usable daily API budget`)
3142
- this.warnLog(` Devices: ${totalDevices} | Refresh rate: ${refreshRate}s | Estimated daily polls: ${totalEstimatedCalls}`)
3143
- this.warnLog(` Usable limit (after reserve): ${usableLimit} | You will use ${percentOfLimit}% of budget`)
3144
- this.warnLog(` Polling may pause when approaching limit. Consider increasing refreshRate to ${Math.ceil((totalDevices * 86400) / usableLimit)}s`)
3145
- } else if (percentOfLimit > 75) {
3146
- this.infoLog(`[API Usage] Using ${percentOfLimit}% of daily budget (${totalEstimatedCalls}/${usableLimit} calls). Monitor usage if adding more devices.`)
3147
- } else {
3148
- this.debugLog(`[API Usage] Configuration looks good: ${percentOfLimit}% of daily budget (${totalEstimatedCalls}/${usableLimit} calls)`)
3149
- }
3150
- } catch (e: any) {
3151
- this.debugErrorLog(`Failed to validate API usage config: ${e.message ?? e}`)
3152
- }
3153
- }
3154
-
3155
- /**
3156
- * Validate and clean a string value for a Name Characteristic.
3157
- * @param displayName - The display name of the accessory.
3158
- * @param name - The name of the characteristic.
3159
- * @param value - The value to be validated and cleaned.
3160
- * @returns The cleaned string value.
3161
- */
3162
- async validateAndCleanDisplayName(displayName: string, name: string, value: string): Promise<string> {
3163
- if (this.config.options?.allowInvalidCharacters) {
3164
- return value
3165
- } else {
3166
- const validPattern = /^[\p{L}\p{N}][\p{L}\p{N} ']*[\p{L}\p{N}]$/u
3167
- const invalidCharsPattern = /[^\p{L}\p{N} ']/gu
3168
- const invalidStartEndPattern = /^[^\p{L}\p{N}]+|[^\p{L}\p{N}]+$/gu
3169
-
3170
- if (typeof value === 'string' && !validPattern.test(value)) {
3171
- this.warnLog(`WARNING: The accessory '${displayName}' has an invalid '${name}' characteristic ('${value}'). Please use only alphanumeric, space, and apostrophe characters. Ensure it starts and ends with an alphabetic or numeric character, and avoid emojis. This may prevent the accessory from being added in the Home App or cause unresponsiveness.`)
3172
-
3173
- // Remove invalid characters
3174
- if (invalidCharsPattern.test(value)) {
3175
- const before = value
3176
- this.warnLog(`Removing invalid characters from '${name}' characteristic, if you feel this is incorrect, please enable \'allowInvalidCharacter\' in the config to allow all characters`)
3177
- value = value.replace(invalidCharsPattern, '')
3178
- this.warnLog(`${name} Before: '${before}' After: '${value}'`)
3179
- }
3180
-
3181
- // Ensure it starts and ends with an alphanumeric character
3182
- if (invalidStartEndPattern.test(value)) {
3183
- const before = value
3184
- this.warnLog(`Removing invalid starting or ending characters from '${name}' characteristic, if you feel this is incorrect, please enable \'allowInvalidCharacter\' in the config to allow all characters`)
3185
- value = value.replace(invalidStartEndPattern, '')
3186
- this.warnLog(`${name} Before: '${before}' After: '${value}'`)
3187
- }
3188
- }
3189
-
3190
- return value
3191
- }
3192
- }
3193
- }