@switchbot/homebridge-switchbot 5.0.0-beta.13 → 5.0.0-beta.131

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 (593) hide show
  1. package/.github/ISSUE_TEMPLATE/e2e-verification.md +36 -0
  2. package/.github/copilot-instructions.md +39 -0
  3. package/.github/workflows/ci.yml +32 -0
  4. package/.github/workflows/manual-e2e.yml +115 -0
  5. package/.github/workflows/release.yml +0 -4
  6. package/CHANGELOG.md +35 -0
  7. package/E2E-VERIFICATION.md +121 -0
  8. package/MIGRATION.md +54 -0
  9. package/README.md +99 -3
  10. package/TODO.md +263 -0
  11. package/config.schema.json +198 -14787
  12. package/dist/device-types.d.ts +31 -0
  13. package/dist/device-types.d.ts.map +1 -0
  14. package/dist/device-types.js +246 -0
  15. package/dist/device-types.js.map +1 -0
  16. package/dist/deviceFactory.d.ts +13 -0
  17. package/dist/deviceFactory.d.ts.map +1 -0
  18. package/dist/deviceFactory.js +165 -0
  19. package/dist/deviceFactory.js.map +1 -0
  20. package/dist/devices/deviceBase.d.ts +50 -0
  21. package/dist/devices/deviceBase.d.ts.map +1 -0
  22. package/dist/devices/deviceBase.js +119 -0
  23. package/dist/devices/deviceBase.js.map +1 -0
  24. package/dist/devices/genericDevice.d.ts +277 -0
  25. package/dist/devices/genericDevice.d.ts.map +1 -0
  26. package/dist/devices/genericDevice.js +1396 -0
  27. package/dist/devices/genericDevice.js.map +1 -0
  28. package/dist/errors.d.ts +5 -0
  29. package/dist/errors.d.ts.map +1 -0
  30. package/dist/errors.js +51 -0
  31. package/dist/errors.js.map +1 -0
  32. package/dist/homebridge-ui/endpoints/config.d.ts +3 -0
  33. package/dist/homebridge-ui/endpoints/config.d.ts.map +1 -0
  34. package/dist/homebridge-ui/endpoints/config.js +107 -0
  35. package/dist/homebridge-ui/endpoints/config.js.map +1 -0
  36. package/dist/homebridge-ui/endpoints/credentials.d.ts +6 -0
  37. package/dist/homebridge-ui/endpoints/credentials.d.ts.map +1 -0
  38. package/dist/homebridge-ui/endpoints/credentials.js +65 -0
  39. package/dist/homebridge-ui/endpoints/credentials.js.map +1 -0
  40. package/dist/homebridge-ui/endpoints/devices.d.ts +6 -0
  41. package/dist/homebridge-ui/endpoints/devices.d.ts.map +1 -0
  42. package/dist/homebridge-ui/endpoints/devices.js +430 -0
  43. package/dist/homebridge-ui/endpoints/devices.js.map +1 -0
  44. package/dist/homebridge-ui/endpoints/discovery.d.ts +7 -0
  45. package/dist/homebridge-ui/endpoints/discovery.d.ts.map +1 -0
  46. package/dist/homebridge-ui/endpoints/discovery.js +212 -0
  47. package/dist/homebridge-ui/endpoints/discovery.js.map +1 -0
  48. package/dist/homebridge-ui/public/css/styles.css +447 -0
  49. package/dist/homebridge-ui/public/index.html +144 -248
  50. package/dist/homebridge-ui/public/js/api.d.ts +62 -0
  51. package/dist/homebridge-ui/public/js/api.d.ts.map +1 -0
  52. package/dist/homebridge-ui/public/js/api.js +225 -0
  53. package/dist/homebridge-ui/public/js/api.js.map +1 -0
  54. package/dist/homebridge-ui/public/js/api.ts +279 -0
  55. package/dist/homebridge-ui/public/js/app.d.ts +2 -0
  56. package/dist/homebridge-ui/public/js/app.d.ts.map +1 -0
  57. package/dist/homebridge-ui/public/js/app.js +3600 -0
  58. package/dist/homebridge-ui/public/js/app.js.map +7 -0
  59. package/dist/homebridge-ui/public/js/app.ts +23 -0
  60. package/dist/homebridge-ui/public/js/constants.d.ts +2 -0
  61. package/dist/homebridge-ui/public/js/constants.d.ts.map +1 -0
  62. package/dist/homebridge-ui/public/js/constants.js +2 -0
  63. package/dist/homebridge-ui/public/js/constants.js.map +1 -0
  64. package/dist/homebridge-ui/public/js/constants.ts +1 -0
  65. package/dist/homebridge-ui/public/js/credentials.d.ts +3 -0
  66. package/dist/homebridge-ui/public/js/credentials.d.ts.map +1 -0
  67. package/dist/homebridge-ui/public/js/credentials.js +96 -0
  68. package/dist/homebridge-ui/public/js/credentials.js.map +1 -0
  69. package/dist/homebridge-ui/public/js/credentials.ts +100 -0
  70. package/dist/homebridge-ui/public/js/devices-delete.d.ts +3 -0
  71. package/dist/homebridge-ui/public/js/devices-delete.d.ts.map +1 -0
  72. package/dist/homebridge-ui/public/js/devices-delete.js +206 -0
  73. package/dist/homebridge-ui/public/js/devices-delete.js.map +1 -0
  74. package/dist/homebridge-ui/public/js/devices-delete.ts +236 -0
  75. package/dist/homebridge-ui/public/js/devices.d.ts +9 -0
  76. package/dist/homebridge-ui/public/js/devices.d.ts.map +1 -0
  77. package/dist/homebridge-ui/public/js/devices.js +94 -0
  78. package/dist/homebridge-ui/public/js/devices.js.map +1 -0
  79. package/dist/homebridge-ui/public/js/devices.ts +114 -0
  80. package/dist/homebridge-ui/public/js/discovery.d.ts +4 -0
  81. package/dist/homebridge-ui/public/js/discovery.d.ts.map +1 -0
  82. package/dist/homebridge-ui/public/js/discovery.js +1364 -0
  83. package/dist/homebridge-ui/public/js/discovery.js.map +1 -0
  84. package/dist/homebridge-ui/public/js/discovery.ts +1492 -0
  85. package/dist/homebridge-ui/public/js/logger.d.ts +6 -0
  86. package/dist/homebridge-ui/public/js/logger.d.ts.map +1 -0
  87. package/dist/homebridge-ui/public/js/logger.js +12 -0
  88. package/dist/homebridge-ui/public/js/logger.js.map +1 -0
  89. package/dist/homebridge-ui/public/js/logger.ts +11 -0
  90. package/dist/homebridge-ui/public/js/modal.d.ts +5 -0
  91. package/dist/homebridge-ui/public/js/modal.d.ts.map +1 -0
  92. package/dist/homebridge-ui/public/js/modal.js +26 -0
  93. package/dist/homebridge-ui/public/js/modal.js.map +1 -0
  94. package/dist/homebridge-ui/public/js/modal.ts +28 -0
  95. package/dist/homebridge-ui/public/js/modals.d.ts +7 -0
  96. package/dist/homebridge-ui/public/js/modals.d.ts.map +1 -0
  97. package/dist/homebridge-ui/public/js/modals.js +494 -0
  98. package/dist/homebridge-ui/public/js/modals.js.map +1 -0
  99. package/dist/homebridge-ui/public/js/modals.ts +546 -0
  100. package/dist/homebridge-ui/public/js/render.d.ts +68 -0
  101. package/dist/homebridge-ui/public/js/render.d.ts.map +1 -0
  102. package/dist/homebridge-ui/public/js/render.js +914 -0
  103. package/dist/homebridge-ui/public/js/render.js.map +1 -0
  104. package/dist/homebridge-ui/public/js/render.ts +1026 -0
  105. package/dist/homebridge-ui/public/js/toast.d.ts +6 -0
  106. package/dist/homebridge-ui/public/js/toast.d.ts.map +1 -0
  107. package/dist/homebridge-ui/public/js/toast.js +29 -0
  108. package/dist/homebridge-ui/public/js/toast.js.map +1 -0
  109. package/dist/homebridge-ui/public/js/toast.ts +37 -0
  110. package/dist/homebridge-ui/public/js/types.d.ts +23 -0
  111. package/dist/homebridge-ui/public/js/types.d.ts.map +1 -0
  112. package/dist/homebridge-ui/public/js/types.js +2 -0
  113. package/dist/homebridge-ui/public/js/types.js.map +1 -0
  114. package/dist/homebridge-ui/public/js/types.ts +26 -0
  115. package/dist/homebridge-ui/server.js +11 -41
  116. package/dist/homebridge-ui/server.js.map +1 -1
  117. package/dist/homebridge-ui/utils/config-parser.d.ts +35 -0
  118. package/dist/homebridge-ui/utils/config-parser.d.ts.map +1 -0
  119. package/dist/homebridge-ui/utils/config-parser.js +87 -0
  120. package/dist/homebridge-ui/utils/config-parser.js.map +1 -0
  121. package/dist/homebridge-ui/utils/device-migration.d.ts +35 -0
  122. package/dist/homebridge-ui/utils/device-migration.d.ts.map +1 -0
  123. package/dist/homebridge-ui/utils/device-migration.js +111 -0
  124. package/dist/homebridge-ui/utils/device-migration.js.map +1 -0
  125. package/dist/homebridge-ui/utils/logger.d.ts +7 -0
  126. package/dist/homebridge-ui/utils/logger.d.ts.map +1 -0
  127. package/dist/homebridge-ui/utils/logger.js +17 -0
  128. package/dist/homebridge-ui/utils/logger.js.map +1 -0
  129. package/dist/index.d.ts.map +1 -1
  130. package/dist/index.js +1 -3
  131. package/dist/index.js.map +1 -1
  132. package/dist/platform.d.ts +39 -0
  133. package/dist/platform.d.ts.map +1 -0
  134. package/dist/platform.js +1587 -0
  135. package/dist/platform.js.map +1 -0
  136. package/dist/settings.d.ts +10 -249
  137. package/dist/settings.d.ts.map +1 -1
  138. package/dist/settings.js +5 -30
  139. package/dist/settings.js.map +1 -1
  140. package/dist/switchbotClient.d.ts +32 -0
  141. package/dist/switchbotClient.d.ts.map +1 -0
  142. package/dist/switchbotClient.js +253 -0
  143. package/dist/switchbotClient.js.map +1 -0
  144. package/dist/utils.d.ts +36 -82
  145. package/dist/utils.d.ts.map +1 -1
  146. package/dist/utils.js +40 -786
  147. package/dist/utils.js.map +1 -1
  148. package/docs/assets/highlight.css +21 -0
  149. package/docs/assets/icons.js +1 -1
  150. package/docs/assets/icons.svg +1 -1
  151. package/docs/assets/main.js +2 -2
  152. package/docs/assets/style.css +3 -3
  153. package/docs/index.html +103 -13
  154. package/docs/variables/default.html +1 -1
  155. package/eslint.config.js +7 -8
  156. package/nodemon.json +2 -2
  157. package/package.json +36 -32
  158. package/scripts/build-ui.js +36 -0
  159. package/scripts/e2e/README.md +25 -0
  160. package/scripts/e2e/curtain-e2e.sh +70 -0
  161. package/scripts/e2e/fan-e2e.sh +75 -0
  162. package/scripts/e2e/light-advanced-e2e.sh +97 -0
  163. package/scripts/e2e/light-e2e.sh +75 -0
  164. package/scripts/e2e/list-accessories.sh +19 -0
  165. package/scripts/e2e/lock-e2e.sh +65 -0
  166. package/scripts/free-dev-ports.mjs +105 -0
  167. package/scripts/generate-matter-maps.js +60 -0
  168. package/scripts/run-e2e-local.sh +14 -0
  169. package/scripts/sync-device-types.mjs +28 -0
  170. package/src/device-types.ts +261 -0
  171. package/src/deviceFactory.ts +208 -0
  172. package/src/devices/deviceBase.ts +141 -0
  173. package/src/devices/genericDevice.ts +1345 -0
  174. package/src/errors.ts +43 -0
  175. package/src/homebridge-ui/endpoints/config.ts +126 -0
  176. package/src/homebridge-ui/endpoints/credentials.ts +74 -0
  177. package/src/homebridge-ui/endpoints/devices.ts +464 -0
  178. package/src/homebridge-ui/endpoints/discovery.ts +233 -0
  179. package/src/homebridge-ui/public/css/styles.css +447 -0
  180. package/src/homebridge-ui/public/index.html +144 -248
  181. package/src/homebridge-ui/public/js/api.ts +279 -0
  182. package/src/homebridge-ui/public/js/app.ts +23 -0
  183. package/src/homebridge-ui/public/js/constants.ts +1 -0
  184. package/src/homebridge-ui/public/js/credentials.ts +100 -0
  185. package/src/homebridge-ui/public/js/devices-delete.ts +236 -0
  186. package/src/homebridge-ui/public/js/devices.ts +114 -0
  187. package/src/homebridge-ui/public/js/discovery.ts +1492 -0
  188. package/src/homebridge-ui/public/js/logger.ts +11 -0
  189. package/src/homebridge-ui/public/js/modal.ts +28 -0
  190. package/src/homebridge-ui/public/js/modals.ts +546 -0
  191. package/src/homebridge-ui/public/js/render.ts +1026 -0
  192. package/src/homebridge-ui/public/js/toast.ts +37 -0
  193. package/src/homebridge-ui/public/js/types.ts +26 -0
  194. package/src/homebridge-ui/server.ts +11 -43
  195. package/src/homebridge-ui/utils/config-parser.ts +108 -0
  196. package/src/homebridge-ui/utils/device-migration.ts +144 -0
  197. package/src/homebridge-ui/utils/logger.ts +17 -0
  198. package/src/index.ts +1 -3
  199. package/src/platform.ts +1601 -0
  200. package/src/settings.ts +12 -277
  201. package/src/switchbotClient.ts +251 -0
  202. package/src/utils.ts +48 -812
  203. package/test/accessory-restore.spec.ts +73 -0
  204. package/test/device-mapping.spec.ts +37 -0
  205. package/test/deviceFactory.spec.ts +18 -0
  206. package/test/e2e/run-e2e.spec.ts +52 -0
  207. package/test/fan-swing.spec.ts +29 -0
  208. package/test/helpers/matter-harness.ts +53 -0
  209. package/test/lock-users.spec.ts +44 -0
  210. package/test/matter-childbridge.spec.ts +59 -0
  211. package/test/matter-descriptors.spec.ts +110 -0
  212. package/test/matter-device-state.spec.ts +101 -0
  213. package/test/matter-integration.spec.ts +136 -0
  214. package/test/platform.integration.spec.ts +55 -0
  215. package/test/switchbot-client-debounce.spec.ts +131 -0
  216. package/test/switchbot-client-openapi.spec.ts +56 -0
  217. package/test/switchbotClient.spec.ts +10 -0
  218. package/test/utils.spec.ts +36 -0
  219. package/todo/COMPLETED.md +542 -0
  220. package/todo/README.md +59 -0
  221. package/todo/TODO.md +190 -0
  222. package/todo/mockups/filtering-sorting.svg +112 -0
  223. package/todo/mockups/modal-switchbot-theme.svg +66 -0
  224. package/todo/mockups/signal-strength-visualization.svg +94 -0
  225. package/vitest.config.ts +7 -0
  226. package/coverage/base.css +0 -224
  227. package/coverage/block-navigation.js +0 -87
  228. package/coverage/clover.xml +0 -15847
  229. package/coverage/coverage-final.json +0 -42
  230. package/coverage/docs/assets/dmt/dmt-component-data.js.html +0 -85
  231. package/coverage/docs/assets/dmt/dmt-components.js.html +0 -286
  232. package/coverage/docs/assets/dmt/index.html +0 -131
  233. package/coverage/docs/assets/hierarchy.js.html +0 -85
  234. package/coverage/docs/assets/icons.js.html +0 -136
  235. package/coverage/docs/assets/index.html +0 -146
  236. package/coverage/docs/assets/main.js.html +0 -265
  237. package/coverage/favicon.png +0 -0
  238. package/coverage/index.html +0 -191
  239. package/coverage/prettify.css +0 -1
  240. package/coverage/prettify.js +0 -2
  241. package/coverage/sort-arrow-sprite.png +0 -0
  242. package/coverage/sorter.js +0 -196
  243. package/coverage/src/device/blindtilt.ts.html +0 -3238
  244. package/coverage/src/device/bot.ts.html +0 -2803
  245. package/coverage/src/device/ceilinglight.ts.html +0 -2338
  246. package/coverage/src/device/colorbulb.ts.html +0 -2824
  247. package/coverage/src/device/contact.ts.html +0 -1465
  248. package/coverage/src/device/curtain.ts.html +0 -2869
  249. package/coverage/src/device/device.ts.html +0 -2500
  250. package/coverage/src/device/fan.ts.html +0 -2242
  251. package/coverage/src/device/hub.ts.html +0 -1408
  252. package/coverage/src/device/humidifier.ts.html +0 -2116
  253. package/coverage/src/device/index.html +0 -416
  254. package/coverage/src/device/iosensor.ts.html +0 -1375
  255. package/coverage/src/device/lightstrip.ts.html +0 -2617
  256. package/coverage/src/device/lock.ts.html +0 -1963
  257. package/coverage/src/device/meter.ts.html +0 -1372
  258. package/coverage/src/device/meterplus.ts.html +0 -1384
  259. package/coverage/src/device/meterpro.ts.html +0 -1618
  260. package/coverage/src/device/motion.ts.html +0 -1264
  261. package/coverage/src/device/plug.ts.html +0 -1372
  262. package/coverage/src/device/relayswitch.ts.html +0 -2284
  263. package/coverage/src/device/robotvacuumcleaner.ts.html +0 -1810
  264. package/coverage/src/device/waterdetector.ts.html +0 -1294
  265. package/coverage/src/homebridge-ui/index.html +0 -116
  266. package/coverage/src/homebridge-ui/server.ts.html +0 -229
  267. package/coverage/src/index.html +0 -161
  268. package/coverage/src/index.ts.html +0 -124
  269. package/coverage/src/irdevice/airconditioner.ts.html +0 -1687
  270. package/coverage/src/irdevice/airpurifier.ts.html +0 -844
  271. package/coverage/src/irdevice/camera.ts.html +0 -475
  272. package/coverage/src/irdevice/fan.ts.html +0 -766
  273. package/coverage/src/irdevice/index.html +0 -251
  274. package/coverage/src/irdevice/irdevice.ts.html +0 -1117
  275. package/coverage/src/irdevice/light.ts.html +0 -826
  276. package/coverage/src/irdevice/other.ts.html +0 -2458
  277. package/coverage/src/irdevice/tv.ts.html +0 -1222
  278. package/coverage/src/irdevice/vacuumcleaner.ts.html +0 -466
  279. package/coverage/src/irdevice/waterheater.ts.html +0 -469
  280. package/coverage/src/platform.ts.html +0 -8776
  281. package/coverage/src/settings.ts.html +0 -934
  282. package/coverage/src/utils.ts.html +0 -2092
  283. package/dist/baseMatterAccessory.test.d.ts +0 -2
  284. package/dist/baseMatterAccessory.test.d.ts.map +0 -1
  285. package/dist/baseMatterAccessory.test.js +0 -71
  286. package/dist/baseMatterAccessory.test.js.map +0 -1
  287. package/dist/devices-hap/airpurifier.d.ts +0 -54
  288. package/dist/devices-hap/airpurifier.d.ts.map +0 -1
  289. package/dist/devices-hap/airpurifier.js +0 -527
  290. package/dist/devices-hap/airpurifier.js.map +0 -1
  291. package/dist/devices-hap/blindtilt.d.ts +0 -90
  292. package/dist/devices-hap/blindtilt.d.ts.map +0 -1
  293. package/dist/devices-hap/blindtilt.js +0 -974
  294. package/dist/devices-hap/blindtilt.js.map +0 -1
  295. package/dist/devices-hap/bot.d.ts +0 -102
  296. package/dist/devices-hap/bot.d.ts.map +0 -1
  297. package/dist/devices-hap/bot.js +0 -811
  298. package/dist/devices-hap/bot.js.map +0 -1
  299. package/dist/devices-hap/ceilinglight.d.ts +0 -85
  300. package/dist/devices-hap/ceilinglight.d.ts.map +0 -1
  301. package/dist/devices-hap/ceilinglight.js +0 -701
  302. package/dist/devices-hap/ceilinglight.js.map +0 -1
  303. package/dist/devices-hap/colorbulb.d.ts +0 -88
  304. package/dist/devices-hap/colorbulb.d.ts.map +0 -1
  305. package/dist/devices-hap/colorbulb.js +0 -881
  306. package/dist/devices-hap/colorbulb.js.map +0 -1
  307. package/dist/devices-hap/contact.d.ts +0 -44
  308. package/dist/devices-hap/contact.d.ts.map +0 -1
  309. package/dist/devices-hap/contact.js +0 -409
  310. package/dist/devices-hap/contact.js.map +0 -1
  311. package/dist/devices-hap/curtain.d.ts +0 -73
  312. package/dist/devices-hap/curtain.d.ts.map +0 -1
  313. package/dist/devices-hap/curtain.js +0 -869
  314. package/dist/devices-hap/curtain.js.map +0 -1
  315. package/dist/devices-hap/device.d.ts +0 -98
  316. package/dist/devices-hap/device.d.ts.map +0 -1
  317. package/dist/devices-hap/device.js +0 -749
  318. package/dist/devices-hap/device.js.map +0 -1
  319. package/dist/devices-hap/fan.d.ts +0 -69
  320. package/dist/devices-hap/fan.d.ts.map +0 -1
  321. package/dist/devices-hap/fan.js +0 -649
  322. package/dist/devices-hap/fan.js.map +0 -1
  323. package/dist/devices-hap/hub.d.ts +0 -37
  324. package/dist/devices-hap/hub.d.ts.map +0 -1
  325. package/dist/devices-hap/hub.js +0 -392
  326. package/dist/devices-hap/hub.js.map +0 -1
  327. package/dist/devices-hap/humidifier.d.ts +0 -68
  328. package/dist/devices-hap/humidifier.d.ts.map +0 -1
  329. package/dist/devices-hap/humidifier.js +0 -628
  330. package/dist/devices-hap/humidifier.js.map +0 -1
  331. package/dist/devices-hap/iosensor.d.ts +0 -42
  332. package/dist/devices-hap/iosensor.d.ts.map +0 -1
  333. package/dist/devices-hap/iosensor.js +0 -382
  334. package/dist/devices-hap/iosensor.js.map +0 -1
  335. package/dist/devices-hap/lightstrip.d.ts +0 -79
  336. package/dist/devices-hap/lightstrip.d.ts.map +0 -1
  337. package/dist/devices-hap/lightstrip.js +0 -797
  338. package/dist/devices-hap/lightstrip.js.map +0 -1
  339. package/dist/devices-hap/lock.d.ts +0 -53
  340. package/dist/devices-hap/lock.d.ts.map +0 -1
  341. package/dist/devices-hap/lock.js +0 -561
  342. package/dist/devices-hap/lock.js.map +0 -1
  343. package/dist/devices-hap/meter.d.ts +0 -37
  344. package/dist/devices-hap/meter.d.ts.map +0 -1
  345. package/dist/devices-hap/meter.js +0 -379
  346. package/dist/devices-hap/meter.js.map +0 -1
  347. package/dist/devices-hap/meterplus.d.ts +0 -42
  348. package/dist/devices-hap/meterplus.d.ts.map +0 -1
  349. package/dist/devices-hap/meterplus.js +0 -384
  350. package/dist/devices-hap/meterplus.js.map +0 -1
  351. package/dist/devices-hap/meterpro.d.ts +0 -43
  352. package/dist/devices-hap/meterpro.d.ts.map +0 -1
  353. package/dist/devices-hap/meterpro.js +0 -468
  354. package/dist/devices-hap/meterpro.js.map +0 -1
  355. package/dist/devices-hap/motion.d.ts +0 -42
  356. package/dist/devices-hap/motion.d.ts.map +0 -1
  357. package/dist/devices-hap/motion.js +0 -345
  358. package/dist/devices-hap/motion.js.map +0 -1
  359. package/dist/devices-hap/plug.d.ts +0 -49
  360. package/dist/devices-hap/plug.d.ts.map +0 -1
  361. package/dist/devices-hap/plug.js +0 -395
  362. package/dist/devices-hap/plug.js.map +0 -1
  363. package/dist/devices-hap/relayswitch.d.ts +0 -96
  364. package/dist/devices-hap/relayswitch.d.ts.map +0 -1
  365. package/dist/devices-hap/relayswitch.js +0 -642
  366. package/dist/devices-hap/relayswitch.js.map +0 -1
  367. package/dist/devices-hap/robotvacuumcleaner.d.ts +0 -54
  368. package/dist/devices-hap/robotvacuumcleaner.d.ts.map +0 -1
  369. package/dist/devices-hap/robotvacuumcleaner.js +0 -523
  370. package/dist/devices-hap/robotvacuumcleaner.js.map +0 -1
  371. package/dist/devices-hap/waterdetector.d.ts +0 -41
  372. package/dist/devices-hap/waterdetector.d.ts.map +0 -1
  373. package/dist/devices-hap/waterdetector.js +0 -356
  374. package/dist/devices-hap/waterdetector.js.map +0 -1
  375. package/dist/devices-matter/BaseMatterAccessory.d.ts +0 -78
  376. package/dist/devices-matter/BaseMatterAccessory.d.ts.map +0 -1
  377. package/dist/devices-matter/BaseMatterAccessory.js +0 -220
  378. package/dist/devices-matter/BaseMatterAccessory.js.map +0 -1
  379. package/dist/devices-matter/ColorLightAccessory.d.ts +0 -20
  380. package/dist/devices-matter/ColorLightAccessory.d.ts.map +0 -1
  381. package/dist/devices-matter/ColorLightAccessory.js +0 -95
  382. package/dist/devices-matter/ColorLightAccessory.js.map +0 -1
  383. package/dist/devices-matter/ColorTemperatureLightAccessory.d.ts +0 -18
  384. package/dist/devices-matter/ColorTemperatureLightAccessory.d.ts.map +0 -1
  385. package/dist/devices-matter/ColorTemperatureLightAccessory.js +0 -76
  386. package/dist/devices-matter/ColorTemperatureLightAccessory.js.map +0 -1
  387. package/dist/devices-matter/ContactSensorAccessory.d.ts +0 -12
  388. package/dist/devices-matter/ContactSensorAccessory.d.ts.map +0 -1
  389. package/dist/devices-matter/ContactSensorAccessory.js +0 -34
  390. package/dist/devices-matter/ContactSensorAccessory.js.map +0 -1
  391. package/dist/devices-matter/DimmableLightAccessory.d.ts +0 -58
  392. package/dist/devices-matter/DimmableLightAccessory.d.ts.map +0 -1
  393. package/dist/devices-matter/DimmableLightAccessory.js +0 -167
  394. package/dist/devices-matter/DimmableLightAccessory.js.map +0 -1
  395. package/dist/devices-matter/DoorLockAccessory.d.ts +0 -14
  396. package/dist/devices-matter/DoorLockAccessory.d.ts.map +0 -1
  397. package/dist/devices-matter/DoorLockAccessory.js +0 -50
  398. package/dist/devices-matter/DoorLockAccessory.js.map +0 -1
  399. package/dist/devices-matter/ExtendedColorLightAccessory.d.ts +0 -21
  400. package/dist/devices-matter/ExtendedColorLightAccessory.d.ts.map +0 -1
  401. package/dist/devices-matter/ExtendedColorLightAccessory.js +0 -106
  402. package/dist/devices-matter/ExtendedColorLightAccessory.js.map +0 -1
  403. package/dist/devices-matter/FanAccessory.d.ts +0 -16
  404. package/dist/devices-matter/FanAccessory.d.ts.map +0 -1
  405. package/dist/devices-matter/FanAccessory.js +0 -81
  406. package/dist/devices-matter/FanAccessory.js.map +0 -1
  407. package/dist/devices-matter/HumiditySensorAccessory.d.ts +0 -12
  408. package/dist/devices-matter/HumiditySensorAccessory.d.ts.map +0 -1
  409. package/dist/devices-matter/HumiditySensorAccessory.js +0 -34
  410. package/dist/devices-matter/HumiditySensorAccessory.js.map +0 -1
  411. package/dist/devices-matter/LeakSensorAccessory.d.ts +0 -12
  412. package/dist/devices-matter/LeakSensorAccessory.d.ts.map +0 -1
  413. package/dist/devices-matter/LeakSensorAccessory.js +0 -33
  414. package/dist/devices-matter/LeakSensorAccessory.js.map +0 -1
  415. package/dist/devices-matter/LightSensorAccessory.d.ts +0 -12
  416. package/dist/devices-matter/LightSensorAccessory.d.ts.map +0 -1
  417. package/dist/devices-matter/LightSensorAccessory.js +0 -34
  418. package/dist/devices-matter/LightSensorAccessory.js.map +0 -1
  419. package/dist/devices-matter/OccupancySensorAccessory.d.ts +0 -12
  420. package/dist/devices-matter/OccupancySensorAccessory.d.ts.map +0 -1
  421. package/dist/devices-matter/OccupancySensorAccessory.js +0 -39
  422. package/dist/devices-matter/OccupancySensorAccessory.js.map +0 -1
  423. package/dist/devices-matter/OnOffLightAccessory.d.ts +0 -38
  424. package/dist/devices-matter/OnOffLightAccessory.d.ts.map +0 -1
  425. package/dist/devices-matter/OnOffLightAccessory.js +0 -110
  426. package/dist/devices-matter/OnOffLightAccessory.js.map +0 -1
  427. package/dist/devices-matter/OnOffOutletAccessory.d.ts +0 -14
  428. package/dist/devices-matter/OnOffOutletAccessory.d.ts.map +0 -1
  429. package/dist/devices-matter/OnOffOutletAccessory.js +0 -43
  430. package/dist/devices-matter/OnOffOutletAccessory.js.map +0 -1
  431. package/dist/devices-matter/OnOffSwitchAccessory.d.ts +0 -14
  432. package/dist/devices-matter/OnOffSwitchAccessory.d.ts.map +0 -1
  433. package/dist/devices-matter/OnOffSwitchAccessory.js +0 -42
  434. package/dist/devices-matter/OnOffSwitchAccessory.js.map +0 -1
  435. package/dist/devices-matter/RoboticVacuumAccessory.d.ts +0 -68
  436. package/dist/devices-matter/RoboticVacuumAccessory.d.ts.map +0 -1
  437. package/dist/devices-matter/RoboticVacuumAccessory.js +0 -334
  438. package/dist/devices-matter/RoboticVacuumAccessory.js.map +0 -1
  439. package/dist/devices-matter/SmokeCOAlarmAccessory.d.ts +0 -11
  440. package/dist/devices-matter/SmokeCOAlarmAccessory.d.ts.map +0 -1
  441. package/dist/devices-matter/SmokeCOAlarmAccessory.js +0 -49
  442. package/dist/devices-matter/SmokeCOAlarmAccessory.js.map +0 -1
  443. package/dist/devices-matter/TemperatureSensorAccessory.d.ts +0 -12
  444. package/dist/devices-matter/TemperatureSensorAccessory.d.ts.map +0 -1
  445. package/dist/devices-matter/TemperatureSensorAccessory.js +0 -36
  446. package/dist/devices-matter/TemperatureSensorAccessory.js.map +0 -1
  447. package/dist/devices-matter/ThermostatAccessory.d.ts +0 -19
  448. package/dist/devices-matter/ThermostatAccessory.d.ts.map +0 -1
  449. package/dist/devices-matter/ThermostatAccessory.js +0 -95
  450. package/dist/devices-matter/ThermostatAccessory.js.map +0 -1
  451. package/dist/devices-matter/VenetianBlindAccessory.d.ts +0 -19
  452. package/dist/devices-matter/VenetianBlindAccessory.d.ts.map +0 -1
  453. package/dist/devices-matter/VenetianBlindAccessory.js +0 -99
  454. package/dist/devices-matter/VenetianBlindAccessory.js.map +0 -1
  455. package/dist/devices-matter/WindowBlindAccessory.d.ts +0 -17
  456. package/dist/devices-matter/WindowBlindAccessory.d.ts.map +0 -1
  457. package/dist/devices-matter/WindowBlindAccessory.js +0 -80
  458. package/dist/devices-matter/WindowBlindAccessory.js.map +0 -1
  459. package/dist/devices-matter/custom/PowerStripAccessory.d.ts +0 -97
  460. package/dist/devices-matter/custom/PowerStripAccessory.d.ts.map +0 -1
  461. package/dist/devices-matter/custom/PowerStripAccessory.js +0 -265
  462. package/dist/devices-matter/custom/PowerStripAccessory.js.map +0 -1
  463. package/dist/devices-matter/custom/index.d.ts +0 -8
  464. package/dist/devices-matter/custom/index.d.ts.map +0 -1
  465. package/dist/devices-matter/custom/index.js +0 -8
  466. package/dist/devices-matter/custom/index.js.map +0 -1
  467. package/dist/devices-matter/index.d.ts +0 -29
  468. package/dist/devices-matter/index.d.ts.map +0 -1
  469. package/dist/devices-matter/index.js +0 -28
  470. package/dist/devices-matter/index.js.map +0 -1
  471. package/dist/index.test.d.ts +0 -2
  472. package/dist/index.test.d.ts.map +0 -1
  473. package/dist/index.test.js +0 -19
  474. package/dist/index.test.js.map +0 -1
  475. package/dist/irdevice/airconditioner.d.ts +0 -61
  476. package/dist/irdevice/airconditioner.d.ts.map +0 -1
  477. package/dist/irdevice/airconditioner.js +0 -472
  478. package/dist/irdevice/airconditioner.js.map +0 -1
  479. package/dist/irdevice/airpurifier.d.ts +0 -50
  480. package/dist/irdevice/airpurifier.d.ts.map +0 -1
  481. package/dist/irdevice/airpurifier.js +0 -213
  482. package/dist/irdevice/airpurifier.js.map +0 -1
  483. package/dist/irdevice/camera.d.ts +0 -32
  484. package/dist/irdevice/camera.d.ts.map +0 -1
  485. package/dist/irdevice/camera.js +0 -107
  486. package/dist/irdevice/camera.js.map +0 -1
  487. package/dist/irdevice/fan.d.ts +0 -36
  488. package/dist/irdevice/fan.d.ts.map +0 -1
  489. package/dist/irdevice/fan.js +0 -200
  490. package/dist/irdevice/fan.js.map +0 -1
  491. package/dist/irdevice/irdevice.d.ts +0 -68
  492. package/dist/irdevice/irdevice.d.ts.map +0 -1
  493. package/dist/irdevice/irdevice.js +0 -298
  494. package/dist/irdevice/irdevice.js.map +0 -1
  495. package/dist/irdevice/light.d.ts +0 -36
  496. package/dist/irdevice/light.d.ts.map +0 -1
  497. package/dist/irdevice/light.js +0 -206
  498. package/dist/irdevice/light.js.map +0 -1
  499. package/dist/irdevice/other.d.ts +0 -57
  500. package/dist/irdevice/other.d.ts.map +0 -1
  501. package/dist/irdevice/other.js +0 -778
  502. package/dist/irdevice/other.js.map +0 -1
  503. package/dist/irdevice/tv.d.ts +0 -45
  504. package/dist/irdevice/tv.d.ts.map +0 -1
  505. package/dist/irdevice/tv.js +0 -327
  506. package/dist/irdevice/tv.js.map +0 -1
  507. package/dist/irdevice/vacuumcleaner.d.ts +0 -28
  508. package/dist/irdevice/vacuumcleaner.d.ts.map +0 -1
  509. package/dist/irdevice/vacuumcleaner.js +0 -104
  510. package/dist/irdevice/vacuumcleaner.js.map +0 -1
  511. package/dist/irdevice/waterheater.d.ts +0 -30
  512. package/dist/irdevice/waterheater.d.ts.map +0 -1
  513. package/dist/irdevice/waterheater.js +0 -105
  514. package/dist/irdevice/waterheater.js.map +0 -1
  515. package/dist/platform-hap.d.ts +0 -149
  516. package/dist/platform-hap.d.ts.map +0 -1
  517. package/dist/platform-hap.js +0 -2861
  518. package/dist/platform-hap.js.map +0 -1
  519. package/dist/platform-matter.d.ts +0 -120
  520. package/dist/platform-matter.d.ts.map +0 -1
  521. package/dist/platform-matter.js +0 -999
  522. package/dist/platform-matter.js.map +0 -1
  523. package/dist/utils.test.d.ts +0 -2
  524. package/dist/utils.test.d.ts.map +0 -1
  525. package/dist/utils.test.js +0 -95
  526. package/dist/utils.test.js.map +0 -1
  527. package/dist/verifyconfig.test.d.ts +0 -2
  528. package/dist/verifyconfig.test.d.ts.map +0 -1
  529. package/dist/verifyconfig.test.js +0 -167
  530. package/dist/verifyconfig.test.js.map +0 -1
  531. package/src/baseMatterAccessory.test.ts +0 -88
  532. package/src/custom.d.ts +0 -7
  533. package/src/devices-hap/airpurifier.ts +0 -563
  534. package/src/devices-hap/blindtilt.ts +0 -1049
  535. package/src/devices-hap/bot.ts +0 -900
  536. package/src/devices-hap/ceilinglight.ts +0 -742
  537. package/src/devices-hap/colorbulb.ts +0 -904
  538. package/src/devices-hap/contact.ts +0 -457
  539. package/src/devices-hap/curtain.ts +0 -944
  540. package/src/devices-hap/device.ts +0 -811
  541. package/src/devices-hap/fan.ts +0 -711
  542. package/src/devices-hap/hub.ts +0 -439
  543. package/src/devices-hap/humidifier.ts +0 -669
  544. package/src/devices-hap/iosensor.ts +0 -427
  545. package/src/devices-hap/lightstrip.ts +0 -836
  546. package/src/devices-hap/lock.ts +0 -620
  547. package/src/devices-hap/meter.ts +0 -426
  548. package/src/devices-hap/meterplus.ts +0 -430
  549. package/src/devices-hap/meterpro.ts +0 -522
  550. package/src/devices-hap/motion.ts +0 -390
  551. package/src/devices-hap/plug.ts +0 -423
  552. package/src/devices-hap/relayswitch.ts +0 -727
  553. package/src/devices-hap/robotvacuumcleaner.ts +0 -568
  554. package/src/devices-hap/waterdetector.ts +0 -400
  555. package/src/devices-matter/BaseMatterAccessory.ts +0 -249
  556. package/src/devices-matter/ColorLightAccessory.ts +0 -110
  557. package/src/devices-matter/ColorTemperatureLightAccessory.ts +0 -90
  558. package/src/devices-matter/ContactSensorAccessory.ts +0 -41
  559. package/src/devices-matter/DimmableLightAccessory.ts +0 -192
  560. package/src/devices-matter/DoorLockAccessory.ts +0 -60
  561. package/src/devices-matter/ExtendedColorLightAccessory.ts +0 -122
  562. package/src/devices-matter/FanAccessory.ts +0 -95
  563. package/src/devices-matter/HumiditySensorAccessory.ts +0 -41
  564. package/src/devices-matter/LeakSensorAccessory.ts +0 -40
  565. package/src/devices-matter/LightSensorAccessory.ts +0 -41
  566. package/src/devices-matter/OccupancySensorAccessory.ts +0 -48
  567. package/src/devices-matter/OnOffLightAccessory.ts +0 -125
  568. package/src/devices-matter/OnOffOutletAccessory.ts +0 -51
  569. package/src/devices-matter/OnOffSwitchAccessory.ts +0 -51
  570. package/src/devices-matter/RoboticVacuumAccessory.ts +0 -407
  571. package/src/devices-matter/SmokeCOAlarmAccessory.ts +0 -59
  572. package/src/devices-matter/TemperatureSensorAccessory.ts +0 -43
  573. package/src/devices-matter/ThermostatAccessory.ts +0 -110
  574. package/src/devices-matter/VenetianBlindAccessory.ts +0 -115
  575. package/src/devices-matter/WindowBlindAccessory.ts +0 -92
  576. package/src/devices-matter/custom/PowerStripAccessory.ts +0 -309
  577. package/src/devices-matter/custom/index.ts +0 -8
  578. package/src/devices-matter/index.ts +0 -29
  579. package/src/index.test.ts +0 -24
  580. package/src/irdevice/airconditioner.ts +0 -533
  581. package/src/irdevice/airpurifier.ts +0 -252
  582. package/src/irdevice/camera.ts +0 -129
  583. package/src/irdevice/fan.ts +0 -226
  584. package/src/irdevice/irdevice.ts +0 -344
  585. package/src/irdevice/light.ts +0 -246
  586. package/src/irdevice/other.ts +0 -790
  587. package/src/irdevice/tv.ts +0 -378
  588. package/src/irdevice/vacuumcleaner.ts +0 -126
  589. package/src/irdevice/waterheater.ts +0 -127
  590. package/src/platform-hap.ts +0 -2997
  591. package/src/platform-matter.ts +0 -1124
  592. package/src/utils.test.ts +0 -96
  593. package/src/verifyconfig.test.ts +0 -197
