@switchbot/homebridge-switchbot 5.0.0-beta.99 → 5.1.0-beta.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 (281) 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 +140 -135
  9. package/MIGRATION.md +21 -6
  10. package/README.md +109 -3
  11. package/TODO.md +263 -0
  12. package/config.schema.json +240 -36
  13. package/dist/SwitchBotHAPPlatform.d.ts +133 -0
  14. package/dist/SwitchBotHAPPlatform.d.ts.map +1 -0
  15. package/dist/SwitchBotHAPPlatform.js +584 -0
  16. package/dist/SwitchBotHAPPlatform.js.map +1 -0
  17. package/dist/SwitchBotMatterPlatform.d.ts +142 -0
  18. package/dist/SwitchBotMatterPlatform.d.ts.map +1 -0
  19. package/dist/SwitchBotMatterPlatform.js +569 -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 +72 -0
  81. package/dist/homebridge-ui/public/js/api.d.ts.map +1 -0
  82. package/dist/homebridge-ui/public/js/api.js +313 -0
  83. package/dist/homebridge-ui/public/js/api.js.map +1 -0
  84. package/dist/homebridge-ui/public/js/api.ts +385 -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 +3798 -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 +104 -0
  108. package/dist/homebridge-ui/public/js/devices.js.map +1 -0
  109. package/dist/homebridge-ui/public/js/devices.ts +112 -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 +16 -0
  126. package/dist/homebridge-ui/public/js/modals.d.ts.map +1 -0
  127. package/dist/homebridge-ui/public/js/modals.js +728 -0
  128. package/dist/homebridge-ui/public/js/modals.js.map +1 -0
  129. package/dist/homebridge-ui/public/js/modals.ts +823 -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 +961 -0
  133. package/dist/homebridge-ui/public/js/render.js.map +1 -0
  134. package/dist/homebridge-ui/public/js/render.ts +1085 -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 +12 -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 +81 -1
  178. package/dist/utils.d.ts.map +1 -1
  179. package/dist/utils.js +1148 -4
  180. package/dist/utils.js.map +1 -1
  181. package/docs/assets/highlight.css +29 -15
  182. package/docs/assets/main.js +1 -1
  183. package/docs/index.html +100 -6
  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 +583 -0
  193. package/src/SwitchBotMatterPlatform.ts +566 -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 +385 -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 +112 -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 +823 -0
  221. package/src/homebridge-ui/public/js/render.ts +1085 -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 +14 -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 +1164 -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 +68 -0
  260. package/todo/TODO.md +80 -0
  261. package/tsconfig.ui.json +11 -0
  262. package/.github/workflows/beta-release.yml +0 -52
  263. package/dist/platform.d.ts +0 -35
  264. package/dist/platform.d.ts.map +0 -1
  265. package/dist/platform.js +0 -945
  266. package/dist/platform.js.map +0 -1
  267. package/src/platform.ts +0 -963
  268. package/test/accessory-restore.spec.ts +0 -73
  269. package/test/device-mapping.spec.ts +0 -37
  270. package/test/deviceFactory.spec.ts +0 -18
  271. package/test/fan-swing.spec.ts +0 -29
  272. package/test/lock-users.spec.ts +0 -44
  273. package/test/matter-childbridge.spec.ts +0 -55
  274. package/test/matter-descriptors.spec.ts +0 -97
  275. package/test/matter-device-state.spec.ts +0 -101
  276. package/test/matter-integration.spec.ts +0 -70
  277. package/test/platform.integration.spec.ts +0 -55
  278. package/test/switchbot-client-debounce.spec.ts +0 -131
  279. package/test/switchbot-client-openapi.spec.ts +0 -56
  280. package/test/switchbotClient.spec.ts +0 -10
  281. package/test/utils.spec.ts +0 -20
