@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,7 @@
1
+ export declare const uiLog: {
2
+ info: (message: string, ...parameters: any[]) => void;
3
+ warn: (message: string, ...parameters: any[]) => void;
4
+ error: (message: string, ...parameters: any[]) => void;
5
+ debug: (message: string, ...parameters: any[]) => void;
6
+ };
7
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/homebridge-ui/utils/logger.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,KAAK;oBACA,MAAM,iBAAiB,GAAG,EAAE;oBAG5B,MAAM,iBAAiB,GAAG,EAAE;qBAG3B,MAAM,iBAAiB,GAAG,EAAE;qBAG5B,MAAM,iBAAiB,GAAG,EAAE;CAG9C,CAAA"}
@@ -0,0 +1,17 @@
1
+ /* eslint-disable no-console */
2
+ const PREFIX = '[SwitchBot UI/Server]';
3
+ export const uiLog = {
4
+ info: (message, ...parameters) => {
5
+ console.log(PREFIX, message, ...parameters);
6
+ },
7
+ warn: (message, ...parameters) => {
8
+ console.warn(PREFIX, message, ...parameters);
9
+ },
10
+ error: (message, ...parameters) => {
11
+ console.error(PREFIX, message, ...parameters);
12
+ },
13
+ debug: (message, ...parameters) => {
14
+ console.debug(PREFIX, message, ...parameters);
15
+ },
16
+ };
17
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../../src/homebridge-ui/utils/logger.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,MAAM,MAAM,GAAG,uBAAuB,CAAA;AAEtC,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,IAAI,EAAE,CAAC,OAAe,EAAE,GAAG,UAAiB,EAAE,EAAE;QAC9C,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC,CAAA;IAC7C,CAAC;IACD,IAAI,EAAE,CAAC,OAAe,EAAE,GAAG,UAAiB,EAAE,EAAE;QAC9C,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC,CAAA;IAC9C,CAAC;IACD,KAAK,EAAE,CAAC,OAAe,EAAE,GAAG,UAAiB,EAAE,EAAE;QAC/C,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC,CAAA;IAC/C,CAAC;IACD,KAAK,EAAE,CAAC,OAAe,EAAE,GAAG,UAAiB,EAAE,EAAE;QAC/C,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC,CAAA;IAC/C,CAAC;CACF,CAAA"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,14 @@
1
1
  import type { API } from 'homebridge';
2
+ /**
3
+ * Registers the SwitchBot platform with Homebridge.
4
+ *
5
+ * @param api The Homebridge API instance.
6
+ * @property {string} PLATFORM_NAME - The Homebridge platform name.
7
+ * @property {string} PLUGIN_NAME - The Homebridge plugin name.
8
+ * @property {typeof SwitchBotHAPPlatform} SwitchBotHAPPlatform - The HAP platform class.
9
+ * @property {typeof SwitchBotMatterPlatform} SwitchBotMatterPlatform - The Matter platform class.
10
+ * @property {Function} createPlatformProxy - Factory for the platform proxy constructor.
11
+ */
2
12
  declare const _default: (api: API) => void;
3
13
  export default _default;
4
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAA;yBAOrB,KAAK,GAAG,KAAG,IAAI;AAA/B,wBAGC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAA;AAOrC;;;;;;;;;GASG;yBACa,KAAK,GAAG,KAAG,IAAI;AAA/B,wBAGC"}
package/dist/index.js CHANGED
@@ -1,7 +1,17 @@
1
- import { SwitchBotHAPPlatform, SwitchBotMatterPlatform } from './platform.js';
2
1
  import { PLATFORM_NAME, PLUGIN_NAME } from './settings.js';
2
+ import { SwitchBotHAPPlatform } from './SwitchBotHAPPlatform.js';
3
+ import { SwitchBotMatterPlatform } from './SwitchBotMatterPlatform.js';
3
4
  import { createPlatformProxy } from './utils.js';