@@ -0,0 +1,36 @@
1
+ ---
2
+ name: E2E Verification Results
3
+ about: Submit manual E2E test results for homebridge-switchbot changes (Matter + node-switchbot v4)
4
+ title: "[E2E] <device-type> verification"
5
+ labels: e2e, testing
6
+ assignees: ''
7
+ ---
8
+
9
+ ### Environment
10
+ - Homebridge version:
11
+ - Plugin commit / branch:
12
+ - macOS version:
13
+ - Bluetooth available: (yes/no)
14
+ - openApiToken used: (yes/no)
15
+
16
+ ### Device under test
17
+ - Device type: (Light / Fan / Curtain / Lock)
18
+ - Device model:
19
+ - Connection used: (BLE / OpenAPI)
20
+
21
+ ### Steps performed
22
+ - Start Homebridge with plugin linked/built
23
+ - Verified Matter registration: (yes/no)
24
+ - Verified HAP fallback when Matter unavailable: (yes/no)
25
+ - Operations tested: (list)
26
+
27
+ ### Results
28
+ - Observed behavior (brief):
29
+ - Any errors in plugin logs (paste relevant snippets):
30
+
31
+ ### Verdict
32
+ - Pass/Fail:
33
+ - Notes and follow-ups:
34
+
35
+ ### Attachments
36
+ - Logs, screenshots, videos
@@ -2,6 +2,45 @@
2
2
 