@@ -0,0 +1,569 @@
1
+ import { createDevice } from './deviceFactory.js';
2
+ import { PLATFORM_NAME, PLUGIN_NAME } from './settings.js';
3
+ import { SwitchBotClient } from './switchbotClient.js';
4
+ import { createMatterHandlers, DEVICE_MATTER_CLUSTERS, DEVICE_MATTER_SUPPORTED, normalizeTypeForMatter, resolveExternalPublishProtocol, resolveMatterDeviceType } from './utils.js';
5
+ /**
6
+ * Homebridge platform class for SwitchBot Matter integration.
7
+ * Handles device discovery, registration, polling, and accessory lifecycle for Matter-enabled SwitchBot devices.
8
+ *
9
+ * @class SwitchBotMatterPlatform
10
+ * @param {Logger} log - Homebridge logger instance
11
+ * @param {PlatformConfig} config - Platform configuration object
12
+ * @param {API} [api] - Optional Homebridge API instance
13
+ * @property {API | undefined} api - Homebridge API instance
14
+ * @property {Logger} log - Homebridge logger instance
15
+ * @property {SwitchBotPluginConfig} config - Parsed plugin config
16
+ * @property {any[]} devices - All created device instances
17
+ * @property {Map<string, any>} accessories - Map of accessory UUID to accessory object
18
+ * @property {string} lastConfigHash - Hash of last loaded config for change detection
19
+ * @property {NodeJS.Timeout | null} configReloadInterval - Interval for periodic config reload
20
+ * @property {Map<string, NodeJS.Timeout>} openApiPollTimers - Timers for per-device OpenAPI polling
21
+ * @property {NodeJS.Timeout | null} openApiBatchTimer - Timer for batched OpenAPI polling
22
+ * @property {number} openApiRequestsToday - Count of OpenAPI requests made today
23
+ * @property {number} openApiLastReset - Timestamp (ms) of last OpenAPI daily counter reset
24
+ */
25
+ export class SwitchBotMatterPlatform {
26
+ /** Homebridge API instance */
27
+ api;
28
+ /** Homebridge logger instance */
29
+ log;
30
+ /** Parsed plugin config */
31
+ config;
32
+ /** All created device instances */
33
+ devices = [];
34
+ /** Map of accessory UUID to accessory object */
35
+ accessories;
36
+ /** Hash of last loaded config for change detection */
37
+ lastConfigHash = '';
38
+ /** Interval for periodic config reload */
39
+ configReloadInterval = null;
40
+ /** Timers for per-device OpenAPI polling */
41
+ openApiPollTimers = new Map();
42
+ /** Timer for batched OpenAPI polling */
43
+ openApiBatchTimer = null;
44
+ /** Count of OpenAPI requests made today */
45
+ openApiRequestsToday = 0;
46
+ /** Timestamp (ms) of last OpenAPI daily counter reset */
47
+ openApiLastReset = 0;
48
+ /**
49
+ * Construct the SwitchBot Matter platform.
50
+ * @param log Homebridge logger
51
+ * @param config Platform config
52
+ * @param api Homebridge API instance
53
+ */
54
+ constructor(log, config, api) {
55
+ this.log = log;
56
+ // Ensure both log and logger are set for downstream device constructors
57
+ this.config = { ...config, log, logger: log };
58
+ this.api = api;
59
+ this.accessories = new Map();
60
+ this.log.info('SwitchBot Matter platform initialized');
61
+ // Create/shared SwitchBot client and attach to config so child devices reuse it.
62
+ try {
63
+ const client = new SwitchBotClient(this.config);
64
+ void client.init();
65
+ this.config._client = client;
66
+ }
67
+ catch (e) {
68
+ this.log.debug('Failed to create shared SwitchBot client', e);
69
+ }
70
+ // Wait for Homebridge to finish launching to create/register accessories
71
+ if (this.api && typeof this.api.on === 'function') {
72
+ this.api.on('didFinishLaunching', async () => {
73
+ await this.loadDevices();
74
+ this._setupOpenApiPolling();
75
+ // Start periodic config reload to pick up UI changes
76
+ this.configReloadInterval = setInterval(() => {
77
+ void this.checkAndReloadDevices();
78
+ }, 10000); // Check every 10 seconds
79
+ // Listen for Homebridge shutdown to clear interval
80
+ if (typeof this.api.on === 'function') {
81
+ this.api.on('shutdown', () => {
82
+ this.shutdown();
83
+ });
84
+ }
85
+ });
86
+ }
87
+ else {
88
+ void this.loadDevices();
89
+ this._setupOpenApiPolling();
90
+ // Start periodic config reload to pick up UI changes
91
+ this.configReloadInterval = setInterval(() => {
92
+ void this.checkAndReloadDevices();
93
+ }, 10000); // Check every 10 seconds
94
+ }
95
+ }
96
+ /**
97
+ * Discover and create all device instances from config.
98
+ * Populates this.devices and logs registration status for each device.
99
+ *
100
+ * @returns {Promise<void>} Resolves when all devices are loaded and registered
101
+ */
102
+ async loadDevices() {
103
+ const newHash = this.getConfigHash();
104
+ if (newHash === this.lastConfigHash) {
105
+ this.log.debug('Config unchanged, skipping device reload');
106
+ return;
107
+ }
108
+ const devices = this.config?.devices ?? [];
109
+ const createdDevices = [];
110
+ for (const raw of devices) {
111
+ // Normalize config keys from UI schema to internal shape (for cross-platform consistency)
112
+ const d = {
113
+ id: raw.deviceId ?? raw.id,
114
+ name: raw.configDeviceName ?? raw.name,
115
+ type: raw.configDeviceType ?? raw.type ?? raw.deviceType ?? 'unknown',
116
+ encryptionKey: raw.encryptionKey,
117
+ keyId: raw.keyId,
118
+ _raw: raw,
119
+ };
120
+ const type = normalizeTypeForMatter(d.type);
121
+ const externalPublishProtocol = resolveExternalPublishProtocol(raw);
122
+ const deviceOpts = { id: d.id, type, name: d.name, encryptionKey: d.encryptionKey, keyId: d.keyId, log: this.log };
123
+ this.log.debug(`[Matter/Debug] Device options for ${d.name ?? d.id}:`, JSON.stringify(deviceOpts, null, 2));
124
+ const matterSupported = !!DEVICE_MATTER_SUPPORTED[(type || '').toLowerCase()];
125
+ const matterAvailable = !!(this.api?.isMatterAvailable?.() && this.api?.isMatterEnabled?.());
126
+ const matterEnabled = matterAvailable || !!this.config.enableMatter;
127
+ const useMatter = matterEnabled && matterSupported;
128
+ try {
129
+ const created = await createDevice(deviceOpts, this.config, useMatter);
130
+ this.devices.push(created);
131
+ createdDevices.push({ created, d, type, useMatter, matterAvailable, externalPublishProtocol });
132
+ if (useMatter) {
133
+ this.log.info(`Prepared Matter accessory for ${d.id} (${type})${matterAvailable ? ' (auto-detected)' : ' (manually enabled)'}`);
134
+ }
135
+ else {
136
+ if (!matterEnabled) {
137
+ this.log.info(`Skipping Matter for ${d.id} (${type}) - Matter not available on this bridge`);
138
+ }
139
+ else if (!matterSupported) {
140
+ this.log.info(`Skipping Matter for ${d.id} (${type}) - device type not supported`);
141
+ }
142
+ else {
143
+ this.log.info(`Skipping Matter for ${d.id} (${type}) - not supported`);
144
+ }
145
+ }
146
+ }
147
+ catch (e) {
148
+ this.log.error(`Failed to create Matter device ${d.id}:`, e instanceof Error ? e.stack || e.message : e);
149
+ }
150
+ }
151
+ // Register Matter accessories after device creation for symmetry with HAP platform
152
+ await this.registerMatterAccessories(createdDevices);
153
+ this.lastConfigHash = newHash;
154
+ }
155
+ /**
156
+ * Registers all Matter accessories with the Homebridge Matter API.
157
+ *
158
+ * This method is called after all device instances have been created. It handles both new and restored
159
+ * accessories, updating their context, clusters, and other Matter-specific metadata as needed. Accessories
160
+ * are registered with Homebridge using the Matter API, and the internal accessory map is updated accordingly.
161
+ *
162
+ * @param {Array<{created: any, d: any, type: string, useMatter: boolean, matterAvailable: boolean}>} createdDevices - Array of device descriptors:
163
+ * - created: The created device instance
164
+ * - d: The normalized device config object
165
+ * - type: The normalized device type string
166
+ * - useMatter: Whether Matter is enabled for this device
167
+ * - matterAvailable: Whether Matter is available on this bridge
168
+ * @returns {Promise<void>} Resolves when registration is complete
169
+ *
170
+ * Differences from HAP registration:
171
+ * - Uses the Matter API (not HAP API) for accessory registration.
172
+ * - Adds Matter clusters and handlers to each accessory based on the device descriptor.
173
+ * - Only registers accessories where Matter is enabled and supported.
174
+ * - Accessory context and cluster wiring are Matter-specific.
175
+ *
176
+ * If the Homebridge Matter API is not available, registration is skipped and a log message is emitted.
177
+ * Accessories that are not enabled for Matter are ignored.
178
+ */
179
+ async registerMatterAccessories(createdDevices) {
180
+ if (!this.api || !this.api.matter || typeof this.api.matter.registerPlatformAccessories !== 'function') {
181
+ this.log.info('Homebridge Matter API not available; skipping Matter accessory registration');
182
+ return;
183
+ }
184
+ const matterApi = this.api.matter;
185
+ const accessoriesToRegister = [];
186
+ const externalAccessoriesToPublish = [];
187
+ for (const { created, d, type, useMatter, matterAvailable, externalPublishProtocol } of createdDevices) {
188
+ // Only register accessories where Matter is enabled and supported
189
+ if (!useMatter) {
190
+ // Log reason for skipping registration
191
+ if (!matterAvailable) {
192
+ this.log.info(`Skipping Matter registration for ${d.id} (${type}) - Matter API not available on this bridge`);
193
+ }
194
+ else {
195
+ this.log.info(`Skipping Matter registration for ${d.id} (${type}) - device type not supported for Matter`);
196
+ }
197
+ continue;
198
+ }
199
+ try {
200
+ // Prepare accessory descriptor from device
201
+ const createdDesc = await created.createAccessory(this.api);
202
+ const uuid = matterApi.uuid.generate(`${d.id}`);
203
+ // Reuse cached accessory if available by uuid
204
+ let accessory = this.accessories.get(uuid);
205
+ // Reuse cached accessory if available by uuid or deviceId
206
+ if (!accessory) {
207
+ for (const [, a] of this.accessories.entries()) {
208
+ try {
209
+ if (a && a.context && a.context.deviceId === d.id) {
210
+ accessory = a;
211
+ break;
212
+ }
213
+ }
214
+ catch (e) {
215
+ // ignore
216
+ }
217
+ }
218
+ }
219
+ if (!accessory) {
220
+ // Create new accessory object for Matter
221
+ let clusters = DEVICE_MATTER_CLUSTERS[type.toLowerCase()];
222
+ if (!clusters) {
223
+ clusters = createdDesc.clusters || { onOff: { onOff: false } };
224
+ }
225
+ const deviceType = resolveMatterDeviceType(matterApi, type, createdDesc.deviceType, clusters);
226
+ accessory = {
227
+ UUID: uuid,
228
+ displayName: createdDesc.name || d.name || type,
229
+ deviceType,
230
+ manufacturer: createdDesc.manufacturer || 'SwitchBot',
231
+ model: createdDesc.model || type,
232
+ serialNumber: createdDesc.serialNumber || d.id,
233
+ reachable: createdDesc.reachable !== false,
234
+ firmwareRevision: createdDesc.firmwareRevision || '1.0.0',
235
+ hardwareRevision: createdDesc.hardwareRevision || '',
236
+ clusters,
237
+ handlers: createdDesc.handlers || createMatterHandlers(this.log, d.id, type, this.config?._client) || undefined,
238
+ context: { deviceId: d.id, type, created: true },
239
+ };
240
+ if (externalPublishProtocol === 'matter') {
241
+ externalAccessoriesToPublish.push(accessory);
242
+ }
243
+ else {
244
+ accessoriesToRegister.push(accessory);
245
+ }
246
+ this.accessories.set(uuid, accessory);
247
+ }
248
+ else {
249
+ // Ensure context and update properties for restored accessory
250
+ let clusters = DEVICE_MATTER_CLUSTERS[type.toLowerCase()];
251
+ if (!clusters) {
252
+ clusters = accessory.clusters || createdDesc.clusters || { onOff: { onOff: false } };
253
+ }
254
+ const deviceType = resolveMatterDeviceType(matterApi, type, accessory.deviceType || createdDesc.deviceType, clusters);
255
+ accessory.context = accessory.context || {};
256
+ accessory.context.deviceId = accessory.context.deviceId || d.id;
257
+ accessory.context.type = accessory.context.type || type;
258
+ accessory.deviceType = deviceType;
259
+ accessory.manufacturer = accessory.manufacturer || createdDesc.manufacturer || 'SwitchBot';
260
+ accessory.model = accessory.model || createdDesc.model || type;
261
+ accessory.serialNumber = accessory.serialNumber || createdDesc.serialNumber || d.id;
262
+ accessory.reachable = accessory.reachable !== false;
263
+ accessory.firmwareRevision = accessory.firmwareRevision || createdDesc.firmwareRevision || '1.0.0';
264
+ accessory.hardwareRevision = accessory.hardwareRevision || createdDesc.hardwareRevision || '';
265
+ accessory.clusters = clusters;
266
+ accessory.handlers = createdDesc.handlers || createMatterHandlers(this.log, d.id, type, this.config?._client) || undefined;
267
+ accessory.displayName = createdDesc.name || d.name || type;
268
+ accessory.UUID = accessory.UUID || accessory.uuid || uuid;
269
+ if (externalPublishProtocol === 'matter') {
270
+ externalAccessoriesToPublish.push(accessory);
271
+ }
272
+ else {
273
+ accessoriesToRegister.push(accessory);
274
+ }
275
+ this.accessories.set(accessory.UUID || uuid, accessory);
276
+ }
277
+ this.log.info(`Created/updated Matter accessory ${d.id} (${type})`);
278
+ }
279
+ catch (e) {
280
+ this.log.warn(`Matter accessory creation failed for ${d.id} (${type})`, e);
281
+ }
282
+ }
283
+ if (accessoriesToRegister.length > 0) {
284
+ try {
285
+ await matterApi.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, accessoriesToRegister);
286
+ this.log.info(`Registered ${accessoriesToRegister.length} Matter accessory(ies) with Homebridge`);
287
+ }
288
+ catch (e) {
289
+ this.log.warn('Failed to register Matter accessories', e);
290
+ }
291
+ }
292
+ else {
293
+ this.log.info('No Matter accessories to register');
294
+ }
295
+ if (externalAccessoriesToPublish.length > 0) {
296
+ try {
297
+ if (typeof matterApi.publishExternalAccessories === 'function') {
298
+ await matterApi.publishExternalAccessories(PLUGIN_NAME, externalAccessoriesToPublish);
299
+ this.log.info(`Published ${externalAccessoriesToPublish.length} Matter external accessory(ies) with Homebridge`);
300
+ }
301
+ else if (typeof matterApi.registerExternalAccessories === 'function') {
302
+ await matterApi.registerExternalAccessories(PLUGIN_NAME, PLATFORM_NAME, externalAccessoriesToPublish);
303
+ this.log.info(`Registered ${externalAccessoriesToPublish.length} Matter external accessory(ies) with Homebridge`);
304
+ }
305
+ else {
306
+ this.log.warn('Matter external accessory publishing API not available; falling back to regular platform registration');
307
+ await matterApi.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, externalAccessoriesToPublish);
308
+ this.log.info(`Registered ${externalAccessoriesToPublish.length} Matter accessory(ies) as fallback (external publishing unavailable)`);
309
+ }
310
+ }
311
+ catch (e) {
312
+ this.log.warn('Failed to publish/register Matter external accessories', e);
313
+ }
314
+ }
315
+ }
316
+ /**
317
+ * Returns the timestamp (ms) of the last OpenAPI daily counter reset.
318
+ * @returns {number} Timestamp in ms
319
+ */
320
+ getOpenApiLastReset() {
321
+ return this.openApiLastReset;
322
+ }
323
+ /**
324
+ * Logs the last OpenAPI reset time in a human-readable format.
325
+ * @returns {void}
326
+ */
327
+ logOpenApiLastReset() {
328
+ if (this.openApiLastReset) {
329
+ const date = new Date(this.openApiLastReset);
330
+ this.log.info(`[OpenAPI] Last daily counter reset: ${date.toLocaleString()}`);
331
+ }
332
+ else {
333
+ this.log.info('[OpenAPI] Daily counter has not been reset yet.');
334
+ }
335
+ }
336
+ /**
337
+ * Compute a hash of the current device config for change detection.
338
+ * @returns {string} JSON string hash of device config
339
+ */
340
+ getConfigHash() {
341
+ // Create a simple hash of current device config to detect changes
342
+ const devices = this.config?.devices ?? [];
343
+ return JSON.stringify(devices.map((d) => ({
344
+ id: d.deviceId ?? d.id,
345
+ type: d.configDeviceType ?? d.type,
346
+ name: d.configDeviceName ?? d.name,
347
+ externalPublishProtocol: resolveExternalPublishProtocol(d),
348
+ })));
349
+ }
350
+ /**
351
+ * Reload devices if config has changed since last load.
352
+ * Unregisters accessories and removes devices no longer in config.
353
+ * Calls loadDevices to repopulate devices and accessories.
354
+ *
355
+ * @returns {Promise<void>} Resolves when reload is complete
356
+ */
357
+ async checkAndReloadDevices() {
358
+ const currentHash = this.getConfigHash();
359
+ if (currentHash !== this.lastConfigHash) {
360
+ this.log.info('[SwitchBot] Detected config changes, reloading devices...');
361
+ // Identify device IDs in new config
362
+ const devicesInConfig = new Set((this.config?.devices ?? []).map((d) => d.deviceId ?? d.id));
363
+ // Find accessories to remove (not in config)
364
+ const accessoriesToRemove = [];
365
+ for (const [uuid, accessory] of this.accessories.entries()) {
366
+ const deviceId = accessory?.context?.deviceId;
367
+ if (deviceId && !devicesInConfig.has(deviceId)) {
368
+ accessoriesToRemove.push({ accessory, uuid });
369
+ }
370
+ }
371
+ // Unregister removed accessories from Homebridge (Matter API)
372
+ if (accessoriesToRemove.length > 0 && this.api && this.api.matter && this.api.matter.unregisterPlatformAccessories) {
373
+ try {
374
+ this.api.matter.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, accessoriesToRemove.map(a => a.accessory));
375
+ this.log.info(`Unregistered ${accessoriesToRemove.length} Matter accessory(ies) removed from config`);
376
+ for (const { uuid } of accessoriesToRemove) {
377
+ this.accessories.delete(uuid);
378
+ }
379
+ }
380
+ catch (e) {
381
+ this.log.warn('Failed to unregister removed Matter accessories', e);
382
+ }
383
+ }
384
+ // Remove devices from this.devices that are no longer in config
385
+ this.devices = this.devices.filter((dev) => devicesInConfig.has(dev?.id));
386
+ await this.loadDevices();
387
+ this.lastConfigHash = currentHash;
388
+ }
389
+ }
390
+ /**
391
+ * Cleanup method to clear config reload interval on shutdown.
392
+ * Called by Homebridge on shutdown event.
393
+ * @returns {void}
394
+ */
395
+ shutdown() {
396
+ if (this.configReloadInterval) {
397
+ clearInterval(this.configReloadInterval);
398
+ this.configReloadInterval = null;
399
+ this.log.info('Cleared config reload interval on shutdown');
400
+ }
401
+ }
402
+ /**
403
+ * Setup OpenAPI polling for all devices according to config (global, per-device, batch, rate limit).
404
+ * Handles daily request limits, per-device and batch polling, and resets.
405
+ *
406
+ * @returns {void}
407
+ */
408
+ _setupOpenApiPolling() {
409
+ // Clear any existing timers
410
+ for (const t of this.openApiPollTimers.values())
411
+ clearInterval(t);
412
+ this.openApiPollTimers.clear();
413
+ if (this.openApiBatchTimer) {
414
+ clearInterval(this.openApiBatchTimer);
415
+ }
416
+ this.openApiBatchTimer = null;
417
+ const cfg = this.config;
418
+ const devices = cfg.devices ?? [];
419
+ const globalRate = Math.max(Number(cfg.openApiRefreshRate) || 300, 30);
420
+ const batchEnabled = cfg.matterBatchEnabled !== false;
421
+ const batchRate = Math.max(Number(cfg.matterBatchRefreshRate) || globalRate, 30);
422
+ const batchConcurrency = Math.max(Number(cfg.matterBatchConcurrency) || 5, 1);
423
+ const batchJitter = Math.max(Number(cfg.matterBatchJitter) || 0, 0);
424
+ const dailyLimit = Math.max(Number(cfg.dailyApiLimit) || 10000, 1000);
425
+ const dailyReserve = Math.max(Number(cfg.dailyApiReserveForCommands) || 1000, 0);
426
+ const resetAtLocalMidnight = !!cfg.dailyApiResetLocalMidnight;
427
+ const webhookOnlyOnReserve = !!cfg.webhookOnlyOnReserve;
428
+ // Helper to reset daily counter
429
+ const resetCounter = () => {
430
+ this.openApiRequestsToday = 0;
431
+ this.openApiLastReset = Date.now();
432
+ this.log.info('[OpenAPI] Daily request counter reset');
433
+ };
434
+ // Schedule reset at midnight
435
+ const scheduleMidnightReset = () => {
436
+ const now = new Date();
437
+ let nextReset;
438
+ if (resetAtLocalMidnight) {
439
+ nextReset = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1, 0, 0, 1);
440
+ }
441
+ else {
442
+ nextReset = new Date(now);
443
+ nextReset.setUTCHours(24, 0, 1, 0);
444
+ }
445
+ const ms = nextReset.getTime() - now.getTime();
446
+ setTimeout(() => {
447
+ resetCounter();
448
+ scheduleMidnightReset();
449
+ }, ms);
450
+ };
451
+ scheduleMidnightReset();
452
+ // Helper to check if polling is allowed
453
+ const canPoll = () => {
454
+ if (this.openApiRequestsToday + dailyReserve >= dailyLimit) {
455
+ if (!webhookOnlyOnReserve) {
456
+ this.log.warn('[OpenAPI] Daily request limit reached, pausing background polling');
457
+ }
458
+ return false;
459
+ }
460
+ return true;
461
+ };
462
+ // Per-device polling (devices with per-device refreshRate)
463
+ for (const dev of devices) {
464
+ const id = dev.deviceId ?? dev.id;
465
+ const enabled = dev.enabled !== false;
466
+ if (!id || !enabled) {
467
+ continue;
468
+ }
469
+ const perDeviceRate = dev.refreshRate ? Math.max(Number(dev.refreshRate), 30) : null;
470
+ if (perDeviceRate) {
471
+ // Individual polling interval for this device
472
+ const timer = setInterval(async () => {
473
+ if (!canPoll()) {
474
+ return;
475
+ }
476
+ try {
477
+ const client = this.config._client;
478
+ if (client && typeof client.getDevice === 'function') {
479
+ await client.getDevice(id);
480
+ this.openApiRequestsToday++;
481
+ this.log.debug(`[OpenAPI] Polled device ${id} (per-device interval ${perDeviceRate}s) [${this.openApiRequestsToday}/${dailyLimit}]`);
482
+ }
483
+ }
484
+ catch (e) {
485
+ this.log.debug(`[OpenAPI] Polling failed for device ${id}:`, e?.message);
486
+ }
487
+ }, perDeviceRate * 1000);
488
+ this.openApiPollTimers.set(id, timer);
489
+ }
490
+ }
491
+ // Batched polling for all other devices
492
+ if (batchEnabled) {
493
+ // Devices not already polled individually
494
+ const batchDevices = devices.filter((dev) => {
495
+ const id = dev.deviceId ?? dev.id;
496
+ const enabled = dev.enabled !== false;
497
+ const perDeviceRate = dev.refreshRate ? Math.max(Number(dev.refreshRate), 30) : null;
498
+ return id && enabled && !perDeviceRate;
499
+ });
500
+ // Optional jitter before first batch
501
+ const startBatch = () => {
502
+ this.openApiBatchTimer = setInterval(async () => {
503
+ if (!canPoll()) {
504
+ return;
505
+ }
506
+ const client = this.config._client;
507
+ if (!client || typeof client.getDevice !== 'function') {
508
+ return;
509
+ }
510
+ // Limit concurrency
511
+ const chunks = [];
512
+ for (let i = 0; i < batchDevices.length; i += batchConcurrency) {
513
+ chunks.push(batchDevices.slice(i, i + batchConcurrency));
514
+ }
515
+ for (const chunk of chunks) {
516
+ await Promise.all(chunk.map(async (dev) => {
517
+ try {
518
+ await client.getDevice(dev.deviceId ?? dev.id);
519
+ this.openApiRequestsToday++;
520
+ this.log.debug(`[OpenAPI] Batched poll device ${dev.deviceId ?? dev.id} [${this.openApiRequestsToday}/${dailyLimit}]`);
521
+ }
522
+ catch (e) {
523
+ this.log.debug(`[OpenAPI] Batched polling failed for device ${dev.deviceId ?? dev.id}:`, e?.message);
524
+ }
525
+ }));
526
+ }
527
+ }, batchRate * 1000);
528
+ };
529
+ if (batchJitter > 0) {
530
+ setTimeout(startBatch, Math.floor(Math.random() * batchJitter * 1000));
531
+ }
532
+ else {
533
+ startBatch();
534
+ }
535
+ }
536
+ }
537
+ /**
538
+ * Called by Homebridge to restore cached Matter accessories on startup.
539
+ * @param {any} accessory - The cached accessory object
540
+ * @returns {Promise<void>} Resolves when accessory is restored
541
+ */
542
+ async configureAccessory(accessory) {
543
+ try {
544
+ const uuid = accessory.UUID || accessory.UUID;
545
+ this.accessories.set(uuid, accessory);
546
+ this.log.info(`Restored cached Matter accessory ${accessory.displayName || uuid}`);
547
+ }
548
+ catch (e) {
549
+ this.log.warn('configureAccessory failed to restore Matter accessory', e);
550
+ }
551
+ }
552
+ /**
553
+ * Called by Homebridge to restore cached Matter accessories (alternate signature).
554
+ * @param {any} accessory - The cached accessory object
555
+ * @returns {void}
556
+ */
557
+ configureMatterAccessory(accessory) {
558
+ try {
559
+ const uuid = accessory.uuid || accessory.UUID || accessory.uuid;
560
+ this.accessories.set(uuid, accessory);
561
+ this.log.info(`Restored cached Matter accessory ${accessory.displayName || uuid}`);
562
+ }
563
+ catch (e) {
564
+ this.log.warn('configureMatterAccessory failed to restore Matter accessory', e);
565
+ }
566
+ }
567
+ }
568
+ export default SwitchBotMatterPlatform;
569
+ //# sourceMappingURL=SwitchBotMatterPlatform.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SwitchBotMatterPlatform.js","sourceRoot":"","sources":["../src/SwitchBotMatterPlatform.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ export declare const DEVICE_TYPES: {
2
+ readonly 'Window Coverings': readonly ["Blind Tilt", "Curtain", "Curtain3", "Roller Shade"];
3
+ readonly 'Locks & Access': readonly ["Keypad", "Keypad Touch", "Keypad Vision", "Keypad Vision Pro", "Lock Vision Pro", "Lock Lite", "Smart Lock", "Smart Lock Pro", "Smart Lock Ultra", "Video Doorbell"];
4
+ readonly Sensors: readonly ["Contact Sensor", "Motion Sensor", "Presence Sensor", "Water Detector"];
5
+ readonly Lighting: readonly ["Candle Warmer Lamp", "Ceiling Light", "Ceiling Light Pro", "Color Bulb", "Floor Lamp", "RGBIC Neon Rope Light", "RGBIC Neon Wire Rope Light", "RGBICWW Floor Lamp", "RGBICWW Strip Light", "Strip Light", "Strip Light 3"];
6
+ readonly 'Climate Control': readonly ["Air Purifier PM2.5", "Air Purifier Table PM2.5", "Air Purifier VOC", "Air Purifier Table VOC", "Battery Circulator Fan", "Circulator Fan", "Humidifier", "Humidifier2", "Meter", "MeterPlus", "Meter Plus", "MeterPro", "Meter Pro", "MeterPro(CO2)", "Meter Pro (CO2)", "Smart Radiator Thermostat", "Standing Circulator Fan", "WoIOSensor"];
7
+ readonly 'Plugs & Switches': readonly ["Garage Door Opener", "Plug", "Plug Mini (EU)", "Plug Mini (JP)", "Plug Mini (US)", "Relay Switch 1", "Relay Switch 1PM", "Relay Switch 2PM"];
8
+ readonly 'Robot Vacuums': readonly ["K10+", "K10+ Pro", "Robot Vacuum Cleaner K10+ Pro Combo", "Robot Vacuum Cleaner K11+", "Robot Vacuum Cleaner K20 Plus Pro", "Robot Vacuum Cleaner S1", "Robot Vacuum Cleaner S1 Plus", "Robot Vacuum Cleaner S10", "Robot Vacuum Cleaner S20"];
9
+ readonly Hubs: readonly ["AI Hub", "Hub", "Hub 2", "Hub 3", "Hub Mini", "Hub Plus"];
10
+ readonly Cameras: readonly ["Indoor Cam", "Pan/Tilt Cam", "Pan/Tilt Cam 2K", "Pan/Tilt Cam Plus 2K", "Pan/Tilt Cam Plus 3K"];
11
+ readonly 'IR Devices': readonly ["Air Conditioner", "Air Purifier", "Camera", "DVD", "Fan", "Light", "Others", "Projector", "Set Top Box", "Speaker", "Streamer", "TV", "Vacuum Cleaner", "Water Heater"];
12
+ readonly 'Other Devices': readonly ["AI Art Frame", "Bot", "Home Climate Panel", "Remote", "remote with screen"];
13
+ };
14
+ export declare const DEVICE_TYPE_NORMALIZATION_MAP: Record<string, string>;
15
+ /**
16
+ * Get all valid device types as a flat set for validation
17
+ */
18
+ export declare function getValidDeviceTypes(): Set<string>;
19
+ /**
20
+ * Normalize and validate a device type, returning a valid type or null
21
+ * @param deviceType The device type to validate/normalize
22
+ * @returns Valid device type string or null if no valid mapping found
23
+ */
24
+ export declare function normalizeDeviceType(deviceType: string | undefined | null): string | null;
25
+ /**
26
+ * Check if a device type is valid
27
+ * @param deviceType The device type to check
28
+ * @returns true if device type is in DEVICE_TYPES
29
+ */
30
+ export declare function isValidDeviceType(deviceType: string | undefined | null): boolean;
31
+ //# sourceMappingURL=device-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device-types.d.ts","sourceRoot":"","sources":["../src/device-types.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY;;;;;;;;;;;;CA8Ff,CAAA;AAEV,eAAO,MAAM,6BAA6B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CA6GhE,CAAA;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,GAAG,CAAC,MAAM,CAAC,CAQjD;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAsBxF;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,CAMhF"}