@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,449 +1,81 @@
1
- <p class="text-center">
2
- <img
3
- src="https://raw.githubusercontent.com/OpenWonderLabs/homebridge-switchbot/latest/branding/Homebridge_x_SwitchBot.svg"
4
- alt="homebridge-switchbot logo" style="width: 50%" />
5
- </p>
6
- <div id="pageIntro" style="display: none">
7
- <p class="lead text-center">Thank you for installing <strong>homebridge-switchbot</strong></p>
8
- <p class="lead text-center">Before continuing:</p>
9
- <ol>
10
- <li class="mb-3">
11
- Download the SwitchBot App from either the
12
- <a href="https://apps.apple.com/us/app/switchbot/id1087374760" target="_blank" rel="noreferrer noopener">App
13
- Store</a> or the
14
- <a href="https://play.google.com/store/apps/details?id=com.theswitchbot.switchbot&hl=en_US&gl=US" target="_blank"
15
- rel="noreferrer noopener">Play Store</a>.
16
- </li>
17
- <li class="mb-3">Select <strong>Profile</strong>.</li>
18
- <li class="mb-3">Select <strong>Preferences</strong>.</li>
19
- <li class="mb-3">Tap the <strong>App version</strong> 10 times, this will enable Developer Options.</li>
20
- <li class="mb-3">Select <strong>Developer Options</strong>.</li>
21
- <li class="mb-3">Copy your token by hitting <strong>Copy to Clipboard</strong>.</li>
22
- <li class="mb-3">Paste the Token into the Token parameter on the next page.</li>
23
- </ol>
24
- <div class="text-center">
25
- <button type="button" class="btn btn-primary" id="introLink">Continue &rarr;</button>
26
- </div>
27
- </div>
28
- <div id="menuWrapper" class="btn-group w-100 mb-0" role="group" aria-label="UI Menu" style="display: none">
29
- <button type="button" class="btn btn-primary" id="menuSettings">Settings</button>
30
- <button type="button" class="btn btn-primary" id="menuDevices">Devices</button>
31
- <button type="button" class="btn btn-primary" id="menuHome">Support</button>
32
- <button type="button" class="btn btn-primary mr-0" id="dynamic-config-tab">Dynamic Config</button>
33
- </div>
34
- <div id="disabledBanner" class="alert alert-secondary mb-0 mt-3" role="alert" style="display: none">
35
- Plugin is currently disabled
36
- <button id="disabledEnable" type="button" class="btn btn-link p-0 m-0 float-right">Enable</button>
37
- </div>
38
- <div id="pageDevices" class="mt-4" style="display: none">
39
- <div id="deviceInfo">
40
- <form>
41
- <div class="form-group">
42
- <select class="form-control" id="deviceSelect"></select>
43
- </div>
44
- </form>
45
- <table class="table w-100" id="deviceTable" style="display: none">
46
- <thead>
47
- <tr>
48
- <th scope="col" style="width: 40%">Device Name</th>
49
- <th scope="col" style="width: 60%" id="displayName"></th>
50
- </tr>
51
- </thead>
52
- <tbody>
53
- <tr>
54
- <th scope="row">Device ID</th>
55
- <td id="deviceId"></td>
56
- </tr>
57
- <tr>
58
- <th scope="row">Model</th>
59
- <td id="model"></td>
60
- </tr>
61
- <tr>
62
- <th scope="row">Firmware Version</th>
63
- <td id="version"></td>
64
- </tr>
65
- <tr>
66
- <th scope="row">Device Type</th>
67
- <td id="deviceType"></td>
68
- </tr>
69
- <tr>
70
- <th scope="row">Connection Type</th>
71
- <td id="connectionType"></td>
72
- </tr>
73
- <tr>
74
- <th scope="row">Refresh Rate</th>
75
- <td id="refreshRate"></td>
76
- </tr>
77
- <tr>
78
- <th scope="row">Update Rate</th>
79
- <td id="updateRate"></td>
80
- </tr>
81
- <tr>
82
- <th scope="row">Push Rate</th>
83
- <td id="pushRate"></td>
84
- </tr>
85
- </tbody>
86
- </table>
87
- <h5 class="mt-4">Cached Accessories</h5>
88
- <ul id="cachedAccessoriesList"></ul>
89
- <p class="text-center">External accessories will not be displayed here.</p>
90
- </div>
91
- </div>
92
- <div id="pageSupport" class="mt-4" style="display: none">
93
- <p class="text-center lead">Thank you for using <strong>homebridge-switchbot</strong></p>
94
- <p class="text-center">The links below will take you to our GitHub wiki</p>
95
- <h5>Setup</h5>
96
- <ul>
97
- <li>
98
- <a href="https://github.com/OpenWonderLabs/homebridge-switchbot/wiki" target="_blank">Wiki Home</a>
99
- </li>
100
- <li>
101
- <a href="https://github.com/OpenWonderLabs/homebridge-switchbot/wiki/Configuration"
102
- target="_blank">Configuration</a>
103
- </li>
104
- <li>
105
- <a href="https://github.com/OpenWonderLabs/homebridge-switchbot/wiki/Beta-Version" target="_blank">Beta
106
- Version</a>
107
- </li>
108
- <li>
109
- <a href="https://github.com/OpenWonderLabs/homebridge-switchbot/wiki/Node-Version" target="_blank">Node
110
- Version</a>
111
- </li>
112
- <li>
113
- <a href="https://github.com/OpenWonderLabs/homebridge-switchbot/wiki/Uninstallation"
114
- target="_blank">Uninstallation</a>
115
- </li>
116
- </ul>
117
- <h5>Features</h5>
118
- <ul>
119
- <li>
120
- <a href="https://github.com/OpenWonderLabs/homebridge-switchbot/wiki/Supported-Devices" target="_blank">Supported
121
- Devices</a>
122
- </li>
123
- </ul>
124
- <h5>Help/About</h5>
125
- <ul>
126
- <li>
127
- <a href="https://github.com/OpenWonderLabs/homebridge-switchbot/issues/new/choose" target="_blank">Support
128
- Request</a>
129
- </li>
130
- <li>
131
- <a href="https://github.com/OpenWonderLabs/homebridge-switchbot/blob/latest/CHANGELOG.md"
132
- target="_blank">Changelog</a>
133
- </li>
134
- </ul>
135
- </div>
136
- <div id="dynamic-config-content" class="tab-content" style="display: none;">
137
- <h2>Dynamic Config</h2>
138
- <p>Discover and configure devices dynamically.</p>
139
- <!-- Placeholder for dynamic content -->
140
- </div>
141
- <script>
142
- (async () => {
143
- try {
144
- const currentConfig = await homebridge.getPluginConfig();
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width,initial-scale=1" />
6
+ <title>SwitchBot Plugin UI</title>
7
+ <style>
8
+ body { font-family: system-ui, -apple-system, Arial; padding: 16px; }
9
+ h1 { font-size: 18px }
10
+ ul { padding-left: 0; list-style: none }
11
+ li { margin: 8px 0; display:flex; gap:8px; align-items:center }
12
+ button { padding: 6px 10px }
13
+ code { background:#f3f3f3; padding:4px 6px; border-radius:4px }
14
+ </style>
15
+ </head>
16
+ <body>
17
+ <h1>SwitchBot: Configured Devices</h1>
18
+ <p>This page lists devices found in your Homebridge config for the SwitchBot platform. Use the copy button to insert device IDs into the plugin configuration. Connection preference (BLE/OpenAPI) is shown when available.</p>
19
+ <div id="status">Loading…</div>
20
+ <ul id="devices"></ul>
145
21
 
146
- // Defensive wrapper: ensure token/secret aren't accidentally cleared by
147
- // the UI/schema form. Some versions of config UI can omit sensitive
148
- // fields from the submitted payload; when that happens we copy the
149
- // existing values from `currentConfig` into the outgoing payload so
150
- // saved config does not inadvertently remove credentials.
151
- try {
152
- if (typeof homebridge.updatePluginConfig === 'function') {
153
- const _origUpdatePluginConfig = homebridge.updatePluginConfig.bind(homebridge)
154
- homebridge.updatePluginConfig = async (cfg) => {
155
- try {
156
- if (Array.isArray(cfg) && cfg.length > 0 && Array.isArray(currentConfig) && currentConfig.length > 0) {
157
- const incoming = cfg[0] || {}
158
- const existing = currentConfig[0] || {}
159
- incoming.credentials = incoming.credentials || {}
160
- // Preserve token/secret when incoming payload leaves them blank/undefined
161
- if ((incoming.credentials.token === undefined || String(incoming.credentials.token).trim() === '') && existing.credentials && existing.credentials.token) {
162
- incoming.credentials.token = existing.credentials.token
163
- }
164
- if ((incoming.credentials.secret === undefined || String(incoming.credentials.secret).trim() === '') && existing.credentials && existing.credentials.secret) {
165
- incoming.credentials.secret = existing.credentials.secret
166
- }
167
- cfg[0] = incoming
168
- }
169
- } catch (e) {
170
- // Swallow any wrapper errors but log to console for debugging
171
- // (do not expose secrets).
172
- console.error('updatePluginConfig wrapper error', e)
173
- }
174
- return await _origUpdatePluginConfig(cfg)
175
- }
22
+ <script>
23
+ async function fetchDevices() {
24
+ try {
25
+ const resp = await homebridge.request('/devices', {})
26
+ if (!resp || !resp.success) throw new Error(resp?.data?.message || 'request failed')
27
+ return resp.data || []
28
+ } catch (e) {
29
+ console.error(e)
30
+ return []
176
31
  }
177
- } catch (e) {
178
- console.error('Failed to attach updatePluginConfig wrapper', e)
179
32
  }
180
- showIntro = () => {
181
- const introLink = document.getElementById('introLink');
182
- introLink.addEventListener('click', () => {
183
- homebridge.showSpinner();
184
- document.getElementById('pageIntro').style.display = 'none';
185
- document.getElementById('menuWrapper').style.display = 'inline-flex';
186
- showSettings();
187
- homebridge.hideSpinner();
188
- });
189
- document.getElementById('pageIntro').style.display = 'block';
190
- };
191
- showDevices = async () => {
192
- homebridge.showSpinner();
193
- homebridge.hideSchemaForm();
194
- document.getElementById('menuHome').classList.remove('btn-elegant');
195
- document.getElementById('menuHome').classList.add('btn-primary');
196
- document.getElementById('menuDevices').classList.add('btn-elegant');
197
- document.getElementById('menuDevices').classList.remove('btn-primary');
198
- document.getElementById('menuSettings').classList.remove('btn-elegant');
199
- document.getElementById('menuSettings').classList.add('btn-primary');
200
- document.getElementById('pageSupport').style.display = 'none';
201
- document.getElementById('pageDevices').style.display = 'block';
202
- let cachedAccessories =
203
- typeof homebridge.getCachedAccessories === 'function'
204
- ? await homebridge.getCachedAccessories()
205
- : await homebridge.request('/getCachedAccessories');
206
33
 
207
- // If no HAP cached accessories were returned, try the Matter cached list using the new native method
208
- if ((!cachedAccessories || cachedAccessories.length === 0)) {
209
- try {
210
- // Use the new native getCachedMatterAccessories() method from @homebridge/plugin-ui-utils v2.1.1-beta.0+
211
- const matter = typeof homebridge.getCachedMatterAccessories === 'function'
212
- ? await homebridge.getCachedMatterAccessories()
213
- : await homebridge.request('/getCachedMatterAccessories'); // Fallback to custom handler for older UI versions
214
- if (Array.isArray(matter) && matter.length > 0) {
215
- cachedAccessories = matter
216
- }
217
- } catch (e) {
218
- // ignore
219
- }
220
- }
221
- console.log('Cached Accessories:', cachedAccessories); // Log cached accessories for debugging
222
- if (cachedAccessories.length > 0) {
223
- cachedAccessories.sort((a, b) => {
224
- return a.displayName.toLowerCase() > b.displayName.toLowerCase()
225
- ? 1
226
- : b.displayName.toLowerCase() > a.displayName.toLowerCase()
227
- ? -1
228
- : 0;
229
- });
34
+ function render(list) {
35
+ const ul = document.getElementById('devices')
36
+ const status = document.getElementById('status')
37
+ if (!list.length) {
38
+ status.textContent = 'No devices found in config.'
39
+ return
230
40
  }
231
- const deviceSelect = document.getElementById('deviceSelect');
232
- deviceSelect.innerHTML = '';
233
- cachedAccessories.forEach((a) => {
234
- const option = document.createElement('option');
235
- option.text = a.displayName;
236
- option.value = a.UUID || a.uuid; // Handle both HAP and Matter UUID formats
237
- deviceSelect.add(option);
238
- });
239
- const cachedAccessoriesList = document.getElementById('cachedAccessoriesList');
240
- cachedAccessoriesList.innerHTML = ''; // Clear previous entries
241
- cachedAccessories.forEach((a) => {
242
- const listItem = document.createElement('li');
243
- listItem.textContent = `${a.displayName} (${a.UUID || a.uuid})`;
244
- cachedAccessoriesList.appendChild(listItem);
245
- });
246
- const validateConfig = (config) => {
247
- const deviceIds = new Set();
248
- const isValid = config[0].options.devices.every((device) => {
249
- if (!device.deviceId || typeof device.deviceId !== 'string') {
250
- homebridge.toast.error(`Invalid device ID: ${device.deviceId}`, 'Error');
251
- return false;
252
- }
253
- if (deviceIds.has(device.deviceId)) {
254
- homebridge.toast.error(`Duplicate device ID found: ${device.deviceId}`, 'Error');
255
- return false;
256
- }
257
- deviceIds.add(device.deviceId);
258
- return true;
259
- });
260
- return isValid;
261
- };
262
-
263
- const addDeviceToConfig = async (deviceId) => {
264
- try {
265
- homebridge.showSpinner();
266
- const currentConfig = await homebridge.getPluginConfig();
267
- if (!currentConfig[0].options.devices) {
268
- currentConfig[0].options.devices = [];
269
- }
270
- currentConfig[0].options.devices.push({
271
- deviceId: deviceId.replace(/:/g, ''),
272
- hide_device: false,
273
- disablePlatformBLE: false,
274
- allowPush: false,
275
- disableCaching: false,
276
- });
277
- if (!validateConfig(currentConfig)) {
278
- homebridge.hideSpinner();
279
- return;
280
- }
281
- await homebridge.updatePluginConfig(currentConfig);
282
- await homebridge.savePluginConfig();
283
- homebridge.toast.success('Device added to config successfully!', 'Success');
284
- } catch (error) {
285
- homebridge.toast.error('Failed to add device to config!', 'Error');
286
- } finally {
287
- homebridge.hideSpinner();
288
- }
289
- };
290
-
291
- const protocolInfo = document.createElement('p');
292
- protocolInfo.id = 'protocolInfo';
293
- protocolInfo.style.marginTop = '10px';
294
- document.getElementById('deviceInfo').appendChild(protocolInfo);
295
-
296
- const addDeviceButton = document.createElement('button');
297
- addDeviceButton.textContent = 'Add Device to Config';
298
- addDeviceButton.className = 'btn btn-success';
299
- addDeviceButton.style.marginTop = '10px';
300
- addDeviceButton.addEventListener('click', () => {
301
- const deviceId = document.getElementById('deviceId').textContent;
302
- if (deviceId) {
303
- addDeviceToConfig(deviceId);
304
- } else {
305
- homebridge.toast.error('No device ID found!', 'Error');
306
- }
307
- });
308
- document.getElementById('deviceInfo').appendChild(addDeviceButton);
309
-
310
- const updateTableWithDetails = (deviceContext) => {
311
- const tableBody = document.querySelector('#deviceTable tbody');
312
-
313
- Object.entries(deviceContext).forEach(([key, value]) => {
314
- if (/string|number|boolean/.test(typeof value) && (typeof value !== 'string' || value.trim())) {
315
- let existingCell = document.getElementById(key);
316
- if (existingCell) {
317
- existingCell.textContent = value;
318
- } else {
319
- const row = document.createElement('tr');
320
- const keyCell = document.createElement('th');
321
- keyCell.scope = 'row';
322
- keyCell.textContent = key;
323
- const valueCell = document.createElement('td');
324
- valueCell.textContent = value;
325
- row.appendChild(keyCell);
326
- row.appendChild(valueCell);
327
- tableBody.appendChild(row);
328
- }
329
- }
330
- });
331
- };
332
-
333
- // Ensure the element exists before attempting to set its innerHTML
334
- const safeSetInnerHTML = (id, value) => {
335
- const element = document.getElementById(id);
336
- if (element) {
337
- element.innerHTML = value;
338
- } else {
339
- console.warn(`Element with id '${id}' not found.`);
340
- }
341
- };
342
-
343
- showDeviceInfo = async (UUID) => {
344
- try {
345
- homebridge.showSpinner();
346
- const thisAcc = cachedAccessories.find((x) => x.UUID === UUID);
347
- if (!thisAcc) {
348
- throw new Error('Device not found');
41
+ status.textContent = `Found ${list.length} device(s)`
42
+ ul.innerHTML = ''
43
+ for (const d of list) {
44
+ const li = document.createElement('li')
45
+ const name = document.createElement('span')
46
+ name.textContent = d.name || d.id
47
+ const code = document.createElement('code')
48
+ code.textContent = d.id
49
+ const meta = document.createElement('span')
50
+ meta.style.opacity = '0.75'
51
+ meta.style.marginLeft = '8px'
52
+ const typeText = d.type ? `type: ${d.type}` : ''
53
+ const connText = d.connectionPreference ? `conn: ${d.connectionPreference}` : ''
54
+ const roomText = d.room ? `room: ${d.room}` : ''
55
+ meta.textContent = [typeText, connText, roomText].filter(Boolean).join(' | ')
56
+ const btn = document.createElement('button')
57
+ btn.textContent = 'Copy ID'
58
+ btn.addEventListener('click', async () => {
59
+ try {
60
+ await navigator.clipboard.writeText(d.id)
61
+ btn.textContent = 'Copied'
62
+ setTimeout(() => (btn.textContent = 'Copy ID'), 1200)
63
+ } catch (e) {
64
+ alert('Failed to copy')
349
65
  }
350
- const context = thisAcc.context;
351
- const protocol = thisAcc.isMatter ? 'Matter Protocol' : 'HAP Protocol';
352
- safeSetInnerHTML('displayName', thisAcc.displayName);
353
- safeSetInnerHTML('deviceId', context.deviceId);
354
- safeSetInnerHTML('model', context.model);
355
- safeSetInnerHTML('version', context.version);
356
- safeSetInnerHTML('deviceType', context.deviceType);
357
- safeSetInnerHTML('connectionType', context.connectionType);
358
- safeSetInnerHTML('refreshRate', context.refreshRate);
359
- safeSetInnerHTML('updateRate', context.updateRate);
360
- safeSetInnerHTML('pushRate', context.pushRate);
361
- safeSetInnerHTML('protocolInfo', protocol);
362
- document.getElementById('deviceTable').style.display = 'inline-table';
363
-
364
-
365
- updateTableWithDetails(context);
366
- } catch (error) {
367
- homebridge.toast.error(error.message, 'Error');
368
- } finally {
369
- homebridge.hideSpinner();
370
- }
371
- };
372
- deviceSelect.addEventListener('change', (event) => showDeviceInfo(event.target.value));
373
- if (cachedAccessories.length > 0) {
374
- showDeviceInfo(cachedAccessories[0].UUID);
375
- } else {
376
- const option = document.createElement('option');
377
- option.text = 'No Devices';
378
- deviceSelect.add(option);
379
- deviceSelect.disabled = true;
66
+ })
67
+ li.appendChild(name)
68
+ li.appendChild(code)
69
+ li.appendChild(meta)
70
+ li.appendChild(btn)
71
+ ul.appendChild(li)
380
72
  }
381
- homebridge.hideSpinner();
382
- };
383
- showSupport = () => {
384
- homebridge.showSpinner();
385
- homebridge.hideSchemaForm();
386
- document.getElementById('menuHome').classList.add('btn-elegant');
387
- document.getElementById('menuHome').classList.remove('btn-primary');
388
- document.getElementById('menuDevices').classList.remove('btn-elegant');
389
- document.getElementById('menuDevices').classList.add('btn-primary');
390
- document.getElementById('menuSettings').classList.remove('btn-elegant');
391
- document.getElementById('menuSettings').classList.add('btn-primary');
392
- document.getElementById('pageSupport').style.display = 'block';
393
- document.getElementById('pageDevices').style.display = 'none';
394
- homebridge.hideSpinner();
395
- };
396
- showSettings = () => {
397
- homebridge.showSpinner();
398
- document.getElementById('menuHome').classList.remove('btn-elegant');
399
- document.getElementById('menuHome').classList.add('btn-primary');
400
- document.getElementById('menuDevices').classList.remove('btn-elegant');
401
- document.getElementById('menuDevices').classList.add('btn-primary');
402
- document.getElementById('menuSettings').classList.add('btn-elegant');
403
- document.getElementById('menuSettings').classList.remove('btn-primary');
404
- document.getElementById('pageSupport').style.display = 'none';
405
- document.getElementById('pageDevices').style.display = 'none';
406
- homebridge.showSchemaForm();
407
- homebridge.hideSpinner();
408
- };
409
- showDisabledBanner = () => {
410
- document.getElementById('disabledBanner').style.display = 'block';
411
- };
412
- enablePlugin = async () => {
413
- homebridge.showSpinner();
414
- document.getElementById('disabledBanner').style.display = 'none';
415
- currentConfig[0].disablePlugin = false;
416
- await homebridge.updatePluginConfig(currentConfig);
417
- await homebridge.savePluginConfig();
418
- homebridge.hideSpinner();
419
- };
420
- menuHome.addEventListener('click', () => showSupport());
421
- menuDevices.addEventListener('click', () => showDevices());
422
- menuSettings.addEventListener('click', () => showSettings());
423
- disabledEnable.addEventListener('click', () => enablePlugin());
424
- if (currentConfig.length) {
425
- document.getElementById('menuWrapper').style.display = 'inline-flex';
426
- showSettings();
427
- if (currentConfig[0].disablePlugin) {
428
- showDisabledBanner();
429
- }
430
- } else {
431
- currentConfig.push({ name: 'SwitchBot' });
432
- await homebridge.updatePluginConfig(currentConfig);
433
- showIntro();
434
73
  }
435
- } catch (err) {
436
- homebridge.toast.error(err.message, 'Error');
437
- } finally {
438
- homebridge.hideSpinner();
439
- }
440
- })();
441
-
442
- document.getElementById('dynamic-config-tab').addEventListener('click', function() {
443
- // Hide other tabs
444
- document.querySelectorAll('.tab-content').forEach(tab => tab.style.display = 'none');
445
74
 
446
- // Show Dynamic Config tab
447
- document.getElementById('dynamic-config-content').style.display = 'block';
448
- });
449
- </script>
75
+ (async () => {
76
+ const list = await fetchDevices()
77
+ render(list)
78
+ })()
79
+ </script>
80
+ </body>
81
+ </html>
@@ -1,14 +1,56 @@
1
- import { HomebridgePluginUiServer } from '@homebridge/plugin-ui-utils'
1
+ import fs from 'node:fs/promises'
2
2
 
3
- class PluginUiServer extends HomebridgePluginUiServer {
4
- constructor() {
5
- super()
6
- this.ready()
3
+ import { HomebridgePluginUiServer, RequestError } from '@homebridge/plugin-ui-utils'
4
+
5
+ const server = new HomebridgePluginUiServer()
6
+
7
+ server.onRequest('/devices', async () => {
8
+ try {
9
+ const cfgPath = server.homebridgeConfigPath
10
+ if (!cfgPath) {
11
+ throw new Error('HOMEBRIDGE_CONFIG_PATH not set')
12
+ }
13
+
14
+ const raw = await fs.readFile(cfgPath, 'utf8')
15
+ const cfg = JSON.parse(raw)
16
+ const found: Array<{ id: string, name?: string, type?: string, connectionPreference?: string, room?: string }> = []
17
+
18
+ const platforms = Array.isArray(cfg.platforms) ? cfg.platforms : []
19
+ for (const p of platforms) {
20
+ try {
21
+ const platformName = p.platform || p.name || ''
22
+ // Match known SwitchBot platform identifiers
23
+ if (!platformName || !/switchbot/i.test(String(platformName))) {
24
+ continue
25
+ }
26
+
27
+ const options = p.options || p
28
+ const devices = Array.isArray(options.devices) ? options.devices : []
29
+ for (const d of devices) {
30
+ const id = d.deviceId ?? d.id
31
+ if (!id) {
32
+ continue
33
+ }
34
+
35
+ found.push({
36
+ id,
37
+ name: d.configDeviceName ?? d.name ?? d.deviceName,
38
+ type: d.configDeviceType ?? d.type ?? d.deviceType,
39
+ connectionPreference: d.connectionPreference ?? d.connection ?? 'auto',
40
+ room: d.room || d.location || undefined,
41
+ })
42
+ }
43
+ } catch (e) {
44
+ // ignore malformed platform entries
45
+ }
46
+ }
47
+
48
+ return found
49
+ } catch (e) {
50
+ throw new RequestError('Failed to read Homebridge config', e)
7
51
  }
8
- }
52
+ })
9
53
 
10
- function startPluginUiServer(): PluginUiServer {
11
- return new PluginUiServer()
12
- }
54
+ server.ready()
13
55
 
14
- startPluginUiServer()
56
+ export default server
package/src/index.ts CHANGED
@@ -4,14 +4,12 @@
4
4
  */
5
5
  import type { API } from 'homebridge'
6
6
 
7
- import { SwitchBotHAPPlatform } from './platform-hap.js'
8
- import { SwitchBotMatterPlatform } from './platform-matter.js'
7
+ import { SwitchBotHAPPlatform, SwitchBotMatterPlatform } from './platform.js'
9
8
  import { PLATFORM_NAME, PLUGIN_NAME } from './settings.js'
10
9
  import { createPlatformProxy } from './utils.js'
11
10
 
12
11
  // Register our platform with homebridge.
13
12
  export default (api: API): void => {
14
- // Create and register a small proxy that selects the correct platform (HAP or Matter) at runtime.
15
13
  const ProxyCtor = createPlatformProxy(SwitchBotHAPPlatform, SwitchBotMatterPlatform)
16
14
  api.registerPlatform(PLUGIN_NAME, PLATFORM_NAME, ProxyCtor as any)
17
15
  }