3
3
  Always reference these instructions first and fallback to search or bash commands only when you encounter unexpected information that does not match the info here.
4
4
 
5
+ ## Topic-Based Reference Priority
6
+
7
+ When a prompt includes the topics below, consult these upstream references first before implementation decisions.
8
+
9
+ ### Matter (keyword examples: "Matter", "child bridge", "cluster", "conformance")
10
+
11
+ Primary references:
12
+ - https://github.com/homebridge-plugins/homebridge-matter
13
+ - https://github.com/homebridge/homebridge/ - only if latest is 2.0.0 or later and contains Matter-related code or reference:
14
+ - https://github.com/homebridge/homebridge/tree/beta-2.0.0/
15
+ - https://github.com/matter-js/matter.js
16
+
17
+ Usage rule:
18
+ - For Matter behavior, conformance, clustering, or registration logic, align implementation with these references before applying local changes.
19
+
20
+ ### SwitchBot BLE (keyword examples: "BLE", "Bluetooth", "RSSI", "advertisement", "scan")
21
+
22
+ Primary references:
23
+ - https://github.com/OpenWonderLabs/SwitchBotAPI-BLE
24
+ - https://github.com/sblibs/pySwitchbot
25
+
26
+ Usage rule:
27
+ - For BLE command/state/scan behavior, prefer these references for protocol expectations and payload shape.
28
+
29
+ ### SwitchBot OpenAPI (keyword examples: "OpenAPI", "cloud API", "device list", "command")
30
+
31
+ Primary reference:
32
+ - https://github.com/OpenWonderLabs/SwitchBotAPI
33
+
34
+ Usage rule:
35
+ - For OpenAPI device models, commands, and response fields, prioritize this reference for compatibility.
36
+
37
+ ### Conflict Resolution
38
+
39
+ If references conflict:
40
+ 1. Prefer official upstream docs/API specs.
41
+ 2. Keep existing plugin behavior unless a clear bug is identified.
42
+ 3. Document any intentional deviation in PR notes.
43
+
5
44
  ## Branch Targeting Strategy
