@switchbot/homebridge-switchbot 5.0.0-beta.99 → 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 -471
  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 -554
  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 -945
  267. package/dist/platform.js.map +0 -1
  268. package/src/platform.ts +0 -963
  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
@@ -0,0 +1,3 @@
1
+ declare function loadAdvancedSettings(): Promise<void>;
2
+ declare function saveAdvancedSettings(): Promise<void>;
3
+ //# sourceMappingURL=advanced-settings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"advanced-settings.d.ts","sourceRoot":"","sources":["../../../../src/homebridge-ui/public/js/advanced-settings.ts"],"names":[],"mappings":"AAGA,iBAAe,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CA+BnD;AAED,iBAAe,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CA+CnD"}
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ // advanced-settings.ts
3
+ // Handles loading and saving global OpenAPI polling/rate config in the Advanced Settings card
4
+ async function loadAdvancedSettings() {
5
+ try {
6
+ if (typeof homebridge.getPluginConfig !== 'function') {
7
+ document.getElementById('advancedSettingsStatus').textContent = 'Homebridge UI API not available.';
8
+ return;
9
+ }
10
+ const pluginConfigBlocks = await homebridge.getPluginConfig();
11
+ if (!Array.isArray(pluginConfigBlocks) || !pluginConfigBlocks.length) {
12
+ return;
13
+ }
14
+ const config = pluginConfigBlocks.find(c => (c.platform || c.name || '').toLowerCase().includes('switchbot'));
15
+ if (!config) {
16
+ return;
17
+ }
18
+ document.getElementById('openApiRefreshRate').value = String(config.openApiRefreshRate ?? 300);
19
+ document.getElementById('matterBatchEnabled').checked = config.matterBatchEnabled !== false;
20
+ document.getElementById('matterBatchRefreshRate').value = String(config.matterBatchRefreshRate ?? 300);
21
+ document.getElementById('dailyApiLimit').value = String(config.dailyApiLimit ?? 10000);
22
+ document.getElementById('dailyApiReserveForCommands').value = String(config.dailyApiReserveForCommands ?? 1000);
23
+ document.getElementById('dailyApiResetLocalMidnight').checked = !!config.dailyApiResetLocalMidnight;
24
+ document.getElementById('webhookOnlyOnReserve').checked = !!config.webhookOnlyOnReserve;
25
+ document.getElementById('matterBatchConcurrency').value = String(config.matterBatchConcurrency ?? 5);
26
+ document.getElementById('matterBatchJitter').value = String(config.matterBatchJitter ?? 0);
27
+ document.getElementById('enableMatter').checked = !!config.enableMatter;
28
+ document.getElementById('preferMatter').checked = !!config.preferMatter;
29
+ document.getElementById('enableBLE').checked = config.enableBLE !== false;
30
+ document.getElementById('blePollingEnabled').checked = config.blePollingEnabled !== false;
31
+ document.getElementById('blePollIntervalMs').value = String(config.blePollIntervalMs ?? 600000);
32
+ }
33
+ catch (e) {
34
+ document.getElementById('advancedSettingsStatus').textContent = 'Failed to load settings.';
35
+ }
36
+ }
37
+ async function saveAdvancedSettings() {
38
+ const status = document.getElementById('advancedSettingsStatus');
39
+ status.textContent = 'Saving...';
40
+ try {
41
+ if (typeof homebridge.getPluginConfig !== 'function') {
42
+ throw new TypeError('homebridge.getPluginConfig is not available');
43
+ }
44
+ // Get the full plugin config array
45
+ const pluginConfigBlocks = await homebridge.getPluginConfig();
46
+ if (!Array.isArray(pluginConfigBlocks) || !pluginConfigBlocks.length) {
47
+ throw new Error('No plugin config blocks returned from Homebridge');
48
+ }
49
+ // Find the SwitchBot config block
50
+ const idx = pluginConfigBlocks.findIndex(c => (c.platform || c.name || '').toLowerCase().includes('switchbot'));
51
+ if (idx === -1) {
52
+ throw new Error('SwitchBot config not found');
53
+ }
54
+ const config = pluginConfigBlocks[idx];
55
+ // Update config values from UI
56
+ config.openApiRefreshRate = Number(document.getElementById('openApiRefreshRate').value) || 300;
57
+ config.matterBatchEnabled = document.getElementById('matterBatchEnabled').checked;
58
+ config.matterBatchRefreshRate = Number(document.getElementById('matterBatchRefreshRate').value) || 300;
59
+ config.dailyApiLimit = Number(document.getElementById('dailyApiLimit').value) || 10000;
60
+ config.dailyApiReserveForCommands = Number(document.getElementById('dailyApiReserveForCommands').value) || 1000;
61
+ config.dailyApiResetLocalMidnight = document.getElementById('dailyApiResetLocalMidnight').checked;
62
+ config.webhookOnlyOnReserve = document.getElementById('webhookOnlyOnReserve').checked;
63
+ config.matterBatchConcurrency = Number(document.getElementById('matterBatchConcurrency').value) || 5;
64
+ config.matterBatchJitter = Number(document.getElementById('matterBatchJitter').value) || 0;
65
+ config.enableMatter = document.getElementById('enableMatter').checked;
66
+ config.preferMatter = document.getElementById('preferMatter').checked;
67
+ config.enableBLE = document.getElementById('enableBLE').checked;
68
+ config.blePollingEnabled = document.getElementById('blePollingEnabled').checked;
69
+ config.blePollIntervalMs = Number(document.getElementById('blePollIntervalMs').value) || 600000;
70
+ // Update config in memory and save to disk
71
+ if (typeof homebridge.updatePluginConfig === 'function') {
72
+ await homebridge.updatePluginConfig(pluginConfigBlocks);
73
+ }
74
+ else {
75
+ throw new TypeError('homebridge.updatePluginConfig is not available');
76
+ }
77
+ if (typeof homebridge.savePluginConfig === 'function') {
78
+ await homebridge.savePluginConfig();
79
+ }
80
+ status.textContent = 'Settings saved!';
81
+ }
82
+ catch (e) {
83
+ status.textContent = `Failed to save: ${e && e.message ? e.message : e}`;
84
+ }
85
+ }
86
+ document.addEventListener('DOMContentLoaded', () => {
87
+ if (document.getElementById('advancedSettingsCard')) {
88
+ loadAdvancedSettings();
89
+ const btn = document.getElementById('saveAdvancedSettingsBtn');
90
+ if (btn) {
91
+ btn.onclick = saveAdvancedSettings;
92
+ }
93
+ }
94
+ });
95
+ //# sourceMappingURL=advanced-settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"advanced-settings.js","sourceRoot":"","sources":["../../../../src/homebridge-ui/public/js/advanced-settings.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,94 @@
1
+ // advanced-settings.ts
2
+ // Handles loading and saving global OpenAPI polling/rate config in the Advanced Settings card
3
+
4
+ async function loadAdvancedSettings(): Promise<void> {
5
+ try {
6
+ if (typeof homebridge.getPluginConfig !== 'function') {
7
+ (document.getElementById('advancedSettingsStatus') as HTMLElement).textContent = 'Homebridge UI API not available.'
8
+ return
9
+ }
10
+ const pluginConfigBlocks = await homebridge.getPluginConfig()
11
+ if (!Array.isArray(pluginConfigBlocks) || !pluginConfigBlocks.length) {
12
+ return
13
+ }
14
+ const config = pluginConfigBlocks.find(c => (c.platform || c.name || '').toLowerCase().includes('switchbot'))
15
+ if (!config) {
16
+ return
17
+ }
18
+ (document.getElementById('openApiRefreshRate') as HTMLInputElement).value = String(config.openApiRefreshRate ?? 300)
19
+ ;(document.getElementById('matterBatchEnabled') as HTMLInputElement).checked = config.matterBatchEnabled !== false
20
+ ;(document.getElementById('matterBatchRefreshRate') as HTMLInputElement).value = String(config.matterBatchRefreshRate ?? 300)
21
+ ;(document.getElementById('dailyApiLimit') as HTMLInputElement).value = String(config.dailyApiLimit ?? 10000)
22
+ ;(document.getElementById('dailyApiReserveForCommands') as HTMLInputElement).value = String(config.dailyApiReserveForCommands ?? 1000)
23
+ ;(document.getElementById('dailyApiResetLocalMidnight') as HTMLInputElement).checked = !!config.dailyApiResetLocalMidnight
24
+ ;(document.getElementById('webhookOnlyOnReserve') as HTMLInputElement).checked = !!config.webhookOnlyOnReserve
25
+ ;(document.getElementById('matterBatchConcurrency') as HTMLInputElement).value = String(config.matterBatchConcurrency ?? 5)
26
+ ;(document.getElementById('matterBatchJitter') as HTMLInputElement).value = String(config.matterBatchJitter ?? 0)
27
+ ;(document.getElementById('enableMatter') as HTMLInputElement).checked = !!config.enableMatter
28
+ ;(document.getElementById('preferMatter') as HTMLInputElement).checked = !!config.preferMatter
29
+ ;(document.getElementById('enableBLE') as HTMLInputElement).checked = config.enableBLE !== false
30
+ ;(document.getElementById('blePollingEnabled') as HTMLInputElement).checked = config.blePollingEnabled !== false
31
+ ;(document.getElementById('blePollIntervalMs') as HTMLInputElement).value = String(config.blePollIntervalMs ?? 600000)
32
+ } catch (e) {
33
+ (document.getElementById('advancedSettingsStatus') as HTMLElement).textContent = 'Failed to load settings.'
34
+ }
35
+ }
36
+
37
+ async function saveAdvancedSettings(): Promise<void> {
38
+ const status = document.getElementById('advancedSettingsStatus') as HTMLElement
39
+ status.textContent = 'Saving...'
40
+ try {
41
+ if (typeof homebridge.getPluginConfig !== 'function') {
42
+ throw new TypeError('homebridge.getPluginConfig is not available')
43
+ }
44
+ // Get the full plugin config array
45
+ const pluginConfigBlocks = await homebridge.getPluginConfig()
46
+ if (!Array.isArray(pluginConfigBlocks) || !pluginConfigBlocks.length) {
47
+ throw new Error('No plugin config blocks returned from Homebridge')
48
+ }
49
+ // Find the SwitchBot config block
50
+ const idx = pluginConfigBlocks.findIndex(c => (c.platform || c.name || '').toLowerCase().includes('switchbot'))
51
+ if (idx === -1) {
52
+ throw new Error('SwitchBot config not found')
53
+ }
54
+ const config = pluginConfigBlocks[idx]
55
+ // Update config values from UI
56
+ config.openApiRefreshRate = Number((document.getElementById('openApiRefreshRate') as HTMLInputElement).value) || 300
57
+ config.matterBatchEnabled = (document.getElementById('matterBatchEnabled') as HTMLInputElement).checked
58
+ config.matterBatchRefreshRate = Number((document.getElementById('matterBatchRefreshRate') as HTMLInputElement).value) || 300
59
+ config.dailyApiLimit = Number((document.getElementById('dailyApiLimit') as HTMLInputElement).value) || 10000
60
+ config.dailyApiReserveForCommands = Number((document.getElementById('dailyApiReserveForCommands') as HTMLInputElement).value) || 1000
61
+ config.dailyApiResetLocalMidnight = (document.getElementById('dailyApiResetLocalMidnight') as HTMLInputElement).checked
62
+ config.webhookOnlyOnReserve = (document.getElementById('webhookOnlyOnReserve') as HTMLInputElement).checked
63
+ config.matterBatchConcurrency = Number((document.getElementById('matterBatchConcurrency') as HTMLInputElement).value) || 5
64
+ config.matterBatchJitter = Number((document.getElementById('matterBatchJitter') as HTMLInputElement).value) || 0
65
+ config.enableMatter = (document.getElementById('enableMatter') as HTMLInputElement).checked
66
+ config.preferMatter = (document.getElementById('preferMatter') as HTMLInputElement).checked
67
+ config.enableBLE = (document.getElementById('enableBLE') as HTMLInputElement).checked
68
+ config.blePollingEnabled = (document.getElementById('blePollingEnabled') as HTMLInputElement).checked
69
+ config.blePollIntervalMs = Number((document.getElementById('blePollIntervalMs') as HTMLInputElement).value) || 600000
70
+
71
+ // Update config in memory and save to disk
72
+ if (typeof homebridge.updatePluginConfig === 'function') {
73
+ await homebridge.updatePluginConfig(pluginConfigBlocks)
74
+ } else {
75
+ throw new TypeError('homebridge.updatePluginConfig is not available')
76
+ }
77
+ if (typeof homebridge.savePluginConfig === 'function') {
78
+ await homebridge.savePluginConfig()
79
+ }
80
+ status.textContent = 'Settings saved!'
81
+ } catch (e: any) {
82
+ status.textContent = `Failed to save: ${e && e.message ? e.message : e}`
83
+ }
84
+ }
85
+
86
+ document.addEventListener('DOMContentLoaded', () => {
87
+ if (document.getElementById('advancedSettingsCard')) {
88
+ loadAdvancedSettings()
89
+ const btn = document.getElementById('saveAdvancedSettingsBtn')
90
+ if (btn) {
91
+ btn.onclick = saveAdvancedSettings
92
+ }
93
+ }
94
+ })
@@ -0,0 +1,66 @@
1
+ import './types.js';
2
+ export declare function fetchDevices(): Promise<any[]>;
3
+ /**
4
+ * Validate and auto-correct device types in the config array before saving.
5
+ * Returns an array of errors for devices that cannot be fixed.
6
+ */
7
+ export declare function validateAndFixDeviceTypes(devices: Array<{
8
+ deviceId: string;
9
+ configDeviceName: string;
10
+ configDeviceType: string;
11
+ }>): {
12
+ deviceId: string;
13
+ name: string;
14
+ type: string;
15
+ }[];
16
+ export declare function syncParentPluginConfigFromDisk(autoSave?: boolean): Promise<boolean>;
17
+ export declare function fetchCredentialStatus(): Promise<any>;
18
+ export declare function saveCredentials(token: string, secret: string): Promise<any>;
19
+ export interface DiscoverRequestOptions {
20
+ bleEnabled?: boolean;
21
+ bleScanDurationSeconds?: number;
22
+ bleTimeoutSeconds?: number;
23
+ }
24
+ export declare function discoverDevices(mode?: 'all' | 'ble' | 'openapi', options?: DiscoverRequestOptions): Promise<any[]>;
25
+ export declare function fetchBluetoothStatus(): Promise<{
26
+ available: boolean;
27
+ message: string;
28
+ }>;
29
+ export declare function testDeviceConnection(payload: {
30
+ deviceId: string;
31
+ connectionType?: string;
32
+ address?: string;
33
+ }): Promise<{
34
+ success: boolean;
35
+ deviceId: string;
36
+ method: string;
37
+ latencyMs: number;
38
+ message: string;
39
+ state?: Record<string, any>;
40
+ }>;
41
+ export declare function addDevice(deviceId: string, name: string, type: string, options?: {
42
+ address?: string;
43
+ model?: string;
44
+ rssi?: number;
45
+ encryptionKey?: string;
46
+ keyId?: string;
47
+ }): Promise<any>;
48
+ export declare function addDevicesInBulk(devices: Array<{
49
+ deviceId: string;
50
+ name: string;
51
+ type: string;
52
+ rssi?: number;
53
+ address?: string;
54
+ model?: string;
55
+ }>): Promise<any>;
56
+ export declare function updateDevice(deviceId: string, configDeviceName?: string, configDeviceType?: string, options?: {
57
+ refreshRate?: number;
58
+ connectionPreference?: string;
59
+ encryptionKey?: string;
60
+ keyId?: string;
61
+ room?: string;
62
+ [key: string]: any;
63
+ }): Promise<any>;
64
+ export declare function deleteDevice(deviceId: string): Promise<any>;
65
+ export declare function deleteAllDevices(): Promise<any>;
66
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../../src/homebridge-ui/public/js/api.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,295 @@
1
+ // Fetch the list of configured devices from the Homebridge UI API
2
+ import { isValidDeviceType, normalizeDeviceType } from '../../../device-types.js';
3
+ import './types.js';
4
+ import { uiLog } from './logger.js';
5
+ import { toastError } from './toast.js';
6
+ export async function fetchDevices() {
7
+ try {
8
+ if (typeof homebridge.getPluginConfig !== 'function') {
9
+ throw new TypeError('Homebridge UI API not available');
10
+ }
11
+ const configArr = await homebridge.getPluginConfig();
12
+ const config = Array.isArray(configArr) && configArr.length > 0 ? configArr.find(isSwitchBotPlatformConfig) : null;
13
+ if (!config || !Array.isArray(config.devices)) {
14
+ return [];
15
+ }
16
+ return config.devices;
17
+ }
18
+ catch (e) {
19
+ const msg = e instanceof Error ? e.message : String(e);
20
+ uiLog.error('Error fetching devices:', msg);
21
+ return [];
22
+ }
23
+ }
24
+ /**
25
+ * Validate and auto-correct device types in the config array before saving.
26
+ * Returns an array of errors for devices that cannot be fixed.
27
+ */
28
+ export function validateAndFixDeviceTypes(devices) {
29
+ const errors = [];
30
+ for (const d of devices) {
31
+ if (!isValidDeviceType(d.configDeviceType)) {
32
+ const fixed = normalizeDeviceType(d.configDeviceType);
33
+ if (fixed) {
34
+ d.configDeviceType = fixed;
35
+ }
36
+ else {
37
+ errors.push({
38
+ deviceId: d.deviceId,
39
+ name: d.configDeviceName,
40
+ type: d.configDeviceType,
41
+ });
42
+ }
43
+ }
44
+ }
45
+ return errors;
46
+ }
47
+ // API wrapper functions for communicating with the Homebridge UI server
48
+ function isSwitchBotPlatformConfig(block) {
49
+ const platformName = String(block?.platform || block?.name || '').toLowerCase();
50
+ return (platformName === 'switchbot'
51
+ || platformName === '@switchbot/homebridge-switchbot'
52
+ || platformName.includes('switchbot'));
53
+ }
54
+ export async function syncParentPluginConfigFromDisk(autoSave = false) {
55
+ try {
56
+ if (typeof homebridge.getPluginConfig !== 'function'
57
+ || typeof homebridge.updatePluginConfig !== 'function') {
58
+ uiLog.warn('Parent config sync API not available');
59
+ return false;
60
+ }
61
+ // Use Homebridge UI API to fetch and update config
62
+ const pluginConfigBlocks = await homebridge.getPluginConfig();
63
+ if (!Array.isArray(pluginConfigBlocks) || !pluginConfigBlocks.length) {
64
+ uiLog.warn('No plugin config blocks returned from Homebridge');
65
+ return false;
66
+ }
67
+ const index = pluginConfigBlocks.findIndex(block => isSwitchBotPlatformConfig(block));
68
+ if (index < 0) {
69
+ uiLog.warn('SwitchBot platform block not found in Homebridge plugin config');
70
+ return false;
71
+ }
72
+ // Validate and fix device types before saving
73
+ const errors = validateAndFixDeviceTypes(pluginConfigBlocks[index].devices || []);
74
+ if (errors.length > 0) {
75
+ toastError(`Invalid device types found: ${errors.map(e => `${e.name} (${e.type})`).join(', ')}`);
76
+ return false;
77
+ }
78
+ // pluginConfigBlocks[index] is already up to date
79
+ await homebridge.updatePluginConfig(pluginConfigBlocks);
80
+ // Auto-save to disk if requested - prevents parent UI from overwriting with stale cache
81
+ if (autoSave && typeof homebridge.savePluginConfig === 'function') {
82
+ uiLog.info('Auto-saving config to disk...');
83
+ await homebridge.savePluginConfig();
84
+ uiLog.info('Config saved successfully');
85
+ }
86
+ return true;
87
+ }
88
+ catch (e) {
89
+ uiLog.warn('Failed to sync parent plugin config cache:', e);
90
+ return false;
91
+ }
92
+ }
93
+ export async function fetchCredentialStatus() {
94
+ try {
95
+ const resp = await homebridge.request('/credentials', {});
96
+ uiLog.info('Load credentials response:', resp);
97
+ if (!resp || resp.success === false) {
98
+ uiLog.error('Failed to load credentials:', resp);
99
+ return null;
100
+ }
101
+ return resp.data || {};
102
+ }
103
+ catch (e) {
104
+ uiLog.error('Error loading credentials:', e);
105
+ return null;
106
+ }
107
+ }
108
+ export async function saveCredentials(token, secret) {
109
+ uiLog.info('Saving credentials...');
110
+ const resp = await homebridge.request('/credentials', { token, secret });
111
+ uiLog.info('Save response:', resp);
112
+ if (!resp || resp.success === false) {
113
+ throw new Error(resp?.message || 'Save failed');
114
+ }
115
+ return resp.data || resp;
116
+ }
117
+ export async function discoverDevices(mode = 'all', options) {
118
+ const resp = await homebridge.request('/discover', { mode, ...options });
119
+ uiLog.info('Discover response:', resp);
120
+ if (!resp || resp.success === false) {
121
+ throw new Error(resp?.data?.message || 'Discovery failed');
122
+ }
123
+ return resp.data || [];
124
+ }
125
+ export async function fetchBluetoothStatus() {
126
+ try {
127
+ const resp = await homebridge.request('/ble-status', {});
128
+ if (!resp || resp.success === false) {
129
+ return { available: false, message: 'Bluetooth status unavailable' };
130
+ }
131
+ return resp.data || { available: false, message: 'Bluetooth status unavailable' };
132
+ }
133
+ catch (_e) {
134
+ return { available: false, message: 'Bluetooth status unavailable' };
135
+ }
136
+ }
137
+ export async function testDeviceConnection(payload) {
138
+ const resp = await homebridge.request('/test-connection', payload);
139
+ if (!resp || resp.success === false) {
140
+ throw new Error(resp?.data?.message || 'Connection test failed');
141
+ }
142
+ return resp.data || {
143
+ success: false,
144
+ deviceId: payload.deviceId,
145
+ method: 'Auto',
146
+ latencyMs: 0,
147
+ message: 'Connection test failed',
148
+ };
149
+ }
150
+ export async function addDevice(deviceId, name, type, options) {
151
+ if (typeof homebridge.getPluginConfig !== 'function' || typeof homebridge.updatePluginConfig !== 'function') {
152
+ throw new TypeError('Homebridge UI API not available');
153
+ }
154
+ const configArr = await homebridge.getPluginConfig();
155
+ const idx = Array.isArray(configArr) ? configArr.findIndex(isSwitchBotPlatformConfig) : -1;
156
+ if (idx === -1) {
157
+ throw new Error('SwitchBot config not found');
158
+ }
159
+ const config = configArr[idx];
160
+ if (!Array.isArray(config.devices)) {
161
+ config.devices = [];
162
+ }
163
+ const normalizedDeviceId = String(deviceId).trim().toLowerCase();
164
+ const exists = config.devices.some((d) => String(d.deviceId ?? d.id ?? '').trim().toLowerCase() === normalizedDeviceId);
165
+ if (exists) {
166
+ return { alreadyExists: true, message: 'Device already in config' };
167
+ }
168
+ const newDevice = { deviceId, configDeviceName: name, configDeviceType: type };
169
+ if (options?.address) {
170
+ newDevice.address = options.address;
171
+ }
172
+ if (options?.model) {
173
+ newDevice.model = options.model;
174
+ }
175
+ if (options?.rssi !== undefined && options?.rssi !== null && options?.rssi !== 0) {
176
+ newDevice.rssi = options.rssi;
177
+ }
178
+ if (options?.encryptionKey) {
179
+ newDevice.encryptionKey = options.encryptionKey;
180
+ }
181
+ if (options?.keyId) {
182
+ newDevice.keyId = options.keyId;
183
+ }
184
+ config.devices.push(newDevice);
185
+ await homebridge.updatePluginConfig(configArr);
186
+ if (typeof homebridge.savePluginConfig === 'function') {
187
+ await homebridge.savePluginConfig();
188
+ }
189
+ return { added: true, message: `Device "${name}" added successfully` };
190
+ }
191
+ export async function addDevicesInBulk(devices) {
192
+ const resp = await homebridge.request('/add-devices', { devices });
193
+ uiLog.info('Bulk add response:', resp);
194
+ if (!resp || resp.success === false) {
195
+ throw new Error(resp?.data?.message || 'Bulk add failed');
196
+ }
197
+ return resp.data || resp;
198
+ }
199
+ export async function updateDevice(deviceId, configDeviceName, configDeviceType, options) {
200
+ if (typeof homebridge.getPluginConfig !== 'function' || typeof homebridge.updatePluginConfig !== 'function') {
201
+ throw new TypeError('Homebridge UI API not available');
202
+ }
203
+ const configArr = await homebridge.getPluginConfig();
204
+ const idx = Array.isArray(configArr) ? configArr.findIndex(isSwitchBotPlatformConfig) : -1;
205
+ if (idx === -1) {
206
+ throw new Error('SwitchBot config not found');
207
+ }
208
+ const config = configArr[idx];
209
+ if (!Array.isArray(config.devices)) {
210
+ throw new TypeError('No devices array in config');
211
+ }
212
+ const normalizedDeviceId = String(deviceId).trim().toLowerCase();
213
+ const device = config.devices.find((d) => String(d.deviceId ?? d.id ?? '').trim().toLowerCase() === normalizedDeviceId);
214
+ if (!device) {
215
+ throw new Error('Device not found in config');
216
+ }
217
+ if (configDeviceName) {
218
+ device.configDeviceName = configDeviceName;
219
+ }
220
+ if (configDeviceType) {
221
+ device.configDeviceType = configDeviceType;
222
+ }
223
+ if (options) {
224
+ Object.assign(device, options);
225
+ }
226
+ await homebridge.updatePluginConfig(configArr);
227
+ if (typeof homebridge.savePluginConfig === 'function') {
228
+ await homebridge.savePluginConfig();
229
+ }
230
+ return { updated: true, message: `Device updated successfully` };
231
+ }
232
+ export async function deleteDevice(deviceId) {
233
+ if (typeof homebridge.getPluginConfig !== 'function' || typeof homebridge.updatePluginConfig !== 'function') {
234
+ throw new TypeError('Homebridge UI API not available');
235
+ }
236
+ const configArr = await homebridge.getPluginConfig();
237
+ const idx = Array.isArray(configArr) ? configArr.findIndex(isSwitchBotPlatformConfig) : -1;
238
+ if (idx === -1) {
239
+ throw new Error('SwitchBot config not found');
240
+ }
241
+ const config = configArr[idx];
242
+ if (!Array.isArray(config.devices)) {
243
+ throw new TypeError('No devices array in config');
244
+ }
245
+ const normalizedDeviceId = String(deviceId).trim().toLowerCase();
246
+ const before = config.devices.length;
247
+ // Remove the target device
248
+ config.devices = config.devices.filter(d => String(d.deviceId ?? d.id ?? '').trim().toLowerCase() !== normalizedDeviceId);
249
+ // Defensive: filter out any invalid device entries (missing required fields)
250
+ config.devices = config.devices.filter(d => d && typeof d === 'object' && d.deviceId && d.configDeviceType);
251
+ if (config.devices.length === before) {
252
+ throw new Error('Device not found in config');
253
+ }
254
+ await homebridge.updatePluginConfig(configArr);
255
+ if (typeof homebridge.savePluginConfig === 'function') {
256
+ await homebridge.savePluginConfig();
257
+ }
258
+ return { deleted: true, message: `Device removed from config` };
259
+ }
260
+ export async function deleteAllDevices() {
261
+ if (typeof homebridge.getPluginConfig !== 'function' || typeof homebridge.updatePluginConfig !== 'function') {
262
+ throw new TypeError('Homebridge UI API not available');
263
+ }
264
+ const configArr = await homebridge.getPluginConfig();
265
+ // Find or create the SwitchBot config block
266
+ let idx = Array.isArray(configArr) ? configArr.findIndex(isSwitchBotPlatformConfig) : -1;
267
+ if (idx === -1) {
268
+ // If not found, create a new config block for SwitchBot
269
+ const newBlock = { platform: 'SwitchBot', devices: [] };
270
+ configArr.push(newBlock);
271
+ idx = configArr.length - 1;
272
+ }
273
+ const config = configArr[idx];
274
+ // Always ensure devices is an array
275
+ if (!Array.isArray(config.devices)) {
276
+ config.devices = [];
277
+ }
278
+ const deletedCount = config.devices.length;
279
+ config.devices = [];
280
+ // Defensive: ensure required fields for schema compliance
281
+ if (!config.platform) {
282
+ config.platform = 'SwitchBot';
283
+ }
284
+ // Ensure 'name' property is present (required by schema for Homebridge platform blocks)
285
+ if (!config.name) {
286
+ config.name = 'SwitchBot';
287
+ }
288
+ // Save updated config
289
+ await homebridge.updatePluginConfig(configArr);
290
+ if (typeof homebridge.savePluginConfig === 'function') {
291
+ await homebridge.savePluginConfig();
292
+ }
293
+ return { deleted: true, deletedCount, message: `Removed ${deletedCount} device(s) from config` };
294
+ }
295
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../../../src/homebridge-ui/public/js/api.ts"],"names":[],"mappings":"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"}