@switchbot/homebridge-switchbot 5.0.0-beta.98 → 5.0.0

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 (282) hide show
  1. package/.changeset/config.json +14 -0
  2. package/.github/copilot-instructions.md +39 -0
  3. package/.github/workflows/ci.yml +4 -1
  4. package/.github/workflows/manual-e2e.yml +6 -3
  5. package/.github/workflows/release.yml +64 -15
  6. package/.github/workflows/stale.yml +2 -4
  7. package/.husky/pre-push +15 -0
  8. package/CHANGELOG.md +126 -134
  9. package/MIGRATION.md +16 -6
  10. package/README.md +84 -3
  11. package/TODO.md +263 -0
  12. package/config.schema.json +229 -36
  13. package/dist/SwitchBotHAPPlatform.d.ts +133 -0
  14. package/dist/SwitchBotHAPPlatform.d.ts.map +1 -0
  15. package/dist/SwitchBotHAPPlatform.js +555 -0
  16. package/dist/SwitchBotHAPPlatform.js.map +1 -0
  17. package/dist/SwitchBotMatterPlatform.d.ts +141 -0
  18. package/dist/SwitchBotMatterPlatform.d.ts.map +1 -0
  19. package/dist/SwitchBotMatterPlatform.js +536 -0
  20. package/dist/SwitchBotMatterPlatform.js.map +1 -0
  21. package/dist/device-types.d.ts +31 -0
  22. package/dist/device-types.d.ts.map +1 -0
  23. package/dist/device-types.js +246 -0
  24. package/dist/device-types.js.map +1 -0
  25. package/dist/deviceCommandMapper.d.ts +10 -0
  26. package/dist/deviceCommandMapper.d.ts.map +1 -0
  27. package/dist/deviceCommandMapper.js +319 -0
  28. package/dist/deviceCommandMapper.js.map +1 -0
  29. package/dist/deviceFactory.d.ts +3 -2
  30. package/dist/deviceFactory.d.ts.map +1 -1
  31. package/dist/deviceFactory.js +107 -29
  32. package/dist/deviceFactory.js.map +1 -1
  33. package/dist/devices/genericDevice.d.ts +59 -37
  34. package/dist/devices/genericDevice.d.ts.map +1 -1
  35. package/dist/devices/genericDevice.js +376 -78
  36. package/dist/devices/genericDevice.js.map +1 -1
  37. package/dist/errors.d.ts +38 -0
  38. package/dist/errors.d.ts.map +1 -0
  39. package/dist/errors.js +32 -0
  40. package/dist/errors.js.map +1 -0
  41. package/dist/homebridge-ui/device-types.js +246 -0
  42. package/dist/homebridge-ui/device-types.js.map +1 -0
  43. package/dist/homebridge-ui/deviceCommandMapper.js +319 -0
  44. package/dist/homebridge-ui/deviceCommandMapper.js.map +1 -0
  45. package/dist/homebridge-ui/endpoints/config.d.ts +3 -0
  46. package/dist/homebridge-ui/endpoints/config.d.ts.map +1 -0
  47. package/dist/homebridge-ui/endpoints/config.js +90 -0
  48. package/dist/homebridge-ui/endpoints/config.js.map +1 -0
  49. package/dist/homebridge-ui/endpoints/devices.d.ts +6 -0
  50. package/dist/homebridge-ui/endpoints/devices.d.ts.map +1 -0
  51. package/dist/homebridge-ui/endpoints/devices.js +144 -0
  52. package/dist/homebridge-ui/endpoints/devices.js.map +1 -0
  53. package/dist/homebridge-ui/endpoints/discovery.d.ts +7 -0
  54. package/dist/homebridge-ui/endpoints/discovery.d.ts.map +1 -0
  55. package/dist/homebridge-ui/endpoints/discovery.js +219 -0
  56. package/dist/homebridge-ui/endpoints/discovery.js.map +1 -0
  57. package/dist/homebridge-ui/errors.js +32 -0
  58. package/dist/homebridge-ui/errors.js.map +1 -0
  59. package/dist/homebridge-ui/homebridge-ui/endpoints/config.js +90 -0
  60. package/dist/homebridge-ui/homebridge-ui/endpoints/config.js.map +1 -0
  61. package/dist/homebridge-ui/homebridge-ui/endpoints/devices.js +144 -0
  62. package/dist/homebridge-ui/homebridge-ui/endpoints/devices.js.map +1 -0
  63. package/dist/homebridge-ui/homebridge-ui/endpoints/discovery.js +219 -0
  64. package/dist/homebridge-ui/homebridge-ui/endpoints/discovery.js.map +1 -0
  65. package/dist/homebridge-ui/homebridge-ui/server.js +11 -0
  66. package/dist/homebridge-ui/homebridge-ui/server.js.map +1 -0
  67. package/dist/homebridge-ui/homebridge-ui/utils/config-parser.js +108 -0
  68. package/dist/homebridge-ui/homebridge-ui/utils/config-parser.js.map +1 -0
  69. package/dist/homebridge-ui/homebridge-ui/utils/device-migration.js +111 -0
  70. package/dist/homebridge-ui/homebridge-ui/utils/device-migration.js.map +1 -0
  71. package/dist/homebridge-ui/homebridge-ui/utils/logger.js +17 -0
  72. package/dist/homebridge-ui/homebridge-ui/utils/logger.js.map +1 -0
  73. package/dist/homebridge-ui/public/css/styles.css +483 -0
  74. package/dist/homebridge-ui/public/index.html +197 -621
  75. package/dist/homebridge-ui/public/js/advanced-settings.d.ts +3 -0
  76. package/dist/homebridge-ui/public/js/advanced-settings.d.ts.map +1 -0
  77. package/dist/homebridge-ui/public/js/advanced-settings.js +95 -0
  78. package/dist/homebridge-ui/public/js/advanced-settings.js.map +1 -0
  79. package/dist/homebridge-ui/public/js/advanced-settings.ts +94 -0
  80. package/dist/homebridge-ui/public/js/api.d.ts +66 -0
  81. package/dist/homebridge-ui/public/js/api.d.ts.map +1 -0
  82. package/dist/homebridge-ui/public/js/api.js +295 -0
  83. package/dist/homebridge-ui/public/js/api.js.map +1 -0
  84. package/dist/homebridge-ui/public/js/api.ts +355 -0
  85. package/dist/homebridge-ui/public/js/app.d.ts +2 -0
  86. package/dist/homebridge-ui/public/js/app.d.ts.map +1 -0
  87. package/dist/homebridge-ui/public/js/app.js +3722 -0
  88. package/dist/homebridge-ui/public/js/app.js.map +7 -0
  89. package/dist/homebridge-ui/public/js/app.ts +22 -0
  90. package/dist/homebridge-ui/public/js/constants.d.ts +2 -0
  91. package/dist/homebridge-ui/public/js/constants.d.ts.map +1 -0
  92. package/dist/homebridge-ui/public/js/constants.js +2 -0
  93. package/dist/homebridge-ui/public/js/constants.js.map +1 -0
  94. package/dist/homebridge-ui/public/js/constants.ts +1 -0
  95. package/dist/homebridge-ui/public/js/credentials.d.ts +3 -0
  96. package/dist/homebridge-ui/public/js/credentials.d.ts.map +1 -0
  97. package/dist/homebridge-ui/public/js/credentials.js +99 -0
  98. package/dist/homebridge-ui/public/js/credentials.js.map +1 -0
  99. package/dist/homebridge-ui/public/js/credentials.ts +105 -0
  100. package/dist/homebridge-ui/public/js/devices-delete.d.ts +3 -0
  101. package/dist/homebridge-ui/public/js/devices-delete.d.ts.map +1 -0
  102. package/dist/homebridge-ui/public/js/devices-delete.js +199 -0
  103. package/dist/homebridge-ui/public/js/devices-delete.js.map +1 -0
  104. package/dist/homebridge-ui/public/js/devices-delete.ts +227 -0
  105. package/dist/homebridge-ui/public/js/devices.d.ts +9 -0
  106. package/dist/homebridge-ui/public/js/devices.d.ts.map +1 -0
  107. package/dist/homebridge-ui/public/js/devices.js +98 -0
  108. package/dist/homebridge-ui/public/js/devices.js.map +1 -0
  109. package/dist/homebridge-ui/public/js/devices.ts +106 -0
  110. package/dist/homebridge-ui/public/js/discovery.d.ts +9 -0
  111. package/dist/homebridge-ui/public/js/discovery.d.ts.map +1 -0
  112. package/dist/homebridge-ui/public/js/discovery.js +1201 -0
  113. package/dist/homebridge-ui/public/js/discovery.js.map +1 -0
  114. package/dist/homebridge-ui/public/js/discovery.ts +1335 -0
  115. package/dist/homebridge-ui/public/js/logger.d.ts +7 -0
  116. package/dist/homebridge-ui/public/js/logger.d.ts.map +1 -0
  117. package/dist/homebridge-ui/public/js/logger.js +17 -0
  118. package/dist/homebridge-ui/public/js/logger.js.map +1 -0
  119. package/dist/homebridge-ui/public/js/logger.ts +17 -0
  120. package/dist/homebridge-ui/public/js/modal.d.ts +5 -0
  121. package/dist/homebridge-ui/public/js/modal.d.ts.map +1 -0
  122. package/dist/homebridge-ui/public/js/modal.js +35 -0
  123. package/dist/homebridge-ui/public/js/modal.js.map +1 -0
  124. package/dist/homebridge-ui/public/js/modal.ts +35 -0
  125. package/dist/homebridge-ui/public/js/modals.d.ts +15 -0
  126. package/dist/homebridge-ui/public/js/modals.d.ts.map +1 -0
  127. package/dist/homebridge-ui/public/js/modals.js +675 -0
  128. package/dist/homebridge-ui/public/js/modals.js.map +1 -0
  129. package/dist/homebridge-ui/public/js/modals.ts +765 -0
  130. package/dist/homebridge-ui/public/js/render.d.ts +71 -0
  131. package/dist/homebridge-ui/public/js/render.d.ts.map +1 -0
  132. package/dist/homebridge-ui/public/js/render.js +960 -0
  133. package/dist/homebridge-ui/public/js/render.js.map +1 -0
  134. package/dist/homebridge-ui/public/js/render.ts +1084 -0
  135. package/dist/homebridge-ui/public/js/toast.d.ts +6 -0
  136. package/dist/homebridge-ui/public/js/toast.d.ts.map +1 -0
  137. package/dist/homebridge-ui/public/js/toast.js +38 -0
  138. package/dist/homebridge-ui/public/js/toast.js.map +1 -0
  139. package/dist/homebridge-ui/public/js/toast.ts +44 -0
  140. package/dist/homebridge-ui/public/js/types.d.ts +23 -0
  141. package/dist/homebridge-ui/public/js/types.d.ts.map +1 -0
  142. package/dist/homebridge-ui/public/js/types.js +2 -0
  143. package/dist/homebridge-ui/public/js/types.js.map +1 -0
  144. package/dist/homebridge-ui/public/js/types.ts +26 -0
  145. package/dist/homebridge-ui/server.d.ts +1 -3
  146. package/dist/homebridge-ui/server.d.ts.map +1 -1
  147. package/dist/homebridge-ui/server.js +8 -450
  148. package/dist/homebridge-ui/server.js.map +1 -1
  149. package/dist/homebridge-ui/settings.js +8 -0
  150. package/dist/homebridge-ui/settings.js.map +1 -0
  151. package/dist/homebridge-ui/switchbotClient.js +247 -0
  152. package/dist/homebridge-ui/switchbotClient.js.map +1 -0
  153. package/dist/homebridge-ui/utils/config-parser.d.ts +39 -0
  154. package/dist/homebridge-ui/utils/config-parser.d.ts.map +1 -0
  155. package/dist/homebridge-ui/utils/config-parser.js +108 -0
  156. package/dist/homebridge-ui/utils/config-parser.js.map +1 -0
  157. package/dist/homebridge-ui/utils/device-migration.d.ts +35 -0
  158. package/dist/homebridge-ui/utils/device-migration.d.ts.map +1 -0
  159. package/dist/homebridge-ui/utils/device-migration.js +111 -0
  160. package/dist/homebridge-ui/utils/device-migration.js.map +1 -0
  161. package/dist/homebridge-ui/utils/logger.d.ts +7 -0
  162. package/dist/homebridge-ui/utils/logger.d.ts.map +1 -0
  163. package/dist/homebridge-ui/utils/logger.js +17 -0
  164. package/dist/homebridge-ui/utils/logger.js.map +1 -0
  165. package/dist/index.d.ts +10 -0
  166. package/dist/index.d.ts.map +1 -1
  167. package/dist/index.js +12 -2
  168. package/dist/index.js.map +1 -1
  169. package/dist/settings.d.ts +1 -0
  170. package/dist/settings.d.ts.map +1 -1
  171. package/dist/settings.js +1 -0
  172. package/dist/settings.js.map +1 -1
  173. package/dist/switchbotClient.d.ts +12 -10
  174. package/dist/switchbotClient.d.ts.map +1 -1
  175. package/dist/switchbotClient.js +156 -103
  176. package/dist/switchbotClient.js.map +1 -1
  177. package/dist/utils.d.ts +76 -1
  178. package/dist/utils.d.ts.map +1 -1
  179. package/dist/utils.js +1121 -4
  180. package/dist/utils.js.map +1 -1
  181. package/docs/assets/highlight.css +16 -2
  182. package/docs/assets/main.js +1 -1
  183. package/docs/index.html +82 -5
  184. package/docs/variables/default.html +3 -1
  185. package/eslint.config.js +9 -5
  186. package/nodemon.json +2 -2
  187. package/package.json +34 -21
  188. package/scripts/build-ui.js +37 -0
  189. package/scripts/free-dev-ports.mjs +105 -0
  190. package/scripts/generate-matter-maps.js +34 -17
  191. package/scripts/sync-device-types.mjs +31 -0
  192. package/src/SwitchBotHAPPlatform.ts +558 -0
  193. package/src/SwitchBotMatterPlatform.ts +538 -0
  194. package/src/device-types.js +246 -0
  195. package/src/device-types.js.map +1 -0
  196. package/src/device-types.ts +261 -0
  197. package/src/deviceCommandMapper.js +319 -0
  198. package/src/deviceCommandMapper.js.map +1 -0
  199. package/src/deviceCommandMapper.ts +333 -0
  200. package/src/deviceFactory.ts +125 -45
  201. package/src/devices/genericDevice.ts +411 -69
  202. package/src/errors.js +32 -0
  203. package/src/errors.js.map +1 -0
  204. package/src/errors.ts +35 -0
  205. package/src/homebridge-ui/endpoints/config.ts +110 -0
  206. package/src/homebridge-ui/endpoints/devices.ts +153 -0
  207. package/src/homebridge-ui/endpoints/discovery.ts +240 -0
  208. package/src/homebridge-ui/public/css/styles.css +483 -0
  209. package/src/homebridge-ui/public/index.html +197 -621
  210. package/src/homebridge-ui/public/js/advanced-settings.ts +94 -0
  211. package/src/homebridge-ui/public/js/api.ts +355 -0
  212. package/src/homebridge-ui/public/js/app.ts +22 -0
  213. package/src/homebridge-ui/public/js/constants.ts +1 -0
  214. package/src/homebridge-ui/public/js/credentials.ts +105 -0
  215. package/src/homebridge-ui/public/js/devices-delete.ts +227 -0
  216. package/src/homebridge-ui/public/js/devices.ts +106 -0
  217. package/src/homebridge-ui/public/js/discovery.ts +1335 -0
  218. package/src/homebridge-ui/public/js/logger.ts +17 -0
  219. package/src/homebridge-ui/public/js/modal.ts +35 -0
  220. package/src/homebridge-ui/public/js/modals.ts +765 -0
  221. package/src/homebridge-ui/public/js/render.ts +1084 -0
  222. package/src/homebridge-ui/public/js/toast.ts +44 -0
  223. package/src/homebridge-ui/public/js/types.ts +26 -0
  224. package/src/homebridge-ui/server.ts +9 -526
  225. package/src/homebridge-ui/utils/config-parser.ts +125 -0
  226. package/src/homebridge-ui/utils/device-migration.ts +144 -0
  227. package/src/homebridge-ui/utils/logger.ts +17 -0
  228. package/src/index.ts +12 -2
  229. package/src/settings.js +8 -0
  230. package/src/settings.js.map +1 -0
  231. package/src/settings.ts +2 -0
  232. package/src/switchbotClient.js +247 -0
  233. package/src/switchbotClient.js.map +1 -0
  234. package/src/switchbotClient.ts +177 -114
  235. package/src/utils.ts +1133 -5
  236. package/test/client/switchbot-client-debounce.spec.ts +35 -0
  237. package/test/client/switchbot-client-openapi.spec.ts +19 -0
  238. package/test/client/switchbotClient.spec.ts +64 -0
  239. package/test/device/device-mapping.spec.ts +23 -0
  240. package/test/device/deviceBase.spec.ts +26 -0
  241. package/test/device/deviceFactory-edge.spec.ts +15 -0
  242. package/test/device/deviceFactory.spec.ts +33 -0
  243. package/test/device/fan-swing.spec.ts +34 -0
  244. package/test/device/genericDevice-blepoll.spec.ts +47 -0
  245. package/test/device/irdevice.spec.ts +9 -0
  246. package/test/device/lock-users.spec.ts +35 -0
  247. package/test/device/matter-descriptors.spec.ts +22 -0
  248. package/test/device/matter-device-state.spec.ts +37 -0
  249. package/test/e2e/run-e2e.spec.ts +18 -19
  250. package/test/errors/errors.spec.ts +10 -0
  251. package/test/helpers/matter-harness.ts +20 -9
  252. package/test/homebridge-ui/server.spec.ts +9 -0
  253. package/test/platform/accessory-restore.spec.ts +37 -0
  254. package/test/platform/matter-childbridge.spec.ts +34 -0
  255. package/test/platform/matter-integration.spec.ts +33 -0
  256. package/test/platform/platform-edge.spec.ts +73 -0
  257. package/test/platform/platform.integration.spec.ts +34 -0
  258. package/test/utils/utils-extra.spec.ts +10 -0
  259. package/test/utils/utils.spec.ts +53 -0
  260. package/todo/TODO.md +80 -0
  261. package/tsconfig.ui.json +11 -0
  262. package/.github/npm-version-script-esm.js +0 -97
  263. package/.github/workflows/beta-release.yml +0 -52
  264. package/dist/platform.d.ts +0 -35
  265. package/dist/platform.d.ts.map +0 -1
  266. package/dist/platform.js +0 -850
  267. package/dist/platform.js.map +0 -1
  268. package/src/platform.ts +0 -867
  269. package/test/accessory-restore.spec.ts +0 -73
  270. package/test/device-mapping.spec.ts +0 -37
  271. package/test/deviceFactory.spec.ts +0 -18
  272. package/test/fan-swing.spec.ts +0 -29
  273. package/test/lock-users.spec.ts +0 -44
  274. package/test/matter-childbridge.spec.ts +0 -55
  275. package/test/matter-descriptors.spec.ts +0 -97
  276. package/test/matter-device-state.spec.ts +0 -101
  277. package/test/matter-integration.spec.ts +0 -70
  278. package/test/platform.integration.spec.ts +0 -55
  279. package/test/switchbot-client-debounce.spec.ts +0 -131
  280. package/test/switchbot-client-openapi.spec.ts +0 -56
  281. package/test/switchbotClient.spec.ts +0 -10
  282. package/test/utils.spec.ts +0 -20