6
45
 
7
46
  When creating pull requests, ALWAYS follow this branch targeting strategy:
@@ -0,0 +1,32 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: ["main", "latest", "beta-*"]
6
+ pull_request:
7
+ branches: ["main", "latest"]
8
+
9
+ jobs:
10
+ build-and-test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ node-version: [20, 22]
15
+
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - name: Setup Node.js
20
+ uses: actions/setup-node@v4
21
+ with:
22
+ node-version: ${{ matrix.node-version }}
23
+ cache: 'npm'
24
+
25
+ - name: Install dependencies
26
+ run: npm ci --legacy-peer-deps
27
+
28
+ - name: Build
29
+ run: npm run build
30
+
31
+ - name: Run tests
32
+ run: npm run test
@@ -0,0 +1,115 @@
1
+ name: Manual E2E (build + optional E2E)
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ run_e2e:
7
+ description: 'Set to true to run the E2E scripts (requires network-accessible Homebridge and valid tokens)'
8
+ required: false
9
+ default: 'false'
10
+ hb_url:
11
+ description: 'Homebridge UI URL (e.g. http://host:8581)'
12
+ required: false
13
+ hb_token:
14
+ description: 'Homebridge UI token (store as secret or pass here)'
15
+ required: false
16
+ light_accessory_id:
17
+ description: 'Accessory ID for light (when running E2E)'
18
+ required: false
19
+ fan_accessory_id:
20
+ description: 'Accessory ID for fan (when running E2E)'
21
+ required: false
22
+ curtain_accessory_id:
23
+ description: 'Accessory ID for curtain (when running E2E)'
24
+ required: false
25
+ lock_accessory_id:
26
+ description: 'Accessory ID for lock (when running E2E)'
27
+ required: false
28
+ light_accessory_name:
29
+ description: 'Accessory display name for light (optional, used to resolve ID)'
30
+ required: false
31
+ fan_accessory_name:
32
+ description: 'Accessory display name for fan (optional, used to resolve ID)'
33
+ required: false
34
+ curtain_accessory_name:
35
+ description: 'Accessory display name for curtain (optional, used to resolve ID)'
36
+ required: false
37
+ lock_accessory_name:
38
+ description: 'Accessory display name for lock (optional, used to resolve ID)'
39
+ required: false
40
+
41
+ jobs:
42
+ build-and-test:
43
+ runs-on: ubuntu-latest
44
+ steps:
45
+ - name: Checkout
46
+ uses: actions/checkout@v4
47
+
48
+ - name: Setup Node
49
+ uses: actions/setup-node@v4
50
+ with:
51
+ node-version: '18'
52
+
53
+ - name: Install dependencies
54
+ run: npm ci --prefer-offline --no-audit --progress=false
55
+
56
+ - name: Build
57
+ run: npm run build
58
+
59
+ - name: Run unit tests
60
+ run: npm run test
61
+
62
+ - name: "Optional: Run E2E scripts"
63
+ if: ${{ github.event.inputs.run_e2e == 'true' }}
64
+ env:
65
+ HB_URL: ${{ github.event.inputs.hb_url }}
66
+ HB_TOKEN: ${{ github.event.inputs.hb_token }}
67
+ LIGHT_ACCESSORY_ID: ${{ github.event.inputs.light_accessory_id }}
68
+ FAN_ACCESSORY_ID: ${{ github.event.inputs.fan_accessory_id }}
69
+ CURTAIN_ACCESSORY_ID: ${{ github.event.inputs.curtain_accessory_id }}
70
+ LOCK_ACCESSORY_ID: ${{ github.event.inputs.lock_accessory_id }}
71
+ LIGHT_ACCESSORY_NAME: ${{ github.event.inputs.light_accessory_name }}
72
+ FAN_ACCESSORY_NAME: ${{ github.event.inputs.fan_accessory_name }}
73
+ CURTAIN_ACCESSORY_NAME: ${{ github.event.inputs.curtain_accessory_name }}
74
+ LOCK_ACCESSORY_NAME: ${{ github.event.inputs.lock_accessory_name }}
75
+ run: |
76
+ echo "Running E2E scripts on runner ($HB_URL) - ensure the runner can access Homebridge and devices"
77
+ # resolve accessory IDs from names when IDs not provided
78
+ echo "Resolving accessory IDs from names (if provided)..."
79
+ rm -f resolved_ids.env || true
80
+ touch resolved_ids.env
81
+
82
+ resolve() {
83
+ idvar="$1"
84
+ namevar="$2"
85
+ nameval="$(eval echo \"\$$namevar\")"
86
+ idval="$(eval echo \"\$$idvar\")"
87
+ if [[ -z "$idval" && -n "$nameval" ]]; then
88
+ resp=$(curl -sS -H "Authorization: Bearer ${HB_TOKEN}" "${HB_URL}/api/accessories" || true)
89
+ found=$(printf '%s' "$resp" | node -e "const fs=require('fs');const name=process.argv[1];try{const j=JSON.parse(fs.readFileSync(0,'utf8'));const arr=Array.isArray(j)?j:(j.accessories||j)||[];for(const a of arr){if(a.displayName===name||a.name===name||(a.context&&a.context.deviceId===name)){if(a.aid){console.log(a.aid);process.exit(0);}else if(a.UUID){console.log(a.UUID);process.exit(0);}}} }catch(e){}" "$nameval" )
90
+ if [[ -n "$found" ]]; then
91
+ echo "Resolved $idvar=$found"
92
+ echo "$idvar=$found" >> resolved_ids.env
93
+ export "$idvar"="$found"
94
+ else
95
+ echo "Could not resolve $namevar='$nameval' to an id"
96
+ fi
97
+ fi
98
+ }
99
+
100
+ resolve LIGHT_ACCESSORY_ID LIGHT_ACCESSORY_NAME
101
+ resolve FAN_ACCESSORY_ID FAN_ACCESSORY_NAME
102
+ resolve CURTAIN_ACCESSORY_ID CURTAIN_ACCESSORY_NAME
103
+ resolve LOCK_ACCESSORY_ID LOCK_ACCESSORY_NAME
104
+
105
+ # set RUN_E2E so the conditional Vitest harness executes
106
+ export RUN_E2E=true
107
+ npm run test
108
+
109
+ - name: Upload logs (if any)
110
+ if: always()
111
+ uses: actions/upload-artifact@v4
112
+ with:
113
+ name: test-logs
114
+ path: |
115
+ test-output.log
@@ -22,8 +22,6 @@ jobs:
22
22
  with:
23
23
  release_type: ${{ needs.determine-release-type.outputs.release_type }}
24
24
  is_esm: ${{ needs.determine-release-type.outputs.is_esm == 'true' }}
25
- secrets:
26
- NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
27
25
 
28
26
  # 3️⃣ Publish to NPM and create GitHub release
29
27
  publish-release:
@@ -48,8 +46,6 @@ jobs:
48
46
  branch_name: ${{ needs.determine-release-type.outputs.branch_name }}
49
47
  release_type: ${{ needs.determine-release-type.outputs.release_type }}
50
48
  is_esm: ${{ needs.determine-release-type.outputs.is_esm == 'true' }}
51
- secrets:
52
- NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
53
49
 
54
50
  # 5️⃣ Notify if any previous job fails
55
51
  workflow-failure:
package/CHANGELOG.md CHANGED
@@ -1,7 +1,42 @@
1
1
  # Changelog
2
2
 
3
+ ## Unreleased — beta-4.3.3
4
+
5
+ ### Added
6
+ - Matter support (child-bridge) with Matter-first registration and HAP fallback.
7
+ - Hybrid `node-switchbot@4` client adapter (BLE + OpenAPI) with OpenAPI fallback.
8
+ - Manual and automated E2E scripts for lights, fans, curtains, and locks (`scripts/e2e/*`).
9
+ - Conditional Vitest E2E harness (`RUN_E2E=true`) and a manual GitHub Actions workflow to run E2E.
10
+
11
+ ### Changed
12
+ - Centralized Matter cluster/attribute numeric ID maps in `src/utils.ts`.
13
+ - Device descriptors refactored to use canonical Matter IDs.
14
+ - OpenAPI fallback hardened with timeouts, retries, backoff, and per-device retry limits.
15
+
16
+ ### Tests
17
+ - Added integration tests and a Matter test harness under `test/`.
18
+
19
+ ### Notes
20
+ - This is a beta release; follow migration notes in MIGRATION.md before upgrading.
21
+ # Changelog
22
+
3
23
  All notable changes to this project will be documented in this file. This project uses [Semantic Versioning](https://semver.org/)
4
24
 
25
+ ## [Unreleased]
26
+
27
+ ### What's Changed
28
+ - Matter platform: register only devices discovered via the SwitchBot OpenAPI by default. Per-device config overrides (by deviceId) are correctly merged into discovered devices.
29
+ - Add `options.allowConfigOnlyDevices` (boolean) to opt-in to registering devices that exist only in config (not discovered).
30
+ - Add unit tests for per-device merging and config-only behavior.
31
+ - Matter (Matter platform): default to discovery-first registration and automatically remove previously-registered "stale" accessories that are no longer discovered or configured.
32
+ - Add `options.keepStaleAccessories` (Advanced Settings) — opt-in to preserve previously-registered accessories when set to true. Default: false (stale accessories are removed automatically).
33
+ - Implement per-device OpenAPI polling with tracked timers and proper lifecycle cleanup (timers and BLE handlers cleared on unregister/shutdown).
34
+ - Centralize OpenAPI/BLE -> Matter mapping and expand BLE/OpenAPI parsing to include PM2.5/PM10/VOC/CO2, temperature/humidity, improved color parsing, and additional sensor/robot-vacuum fields.
35
+ - Prefer accessory-specific update helpers where available; fall back to generic Matter updates otherwise.
36
+ - Add unit tests covering BLE parsing, stale-accessory behavior, mapping helpers, and lifecycle cleanup.
37
+ - Add `options.dailyApiResetLocalMidnight` (boolean) to control whether the daily API budget resets at local midnight (true) or UTC midnight (false, default).
38
+ - Fix configuration schema placement for the "Reset Daily Counter at Local Midnight" option: remove erroneous insertion inside IR remote type list and expose it correctly under platform `options`.
39
+
5
40
  ## [4.3.1](https://github.com/OpenWonderLabs/homebridge-switchbot/releases/tag/v4.3.1) (2025-03-04)
6
41
 
7
42
  # *No New Releases During Lent*
@@ -0,0 +1,121 @@
1
+ # Manual End-to-End Verification
2
+
3
+ This guide walks through manual end-to-end verification for representative devices (light, fan, curtain, lock) across BLE and OpenAPI paths, and verifies Matter-first behavior with HAP fallback.
4
+
5
+ ## Prerequisites
6
+
7
+ - macOS with Bluetooth (for BLE verification)
8
+ - Local development environment set up (Node.js, npm)
9
+ - Homebridge installed locally or available (for running a test instance)
10
+ - SwitchBot devices available (at least one light, one fan, one curtain, one lock) OR corresponding cloud-hub access
11
+ - `openApiToken` when testing OpenAPI path
12
+
13
+ ## Quick setup
14
+
15
+ 1. Install dependencies:
16
+
17
+ ```bash
18
+ npm install --legacy-peer-deps
19
+ ```
20
+
21
+ 2. Build the plugin:
22
+
23
+ ```bash
24
+ npm run build
25
+ ```
26
+
27
+ 3. Recommended: run the watch task which links the plugin and restarts on changes (requires a local Homebridge installation):
28
+
29
+ ```bash
30
+ npm run watch
31
+ ```
32
+
33
+ Alternative (manual linking):
34
+
35
+ ```bash
36
+ npm run build && npm link
37
+ # then run your Homebridge instance (system/homebridge UI) so it picks up the linked plugin
38
+ ```
39
+
40
+ ## Example platform config snippets
41
+
42
+ OpenAPI (cloud) path — enable Matter preference:
43
+
44
+ ```json
45
+ {
46
+ "platform": "SwitchBot",
47
+ "openApiToken": "<YOUR_OPENAPI_TOKEN>",
48
+ "enableMatter": true,
49
+ "preferMatter": true
50
+ }
51
+ ```
52
+
53
+ BLE (direct) path — specify device by MAC address and prefer Matter:
54
+
55
+ ```json
56
+ {
57
+ "platform": "SwitchBot",
58
+ "devices": [
59
+ { "deviceId": "AA:BB:CC:DD:EE:FF", "type": "Light" }
60
+ ],
61
+ "enableMatter": true,
62
+ "preferMatter": true
63
+ }
64
+ ```
65
+
66
+ ## Verification checklist
67
+
68
+ Run the steps below for each device type; repeat once using BLE and once using OpenAPI (where applicable).
69
+
70
+ - Start Homebridge (with the plugin linked) and verify the plugin logs indicate Matter registration attempt.
71
+ - Look for log lines: `Attempting Matter registration for ...` or `Homebridge Matter API not available; will fallback to HAP`.
72
+ - Confirm accessories are registered in Matter (if Homebridge Matter child-bridge present) or appear as HAP accessories otherwise.
73
+
74
+ Device-specific tests
75
+
76
+ - Light
77
+ - Toggle On/Off from Home app (or Homebridge UI) and confirm device responds.
78
+ - Set brightness to 25%, 50%, 100% and confirm device reports matching levels.
79
+ - If supported, change color temperature and/or color; confirm device applies new values.
80
+
81
+ - Fan
82
+ - Toggle On/Off and verify.
83
+ - Change rotation speed in steps (e.g., 25%, 50%, 100%).
84
+ - Toggle oscillation / swing and verify position changes.
85
+
86
+ - Curtain
87
+ - Open and Close via Home app / controller and verify movement.
88
+ - Set specific position (e.g., 50%) and verify accurate reporting.
89
+
90
+ - Lock
91
+ - Lock and Unlock from controller and verify state.
92
+ - If lock user management supported, add/remove a test user per plugin UI and verify expected behavior.
93
+
94
+ ## Logs & debugging
95
+
96
+ - Enable verbose logs from Homebridge or the plugin. Example: start Homebridge with a higher log level, or watch console output from `npm run watch`.
97
+ - Capture logs while you perform each operation; note the request path used by the plugin:
98
+ - For OpenAPI: logs will show `https://api.switch-bot.com/v1.0/...` calls.
99
+ - For BLE: logs will show local device discovery / BLE connect attempts.
100
+
101
+ ## Run validation script (optional)
102
+
103
+ You can run the TypeScript build and unit tests to confirm the codebase is healthy before manual tests:
104
+
105
+ ```bash
106
+ npm run build && npm run test
107
+ ```
108
+
109
+ ## Expected outcomes
110
+
111
+ - Matter-first registration: when Homebridge Matter API is available and `enableMatter` is true, accessories should be registered as Matter child-bridge accessories and re-used if restored from cache.
112
+ - HAP fallback: when Matter API is not available, the plugin must continue to register HAP accessories and reuse restored accessories by `accessory.context.deviceId`.
113
+ - Hybrid client paths: when `openApiToken` present the plugin should prefer OpenAPI for devices reachable via cloud; when BLE is available and configured the plugin should connect directly via BLE.
114
+ - Logs should show robust retry attempts for transient network errors and per-device retry throttling if configured.
115
+
116
+ ## Next steps I can take
117
+
118
+ - Create small automated verification scripts that use the Homebridge API test harness to toggle characteristic values (requires more test harness code).
119
+ - Generate a printable checklist or a GitHub issue template for manual verification results.
120
+
121
+ If you want, I can add the automated verification scripts now — would you prefer a simple script that exercises On/Off and Brightness for lights, or a broader script covering all device types?
package/MIGRATION.md ADDED
@@ -0,0 +1,54 @@
1
+ # Migration notes — v4.3.x → beta
2
+
3
+ This document highlights important changes and recommended actions before upgrading to the beta containing Matter and `node-switchbot@4` support.
4
+
5
+ 1. Matter-first behavior
6
+ - The plugin will prefer registering accessories with Homebridge's Matter child-bridge when `enableMatter: true` and the Homebridge Matter API is available.
7
+ - If Matter is not available, the plugin falls back to HAP and will reuse restored accessories by `accessory.context.deviceId`.
8
+
9
+ 2. Configuration keys
10
+ - `enableMatter` (boolean) — enable Matter child-bridge registration.
11
+ - `preferMatter` (boolean) — prefer Matter for devices that support Matter descriptors; HAP fallback still available.
12
+ - `openApiToken` (string) — when present the plugin may prefer OpenAPI calls for cloud-reachable devices.
13
+ - `perDeviceMaxRetries`, `requestTimeout`, `maxRetries` — network retry/timing options for OpenAPI fallback.
14
+
15
+ - `writeDebounceMs` (number, milliseconds, default 100) — global write coalescing debounce window. Commands sent to the same device within this window are coalesced (last-write-wins) to reduce duplicate network/API commands. Set to `0` to disable coalescing if you require immediate, per-command delivery.
16
+
17
+ 3. Hybrid client
18
+ - The plugin dynamically imports `node-switchbot` when available and falls back to OpenAPI when an `openApiToken` is configured.
19
+ - If you rely on BLE-only operation, ensure devices and the host have BLE available.
20
+
21
+ 4. UI changes
22
+ - A small plugin UI was added; it's only enabled/copied into `dist/homebridge-ui` when `npm run build` is run and the UI files exist in `src/homebridge-ui/public`.
23
+
24
+ - The UI is always served when Homebridge UI support is present; there is no opt-out flag in the platform config. The server-side guard that previously allowed disabling the UI has been removed—if you need to restrict access, manage it via Homebridge UI / host network access controls.
25
+
26
+ 5. Tests and verification
27
+ - Manual E2E scripts are provided in `scripts/e2e/` and a GitHub `workflow_dispatch` job can optionally run them against a reachable Homebridge.
28
+ - Run the local test suite before upgrading to confirm TypeScript and unit tests pass: `npm run build && npm run test`.
29
+
30
+ 6. Rollback plan
31
+ - If the beta causes issues, revert to the previous stable plugin version by reinstalling the prior package or checking out the stable branch.
32
+
33
+
34
+ 8. BLE encryption key and keyId fields
35
+
36
+ - The plugin now supports BLE encryption for devices that require it (e.g., SwitchBot Lock, Curtain 3, and some sensors).
37
+ - New config fields: `encryptionKey` and `keyId` can be set per-device in the Homebridge UI or config.json.
38
+ - To upgrade, obtain your device's BLE encryption key and keyId from the SwitchBot app (see README for instructions) and add them to your device config if required.
39
+ - Devices that do not require encryption can leave these fields blank.
40
+
41
+ ---
42
+
43
+ 7. Regenerating Matter ID maps
44
+
45
+ - A helper script `scripts/generate-matter-maps.js` is included to generate `src/matter-maps.generated.ts` from official zap/matter JSON metadata. The script expects a JSON input with a `clusters` array and will write mapped `MATTER_CLUSTER_IDS` and `MATTER_ATTRIBUTE_IDS` constants.
46
+ - Usage example:
47
+
48
+ ```bash
49
+ node scripts/generate-matter-maps.js ./zap-matter.json
50
+ ```
51
+
52
+ Place the official metadata JSON as `zap-matter.json` at the repo root (or pass a path) and commit the generated `src/matter-maps.generated.ts` to keep maps up to date.
53
+
54
+ If you want, I can open a PR with these notes and the changelog stub targeting a beta branch I create next.
package/README.md CHANGED
@@ -52,16 +52,13 @@
52
52
  ## Troubleshooting
53
53
 
54
54
  - ### If using Linux / Raspberry Pi OS
55
-
56
55
  1. `bluetoothctl` must be installed on the device, otherwise it cannot communicate via Bluetooth. Enable it with `sudo bluetoothctl power on`.
57
56
 
58
57
  2. If errors occur, while enabling it, restart the process:
59
-
60
58
  - `rfkill block bluetooth`
61
59
  - `rfkill unblock bluetooth`
62
60
 
63
61
  3. Also make sure, that the computer can discover the SwitchBot device:
64
-
65
62
  - `sudo bluetoothctl`
66
63
  - `scan on`
67
64
 
@@ -179,6 +176,49 @@
179
176
  - [SwitchBot Water Leak Detector](https://us.switch-bot.com/products/switchbot-water-leak-detector)
180
177
  - Supports OpenAPI & Bluetooth Low Energy (BLE) Connections
181
178
 
179
+
180
+ ## BLE Encryption Support
181
+
182
+ ### BLE Encryption Key and Key ID
183
+
184
+ Some SwitchBot devices (notably newer locks, curtains, and select sensors) require a BLE encryption key and keyId for secure Bluetooth communication. This plugin supports configuring these fields for each device.
185
+
186
+ #### How to Obtain BLE Encryption Key and Key ID
187
+
188
+ 1. **Open the SwitchBot App** and select your device.
189
+ 2. Go to **Device Settings** (gear icon).
190
+ 3. Tap **Device Info**.
191
+ 4. If your device supports BLE encryption, you will see fields for **Encryption Key** and **Key ID**. (If not visible, your device may not require encryption or may need a firmware update.)
192
+ 5. Copy the **Encryption Key** and **Key ID** values.
193
+
194
+ #### How to Configure in Homebridge
195
+
196
+ In the Homebridge UI, when adding or editing a SwitchBot device, enter the **Encryption Key** and **Key ID** in the provided fields. These values will be securely used for BLE communication with your device.
197
+
198
+ **Example device config excerpt:**
199
+
200
+ ```json
201
+ {
202
+ "deviceId": "E7F8A1B2C3D4",
203
+ "deviceName": "SwitchBot Lock",
204
+ "enableBLE": true,
205
+ "encryptionKey": "0123456789abcdef0123456789abcdef",
206
+ "keyId": "01"
207
+ }
208
+ ```
209
+
210
+ #### Which Devices Require BLE Encryption?
211
+
212
+ - SwitchBot Lock (and Lock Pro)
213
+ - SwitchBot Curtain 3 (and some Curtain 2 with updated firmware)
214
+ - Some sensors and new device models (see device info in app)
215
+
216
+ If you are unsure, check your device's info in the SwitchBot app. If the fields are present, copy them into the plugin config.
217
+
218
+ **Note:** If you enter an incorrect key or keyId, BLE communication will fail for that device. Double-check values if you encounter connection issues.
219
+
220
+ ---
221
+
182
222
  ## Supported IR Devices
183
223
 
184
224
  ### _(All IR Devices require [SwitchBot Hub 2](https://us.switch-bot.com/products/switchbot-hub-2), [SwitchBot Hub 3](https://us.switch-bot.com/products/switchbot-hub-3), or [Hub Mini](https://www.switch-bot.com/products/switchbot-hub-mini))_
@@ -218,6 +258,62 @@
218
258
  - Supports Fan Device Type
219
259
  - Allows for On/Off Controls
220
260
 
261
+ ## Matter Platform
262
+
263
+ ### Batched refresh and API load control
264
+
265
+ By default, the Matter platform uses a single batched refresh to update device status. You can tune or override this behavior with the following options under `options`:
266
+
267
+ - `matterBatchEnabled` (boolean, default true): enable/disable platform-level batched refresh. Devices with a per-device `refreshRate` still run their own timers.
268
+ - `matterBatchRefreshRate` (number, seconds): batch interval (falls back to `options.refreshRate`, then 300 if not set).
269
+ - `matterBatchConcurrency` (number): limit of parallel OpenAPI status calls during a batch (default 5).
270
+ - `matterBatchJitter` (number, seconds): random startup delay before the first batch to reduce synchronized spikes.
271
+
272
+ Device-level override:
273
+
274
+ - If a device sets `refreshRate` in its config, it uses a per-device timer and is excluded from the platform batch.
275
+
276
+ Reliability and rate-limiting:
277
+
278
+ - Each device status call retries with exponential backoff on non-success responses.
279
+ - After exhausting retries, the device enters a short cooldown before being retried; cooldowns are persisted across restarts.
280
+ - The batch worklist is randomized every cycle to further distribute API load.
281
+
282
+ These controls keep API usage smooth and predictable while preserving per-device control when needed.
283
+
284
+ ## What's new in the v4 beta (summary)
285
+
286
+ - Matter-first: when Homebridge Matter is available the plugin now prefers registering Matter accessories (with HAP fallback).
287
+ - Hybrid client: the plugin dynamically imports `node-switchbot@4` if available and falls back to OpenAPI when `openApiToken` is configured.
288
+ - UI always served: the plugin UI is packaged into `dist/homebridge-ui` and is always served when Homebridge UI support is present; there is no platform-level opt-out.
289
+ - OpenAPI hardening: OpenAPI calls have AbortController timeouts, jittered exponential backoff, per-device retry limits and cooldowns, and safe response parsing for resilient behavior.
290
+
291
+ - Write coalescing (debounce): command writes to the same device are coalesced by default to avoid command floods. Configure with `writeDebounceMs` (milliseconds, default 100). Set to `0` to disable coalescing.
292
+
293
+ See `MIGRATION.md` for migration notes and recommended upgrade steps.
294
+
295
+ ## OpenAPI rate limiting and daily budget
296
+
297
+ To prevent hitting SwitchBot’s daily OpenAPI limit, the plugin provides several platform-level options under `options`:
298
+
299
+ - `dailyApiLimit` (number, default 10000): maximum OpenAPI requests per day that the plugin will allow.
300
+ - `dailyApiReserveForCommands` (number, default 1000): requests reserved for user actions so background polling pauses before the hard limit.
301
+ - `webhookOnlyOnReserve` (boolean, default false): when remaining budget reaches the reserve, pause background polling/discovery; webhooks and commands continue until the hard limit.
302
+ - `dailyApiResetLocalMidnight` (boolean, default false): if true, resets the daily counter at local midnight; when false, resets at UTC midnight.
303
+
304
+ Example (excerpt):
305
+
306
+ ```json
307
+ {
308
+ "options": {
309
+ "dailyApiLimit": 10000,
310
+ "dailyApiReserveForCommands": 1000,
311
+ "webhookOnlyOnReserve": false,
312
+ "dailyApiResetLocalMidnight": true
313
+ }
314
+ }
315
+ ```
316
+
221
317
  ## SwitchBot APIs
222
318
 
223
319
  - [OpenWonderLabs/node-switchbot](https://github.com/OpenWonderLabs/node-switchbot)