4
- // Register our platform with homebridge.
5
+ /**
6
+ * Registers the SwitchBot platform with Homebridge.
7
+ *
8
+ * @param api The Homebridge API instance.
9
+ * @property {string} PLATFORM_NAME - The Homebridge platform name.
10
+ * @property {string} PLUGIN_NAME - The Homebridge plugin name.
11
+ * @property {typeof SwitchBotHAPPlatform} SwitchBotHAPPlatform - The HAP platform class.
12
+ * @property {typeof SwitchBotMatterPlatform} SwitchBotMatterPlatform - The Matter platform class.
13
+ * @property {Function} createPlatformProxy - Factory for the platform proxy constructor.
14
+ */
5
15
  export default (api) => {
6
16
  const ProxyCtor = createPlatformProxy(SwitchBotHAPPlatform, SwitchBotMatterPlatform);
7
17
  api.registerPlatform(PLUGIN_NAME, PLATFORM_NAME, ProxyCtor);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAA;AAC7E,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAEhD,yCAAyC;AACzC,eAAe,CAAC,GAAQ,EAAQ,EAAE;IAChC,MAAM,SAAS,GAAG,mBAAmB,CAAC,oBAAoB,EAAE,uBAAuB,CAAC,CAAA;IACpF,GAAG,CAAC,gBAAgB,CAAC,WAAW,EAAE,aAAa,EAAE,SAAgB,CAAC,CAAA;AACpE,CAAC,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAA;AAChE,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAA;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAEhD;;;;;;;;;GASG;AACH,eAAe,CAAC,GAAQ,EAAQ,EAAE;IAChC,MAAM,SAAS,GAAG,mBAAmB,CAAC,oBAAoB,EAAE,uBAAuB,CAAC,CAAA;IACpF,GAAG,CAAC,gBAAgB,CAAC,WAAW,EAAE,aAAa,EAAE,SAAgB,CAAC,CAAA;AACpE,CAAC,CAAA"}
@@ -5,6 +5,7 @@ export interface SwitchBotPluginConfig {
5
5
  openApiSecret?: string;
6
6
  preferMatter?: boolean;
7
7
  enableMatter?: boolean;
8
+ enableBLE?: boolean;
8
9
  [key: string]: any;
9
10
  }
10
11
  export declare const DEFAULT_CONFIG: Partial<SwitchBotPluginConfig>;
@@ -1 +1 @@
1
- {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,oCAAoC,CAAA;AAC5D,eAAO,MAAM,aAAa,cAAc,CAAA;AAExC,MAAM,WAAW,qBAAqB;IACpC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,YAAY,CAAC,EAAE,OAAO,CAAA;IAEtB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CACnB;AAED,eAAO,MAAM,cAAc,EAAE,OAAO,CAAC,qBAAqB,CAGzD,CAAA;AAED,MAAM,MAAM,UAAU,GAAG,MAAM,CAAA"}
1
+ {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,oCAAoC,CAAA;AAC5D,eAAO,MAAM,aAAa,cAAc,CAAA;AAExC,MAAM,WAAW,qBAAqB;IACpC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,SAAS,CAAC,EAAE,OAAO,CAAA;IAEnB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CACnB;AAED,eAAO,MAAM,cAAc,EAAE,OAAO,CAAC,qBAAqB,CAIzD,CAAA;AAED,MAAM,MAAM,UAAU,GAAG,MAAM,CAAA"}
package/dist/settings.js CHANGED
@@ -3,5 +3,6 @@ export const PLATFORM_NAME = 'SwitchBot';
3
3
  export const DEFAULT_CONFIG = {
4
4
  preferMatter: true,
5
5
  enableMatter: true,
6
+ enableBLE: true,
6
7
  };
7
8
  //# sourceMappingURL=settings.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG,iCAAiC,CAAA;AAC5D,MAAM,CAAC,MAAM,aAAa,GAAG,WAAW,CAAA;AAWxC,MAAM,CAAC,MAAM,cAAc,GAAmC;IAC5D,YAAY,EAAE,IAAI;IAClB,YAAY,EAAE,IAAI;CACnB,CAAA"}
1
+ {"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG,iCAAiC,CAAA;AAC5D,MAAM,CAAC,MAAM,aAAa,GAAG,WAAW,CAAA;AAYxC,MAAM,CAAC,MAAM,cAAc,GAAmC;IAC5D,YAAY,EAAE,IAAI;IAClB,YAAY,EAAE,IAAI;IAClB,SAAS,EAAE,IAAI;CAChB,CAAA"}
@@ -1,32 +1,34 @@
1
1
  import type { SwitchBotPluginConfig } from './settings.js';
2
2
  export interface ISwitchBotClient {
3
- init(): Promise<void>;
4
- getDevice(id: string): Promise<any>;
5
- getDevices(): Promise<any[]>;
6
- setDeviceState(id: string, body: any): Promise<any>;
7
- destroy(): Promise<void>;
3
+ init: () => Promise<void>;
4
+ getDevice: (id: string) => Promise<any>;
5
+ getDevices: () => Promise<any[]>;
6
+ setDeviceState: (id: string, body: any) => Promise<any>;
7
+ destroy: () => Promise<void>;
8
8
  }
9
9
  /**
10
- * Thin wrapper around node-switchbot v4.0.0-beta.2+
10
+ * Thin wrapper around node-switchbot v4.0.0+
11
11
  * Leverages upstream resilience features (retry, circuit breaker, connection intelligence)
12
12
  * while maintaining plugin-specific features like write debouncing and OpenAPI fallback.
13
13
  */
14
14
  export declare class SwitchBotClient implements ISwitchBotClient {
15
15
  private cfg;
16
16
  private client;
17
- private baseUrl;
18
- private requestTimeout;
19
- private maxRetries;
20
17
  private writeDebounceMs;
18
+ private discoveryCacheTtlMs;
19
+ private lastDiscoveryAt;
21
20
  private logger;
22
21
  private pendingWrites;
23
22
  constructor(cfg: SwitchBotPluginConfig);
24
23
  init(): Promise<void>;
25
- private fetchWithTimeoutAndRetry;
26
24
  getDevice(id: string): Promise<any>;
27
25
  getDevices(): Promise<any[]>;
28
26
  setDeviceState(id: string, body: any): Promise<any>;
29
27
  private _doSetDeviceState;
30
28
  destroy(): Promise<void>;
29
+ private resolveScanTimeoutMs;
30
+ private getManagedDevice;
31
+ private getManagedDevices;
32
+ private ensureDiscovered;
31
33
  }
32
34
  //# sourceMappingURL=switchbotClient.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"switchbotClient.d.ts","sourceRoot":"","sources":["../src/switchbotClient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AAE1D,MAAM,WAAW,gBAAgB;IAC/B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACrB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAA;IACnC,UAAU,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAA;IAC5B,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAA;IACnD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACzB;AAED;;;;GAIG;AACH,qBAAa,eAAgB,YAAW,gBAAgB;IACtD,OAAO,CAAC,GAAG,CAAuB;IAClC,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,OAAO,CAAoC;IACnD,OAAO,CAAC,cAAc,CAAO;IAC7B,OAAO,CAAC,UAAU,CAAI;IACtB,OAAO,CAAC,eAAe,CAAM;IAC7B,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,aAAa,CAA0H;gBAEnI,GAAG,EAAE,qBAAqB;IAQhC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAqBb,wBAAwB;IAkChC,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAmBnC,UAAU,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAoB5B,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;YA+B3C,iBAAiB;IAqCzB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAM/B"}
1
+ {"version":3,"file":"switchbotClient.d.ts","sourceRoot":"","sources":["../src/switchbotClient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AAM1D,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IACzB,SAAS,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,CAAC,CAAA;IACvC,UAAU,EAAE,MAAM,OAAO,CAAC,GAAG,EAAE,CAAC,CAAA;IAChC,cAAc,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,CAAA;IACvD,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC7B;AAED;;;;GAIG;AACH,qBAAa,eAAgB,YAAW,gBAAgB;IACtD,OAAO,CAAC,GAAG,CAAuB;IAClC,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,eAAe,CAAM;IAC7B,OAAO,CAAC,mBAAmB,CAAS;IACpC,OAAO,CAAC,eAAe,CAAI;IAC3B,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,aAAa,CAA+H;gBAExI,GAAG,EAAE,qBAAqB;IAchC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA8BrB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAmCnC,UAAU,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAgB5B,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;YAwC3C,iBAAiB;IAqCzB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB9B,OAAO,CAAC,oBAAoB;IAgB5B,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,iBAAiB;YASX,gBAAgB;CAe/B"}
@@ -1,41 +1,53 @@
1
+ import { getDeviceCommandHandler } from './deviceCommandMapper.js';
2
+ import { CharacteristicMissingError, SwitchbotAuthenticationError, SwitchbotOperationError } from './errors.js';
1
3
  /**
2
- * Thin wrapper around node-switchbot v4.0.0-beta.2+
4
+ * Thin wrapper around node-switchbot v4.0.0+
3
5
  * Leverages upstream resilience features (retry, circuit breaker, connection intelligence)
4
6
  * while maintaining plugin-specific features like write debouncing and OpenAPI fallback.
5
7
  */
6
8
  export class SwitchBotClient {
7
9
  cfg;
8
10
  client = null;
9
- baseUrl = 'https://api.switch-bot.com/v1.0';
10
- requestTimeout = 5000;
11
- maxRetries = 2;
12
11
  writeDebounceMs = 100;
12
+ discoveryCacheTtlMs = 30_000;
13
+ lastDiscoveryAt = 0;
13
14
  logger;
14
15
  pendingWrites = new Map();
15
16
  constructor(cfg) {
16
17
  this.cfg = cfg;
17
- this.logger = cfg?.logger ?? console;
18
- if (typeof cfg?.requestTimeout === 'number')
19
- this.requestTimeout = cfg.requestTimeout;
20
- if (typeof cfg?.maxRetries === 'number')
21
- this.maxRetries = cfg.maxRetries;
22
- if (typeof cfg?.writeDebounceMs === 'number')
18
+ this.logger = cfg?.logger;
19
+ if (!this.logger) {
20
+ throw new Error('SwitchBotClient requires a logger (Homebridge logger) in config');
21
+ }
22
+ if (typeof cfg?.writeDebounceMs === 'number') {
23
23
  this.writeDebounceMs = cfg.writeDebounceMs;
24
+ }
25
+ if (typeof cfg?.discoveryCacheTtlMs === 'number') {
26
+ this.discoveryCacheTtlMs = Math.max(0, cfg.discoveryCacheTtlMs);
27
+ }
24
28
  }
25
29
  async init() {
30
+ if (this.client) {
31
+ return;
32
+ }
26
33
  try {
27
34
  // Dynamic import of node-switchbot v4 with native resilience features
28
35
  const { SwitchBot } = await import('node-switchbot');
36
+ const rawNodeClientConfig = typeof this.cfg?.nodeClientConfig === 'object' ? this.cfg.nodeClientConfig : {};
37
+ const scanTimeout = this.resolveScanTimeoutMs(rawNodeClientConfig);
29
38
  this.client = new SwitchBot({
30
39
  token: this.cfg.openApiToken,
31
40
  secret: this.cfg.openApiSecret,
32
- // Enable all built-in resilience features from node-switchbot v4
41
+ // Enable built-in resilience features from node-switchbot v4.
33
42
  enableFallback: true, // Auto-fallback from BLE to API
34
43
  enableRetry: true, // Retry with exponential backoff
35
44
  enableCircuitBreaker: true, // Circuit breaker per connection type
36
- enableMetrics: true, // Connection tracking and statistics
37
- ...(typeof this.cfg?.nodeClientConfig === 'object' && this.cfg.nodeClientConfig),
45
+ enableConnectionIntelligence: true, // Connection tracking and route preference
46
+ enableBLE: this.cfg.enableBLE !== false, // Use config value, default true
47
+ scanTimeout,
48
+ ...rawNodeClientConfig,
38
49
  });
50
+ this.lastDiscoveryAt = 0;
39
51
  this.logger?.info?.('SwitchBot client initialized with native resilience features');
40
52
  }
41
53
  catch (e) {
@@ -43,80 +55,57 @@ export class SwitchBotClient {
43
55
  this.client = null;
44
56
  }
45
57
  }
46
- async fetchWithTimeoutAndRetry(url, opts = {}, timeoutMs, retries) {
47
- const to = typeof timeoutMs === 'number' ? timeoutMs : this.requestTimeout;
48
- const max = typeof retries === 'number' ? retries : this.maxRetries;
49
- let attempt = 0;
50
- while (true) {
51
- attempt += 1;
52
- const controller = new AbortController();
53
- const timer = setTimeout(() => controller.abort(), to);
58
+ async getDevice(id) {
59
+ if (this.client) {
54
60
  try {
55
- const fetchOpts = Object.assign({}, opts);
56
- try {
57
- Object.defineProperty(fetchOpts, 'signal', { value: controller.signal, enumerable: false, configurable: true });
61
+ const fromManager = this.getManagedDevice(id);
62
+ if (fromManager) {
63
+ return fromManager;
58
64
  }
59
- catch (_e) {
60
- // ignore
65
+ const devices = await this.ensureDiscovered(false);
66
+ const fromDiscovery = devices.find((d) => d.id === id);
67
+ if (fromDiscovery) {
68
+ return fromDiscovery;
61
69
  }
62
- const resp = await fetch(url, fetchOpts);
63
- clearTimeout(timer);
64
- if (resp.ok)
65
- return resp;
66
- // server error / rate limit: retry
67
- if (resp.status >= 500 || resp.status === 429) {
68
- throw new Error(`retriable response: ${resp.status}`);
69
- }
70
- return resp;
71
- }
72
- catch (err) {
73
- clearTimeout(timer);
74
- if (attempt > max)
75
- throw err;
76
- // exponential backoff
77
- const backoff = Math.min(100 * Math.pow(2, attempt - 1), 2000);
78
- await new Promise((r) => setTimeout(r, backoff));
79
- }
80
- }
81
- }
82
- async getDevice(id) {
83
- // Try client API first (with node-switchbot's smart fallback and retry)
84
- if (this.client?.getDevice) {
85
- try {
86
- return await this.client.getDevice(id);
70
+ const refreshDevices = await this.ensureDiscovered(true);
71
+ return refreshDevices.find((d) => d.id === id);
87
72
  }
88
73
  catch (e) {
89
- this.logger?.warn?.(`Client getDevice failed for ${id}, trying OpenAPI fallback:`, e);
74
+ if (e instanceof SwitchbotAuthenticationError) {
75
+ this.logger?.error?.(`Authentication error for getDevice(${id}):`, e.message);
76
+ throw e;
77
+ }
78
+ else if (e instanceof SwitchbotOperationError) {
79
+ this.logger?.warn?.(`Operation error for getDevice(${id}):`, e.message, e.code);
80
+ throw e;
81
+ }
82
+ else if (e instanceof CharacteristicMissingError) {
83
+ this.logger?.warn?.(`Characteristic missing for getDevice(${id}):`, e.characteristic);
84
+ throw e;
85
+ }
86
+ else {
87
+ this.logger?.warn?.(`Client getDevice failed for ${id}:`, e);
88
+ throw e;
89
+ }
90
90
  }
91
91
  }
92
- // Fallback: call OpenAPI via HTTP
93
- if (this.cfg.openApiToken) {
94
- const url = `${this.baseUrl}/devices/${id}`;
95
- const opts = { headers: { Authorization: this.cfg.openApiToken } };
96
- const resp = await this.fetchWithTimeoutAndRetry(url, opts);
97
- return resp.json();
98
- }
99
- throw new Error('No SwitchBot client available');
92
+ throw new SwitchbotOperationError('No SwitchBot client available', 'no_client');
100
93
  }
101
94
  async getDevices() {
102
- // Try client API first
103
- if (this.client?.getDevices) {
95
+ if (this.client) {
104
96
  try {
105
- return await this.client.getDevices();
97
+ const fromManager = this.getManagedDevices();
98
+ if (fromManager.length > 0) {
99
+ return fromManager;
100
+ }
101
+ return await this.ensureDiscovered(false);
106
102
  }
107
103
  catch (e) {
108
- this.logger?.warn?.('Client getDevices failed, trying OpenAPI fallback:', e);
104
+ this.logger?.warn?.('Client getDevices failed:', e);
105
+ throw e;
109
106
  }
110
107
  }
111
- // Fallback: call OpenAPI
112
- if (this.cfg.openApiToken) {
113
- const url = `${this.baseUrl}/devices`;
114
- const opts = { headers: { Authorization: this.cfg.openApiToken } };
115
- const resp = await this.fetchWithTimeoutAndRetry(url, opts);
116
- const data = await resp.json();
117
- return (data?.body || data);
118
- }
119
- return [];
108
+ throw new SwitchbotOperationError('No SwitchBot client available', 'no_client');
120
109
  }
121
110
  async setDeviceState(id, body) {
122
111
  // Plugin-level debounce: coalesce rapid writes per device
@@ -133,8 +122,9 @@ export class SwitchBotClient {
133
122
  const resolvers = [{ resolve, reject }];
134
123
  const timer = setTimeout(async () => {
135
124
  const entry = this.pendingWrites.get(id);
136
- if (!entry)
125
+ if (!entry) {
137
126
  return;
127
+ }
138
128
  this.pendingWrites.delete(id);
139
129
  try {
140
130
  const out = await this._doSetDeviceState(id, entry.body);
@@ -142,6 +132,15 @@ export class SwitchBotClient {
142
132
  r.resolve(out);
143
133
  }
144
134
  catch (e) {
135
+ if (e instanceof SwitchbotAuthenticationError) {
136
+ this.logger?.error?.(`Authentication error for setDeviceState(${id}):`, e.message);
137
+ }
138
+ else if (e instanceof SwitchbotOperationError) {
139
+ this.logger?.warn?.(`Operation error for setDeviceState(${id}):`, e.message, e.code);
140
+ }
141
+ else if (e instanceof CharacteristicMissingError) {
142
+ this.logger?.warn?.(`Characteristic missing for setDeviceState(${id}):`, e.characteristic);
143
+ }
145
144
  for (const r of entry.resolvers)
146
145
  r.reject(e);
147
146
  }
@@ -150,45 +149,99 @@ export class SwitchBotClient {
150
149
  });
151
150
  }
152
151
  async _doSetDeviceState(id, body) {
153
- // Prefer client API (which has node-switchbot's native resilience)
154
- if (this.client?.setDeviceState) {
155
- try {
156
- return await this.client.setDeviceState(id, body);
152
+ if (!this.client) {
153
+ throw new SwitchbotOperationError('No SwitchBot client available for setDeviceState', 'no_client');
154
+ }
155
+ try {
156
+ const device = await this.getDevice(id);
157
+ if (!device) {
158
+ throw new SwitchbotOperationError(`Device ${id} not found`, 'device_not_found');
157
159
  }
158
- catch (e) {
159
- this.logger?.warn?.(`Client setDeviceState failed for ${id}, trying fallback:`, e);
160
+ const deviceType = (device.deviceType ?? '').toLowerCase();
161
+ const command = body?.command;
162
+ if (!command) {
163
+ throw new SwitchbotOperationError('No command specified in body', 'no_command');
160
164
  }
165
+ const handler = getDeviceCommandHandler(deviceType, command);
166
+ if (!handler) {
167
+ throw new SwitchbotOperationError(`Unsupported command '${command}' for device type '${deviceType}'`, 'unsupported_command');
168
+ }
169
+ this.logger?.debug?.(`[${id}] Calling mapped command '${command}' for device type '${deviceType}'`);
170
+ return await handler(device, body);
161
171
  }
162
- // Try generic sendCommand if available
163
- if (this.client?.sendCommand) {
164
- try {
165
- return await this.client.sendCommand(id, body);
172
+ catch (e) {
173
+ if (e instanceof SwitchbotAuthenticationError) {
174
+ this.logger?.error?.(`Authentication error for setDeviceState(${id}):`, e.message);
175
+ throw e;
166
176
  }
167
- catch (e) {
168
- this.logger?.warn?.(`Client sendCommand failed for ${id}, trying OpenAPI:`, e);
177
+ else if (e instanceof SwitchbotOperationError) {
178
+ this.logger?.warn?.(`Operation error for setDeviceState(${id}):`, e.message, e.code);
179
+ throw e;
180
+ }
181
+ else if (e instanceof CharacteristicMissingError) {
182
+ this.logger?.warn?.(`Characteristic missing for setDeviceState(${id}):`, e.characteristic);
183
+ throw e;
184
+ }
185
+ else {
186
+ this.logger?.warn?.(`Device command failed for ${id}:`, e);
187
+ throw e;
169
188
  }
170
189
  }
171
- // OpenAPI fallback
172
- if (this.cfg.openApiToken) {
173
- const url = `${this.baseUrl}/devices/${id}/commands`;
174
- const opts = {
175
- method: 'POST',
176
- headers: {
177
- Authorization: this.cfg.openApiToken,
178
- 'Content-Type': 'application/json',
179
- },
180
- body: JSON.stringify(body),
181
- };
182
- const resp = await this.fetchWithTimeoutAndRetry(url, opts);
183
- return resp.json();
184
- }
185
- throw new Error('No SwitchBot client available for setDeviceState');
186
190
  }
187
191
  async destroy() {
188
- if (this.client?.destroy) {
189
- await this.client.destroy();
192
+ for (const [, pending] of this.pendingWrites) {
193
+ clearTimeout(pending.timer);
194
+ const err = new SwitchbotOperationError('Client destroyed before pending write was sent', 'client_destroyed');
195
+ for (const r of pending.resolvers) {
196
+ r.reject(err);
197
+ }
198
+ }
199
+ this.pendingWrites.clear();
200
+ if (this.client?.cleanup) {
201
+ await this.client.cleanup();
190
202
  }
191
203
  this.client = null;
204
+ this.lastDiscoveryAt = 0;
205
+ }
206
+ resolveScanTimeoutMs(rawNodeClientConfig) {
207
+ if (typeof rawNodeClientConfig.scanTimeout === 'number' && Number.isFinite(rawNodeClientConfig.scanTimeout)) {
208
+ return Math.max(500, rawNodeClientConfig.scanTimeout);
209
+ }
210
+ if (typeof rawNodeClientConfig.scanDuration === 'number' && Number.isFinite(rawNodeClientConfig.scanDuration)) {
211
+ return Math.max(500, rawNodeClientConfig.scanDuration);
212
+ }
213
+ if (typeof this.cfg?.bleScanDurationSeconds === 'number') {
214
+ return Math.max(500, this.cfg.bleScanDurationSeconds * 1000);
215
+ }
216
+ return 5000;
217
+ }
218
+ getManagedDevice(id) {
219
+ const manager = this.client?.devices;
220
+ if (manager?.get) {
221
+ return manager.get(id);
222
+ }
223
+ return undefined;
224
+ }
225
+ getManagedDevices() {
226
+ const manager = this.client?.devices;
227
+ if (manager?.list) {
228
+ const list = manager.list();
229
+ return Array.isArray(list) ? list : [];
230
+ }
231
+ return [];
232
+ }
233
+ async ensureDiscovered(force) {
234
+ if (!this.client) {
235
+ throw new SwitchbotOperationError('No SwitchBot client available', 'no_client');
236
+ }
237
+ const fromManager = this.getManagedDevices();
238
+ const cacheValid = this.discoveryCacheTtlMs > 0 && (Date.now() - this.lastDiscoveryAt) < this.discoveryCacheTtlMs;
239
+ if (!force && cacheValid && fromManager.length > 0) {
240
+ return fromManager;
241
+ }
242
+ const discovered = await this.client.discover();
243
+ this.lastDiscoveryAt = Date.now();
244
+ return discovered;
192
245
  }
193
246
  }
194
247
  //# sourceMappingURL=switchbotClient.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"switchbotClient.js","sourceRoot":"","sources":["../src/switchbotClient.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"switchbotClient.js","sourceRoot":"","sources":["../src/switchbotClient.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAA;AAClE,OAAO,EAAE,0BAA0B,EAAE,4BAA4B,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AAU/G;;;;GAIG;AACH,MAAM,OAAO,eAAe;IAClB,GAAG,CAAuB;IAC1B,MAAM,GAAqB,IAAI,CAAA;IAC/B,eAAe,GAAG,GAAG,CAAA;IACrB,mBAAmB,GAAG,MAAM,CAAA;IAC5B,eAAe,GAAG,CAAC,CAAA;IACnB,MAAM,CAA6B;IACnC,aAAa,GAAsH,IAAI,GAAG,EAAE,CAAA;IAEpJ,YAAY,GAA0B;QACpC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAA;QACd,IAAI,CAAC,MAAM,GAAI,GAAW,EAAE,MAAqC,CAAA;QACjE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAA;QACpF,CAAC;QACD,IAAI,OAAQ,GAAW,EAAE,eAAe,KAAK,QAAQ,EAAE,CAAC;YACtD,IAAI,CAAC,eAAe,GAAI,GAAW,CAAC,eAAe,CAAA;QACrD,CAAC;QACD,IAAI,OAAQ,GAAW,EAAE,mBAAmB,KAAK,QAAQ,EAAE,CAAC;YAC1D,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAG,GAAW,CAAC,mBAAmB,CAAC,CAAA;QAC1E,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,OAAM;QACR,CAAC;QAED,IAAI,CAAC;YACH,sEAAsE;YACtE,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAA;YACpD,MAAM,mBAAmB,GAAG,OAAQ,IAAI,CAAC,GAAW,EAAE,gBAAgB,KAAK,QAAQ,CAAC,CAAC,CAAE,IAAI,CAAC,GAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAA;YAC7H,MAAM,WAAW,GAAG,IAAI,CAAC,oBAAoB,CAAC,mBAAmB,CAAC,CAAA;YAClE,IAAI,CAAC,MAAM,GAAG,IAAI,SAAS,CAAC;gBAC1B,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,YAAY;gBAC5B,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,aAAa;gBAC9B,8DAA8D;gBAC9D,cAAc,EAAE,IAAI,EAAE,gCAAgC;gBACtD,WAAW,EAAE,IAAI,EAAE,iCAAiC;gBACpD,oBAAoB,EAAE,IAAI,EAAE,sCAAsC;gBAClE,4BAA4B,EAAE,IAAI,EAAE,2CAA2C;gBAC/E,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,SAAS,KAAK,KAAK,EAAE,iCAAiC;gBAC1E,WAAW;gBACX,GAAG,mBAAmB;aACvB,CAAC,CAAA;YACF,IAAI,CAAC,eAAe,GAAG,CAAC,CAAA;YACxB,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,8DAA8D,CAAC,CAAA;QACrF,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,2DAA2D,EAAE,CAAC,CAAC,CAAA;YACnF,IAAI,CAAC,MAAM,GAAG,IAAI,CAAA;QACpB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,EAAU;QACxB,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,IAAI,CAAC;gBACH,MAAM,WAAW,GAAG,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAA;gBAC7C,IAAI,WAAW,EAAE,CAAC;oBAChB,OAAO,WAAW,CAAA;gBACpB,CAAC;gBAED,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAA;gBAClD,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;gBAC3D,IAAI,aAAa,EAAE,CAAC;oBAClB,OAAO,aAAa,CAAA;gBACtB,CAAC;gBAED,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAA;gBACxD,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;YACrD,CAAC;YAAC,OAAO,CAAM,EAAE,CAAC;gBAChB,IAAI,CAAC,YAAY,4BAA4B,EAAE,CAAC;oBAC9C,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,sCAAsC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAA;oBAC7E,MAAM,CAAC,CAAA;gBACT,CAAC;qBAAM,IAAI,CAAC,YAAY,uBAAuB,EAAE,CAAC;oBAChD,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,iCAAiC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAA;oBAC/E,MAAM,CAAC,CAAA;gBACT,CAAC;qBAAM,IAAI,CAAC,YAAY,0BAA0B,EAAE,CAAC;oBACnD,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,wCAAwC,EAAE,IAAI,EAAE,CAAC,CAAC,cAAc,CAAC,CAAA;oBACrF,MAAM,CAAC,CAAA;gBACT,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE,CAAC,CAAC,CAAA;oBAC5D,MAAM,CAAC,CAAA;gBACT,CAAC;YACH,CAAC;QACH,CAAC;QACD,MAAM,IAAI,uBAAuB,CAAC,+BAA+B,EAAE,WAAW,CAAC,CAAA;IACjF,CAAC;IAED,KAAK,CAAC,UAAU;QACd,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,IAAI,CAAC;gBACH,MAAM,WAAW,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAA;gBAC5C,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC3B,OAAO,WAAW,CAAA;gBACpB,CAAC;gBACD,OAAO,MAAM,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAA;YAC3C,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,2BAA2B,EAAE,CAAC,CAAC,CAAA;gBACnD,MAAM,CAAC,CAAA;YACT,CAAC;QACH,CAAC;QACD,MAAM,IAAI,uBAAuB,CAAC,+BAA+B,EAAE,WAAW,CAAC,CAAA;IACjF,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,EAAU,EAAE,IAAS;QACxC,0DAA0D;QAC1D,IAAI,CAAC,IAAI,CAAC,eAAe,IAAI,IAAI,CAAC,eAAe,IAAI,CAAC,EAAE,CAAC;YACvD,OAAO,IAAI,CAAC,iBAAiB,CAAC,EAAE,EAAE,IAAI,CAAC,CAAA;QACzC,CAAC;QAED,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;YAC3C,IAAI,QAAQ,EAAE,CAAC;gBACb,QAAQ,CAAC,IAAI,GAAG,IAAI,CAAA;gBACpB,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAA;gBAC5C,OAAM;YACR,CAAC;YAED,MAAM,SAAS,GAAmE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAA;YACvG,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,IAAI,EAAE;gBAClC,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;gBACxC,IAAI,CAAC,KAAK,EAAE,CAAC;oBACX,OAAM;gBACR,CAAC;gBACD,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;gBAC7B,IAAI,CAAC;oBACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,CAAC,CAAA;oBACxD,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,SAAS;wBAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;gBACjD,CAAC;gBAAC,OAAO,CAAM,EAAE,CAAC;oBAChB,IAAI,CAAC,YAAY,4BAA4B,EAAE,CAAC;wBAC9C,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,2CAA2C,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAA;oBACpF,CAAC;yBAAM,IAAI,CAAC,YAAY,uBAAuB,EAAE,CAAC;wBAChD,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,sCAAsC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAA;oBACtF,CAAC;yBAAM,IAAI,CAAC,YAAY,0BAA0B,EAAE,CAAC;wBACnD,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,6CAA6C,EAAE,IAAI,EAAE,CAAC,CAAC,cAAc,CAAC,CAAA;oBAC5F,CAAC;oBACD,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,SAAS;wBAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;gBAC9C,CAAC;YACH,CAAC,EAAE,IAAI,CAAC,eAAe,CAAC,CAAA;YAExB,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAA;QACxD,CAAC,CAAC,CAAA;IACJ,CAAC;IAEO,KAAK,CAAC,iBAAiB,CAAC,EAAU,EAAE,IAAS;QACnD,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM,IAAI,uBAAuB,CAAC,kDAAkD,EAAE,WAAW,CAAC,CAAA;QACpG,CAAC;QACD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAA;YACvC,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,MAAM,IAAI,uBAAuB,CAAC,UAAU,EAAE,YAAY,EAAE,kBAAkB,CAAC,CAAA;YACjF,CAAC;YACD,MAAM,UAAU,GAAG,CAAC,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAA;YAC1D,MAAM,OAAO,GAAG,IAAI,EAAE,OAAO,CAAA;YAC7B,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,IAAI,uBAAuB,CAAC,8BAA8B,EAAE,YAAY,CAAC,CAAA;YACjF,CAAC;YACD,MAAM,OAAO,GAAG,uBAAuB,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;YAC5D,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,IAAI,uBAAuB,CAAC,wBAAwB,OAAO,sBAAsB,UAAU,GAAG,EAAE,qBAAqB,CAAC,CAAA;YAC9H,CAAC;YACD,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,IAAI,EAAE,6BAA6B,OAAO,sBAAsB,UAAU,GAAG,CAAC,CAAA;YACnG,OAAO,MAAM,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;QACpC,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YAChB,IAAI,CAAC,YAAY,4BAA4B,EAAE,CAAC;gBAC9C,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,2CAA2C,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAA;gBAClF,MAAM,CAAC,CAAA;YACT,CAAC;iBAAM,IAAI,CAAC,YAAY,uBAAuB,EAAE,CAAC;gBAChD,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,sCAAsC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAA;gBACpF,MAAM,CAAC,CAAA;YACT,CAAC;iBAAM,IAAI,CAAC,YAAY,0BAA0B,EAAE,CAAC;gBACnD,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,6CAA6C,EAAE,IAAI,EAAE,CAAC,CAAC,cAAc,CAAC,CAAA;gBAC1F,MAAM,CAAC,CAAA;YACT,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE,CAAC,CAAC,CAAA;gBAC1D,MAAM,CAAC,CAAA;YACT,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAO;QACX,KAAK,MAAM,CAAC,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YAC7C,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;YAC3B,MAAM,GAAG,GAAG,IAAI,uBAAuB,CAAC,gDAAgD,EAAE,kBAAkB,CAAC,CAAA;YAC7G,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;gBAClC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YACf,CAAC;QACH,CAAC;QACD,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAA;QAE1B,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;YACzB,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAA;QAC7B,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAA;QAClB,IAAI,CAAC,eAAe,GAAG,CAAC,CAAA;IAC1B,CAAC;IAEO,oBAAoB,CAAC,mBAAwC;QACnE,IAAI,OAAO,mBAAmB,CAAC,WAAW,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAC,WAAW,CAAC,EAAE,CAAC;YAC5G,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,mBAAmB,CAAC,WAAW,CAAC,CAAA;QACvD,CAAC;QAED,IAAI,OAAO,mBAAmB,CAAC,YAAY,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAC,YAAY,CAAC,EAAE,CAAC;YAC9G,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,mBAAmB,CAAC,YAAY,CAAC,CAAA;QACxD,CAAC;QAED,IAAI,OAAQ,IAAI,CAAC,GAAW,EAAE,sBAAsB,KAAK,QAAQ,EAAE,CAAC;YAClE,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAG,IAAI,CAAC,GAAW,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAAA;QACvE,CAAC;QAED,OAAO,IAAI,CAAA;IACb,CAAC;IAEO,gBAAgB,CAAC,EAAU;QACjC,MAAM,OAAO,GAAI,IAAI,CAAC,MAAc,EAAE,OAAO,CAAA;QAC7C,IAAI,OAAO,EAAE,GAAG,EAAE,CAAC;YACjB,OAAO,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACxB,CAAC;QACD,OAAO,SAAS,CAAA;IAClB,CAAC;IAEO,iBAAiB;QACvB,MAAM,OAAO,GAAI,IAAI,CAAC,MAAc,EAAE,OAAO,CAAA;QAC7C,IAAI,OAAO,EAAE,IAAI,EAAE,CAAC;YAClB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,CAAA;YAC3B,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAA;QACxC,CAAC;QACD,OAAO,EAAE,CAAA;IACX,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAAC,KAAc;QAC3C,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM,IAAI,uBAAuB,CAAC,+BAA+B,EAAE,WAAW,CAAC,CAAA;QACjF,CAAC;QAED,MAAM,WAAW,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAA;QAC5C,MAAM,UAAU,GAAG,IAAI,CAAC,mBAAmB,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,IAAI,CAAC,mBAAmB,CAAA;QACjH,IAAI,CAAC,KAAK,IAAI,UAAU,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnD,OAAO,WAAW,CAAA;QACpB,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAA;QAC/C,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QACjC,OAAO,UAAU,CAAA;IACnB,CAAC;CACF"}