package/MIGRATION.md CHANGED
@@ -1,6 +1,6 @@
1
- # Migration notes — v4.3.x → beta
1
+ # Migration notes — v4.3.x → v5.x
2
2
 
3
- This document highlights important changes and recommended actions before upgrading to the beta containing Matter and `node-switchbot@4` support.
3
+ This document highlights important changes and recommended actions before upgrading to the release that includes Matter and stable `node-switchbot@4` support.
4
4
 
5
5
  1. Matter-first behavior
6
6
  - The plugin will prefer registering accessories with Homebridge's Matter child-bridge when `enableMatter: true` and the Homebridge Matter API is available.
@@ -9,13 +9,13 @@ This document highlights important changes and recommended actions before upgrad
9
9
  2. Configuration keys
10
10
  - `enableMatter` (boolean) — enable Matter child-bridge registration.
11
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.
12
+ - `openApiToken` + `openApiSecret` (string) — both are required for OpenAPI discovery/calls for cloud-reachable devices.
13
13
  - `perDeviceMaxRetries`, `requestTimeout`, `maxRetries` — network retry/timing options for OpenAPI fallback.
14
14
 
15
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
16
 
17
17
  3. Hybrid client
18
- - The plugin dynamically imports `node-switchbot` when available and falls back to OpenAPI when an `openApiToken` is configured.
18
+ - The plugin dynamically imports `node-switchbot` when available and uses OpenAPI fallback when both `openApiToken` and `openApiSecret` are configured.
19
19
  - If you rely on BLE-only operation, ensure devices and the host have BLE available.
20
20
 
21
21
  4. UI changes
@@ -28,8 +28,18 @@ This document highlights important changes and recommended actions before upgrad
28
28
  - Run the local test suite before upgrading to confirm TypeScript and unit tests pass: `npm run build && npm run test`.
29
29
 
30
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.
31
+ - If the upgrade causes issues, revert to the previous plugin version by reinstalling the prior package version.
32
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
+
33
43
  7. Regenerating Matter ID maps
34
44
 
35
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.
@@ -41,4 +51,4 @@ node scripts/generate-matter-maps.js ./zap-matter.json
41
51
 
42
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.
43
53
 
44
- If you want, I can open a PR with these notes and the changelog stub targeting a beta branch I create next.
54
+ These notes should be kept in sync with README and CHANGELOG updates for each release.
package/README.md CHANGED
@@ -21,8 +21,31 @@
21
21
  - See noble [prerequisites](https://github.com/abandonware/noble#prerequisites) for your OS. (This is used for BLE connection.)
22
22
  3. Click **Install**
23
23
 
24
+
24
25
  ## Configuration
25
26
 
27
+ ### OpenAPI Polling/Rate Advanced Settings (UI)
28
+
29
+ You can now configure global OpenAPI polling and rate-limiting options directly from the Homebridge UI:
30
+
31
+ - Go to the SwitchBot plugin settings in Homebridge Config UI X.
32
+ - Scroll to the **Advanced Settings** section at the bottom of the page.
33
+ - Adjust the following options as needed:
34
+ - **OpenAPI Polling Interval (seconds):** How often to poll devices via OpenAPI for status. Default: 300 (5 min). Min: 30. Can be overridden per device.
35
+ - **Enable Batched OpenAPI Polling:** Poll all OpenAPI devices in a single batch at the configured interval. Devices with per-device refreshRate are excluded from the batch.
36
+ - **OpenAPI Batch Polling Interval (seconds):** Interval for batched OpenAPI polling. Falls back to OpenAPI Polling Interval if not set. Default: 300.
37
+ - **OpenAPI Daily Request Limit:** Maximum OpenAPI requests per day allowed by the plugin. Default: 10000.
38
+ - **OpenAPI Reserve for Commands:** Requests reserved for user actions. When remaining budget reaches this value, background polling pauses. Default: 1000.
39
+ - **Reset OpenAPI Counter at Local Midnight:** If true, resets the daily OpenAPI request counter at local midnight. If false, resets at UTC midnight.
40
+ - **Only Allow Webhooks on Reserve:** When remaining OpenAPI budget reaches the reserve, only webhooks and user commands are allowed. Background polling/discovery pauses.
41
+ - **OpenAPI Batch Concurrency:** Maximum number of parallel OpenAPI status calls during a batch. Default: 5.
42
+ - **OpenAPI Batch Jitter (seconds):** Random startup delay before the first batch to reduce synchronized spikes. Default: 0.
43
+
44
+ Click **Save Advanced Settings** to apply changes. These settings match the options available in `config.schema.json` and can be overridden per device.
45
+
46
+ <!-- Optionally add a screenshot here -->
47
+
48
+
26
49
  - ### If using OpenAPI Connection
27
50
  1. Download SwitchBot App on App Store or Google Play Store
28
51
  2. Register a SwitchBot account and log in into your account
@@ -168,6 +191,9 @@
168
191
  - [SwitchBot Hub 2](https://us.switch-bot.com/products/switchbot-hub-2)
169
192
  - Supports OpenAPI & Bluetooth Low Energy (BLE) Connections
170
193
  - Enables Humidity, Temperature, and Light Sensor
194
+ - [SwitchBot Hub Mini 2](https://us.switch-bot.com/products/switchbot-hub-mini-2)
195
+ - Supports OpenAPI & Bluetooth Low Energy (BLE) Connections
196
+ - Enables Humidity, Temperature, and Light Sensor
171
197
  - [SwitchBot Hub 3](https://us.switch-bot.com/products/switchbot-hub-3)
172
198
  - Supports OpenAPI & Bluetooth Low Energy (BLE) Connections
173
199
  - Enables Humidity, Temperature, and Light Sensor
@@ -176,9 +202,52 @@
176
202
  - [SwitchBot Water Leak Detector](https://us.switch-bot.com/products/switchbot-water-leak-detector)
177
203
  - Supports OpenAPI & Bluetooth Low Energy (BLE) Connections
178
204
 
205
+
206
+ ## BLE Encryption Support
207
+
208
+ ### BLE Encryption Key and Key ID
209
+
210
+ 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.
211
+
212
+ #### How to Obtain BLE Encryption Key and Key ID
213
+
214
+ 1. **Open the SwitchBot App** and select your device.
215
+ 2. Go to **Device Settings** (gear icon).
216
+ 3. Tap **Device Info**.
217
+ 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.)
218
+ 5. Copy the **Encryption Key** and **Key ID** values.
219
+
220
+ #### How to Configure in Homebridge
221
+
222
+ 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.
223
+
224
+ **Example device config excerpt:**
225
+
226
+ ```json
227
+ {
228
+ "deviceId": "E7F8A1B2C3D4",
229
+ "deviceName": "SwitchBot Lock",
230
+ "enableBLE": true,
231
+ "encryptionKey": "0123456789abcdef0123456789abcdef",
232
+ "keyId": "01"
233
+ }
234
+ ```
235
+
236
+ #### Which Devices Require BLE Encryption?
237
+
238
+ - SwitchBot Lock (and Lock Pro)
239
+ - SwitchBot Curtain 3 (and some Curtain 2 with updated firmware)
240
+ - Some sensors and new device models (see device info in app)
241
+
242
+ If you are unsure, check your device's info in the SwitchBot app. If the fields are present, copy them into the plugin config.
243
+
244
+ **Note:** If you enter an incorrect key or keyId, BLE communication will fail for that device. Double-check values if you encounter connection issues.
245
+
246
+ ---
247
+
179
248
  ## Supported IR Devices
180
249
 
181
- ### _(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))_
250
+ ### _(All IR Devices require [SwitchBot Hub 2](https://us.switch-bot.com/products/switchbot-hub-2), [SwitchBot Hub Mini 2](https://us.switch-bot.com/products/switchbot-hub-mini-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))_
182
251
 
183
252
  - TV
184
253
  - Allows for On/Off and Volume Controls
@@ -238,12 +307,14 @@ Reliability and rate-limiting:
238
307
 
239
308
  These controls keep API usage smooth and predictable while preserving per-device control when needed.
240
309
 
241
- ## What's new in the v4 beta (summary)
310
+ ## What's new with node-switchbot v4.0.0
242
311
 
243
312
  - Matter-first: when Homebridge Matter is available the plugin now prefers registering Matter accessories (with HAP fallback).
244
- - Hybrid client: the plugin dynamically imports `node-switchbot@4` if available and falls back to OpenAPI when `openApiToken` is configured.
313
+ - Hybrid client: the plugin uses `node-switchbot@^4.0.0` with BLE + OpenAPI discovery and OpenAPI fallback.
314
+ - OpenAPI credentials: cloud discovery and cloud fallback paths require both `openApiToken` and `openApiSecret`.
245
315
  - 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.
246
316
  - OpenAPI hardening: OpenAPI calls have AbortController timeouts, jittered exponential backoff, per-device retry limits and cooldowns, and safe response parsing for resilient behavior.
317
+ - v4 resilience enabled in discovery: plugin discovery enables retry, circuit-breaker, and connection-intelligence flags from `node-switchbot` v4.
247
318
 
248
319
  - 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.
249
320
 
@@ -277,6 +348,16 @@ Example (excerpt):
277
348
  - [OpenWonderLabs/SwitchBotAPI](https://github.com/OpenWonderLabs/SwitchBotAPI)
278
349
  - [OpenWonderLabs/SwitchBotAPI-BLE](https://github.com/OpenWonderLabs/SwitchBotAPI-BLE)
279
350
 
351
+ ## Development / Tests
352
+
353
+ - Run unit tests:
354
+ ```bash
355
+ npm run test
356
+ ```
357
+
358
+ - Notes:
359
+ - Added Lock Ultra (Cloud + BLE) support with `node-switchbot` v4.
360
+
280
361
  ## Community
281
362
 
282
363
  - [SwitchBot (Official website)](https://www.switch-bot.com/)
package/TODO.md ADDED
@@ -0,0 +1,263 @@
1
+ # SwitchBot Plugin TODO List
2
+
3
+ ## Code Refactoring & Architecture
4
+
5
+ ### Server-Side Refactoring (Priority: High)
6
+
7
+ - [x] **Split `server.ts` into modular structure** ✅ COMPLETED
8
+ - [x] Created `src/homebridge-ui/endpoints/discovery.ts` - Discovery endpoint
9
+ - [x] Created `src/homebridge-ui/endpoints/config.ts` - Config management endpoint
10
+ - [x] Created `src/homebridge-ui/endpoints/devices.ts` - Device CRUD operations
11
+ - [x] Created `src/homebridge-ui/endpoints/credentials.ts` - Credentials endpoint
12
+ - [x] Created `src/homebridge-ui/utils/config-parser.ts` - Config parsing helpers
13
+ - [x] Created `src/homebridge-ui/utils/logger.ts` - Logging utility
14
+ - [x] Updated `src/homebridge-ui/server.ts` - Main entry point (imports and registers endpoints)
15
+
16
+ **Status:** Server endpoints are fully modularized and organized by concern.
17
+
18
+ ---
19
+
20
+ ## Bug Fixes (Priority: Critical)
21
+
22
+ ### Matter Window Covering Conformance Issue
23
+
24
+ - [ ] **Fix Matter window covering Drapery enum validation error**
25
+ - [ ] **Issue:** Matter accessory registration fails for Curtain devices
26
+ - [ ] **Error:** `Conformance "LF & !TL": Matter does not allow enum value Drapery (ID 4) here`
27
+ - [ ] **Root Cause:** windowCovering.state.type is set to "Drapery" but Matter spec requires "LF & !TL" conformance (Lift Fail without Tilt)
28
+ - [ ] **Solution:** Need to validate/correct window covering type mappings for Matter compatibility
29
+ - [ ] **Affected Devices:** Curtain-type devices (e.g., "Master Bathroom Left Curtain")
30
+ - [ ] **Steps to Fix:**
31
+ - [ ] Check Matter window covering specification for valid type combinations
32
+ - [ ] Update device type mapping to use compliant enum values
33
+ - [ ] Validate conformance rules for Lift/Tilt combinations
34
+ - [ ] Test with Curtain, Curtain3, and Roller Shade devices
35
+
36
+ ---
37
+
38
+ ### Invalid Device Type Validation ✅ COMPLETED
39
+
40
+ - [x] **Fix invalid device type in config schema validation**
41
+ - [x] **Issue:** Config validation rejects devices with invalid `configDeviceType` values (e.g., "Lock Vision Pro" is not in valid enum)
42
+ - [x] **Error:** "Value is not accepted. Valid values: ..." error shown in Homebridge UI
43
+ - [x] **Root Cause:** Device types in existing configs may not match current DEVICE_TYPES enum (legacy names, typos, or renamed devices)
44
+ - [x] **Affected Devices:** Any device with `configDeviceType` not matching DEVICE_TYPES enum
45
+ - [x] **Solution:** Implemented device type validation migration and auto-correction
46
+
47
+ **Implementation:**
48
+ - Added `normalizeDeviceType()` — Validates and maps invalid types to valid equivalents
49
+ - Added `isValidDeviceType()` — Checks if device type is in DEVICE_TYPES enum
50
+ - Added `getValidDeviceTypes()` — Returns set of all valid device types
51
+ - Created `src/homebridge-ui/utils/device-migration.ts` — Migration utilities for batch validation
52
+ - Updated `src/homebridge-ui/endpoints/config.ts` — Device loading now validates types and warns about invalid ones
53
+ - Added migration mapping: `"Lock Vision Pro"` → `"Keypad Vision Pro"` (and others)
54
+ - Config endpoint returns `validationWarnings` with invalid device types and suggestions
55
+
56
+ **Status:** Device type validation is now automatic. Invalid types are detected and suggestions provided to users. Auto-correction mappings handle legacy/typo device names.
57
+
58
+ ---
59
+
60
+ ### Client-Side Refactoring (Priority: Medium)
61
+
62
+ #### Phase 1: Quick Wins
63
+
64
+ - [x] **Extract DEVICE_TYPES constant** (~100 lines) ✅ COMPLETED
65
+ - [x] Created `src/device-types.ts` as single source of truth
66
+ - [x] Updated `src/homebridge-ui/public/js/constants.ts` to import from shared source
67
+ - [x] Added `DEVICE_TYPE_NORMALIZATION_MAP` for plugin type lookups
68
+ - [x] Updated `src/deviceFactory.ts` to use normalized type mappings
69
+ - [x] Created `scripts/sync-device-types.mjs` to auto-sync config.schema.json
70
+ - [x] Integrated sync into build process (runs before tsc)
71
+
72
+ **Status:** Device types now single-sourced with auto-sync. Config schema, UI dropdown, and plugin type handling all stay aligned automatically.
73
+
74
+
75
+
76
+ # SwitchBot Plugin TODO List (2026)
77
+
78
+ ---
79
+
80
+ ## PRIORITY: HIGH (Start Here)
81
+
82
+ - [ ] **One-Click Device Import**
83
+ Add "Add to Config" button next to each discovered device. Dramatically speeds up onboarding, reduces manual steps for users.
84
+ - [ ] **Auto-populate Device Config Modal**
85
+ When importing, auto-fill the config modal with discovered values. Reduces user error, makes adding devices nearly frictionless.
86
+ - [ ] **Pre-fill MAC Address for BLE Devices**
87
+ Ensure BLE devices are always added with correct MAC, avoids connection issues.
88
+ - [ ] **Duplicate Detection**
89
+ Check if discovered device ID already exists in config. Prevents duplicate entries, avoids user confusion.
90
+
91
+ ---
92
+
93
+ ## PRIORITY: MEDIUM
94
+
95
+ - [ ] **Confirmation Toast on Import**
96
+ Show a toast message on successful import for user feedback.
97
+ - [ ] **Loading States for Discovery**
98
+ Show progress indicator, spinner, and allow cancel during discovery. Improves perceived performance and transparency.
99
+ - [ ] **Device Grouping**
100
+ Group devices by hub or connection type. Useful for users with many devices/hubs.
101
+ - [ ] **Connection Recommendations**
102
+ Show badges for recommended connection (BLE/API) based on signal/device type.
103
+
104
+ ---
105
+
106
+ ## PRIORITY: LOW
107
+
108
+ - [ ] **UI Polish: Badges, View in Config, Group Headers**
109
+ Add badges for "Already Added"/"New Device", view-in-config links, expandable group headers, device count per group, and remember expanded/collapsed state.
110
+ - [ ] **Configurable BLE Scan**
111
+ Add scan duration, BLE timeout, and Bluetooth availability status in settings. Remember user preferences in localStorage.
112
+ - [ ] **Discovery History/Cache**
113
+ Cache last discovery results, show last scanned timestamp, refresh button, and auto-refresh option.
114
+
115
+ ---
116
+
117
+ **Recommendation:**
118
+
119
+ Start with the HIGH priority section—these features have the biggest impact on user experience and onboarding. MEDIUM priority items improve polish and usability for power users. LOW priority items are mostly UI/UX enhancements and advanced options.
120
+
121
+ - [ ] **Build & Test**
122
+ - [ ] Run `npm run build`
123
+ - [ ] Test add device modal
124
+ - [ ] Test edit device modal
125
+ - [ ] Test delete confirmation modal
126
+ - [ ] Verify form validation works
127
+
128
+ ### Step 6: Extract Form Handling
129
+
130
+ **Goal:** Move form validation and submission logic
131
+
132
+ - [ ] **Create forms module**
133
+ - [ ] Create `src/homebridge-ui/public/js/forms.js`
134
+ - [ ] Extract and export these functions:
135
+ - [ ] `validateDeviceForm(formData)` - Validate form inputs
136
+ - [ ] `handleDeviceSubmit(formData)` - Process form submission
137
+ - [ ] `resetForm()` - Clear form fields
138
+ - [ ] `formatFormData(rawData)` - Format form data for API
139
+ - [ ] `showFormError(field, message)` - Display validation error
140
+ - [ ] `clearFormErrors()` - Clear all validation errors
141
+
142
+ - [ ] **Update HTML**
143
+ - [ ] Remove form handling functions from `<script>` block
144
+ - [ ] Add import: `import * as forms from './js/forms.js'`
145
+ - [ ] Update event handlers to use imported functions
146
+ - [ ] Test form validation and submission
147
+
148
+ - [ ] **Build & Test**
149
+ - [ ] Run `npm run build`
150
+ - [ ] Test form validation (empty fields, invalid data)
151
+ - [ ] Test form submission (add/edit device)
152
+ - [ ] Verify error messages display correctly
153
+
154
+ ### Step 7: Create Main App Module
155
+
156
+ **Goal:** Create central app initialization and coordination
157
+
158
+ - [ ] **Create app module**
159
+ - [ ] Create `src/homebridge-ui/public/js/app.ts`
160
+ - [ ] Export `init()` function that:
161
+ - [ ] Loads initial config on page load
162
+ - [ ] Sets up all event listeners
163
+ - [ ] Initializes UI components
164
+ - [ ] Handles global state
165
+ - [ ] Move event listeners from HTML to app.js
166
+ - [ ] Coordinate between all other modules
167
+
168
+ - [ ] **Update HTML**
169
+ - [ ] Remove all remaining JavaScript from `<script>` block
170
+ - [ ] Keep only imports and single line: `import { init } from './js/app.js'; init();`
171
+ - [ ] Or use DOMContentLoaded: `document.addEventListener('DOMContentLoaded', () => init())`
172
+ - [ ] Remove now-empty `<script>` block if all code moved
173
+
174
+ - [ ] **Build & Test**
175
+ - [ ] Run `npm run build`
176
+ - [ ] Test complete page load and initialization
177
+ - [ ] Test all features end-to-end
178
+ - [ ] Verify no console errors
179
+
180
+ ### Step 8: Final Cleanup and Verification
181
+
182
+ **Goal:** Ensure everything works and clean up
183
+
184
+ - [ ] **Verify build output**
185
+ - [ ] Check all files copied to `dist/homebridge-ui/public/`
186
+ - [ ] Verify file structure matches source
187
+ - [ ] Check file sizes (modules should be reasonable)
188
+
189
+ - [ ] **Test all functionality**
190
+ - [ ] Load config on page open
191
+ - [ ] Add new device
192
+ - [ ] Edit existing device
193
+ - [ ] Delete device
194
+ - [ ] Run discovery
195
+ - [ ] Test all filters/sorting (if implemented)
196
+ - [ ] Test on different browsers (Chrome, Safari, Firefox)
197
+
198
+ - [ ] **Code cleanup**
199
+ - [ ] Remove any unused functions
200
+ - [ ] Add JSDoc comments to all exports
201
+ - [ ] Ensure consistent code style
202
+ - [ ] Remove console.log statements (or convert to proper logging)
203
+
204
+ - [ ] **Documentation**
205
+ - [ ] Update comments in code
206
+ - [ ] Document module dependencies
207
+ - [ ] Add README in `src/homebridge-ui/public/js/` if needed
208
+ - [ ] Update main README if UI architecture changed significantly
209
+
210
+ ### Step 9: Optional Enhancements
211
+
212
+ **Goal:** Further improvements after basic split
213
+
214
+ - [ ] **Add TypeScript for UI code**
215
+ - [ ] Rename `.js` files to `.ts`
216
+ - [ ] Add type definitions
217
+ - [ ] Update build to compile UI TypeScript
218
+ - [ ] Add type checking to lint scripts
219
+
220
+ - [ ] **Add minification**
221
+ - [ ] Consider adding Terser for JS minification
222
+ - [ ] Consider adding cssnano for CSS minification
223
+ - [ ] Update build script for production builds
224
+
225
+ - [ ] **Add source maps**
226
+ - [ ] Generate source maps for easier debugging
227
+ - [ ] Configure build to include maps
228
+ - [ ] Test debugging in browser DevTools
229
+
230
+ ---
231
+
232
+ ## Implementation Notes
233
+
234
+ ### Why Native ES6 Modules?
235
+
236
+ - ✅ No bundler needed (simpler build process)
237
+ - ✅ Native browser support (Safari 11+, Chrome 61+, Firefox 60+)
238
+ - ✅ Easier debugging (direct source code visibility)
239
+ - ✅ Suitable for local Homebridge UI (no network latency concerns)
240
+ - ✅ Hot reload friendly (just refresh browser)
241
+
242
+ ### Browser Compatibility
243
+
244
+ - ES6 modules work in all modern browsers (2017+)
245
+ - Homebridge UI runs locally, so old browser support not critical
246
+ - Most Homebridge users have up-to-date browsers
247
+
248
+ ### Build Process
249
+
250
+ - Current: `npm run plugin-ui` copies `src/homebridge-ui/public` → `dist/homebridge-ui/public`
251
+ - After split: Same command, just copies more files (no changes needed)
252
+ - Glob pattern `**/*` already handles subdirectories
253
+
254
+ ### Testing Checklist
255
+
256
+ Each step should be tested before moving to next:
257
+
258
+ 1. Build succeeds without errors
259
+ 2. Files copied to dist/ correctly
260
+ 3. UI loads in browser without errors
261
+ 4. All functionality works as before
262
+ 5. No console errors or warnings
263
+ 6. Performance is same or better