@switchbot/homebridge-switchbot 5.0.0-beta.70 → 5.0.0-beta.72

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 (534) hide show
  1. package/.github/ISSUE_TEMPLATE/e2e-verification.md +36 -0
  2. package/.github/workflows/ci.yml +61 -0
  3. package/.github/workflows/manual-e2e.yml +103 -0
  4. package/CHANGELOG.md +20 -0
  5. package/E2E-VERIFICATION.md +121 -0
  6. package/MIGRATION.md +44 -0
  7. package/README.md +11 -0
  8. package/config.schema.json +99 -1940
  9. package/dist/deviceFactory.d.ts +13 -0
  10. package/dist/deviceFactory.d.ts.map +1 -0
  11. package/dist/deviceFactory.js +81 -0
  12. package/dist/deviceFactory.js.map +1 -0
  13. package/dist/devices/deviceBase.d.ts +50 -0
  14. package/dist/devices/deviceBase.d.ts.map +1 -0
  15. package/dist/devices/deviceBase.js +119 -0
  16. package/dist/devices/deviceBase.js.map +1 -0
  17. package/dist/devices/genericDevice.d.ts +283 -0
  18. package/dist/devices/genericDevice.d.ts.map +1 -0
  19. package/dist/devices/genericDevice.js +1035 -0
  20. package/dist/devices/genericDevice.js.map +1 -0
  21. package/dist/homebridge-ui/public/index.html +72 -440
  22. package/dist/homebridge-ui/server.d.ts +3 -1
  23. package/dist/homebridge-ui/server.d.ts.map +1 -1
  24. package/dist/homebridge-ui/server.js +47 -10
  25. package/dist/homebridge-ui/server.js.map +1 -1
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +1 -3
  28. package/dist/index.js.map +1 -1
  29. package/dist/platform.d.ts +27 -0
  30. package/dist/platform.d.ts.map +1 -0
  31. package/dist/platform.js +404 -0
  32. package/dist/platform.js.map +1 -0
  33. package/dist/settings.d.ts +10 -317
  34. package/dist/settings.d.ts.map +1 -1
  35. package/dist/settings.js +5 -30
  36. package/dist/settings.js.map +1 -1
  37. package/dist/switchbotClient.d.ts +32 -0
  38. package/dist/switchbotClient.d.ts.map +1 -0
  39. package/dist/switchbotClient.js +259 -0
  40. package/dist/switchbotClient.js.map +1 -0
  41. package/dist/utils.d.ts +36 -248
  42. package/dist/utils.d.ts.map +1 -1
  43. package/dist/utils.js +38 -1367
  44. package/dist/utils.js.map +1 -1
  45. package/docs/assets/icons.js +1 -1
  46. package/docs/assets/icons.svg +1 -1
  47. package/docs/assets/style.css +3 -3
  48. package/docs/index.html +50 -15
  49. package/docs/variables/default.html +1 -1
  50. package/package.json +19 -18
  51. package/scripts/e2e/README.md +25 -0
  52. package/scripts/e2e/curtain-e2e.sh +70 -0
  53. package/scripts/e2e/fan-e2e.sh +75 -0
  54. package/scripts/e2e/light-advanced-e2e.sh +97 -0
  55. package/scripts/e2e/light-e2e.sh +75 -0
  56. package/scripts/e2e/list-accessories.sh +19 -0
  57. package/scripts/e2e/lock-e2e.sh +65 -0
  58. package/scripts/generate-matter-maps.js +60 -0
  59. package/scripts/run-e2e-local.sh +14 -0
  60. package/src/deviceFactory.ts +122 -0
  61. package/src/devices/deviceBase.ts +141 -0
  62. package/src/devices/genericDevice.ts +965 -0
  63. package/src/homebridge-ui/public/index.html +72 -440
  64. package/src/homebridge-ui/server.ts +52 -10
  65. package/src/index.ts +1 -3
  66. package/src/platform.ts +395 -0
  67. package/src/settings.ts +12 -352
  68. package/src/switchbotClient.ts +266 -0
  69. package/src/utils.ts +47 -1456
  70. package/test/accessory-restore.spec.ts +73 -0
  71. package/test/device-mapping.spec.ts +37 -0
  72. package/test/deviceFactory.spec.ts +18 -0
  73. package/test/e2e/run-e2e.spec.ts +50 -0
  74. package/test/fan-swing.spec.ts +29 -0
  75. package/test/helpers/matter-harness.ts +53 -0
  76. package/test/lock-users.spec.ts +44 -0
  77. package/test/matter-childbridge.spec.ts +55 -0
  78. package/test/matter-descriptors.spec.ts +97 -0
  79. package/test/matter-device-state.spec.ts +101 -0
  80. package/test/matter-integration.spec.ts +70 -0
  81. package/test/platform.integration.spec.ts +55 -0
  82. package/test/switchbot-client-debounce.spec.ts +131 -0
  83. package/test/switchbot-client-openapi.spec.ts +56 -0
  84. package/test/switchbotClient.spec.ts +10 -0
  85. package/test/utils.spec.ts +20 -0
  86. package/vitest.config.ts +7 -0
  87. package/coverage/base.css +0 -224
  88. package/coverage/block-navigation.js +0 -87
  89. package/coverage/clover.xml +0 -15847
  90. package/coverage/coverage-final.json +0 -42
  91. package/coverage/docs/assets/dmt/dmt-component-data.js.html +0 -85
  92. package/coverage/docs/assets/dmt/dmt-components.js.html +0 -286
  93. package/coverage/docs/assets/dmt/index.html +0 -131
  94. package/coverage/docs/assets/hierarchy.js.html +0 -85
  95. package/coverage/docs/assets/icons.js.html +0 -136
  96. package/coverage/docs/assets/index.html +0 -146
  97. package/coverage/docs/assets/main.js.html +0 -265
  98. package/coverage/favicon.png +0 -0
  99. package/coverage/index.html +0 -191
  100. package/coverage/prettify.css +0 -1
  101. package/coverage/prettify.js +0 -2
  102. package/coverage/sort-arrow-sprite.png +0 -0
  103. package/coverage/sorter.js +0 -196
  104. package/coverage/src/device/blindtilt.ts.html +0 -3238
  105. package/coverage/src/device/bot.ts.html +0 -2803
  106. package/coverage/src/device/ceilinglight.ts.html +0 -2338
  107. package/coverage/src/device/colorbulb.ts.html +0 -2824
  108. package/coverage/src/device/contact.ts.html +0 -1465
  109. package/coverage/src/device/curtain.ts.html +0 -2869
  110. package/coverage/src/device/device.ts.html +0 -2500
  111. package/coverage/src/device/fan.ts.html +0 -2242
  112. package/coverage/src/device/hub.ts.html +0 -1408
  113. package/coverage/src/device/humidifier.ts.html +0 -2116
  114. package/coverage/src/device/index.html +0 -416
  115. package/coverage/src/device/iosensor.ts.html +0 -1375
  116. package/coverage/src/device/lightstrip.ts.html +0 -2617
  117. package/coverage/src/device/lock.ts.html +0 -1963
  118. package/coverage/src/device/meter.ts.html +0 -1372
  119. package/coverage/src/device/meterplus.ts.html +0 -1384
  120. package/coverage/src/device/meterpro.ts.html +0 -1618
  121. package/coverage/src/device/motion.ts.html +0 -1264
  122. package/coverage/src/device/plug.ts.html +0 -1372
  123. package/coverage/src/device/relayswitch.ts.html +0 -2284
  124. package/coverage/src/device/robotvacuumcleaner.ts.html +0 -1810
  125. package/coverage/src/device/waterdetector.ts.html +0 -1294
  126. package/coverage/src/homebridge-ui/index.html +0 -116
  127. package/coverage/src/homebridge-ui/server.ts.html +0 -229
  128. package/coverage/src/index.html +0 -161
  129. package/coverage/src/index.ts.html +0 -124
  130. package/coverage/src/irdevice/airconditioner.ts.html +0 -1687
  131. package/coverage/src/irdevice/airpurifier.ts.html +0 -844
  132. package/coverage/src/irdevice/camera.ts.html +0 -475
  133. package/coverage/src/irdevice/fan.ts.html +0 -766
  134. package/coverage/src/irdevice/index.html +0 -251
  135. package/coverage/src/irdevice/irdevice.ts.html +0 -1117
  136. package/coverage/src/irdevice/light.ts.html +0 -826
  137. package/coverage/src/irdevice/other.ts.html +0 -2458
  138. package/coverage/src/irdevice/tv.ts.html +0 -1222
  139. package/coverage/src/irdevice/vacuumcleaner.ts.html +0 -466
  140. package/coverage/src/irdevice/waterheater.ts.html +0 -469
  141. package/coverage/src/platform.ts.html +0 -8776
  142. package/coverage/src/settings.ts.html +0 -934
  143. package/coverage/src/utils.ts.html +0 -2092
  144. package/dist/devices-hap/airpurifier.d.ts +0 -54
  145. package/dist/devices-hap/airpurifier.d.ts.map +0 -1
  146. package/dist/devices-hap/airpurifier.js +0 -533
  147. package/dist/devices-hap/airpurifier.js.map +0 -1
  148. package/dist/devices-hap/blindtilt.d.ts +0 -90
  149. package/dist/devices-hap/blindtilt.d.ts.map +0 -1
  150. package/dist/devices-hap/blindtilt.js +0 -974
  151. package/dist/devices-hap/blindtilt.js.map +0 -1
  152. package/dist/devices-hap/bot.d.ts +0 -102
  153. package/dist/devices-hap/bot.d.ts.map +0 -1
  154. package/dist/devices-hap/bot.js +0 -822
  155. package/dist/devices-hap/bot.js.map +0 -1
  156. package/dist/devices-hap/ceilinglight.d.ts +0 -85
  157. package/dist/devices-hap/ceilinglight.d.ts.map +0 -1
  158. package/dist/devices-hap/ceilinglight.js +0 -707
  159. package/dist/devices-hap/ceilinglight.js.map +0 -1
  160. package/dist/devices-hap/colorbulb.d.ts +0 -88
  161. package/dist/devices-hap/colorbulb.d.ts.map +0 -1
  162. package/dist/devices-hap/colorbulb.js +0 -921
  163. package/dist/devices-hap/colorbulb.js.map +0 -1
  164. package/dist/devices-hap/contact.d.ts +0 -44
  165. package/dist/devices-hap/contact.d.ts.map +0 -1
  166. package/dist/devices-hap/contact.js +0 -409
  167. package/dist/devices-hap/contact.js.map +0 -1
  168. package/dist/devices-hap/curtain.d.ts +0 -73
  169. package/dist/devices-hap/curtain.d.ts.map +0 -1
  170. package/dist/devices-hap/curtain.js +0 -869
  171. package/dist/devices-hap/curtain.js.map +0 -1
  172. package/dist/devices-hap/device.d.ts +0 -108
  173. package/dist/devices-hap/device.d.ts.map +0 -1
  174. package/dist/devices-hap/device.js +0 -821
  175. package/dist/devices-hap/device.js.map +0 -1
  176. package/dist/devices-hap/fan.d.ts +0 -69
  177. package/dist/devices-hap/fan.d.ts.map +0 -1
  178. package/dist/devices-hap/fan.js +0 -655
  179. package/dist/devices-hap/fan.js.map +0 -1
  180. package/dist/devices-hap/hub.d.ts +0 -37
  181. package/dist/devices-hap/hub.d.ts.map +0 -1
  182. package/dist/devices-hap/hub.js +0 -393
  183. package/dist/devices-hap/hub.js.map +0 -1
  184. package/dist/devices-hap/humidifier.d.ts +0 -73
  185. package/dist/devices-hap/humidifier.d.ts.map +0 -1
  186. package/dist/devices-hap/humidifier.js +0 -716
  187. package/dist/devices-hap/humidifier.js.map +0 -1
  188. package/dist/devices-hap/iosensor.d.ts +0 -42
  189. package/dist/devices-hap/iosensor.d.ts.map +0 -1
  190. package/dist/devices-hap/iosensor.js +0 -397
  191. package/dist/devices-hap/iosensor.js.map +0 -1
  192. package/dist/devices-hap/lightstrip.d.ts +0 -79
  193. package/dist/devices-hap/lightstrip.d.ts.map +0 -1
  194. package/dist/devices-hap/lightstrip.js +0 -827
  195. package/dist/devices-hap/lightstrip.js.map +0 -1
  196. package/dist/devices-hap/lock.d.ts +0 -53
  197. package/dist/devices-hap/lock.d.ts.map +0 -1
  198. package/dist/devices-hap/lock.js +0 -569
  199. package/dist/devices-hap/lock.js.map +0 -1
  200. package/dist/devices-hap/meter.d.ts +0 -37
  201. package/dist/devices-hap/meter.d.ts.map +0 -1
  202. package/dist/devices-hap/meter.js +0 -380
  203. package/dist/devices-hap/meter.js.map +0 -1
  204. package/dist/devices-hap/meterplus.d.ts +0 -42
  205. package/dist/devices-hap/meterplus.d.ts.map +0 -1
  206. package/dist/devices-hap/meterplus.js +0 -385
  207. package/dist/devices-hap/meterplus.js.map +0 -1
  208. package/dist/devices-hap/meterpro.d.ts +0 -43
  209. package/dist/devices-hap/meterpro.d.ts.map +0 -1
  210. package/dist/devices-hap/meterpro.js +0 -469
  211. package/dist/devices-hap/meterpro.js.map +0 -1
  212. package/dist/devices-hap/motion.d.ts +0 -42
  213. package/dist/devices-hap/motion.d.ts.map +0 -1
  214. package/dist/devices-hap/motion.js +0 -345
  215. package/dist/devices-hap/motion.js.map +0 -1
  216. package/dist/devices-hap/plug.d.ts +0 -49
  217. package/dist/devices-hap/plug.d.ts.map +0 -1
  218. package/dist/devices-hap/plug.js +0 -400
  219. package/dist/devices-hap/plug.js.map +0 -1
  220. package/dist/devices-hap/relayswitch.d.ts +0 -96
  221. package/dist/devices-hap/relayswitch.d.ts.map +0 -1
  222. package/dist/devices-hap/relayswitch.js +0 -642
  223. package/dist/devices-hap/relayswitch.js.map +0 -1
  224. package/dist/devices-hap/robotvacuumcleaner.d.ts +0 -54
  225. package/dist/devices-hap/robotvacuumcleaner.d.ts.map +0 -1
  226. package/dist/devices-hap/robotvacuumcleaner.js +0 -530
  227. package/dist/devices-hap/robotvacuumcleaner.js.map +0 -1
  228. package/dist/devices-hap/waterdetector.d.ts +0 -41
  229. package/dist/devices-hap/waterdetector.d.ts.map +0 -1
  230. package/dist/devices-hap/waterdetector.js +0 -356
  231. package/dist/devices-hap/waterdetector.js.map +0 -1
  232. package/dist/devices-matter/BaseMatterAccessory.d.ts +0 -90
  233. package/dist/devices-matter/BaseMatterAccessory.d.ts.map +0 -1
  234. package/dist/devices-matter/BaseMatterAccessory.js +0 -264
  235. package/dist/devices-matter/BaseMatterAccessory.js.map +0 -1
  236. package/dist/devices-matter/ColorLightAccessory.d.ts +0 -20
  237. package/dist/devices-matter/ColorLightAccessory.d.ts.map +0 -1
  238. package/dist/devices-matter/ColorLightAccessory.js +0 -95
  239. package/dist/devices-matter/ColorLightAccessory.js.map +0 -1
  240. package/dist/devices-matter/ColorTemperatureLightAccessory.d.ts +0 -18
  241. package/dist/devices-matter/ColorTemperatureLightAccessory.d.ts.map +0 -1
  242. package/dist/devices-matter/ColorTemperatureLightAccessory.js +0 -76
  243. package/dist/devices-matter/ColorTemperatureLightAccessory.js.map +0 -1
  244. package/dist/devices-matter/ContactSensorAccessory.d.ts +0 -12
  245. package/dist/devices-matter/ContactSensorAccessory.d.ts.map +0 -1
  246. package/dist/devices-matter/ContactSensorAccessory.js +0 -34
  247. package/dist/devices-matter/ContactSensorAccessory.js.map +0 -1
  248. package/dist/devices-matter/DimmableLightAccessory.d.ts +0 -58
  249. package/dist/devices-matter/DimmableLightAccessory.d.ts.map +0 -1
  250. package/dist/devices-matter/DimmableLightAccessory.js +0 -167
  251. package/dist/devices-matter/DimmableLightAccessory.js.map +0 -1
  252. package/dist/devices-matter/DoorLockAccessory.d.ts +0 -14
  253. package/dist/devices-matter/DoorLockAccessory.d.ts.map +0 -1
  254. package/dist/devices-matter/DoorLockAccessory.js +0 -50
  255. package/dist/devices-matter/DoorLockAccessory.js.map +0 -1
  256. package/dist/devices-matter/ExtendedColorLightAccessory.d.ts +0 -21
  257. package/dist/devices-matter/ExtendedColorLightAccessory.d.ts.map +0 -1
  258. package/dist/devices-matter/ExtendedColorLightAccessory.js +0 -106
  259. package/dist/devices-matter/ExtendedColorLightAccessory.js.map +0 -1
  260. package/dist/devices-matter/FanAccessory.d.ts +0 -16
  261. package/dist/devices-matter/FanAccessory.d.ts.map +0 -1
  262. package/dist/devices-matter/FanAccessory.js +0 -81
  263. package/dist/devices-matter/FanAccessory.js.map +0 -1
  264. package/dist/devices-matter/HumiditySensorAccessory.d.ts +0 -12
  265. package/dist/devices-matter/HumiditySensorAccessory.d.ts.map +0 -1
  266. package/dist/devices-matter/HumiditySensorAccessory.js +0 -34
  267. package/dist/devices-matter/HumiditySensorAccessory.js.map +0 -1
  268. package/dist/devices-matter/LeakSensorAccessory.d.ts +0 -12
  269. package/dist/devices-matter/LeakSensorAccessory.d.ts.map +0 -1
  270. package/dist/devices-matter/LeakSensorAccessory.js +0 -33
  271. package/dist/devices-matter/LeakSensorAccessory.js.map +0 -1
  272. package/dist/devices-matter/LightSensorAccessory.d.ts +0 -12
  273. package/dist/devices-matter/LightSensorAccessory.d.ts.map +0 -1
  274. package/dist/devices-matter/LightSensorAccessory.js +0 -34
  275. package/dist/devices-matter/LightSensorAccessory.js.map +0 -1
  276. package/dist/devices-matter/OccupancySensorAccessory.d.ts +0 -12
  277. package/dist/devices-matter/OccupancySensorAccessory.d.ts.map +0 -1
  278. package/dist/devices-matter/OccupancySensorAccessory.js +0 -39
  279. package/dist/devices-matter/OccupancySensorAccessory.js.map +0 -1
  280. package/dist/devices-matter/OnOffLightAccessory.d.ts +0 -38
  281. package/dist/devices-matter/OnOffLightAccessory.d.ts.map +0 -1
  282. package/dist/devices-matter/OnOffLightAccessory.js +0 -110
  283. package/dist/devices-matter/OnOffLightAccessory.js.map +0 -1
  284. package/dist/devices-matter/OnOffOutletAccessory.d.ts +0 -14
  285. package/dist/devices-matter/OnOffOutletAccessory.d.ts.map +0 -1
  286. package/dist/devices-matter/OnOffOutletAccessory.js +0 -43
  287. package/dist/devices-matter/OnOffOutletAccessory.js.map +0 -1
  288. package/dist/devices-matter/OnOffSwitchAccessory.d.ts +0 -14
  289. package/dist/devices-matter/OnOffSwitchAccessory.d.ts.map +0 -1
  290. package/dist/devices-matter/OnOffSwitchAccessory.js +0 -42
  291. package/dist/devices-matter/OnOffSwitchAccessory.js.map +0 -1
  292. package/dist/devices-matter/RoboticVacuumAccessory.d.ts +0 -61
  293. package/dist/devices-matter/RoboticVacuumAccessory.d.ts.map +0 -1
  294. package/dist/devices-matter/RoboticVacuumAccessory.js +0 -544
  295. package/dist/devices-matter/RoboticVacuumAccessory.js.map +0 -1
  296. package/dist/devices-matter/SmokeCOAlarmAccessory.d.ts +0 -11
  297. package/dist/devices-matter/SmokeCOAlarmAccessory.d.ts.map +0 -1
  298. package/dist/devices-matter/SmokeCOAlarmAccessory.js +0 -49
  299. package/dist/devices-matter/SmokeCOAlarmAccessory.js.map +0 -1
  300. package/dist/devices-matter/TemperatureSensorAccessory.d.ts +0 -12
  301. package/dist/devices-matter/TemperatureSensorAccessory.d.ts.map +0 -1
  302. package/dist/devices-matter/TemperatureSensorAccessory.js +0 -36
  303. package/dist/devices-matter/TemperatureSensorAccessory.js.map +0 -1
  304. package/dist/devices-matter/ThermostatAccessory.d.ts +0 -19
  305. package/dist/devices-matter/ThermostatAccessory.d.ts.map +0 -1
  306. package/dist/devices-matter/ThermostatAccessory.js +0 -95
  307. package/dist/devices-matter/ThermostatAccessory.js.map +0 -1
  308. package/dist/devices-matter/VenetianBlindAccessory.d.ts +0 -19
  309. package/dist/devices-matter/VenetianBlindAccessory.d.ts.map +0 -1
  310. package/dist/devices-matter/VenetianBlindAccessory.js +0 -99
  311. package/dist/devices-matter/VenetianBlindAccessory.js.map +0 -1
  312. package/dist/devices-matter/WindowBlindAccessory.d.ts +0 -17
  313. package/dist/devices-matter/WindowBlindAccessory.d.ts.map +0 -1
  314. package/dist/devices-matter/WindowBlindAccessory.js +0 -131
  315. package/dist/devices-matter/WindowBlindAccessory.js.map +0 -1
  316. package/dist/devices-matter/custom/PowerStripAccessory.d.ts +0 -97
  317. package/dist/devices-matter/custom/PowerStripAccessory.d.ts.map +0 -1
  318. package/dist/devices-matter/custom/PowerStripAccessory.js +0 -265
  319. package/dist/devices-matter/custom/PowerStripAccessory.js.map +0 -1
  320. package/dist/devices-matter/custom/index.d.ts +0 -8
  321. package/dist/devices-matter/custom/index.d.ts.map +0 -1
  322. package/dist/devices-matter/custom/index.js +0 -8
  323. package/dist/devices-matter/custom/index.js.map +0 -1
  324. package/dist/devices-matter/index.d.ts +0 -29
  325. package/dist/devices-matter/index.d.ts.map +0 -1
  326. package/dist/devices-matter/index.js +0 -28
  327. package/dist/devices-matter/index.js.map +0 -1
  328. package/dist/irdevice/airconditioner.d.ts +0 -61
  329. package/dist/irdevice/airconditioner.d.ts.map +0 -1
  330. package/dist/irdevice/airconditioner.js +0 -472
  331. package/dist/irdevice/airconditioner.js.map +0 -1
  332. package/dist/irdevice/airpurifier.d.ts +0 -50
  333. package/dist/irdevice/airpurifier.d.ts.map +0 -1
  334. package/dist/irdevice/airpurifier.js +0 -213
  335. package/dist/irdevice/airpurifier.js.map +0 -1
  336. package/dist/irdevice/camera.d.ts +0 -32
  337. package/dist/irdevice/camera.d.ts.map +0 -1
  338. package/dist/irdevice/camera.js +0 -107
  339. package/dist/irdevice/camera.js.map +0 -1
  340. package/dist/irdevice/fan.d.ts +0 -36
  341. package/dist/irdevice/fan.d.ts.map +0 -1
  342. package/dist/irdevice/fan.js +0 -200
  343. package/dist/irdevice/fan.js.map +0 -1
  344. package/dist/irdevice/irdevice.d.ts +0 -69
  345. package/dist/irdevice/irdevice.d.ts.map +0 -1
  346. package/dist/irdevice/irdevice.js +0 -339
  347. package/dist/irdevice/irdevice.js.map +0 -1
  348. package/dist/irdevice/light.d.ts +0 -36
  349. package/dist/irdevice/light.d.ts.map +0 -1
  350. package/dist/irdevice/light.js +0 -206
  351. package/dist/irdevice/light.js.map +0 -1
  352. package/dist/irdevice/other.d.ts +0 -57
  353. package/dist/irdevice/other.d.ts.map +0 -1
  354. package/dist/irdevice/other.js +0 -778
  355. package/dist/irdevice/other.js.map +0 -1
  356. package/dist/irdevice/tv.d.ts +0 -45
  357. package/dist/irdevice/tv.d.ts.map +0 -1
  358. package/dist/irdevice/tv.js +0 -327
  359. package/dist/irdevice/tv.js.map +0 -1
  360. package/dist/irdevice/vacuumcleaner.d.ts +0 -28
  361. package/dist/irdevice/vacuumcleaner.d.ts.map +0 -1
  362. package/dist/irdevice/vacuumcleaner.js +0 -104
  363. package/dist/irdevice/vacuumcleaner.js.map +0 -1
  364. package/dist/irdevice/waterheater.d.ts +0 -30
  365. package/dist/irdevice/waterheater.d.ts.map +0 -1
  366. package/dist/irdevice/waterheater.js +0 -105
  367. package/dist/irdevice/waterheater.js.map +0 -1
  368. package/dist/platform-hap.d.ts +0 -160
  369. package/dist/platform-hap.d.ts.map +0 -1
  370. package/dist/platform-hap.js +0 -3041
  371. package/dist/platform-hap.js.map +0 -1
  372. package/dist/platform-matter.d.ts +0 -188
  373. package/dist/platform-matter.d.ts.map +0 -1
  374. package/dist/platform-matter.js +0 -2545
  375. package/dist/platform-matter.js.map +0 -1
  376. package/dist/test/apiRequestTracker.test.d.ts +0 -2
  377. package/dist/test/apiRequestTracker.test.d.ts.map +0 -1
  378. package/dist/test/apiRequestTracker.test.js +0 -392
  379. package/dist/test/apiRequestTracker.test.js.map +0 -1
  380. package/dist/test/hap/device-webhook-context.test.d.ts +0 -2
  381. package/dist/test/hap/device-webhook-context.test.d.ts.map +0 -1
  382. package/dist/test/hap/device-webhook-context.test.js +0 -128
  383. package/dist/test/hap/device-webhook-context.test.js.map +0 -1
  384. package/dist/test/hap/platform-hap.logging.test.d.ts +0 -2
  385. package/dist/test/hap/platform-hap.logging.test.d.ts.map +0 -1
  386. package/dist/test/hap/platform-hap.logging.test.js +0 -33
  387. package/dist/test/hap/platform-hap.logging.test.js.map +0 -1
  388. package/dist/test/hap/platform-hap.test.d.ts +0 -2
  389. package/dist/test/hap/platform-hap.test.d.ts.map +0 -1
  390. package/dist/test/hap/platform-hap.test.js +0 -62
  391. package/dist/test/hap/platform-hap.test.js.map +0 -1
  392. package/dist/test/helpers/platform-fixtures.d.ts +0 -9
  393. package/dist/test/helpers/platform-fixtures.d.ts.map +0 -1
  394. package/dist/test/helpers/platform-fixtures.js +0 -30
  395. package/dist/test/helpers/platform-fixtures.js.map +0 -1
  396. package/dist/test/homebridge-ui/server.test.d.ts +0 -2
  397. package/dist/test/homebridge-ui/server.test.d.ts.map +0 -1
  398. package/dist/test/homebridge-ui/server.test.js +0 -445
  399. package/dist/test/homebridge-ui/server.test.js.map +0 -1
  400. package/dist/test/index.test.d.ts +0 -2
  401. package/dist/test/index.test.d.ts.map +0 -1
  402. package/dist/test/index.test.js +0 -19
  403. package/dist/test/index.test.js.map +0 -1
  404. package/dist/test/matter/devices-matter/baseMatterAccessory.test.d.ts +0 -2
  405. package/dist/test/matter/devices-matter/baseMatterAccessory.test.d.ts.map +0 -1
  406. package/dist/test/matter/devices-matter/baseMatterAccessory.test.js +0 -71
  407. package/dist/test/matter/devices-matter/baseMatterAccessory.test.js.map +0 -1
  408. package/dist/test/matter/platform-matter.additional.test.d.ts +0 -2
  409. package/dist/test/matter/platform-matter.additional.test.d.ts.map +0 -1
  410. package/dist/test/matter/platform-matter.additional.test.js +0 -35
  411. package/dist/test/matter/platform-matter.additional.test.js.map +0 -1
  412. package/dist/test/matter/platform-matter.bleparse.test.d.ts +0 -2
  413. package/dist/test/matter/platform-matter.bleparse.test.d.ts.map +0 -1
  414. package/dist/test/matter/platform-matter.bleparse.test.js +0 -43
  415. package/dist/test/matter/platform-matter.bleparse.test.js.map +0 -1
  416. package/dist/test/matter/platform-matter.cleanup.test.d.ts +0 -2
  417. package/dist/test/matter/platform-matter.cleanup.test.d.ts.map +0 -1
  418. package/dist/test/matter/platform-matter.cleanup.test.js +0 -70
  419. package/dist/test/matter/platform-matter.cleanup.test.js.map +0 -1
  420. package/dist/test/matter/platform-matter.keepstale.test.d.ts +0 -2
  421. package/dist/test/matter/platform-matter.keepstale.test.d.ts.map +0 -1
  422. package/dist/test/matter/platform-matter.keepstale.test.js +0 -27
  423. package/dist/test/matter/platform-matter.keepstale.test.js.map +0 -1
  424. package/dist/test/matter/platform-matter.logging.test.d.ts +0 -2
  425. package/dist/test/matter/platform-matter.logging.test.d.ts.map +0 -1
  426. package/dist/test/matter/platform-matter.logging.test.js +0 -29
  427. package/dist/test/matter/platform-matter.logging.test.js.map +0 -1
  428. package/dist/test/matter/platform-matter.mapping.test.d.ts +0 -2
  429. package/dist/test/matter/platform-matter.mapping.test.d.ts.map +0 -1
  430. package/dist/test/matter/platform-matter.mapping.test.js +0 -43
  431. package/dist/test/matter/platform-matter.mapping.test.js.map +0 -1
  432. package/dist/test/matter/platform-matter.openapi-mapping.test.d.ts +0 -2
  433. package/dist/test/matter/platform-matter.openapi-mapping.test.d.ts.map +0 -1
  434. package/dist/test/matter/platform-matter.openapi-mapping.test.js +0 -84
  435. package/dist/test/matter/platform-matter.openapi-mapping.test.js.map +0 -1
  436. package/dist/test/matter/platform-matter.test.d.ts +0 -2
  437. package/dist/test/matter/platform-matter.test.d.ts.map +0 -1
  438. package/dist/test/matter/platform-matter.test.js +0 -117
  439. package/dist/test/matter/platform-matter.test.js.map +0 -1
  440. package/dist/test/matter/platform-matter.unregister.test.d.ts +0 -2
  441. package/dist/test/matter/platform-matter.unregister.test.d.ts.map +0 -1
  442. package/dist/test/matter/platform-matter.unregister.test.js +0 -30
  443. package/dist/test/matter/platform-matter.unregister.test.js.map +0 -1
  444. package/dist/test/matter/platform-matter.webhook.test.d.ts +0 -2
  445. package/dist/test/matter/platform-matter.webhook.test.d.ts.map +0 -1
  446. package/dist/test/matter/platform-matter.webhook.test.js +0 -46
  447. package/dist/test/matter/platform-matter.webhook.test.js.map +0 -1
  448. package/dist/test/utils.test.d.ts +0 -2
  449. package/dist/test/utils.test.d.ts.map +0 -1
  450. package/dist/test/utils.test.js +0 -95
  451. package/dist/test/utils.test.js.map +0 -1
  452. package/dist/test/verifyconfig.test.d.ts +0 -2
  453. package/dist/test/verifyconfig.test.d.ts.map +0 -1
  454. package/dist/test/verifyconfig.test.js +0 -167
  455. package/dist/test/verifyconfig.test.js.map +0 -1
  456. package/src/custom.d.ts +0 -7
  457. package/src/devices-hap/airpurifier.ts +0 -568
  458. package/src/devices-hap/blindtilt.ts +0 -1049
  459. package/src/devices-hap/bot.ts +0 -910
  460. package/src/devices-hap/ceilinglight.ts +0 -747
  461. package/src/devices-hap/colorbulb.ts +0 -940
  462. package/src/devices-hap/contact.ts +0 -457
  463. package/src/devices-hap/curtain.ts +0 -944
  464. package/src/devices-hap/device.ts +0 -890
  465. package/src/devices-hap/fan.ts +0 -716
  466. package/src/devices-hap/hub.ts +0 -440
  467. package/src/devices-hap/humidifier.ts +0 -762
  468. package/src/devices-hap/iosensor.ts +0 -442
  469. package/src/devices-hap/lightstrip.ts +0 -863
  470. package/src/devices-hap/lock.ts +0 -627
  471. package/src/devices-hap/meter.ts +0 -427
  472. package/src/devices-hap/meterplus.ts +0 -431
  473. package/src/devices-hap/meterpro.ts +0 -523
  474. package/src/devices-hap/motion.ts +0 -390
  475. package/src/devices-hap/plug.ts +0 -427
  476. package/src/devices-hap/relayswitch.ts +0 -727
  477. package/src/devices-hap/robotvacuumcleaner.ts +0 -574
  478. package/src/devices-hap/waterdetector.ts +0 -400
  479. package/src/devices-matter/BaseMatterAccessory.ts +0 -302
  480. package/src/devices-matter/ColorLightAccessory.ts +0 -110
  481. package/src/devices-matter/ColorTemperatureLightAccessory.ts +0 -90
  482. package/src/devices-matter/ContactSensorAccessory.ts +0 -41
  483. package/src/devices-matter/DimmableLightAccessory.ts +0 -192
  484. package/src/devices-matter/DoorLockAccessory.ts +0 -60
  485. package/src/devices-matter/ExtendedColorLightAccessory.ts +0 -122
  486. package/src/devices-matter/FanAccessory.ts +0 -95
  487. package/src/devices-matter/HumiditySensorAccessory.ts +0 -41
  488. package/src/devices-matter/LeakSensorAccessory.ts +0 -40
  489. package/src/devices-matter/LightSensorAccessory.ts +0 -41
  490. package/src/devices-matter/OccupancySensorAccessory.ts +0 -48
  491. package/src/devices-matter/OnOffLightAccessory.ts +0 -125
  492. package/src/devices-matter/OnOffOutletAccessory.ts +0 -51
  493. package/src/devices-matter/OnOffSwitchAccessory.ts +0 -51
  494. package/src/devices-matter/RoboticVacuumAccessory.ts +0 -621
  495. package/src/devices-matter/SmokeCOAlarmAccessory.ts +0 -59
  496. package/src/devices-matter/TemperatureSensorAccessory.ts +0 -43
  497. package/src/devices-matter/ThermostatAccessory.ts +0 -110
  498. package/src/devices-matter/VenetianBlindAccessory.ts +0 -115
  499. package/src/devices-matter/WindowBlindAccessory.ts +0 -135
  500. package/src/devices-matter/custom/PowerStripAccessory.ts +0 -309
  501. package/src/devices-matter/custom/index.ts +0 -8
  502. package/src/devices-matter/index.ts +0 -29
  503. package/src/irdevice/airconditioner.ts +0 -533
  504. package/src/irdevice/airpurifier.ts +0 -252
  505. package/src/irdevice/camera.ts +0 -129
  506. package/src/irdevice/fan.ts +0 -226
  507. package/src/irdevice/irdevice.ts +0 -383
  508. package/src/irdevice/light.ts +0 -246
  509. package/src/irdevice/other.ts +0 -790
  510. package/src/irdevice/tv.ts +0 -378
  511. package/src/irdevice/vacuumcleaner.ts +0 -126
  512. package/src/irdevice/waterheater.ts +0 -127
  513. package/src/platform-hap.ts +0 -3193
  514. package/src/platform-matter.ts +0 -2703
  515. package/src/test/apiRequestTracker.test.ts +0 -417
  516. package/src/test/hap/device-webhook-context.test.ts +0 -136
  517. package/src/test/hap/platform-hap.logging.test.ts +0 -36
  518. package/src/test/hap/platform-hap.test.ts +0 -70
  519. package/src/test/helpers/platform-fixtures.ts +0 -33
  520. package/src/test/homebridge-ui/server.test.ts +0 -486
  521. package/src/test/index.test.ts +0 -24
  522. package/src/test/matter/devices-matter/baseMatterAccessory.test.ts +0 -88
  523. package/src/test/matter/platform-matter.additional.test.ts +0 -44
  524. package/src/test/matter/platform-matter.bleparse.test.ts +0 -47
  525. package/src/test/matter/platform-matter.cleanup.test.ts +0 -86
  526. package/src/test/matter/platform-matter.keepstale.test.ts +0 -37
  527. package/src/test/matter/platform-matter.logging.test.ts +0 -33
  528. package/src/test/matter/platform-matter.mapping.test.ts +0 -57
  529. package/src/test/matter/platform-matter.openapi-mapping.test.ts +0 -109
  530. package/src/test/matter/platform-matter.test.ts +0 -144
  531. package/src/test/matter/platform-matter.unregister.test.ts +0 -39
  532. package/src/test/matter/platform-matter.webhook.test.ts +0 -54
  533. package/src/test/utils.test.ts +0 -96
  534. package/src/test/verifyconfig.test.ts +0 -198
package/src/settings.ts CHANGED
@@ -1,358 +1,18 @@
1
- /* Copyright(C) 2017-2024, donavanbecker (https://github.com/donavanbecker). All rights reserved.
2
- *
3
- * settings.ts: @switchbot/homebridge-switchbot platform class.
4
- */
5
- import type { IClientOptions } from 'async-mqtt'
6
- import type { PlatformConfig } from 'homebridge'
7
- /*
8
- * For Testing Locally:
9
- * import type { device, irdevice, SwitchBotBLEModel, SwitchBotBLEModelFriendlyName, SwitchBotBLEModelName } from '/Users/Shared/GitHub/OpenWonderLabs/node-switchbot/dist/index.js';
10
- */
11
- import type { device, irdevice, SwitchBotBLEModel, SwitchBotBLEModelFriendlyName, SwitchBotBLEModelName, SwitchBotModel } from 'node-switchbot'
12
- /**
13
- * This is the name of the platform that users will use to register the plugin in the Homebridge config.json
14
- */
15
- export const PLATFORM_NAME = 'SwitchBot'
16
-
17
- /**
18
- * This must match the name of your plugin as defined the package.json
19
- */
20
1
  export const PLUGIN_NAME = '@switchbot/homebridge-switchbot'
2
+ export const PLATFORM_NAME = 'SwitchBot'
21
3
 
22
- // Config
23
- export interface SwitchBotPlatformConfig extends PlatformConfig {
24
- credentials?: credentials
25
- options?: options
26
- }
27
- interface credentials {
28
- token?: string
29
- secret?: string
30
- notice?: string
31
- }
32
-
33
- export interface options {
34
- devices?: devicesConfig[]
35
- irdevices?: irDevicesConfig[]
36
- allowInvalidCharacters?: boolean
37
- // When true, devices declared in config.options.devices that are not
38
- // discovered via the SwitchBot OpenAPI will still be included (config-only
39
- // devices). Default: false.
40
- allowConfigOnlyDevices?: boolean
41
- /**
42
- * When true, previously-registered accessories for devices that are no
43
- * longer discovered or configured will be kept on the bridge. Default: false.
44
- * When false (default), stale accessories are removed automatically.
45
- */
46
- keepStaleAccessories?: boolean
47
- mqttURL?: string
48
- mqttOptions?: IClientOptions
49
- mqttPubOptions?: IClientOptions
50
- BLE?: boolean
51
- discoverBLE?: boolean
52
- disableLogsforBLE?: boolean
53
- disableLogsforOpenAPI?: boolean
54
- hostname?: string
55
- webhookURL?: string
56
- /**
57
- * When true, enables webhook support for all devices by default.
58
- * Individual devices can override this with their own webhook setting.
59
- * Requires webhookURL to be configured.
60
- */
61
- webhook?: boolean
62
- maxRetries?: number
63
- delayBetweenRetries?: number
64
- refreshRate?: number
65
- updateRate?: number
66
- pushRate?: number
67
- logging?: string
68
- /**
69
- * Maximum number of SwitchBot OpenAPI requests allowed per day.
70
- * Defaults to 10,000 if not specified.
71
- */
72
- dailyApiLimit?: number
73
- /**
74
- * Number of daily API requests reserved for user-initiated commands.
75
- * When remaining budget falls below this reserve, background polling and discovery
76
- * are paused until the daily counter resets. Defaults to 1,000.
77
- */
78
- dailyApiReserveForCommands?: number
79
- /**
80
- * When true, the plugin will completely stop background polling/discovery
81
- * once the remaining daily budget reaches the reserve (webhook-only mode).
82
- * When false, polling continues until the hard daily limit is reached.
83
- * Default: false.
84
- */
85
- webhookOnlyOnReserve?: boolean
86
- /**
87
- * When true, reset the daily API request counter at LOCAL midnight (system timezone).
88
- * When false (default), reset at UTC midnight. Default: false.
89
- */
90
- dailyApiResetAtLocalMidnight?: boolean
91
- /**
92
- * When true, resets the daily API request counter to zero. This is useful for testing purposes.
93
- */
94
- resetDailyApiCounter?: boolean
95
- /**
96
- * When set, configures the batch refresh rate (in milliseconds) for Matter devices. Default: 5000 ms.
97
- */
98
- matterBatchRefreshRate?: number
99
- /**
100
- * When true, enables batch processing for Matter devices. Default: false.
101
- */
102
- matterBatchConcurrency?: number
103
- /**
104
- * When true, enables batch processing for Matter devices. Default: false.
105
- */
106
- matterBatchEnabled?: boolean
107
- /**
108
- * When set, adds a random delay (jitter) to batch requests to avoid thundering herd problems.
109
- */
110
- matterBatchJitter?: number
111
- newFeatureEnabled?: boolean
112
- };
113
-
114
- export type devicesConfig = botConfig | relaySwitch1Config | relaySwitch1PMConfig | meterConfig | meterProConfig | indoorOutdoorSensorConfig | humidifierConfig | curtainConfig | blindTiltConfig | contactConfig | motionConfig | waterDetectorConfig | plugConfig | colorBulbConfig | stripLightConfig | ceilingLightConfig | lockConfig | hubConfig
115
-
116
- export interface BaseDeviceConfig extends device {
117
- bleMac?: string
118
- model: SwitchBotModel
119
- bleModel: SwitchBotBLEModel
120
- bleModelName: SwitchBotBLEModelName
121
- bleModelFriednlyName: SwitchBotBLEModelFriendlyName
122
- configDeviceType: string
123
- configDeviceName?: string
124
- deviceId: string
125
- external?: boolean
126
- refreshRate?: number
127
- updateRate?: number
128
- pushRate?: number
129
- firmware?: string
130
- logging?: string
131
- connectionType?: string
132
- customBLEaddress?: string
133
- scanDuration?: number
134
- hide_device?: boolean
135
- offline?: boolean
136
- maxRetry?: number
137
- maxRetries?: number
138
- delayBetweenRetries?: number
139
- disableCaching?: boolean
140
- disablePlatformBLE?: boolean
141
- mqttURL?: string
142
- mqttOptions?: IClientOptions
143
- mqttPubOptions?: IClientOptions
144
- history?: boolean
145
- webhook?: boolean
146
- /**
147
- * When true, applies this device's configuration to all other devices
148
- * of the same deviceType/configDeviceType (e.g., all Humidifiers).
149
- * Specific per-device settings will override these template settings.
150
- */
151
- applyToAllDevicesOfType?: boolean
4
+ export interface SwitchBotPluginConfig {
5
+ openApiToken?: string
6
+ openApiSecret?: string
7
+ preferMatter?: boolean
8
+ enableMatter?: boolean
9
+ // other plugin-specific configuration
10
+ [key: string]: any
152
11
  }
153
12
 
154
- export interface botConfig extends BaseDeviceConfig {
155
- configDeviceType: 'Bot'
156
- mode?: string
157
- type: string
158
- doublePress?: number
159
- pushRatePress?: number
160
- allowPush?: boolean
161
- multiPress?: boolean
162
- };
163
-
164
- export interface relaySwitch1Config extends BaseDeviceConfig {
165
- configDeviceType: 'Relay Switch 1'
166
- type: string
167
- allowPush?: boolean
168
- };
169
-
170
- export interface relaySwitch1PMConfig extends BaseDeviceConfig {
171
- configDeviceType: 'Relay Switch 1PM'
172
- type: string
173
- allowPush?: boolean
174
- };
175
-
176
- export interface meterConfig extends BaseDeviceConfig {
177
- configDeviceType: 'Meter' | 'MeterPlus'
178
- hide_temperature?: boolean
179
- convertUnitTo?: string
180
- hide_humidity?: boolean
181
- };
182
-
183
- export interface meterProConfig extends BaseDeviceConfig {
184
- configDeviceType: 'Meter Pro' | 'MeterPro(CO2)'
185
- hide_temperature?: boolean
186
- convertUnitTo?: string
187
- hide_humidity?: boolean
188
- hide_co2?: boolean
189
- };
190
-
191
- export interface indoorOutdoorSensorConfig extends BaseDeviceConfig {
192
- configDeviceType: 'WoIOSensor'
193
- hide_temperature?: boolean
194
- convertUnitTo?: string
195
- hide_humidity?: boolean
196
- };
197
-
198
- export interface humidifierConfig extends BaseDeviceConfig {
199
- configDeviceType: 'Humidifier' | 'Humidifier2'
200
- hide_temperature?: boolean
201
- convertUnitTo?: string
202
- set_minStep?: number
203
- /**
204
- * When true (Humidifier2 only), exposes a Switch service in HomeKit
205
- * to trigger the built-in Drying Filter mode via OpenAPI (setMode 8).
206
- */
207
- activate_dryingfilter?: boolean
208
- };
209
-
210
- export interface curtainConfig extends BaseDeviceConfig {
211
- configDeviceType: 'Curtain' | 'Curtain3' | 'WoRollerShade' | 'Roller Shade'
212
- disable_group?: boolean
213
- hide_lightsensor?: boolean
214
- set_minLux?: number
215
- set_maxLux?: number
216
- set_max?: number
217
- set_min?: number
218
- set_minStep?: number
219
- setCloseMode?: string
220
- setOpenMode?: string
221
- silentModeSwitch?: boolean
222
- };
223
-
224
- export interface blindTiltConfig extends BaseDeviceConfig {
225
- configDeviceType: 'Blind Tilt'
226
- disable_group?: boolean
227
- mapping?: string
228
- hide_lightsensor?: boolean
229
- set_minLux?: number
230
- set_maxLux?: number
231
- set_max?: number
232
- set_min?: number
233
- set_minStep?: number
234
- setCloseMode?: string
235
- setOpenMode?: string
236
- silentModeSwitch?: boolean
237
- };
238
-
239
- export interface contactConfig extends BaseDeviceConfig {
240
- configDeviceType: 'Contact Sensor'
241
- hide_lightsensor?: boolean
242
- set_minLux?: number
243
- set_maxLux?: number
244
- hide_motionsensor?: boolean
245
- };
246
-
247
- export interface motionConfig extends BaseDeviceConfig {
248
- configDeviceType: 'Motion Sensor'
249
- hide_lightsensor?: boolean
250
- set_minLux?: number
251
- set_maxLux?: number
252
- };
253
-
254
- export interface waterDetectorConfig extends BaseDeviceConfig {
255
- configDeviceType: 'Water Detector'
256
- hide_leak?: boolean
257
- dry?: boolean
258
- };
259
-
260
- export interface plugConfig extends BaseDeviceConfig {
261
- configDeviceType: 'Plug' | 'Plug Mini (US)' | 'Plug Mini (JP)'
262
- };
263
-
264
- export interface colorBulbConfig extends BaseDeviceConfig {
265
- configDeviceType: 'Color Bulb'
266
- set_minStep?: number
267
- adaptiveLightingShift?: number
268
- };
269
-
270
- export interface stripLightConfig extends BaseDeviceConfig {
271
- configDeviceType: 'Strip Light'
272
- set_minStep?: number
273
- adaptiveLightingShift?: number
274
- };
275
-
276
- export interface ceilingLightConfig extends BaseDeviceConfig {
277
- configDeviceType: 'Ceiling Light' | 'Ceiling Light Pro'
278
- set_minStep?: number
279
- adaptiveLightingShift?: number
280
- };
281
-
282
- export interface lockConfig extends BaseDeviceConfig {
283
- configDeviceType: 'Smart Lock' | 'Smart Lock Pro' | 'Smart Lock Ultra'
284
- hide_contactsensor?: boolean
285
- activate_latchbutton?: boolean
286
- };
287
-
288
- export interface hubConfig extends BaseDeviceConfig {
289
- configDeviceType: 'Hub 2'
290
- hide_temperature?: boolean
291
- convertUnitTo?: string
292
- hide_humidity?: boolean
293
- hide_lightsensor?: boolean
294
- set_minLux?: number
295
- set_maxLux?: number
296
- };
297
-
298
- export type irDevicesConfig = irFanConfig | irLightConfig | irAirConfig | irOtherConfig
299
-
300
- export interface irBaseDeviceConfig extends irdevice {
301
- configDeviceName?: string
302
- configRemoteType?: string
303
- connectionType?: string
304
- hide_device?: boolean
305
- external?: boolean
306
- refreshRate?: number
307
- updateRate?: number
308
- pushRate?: number
309
- maxRetries?: number
310
- delayBetweenRetries?: number
311
- firmware?: string
312
- deviceId: string
313
- logging?: string
314
- customOn?: string
315
- customOff?: string
316
- /**
317
- * When true, applies this IR device's configuration to all other IR devices
318
- * of the same remoteType/configRemoteType (e.g., all IR Fans).
319
- * Specific per-device settings will override these template settings.
320
- */
321
- applyToAllDevicesOfType?: boolean
322
- customize?: boolean
323
- commandType?: string
324
- disablePushOn?: boolean
325
- disablePushOff?: boolean
326
- disablePushDetail?: boolean
13
+ export const DEFAULT_CONFIG: Partial<SwitchBotPluginConfig> = {
14
+ preferMatter: true,
15
+ enableMatter: true,
327
16
  }
328
17
 
329
- export interface irFanConfig extends irBaseDeviceConfig {
330
- configRemoteType?: 'Fan' | 'DIY Fan'
331
- swing_mode?: boolean
332
- rotation_speed?: boolean
333
- set_minStep?: number
334
- set_max?: number
335
- set_min?: number
336
- };
337
-
338
- export interface irLightConfig extends irBaseDeviceConfig {
339
- configRemoteType?: 'Light' | 'DIY Light'
340
- stateless?: boolean
341
- };
342
-
343
- export interface irAirConfig extends irBaseDeviceConfig {
344
- configRemoteType?: 'Air Conditioner' | 'DIY Air Conditioner'
345
- hide_automode?: boolean
346
- set_max_heat?: number
347
- set_min_heat?: number
348
- set_max_cool?: number
349
- set_min_cool?: number
350
- meterType?: string
351
- meterId?: string
352
- meterUuid?: string
353
- };
354
-
355
- export interface irOtherConfig extends irBaseDeviceConfig {
356
- configRemoteType?: 'Others'
357
- type?: string
358
- };
18
+ export type DeviceType = string
@@ -0,0 +1,266 @@
1
+ import type { SwitchBotPluginConfig } from './settings.js'
2
+
3
+ export interface ISwitchBotClient {
4
+ init(): Promise<void>
5
+ getDevice(id: string): Promise<any>
6
+ destroy(): Promise<void>
7
+ }
8
+
9
+ // Adapter that tries to use the node-switchbot v4 hybrid API when available.
10
+ export class SwitchBotClient implements ISwitchBotClient {
11
+ private cfg: SwitchBotPluginConfig
12
+ private client: any | null = null
13
+ private baseUrl = 'https://api.switch-bot.com/v1.0'
14
+ // configurable network options
15
+ private requestTimeout = 5000
16
+ private maxRetries = 2
17
+ private baseBackoffMs = 100
18
+ private maxBackoffMs = 2000
19
+ private backoffFactor = 2
20
+ private jitter = true
21
+ // per-device write debounce (ms). 0 = disabled. Configurable via plugin options.
22
+ // Default enabled to coalesce rapid writes and prevent command floods.
23
+ private writeDebounceMs = 100
24
+ // structured logger (expects info/warn/error/debug); defaults to console
25
+ private logger: any
26
+ // per-device retry tracking
27
+ private perDeviceRetries: Map<string, number> = new Map()
28
+ private perDeviceMaxRetries = 3
29
+ // per-device cooldown after exceeding retries (ms)
30
+ private perDeviceCooldownMs = 60_000
31
+ private perDeviceCooldownUntil: Map<string, number> = new Map()
32
+
33
+ constructor(cfg: SwitchBotPluginConfig) {
34
+ this.cfg = cfg
35
+ this.logger = (cfg as any)?.logger ?? console
36
+ if (typeof (cfg as any)?.requestTimeout === 'number') this.requestTimeout = (cfg as any).requestTimeout
37
+ if (typeof (cfg as any)?.maxRetries === 'number') this.maxRetries = (cfg as any).maxRetries
38
+ if (typeof (cfg as any)?.perDeviceMaxRetries === 'number') this.perDeviceMaxRetries = (cfg as any).perDeviceMaxRetries
39
+ if (typeof (cfg as any)?.baseBackoffMs === 'number') this.baseBackoffMs = (cfg as any).baseBackoffMs
40
+ if (typeof (cfg as any)?.maxBackoffMs === 'number') this.maxBackoffMs = (cfg as any).maxBackoffMs
41
+ if (typeof (cfg as any)?.backoffFactor === 'number') this.backoffFactor = (cfg as any).backoffFactor
42
+ if (typeof (cfg as any)?.jitter === 'boolean') this.jitter = (cfg as any).jitter
43
+ if (typeof (cfg as any)?.perDeviceCooldownMs === 'number') this.perDeviceCooldownMs = (cfg as any).perDeviceCooldownMs
44
+ if (typeof (cfg as any)?.writeDebounceMs === 'number') this.writeDebounceMs = (cfg as any).writeDebounceMs
45
+ }
46
+
47
+ // pending writes coalescing: deviceId -> { timer, body, resolvers }
48
+ private pendingWrites: Map<string, { timer: any; body: any; resolvers: Array<{ resolve: (v:any)=>void; reject: (e:any)=>void }>; }> = new Map()
49
+
50
+ async init(): Promise<void> {
51
+ // Try to dynamically import the new node-switchbot package. If it exposes
52
+ // a hybrid client we will use it. Otherwise the consumer can implement
53
+ // OpenAPI fallback logic here.
54
+ try {
55
+ const mod = await import('node-switchbot')
56
+ // The new library may export a default or named client. Try common names.
57
+ const m: any = mod as any
58
+ this.client = m?.default ?? m?.SwitchBot ?? m
59
+ if (typeof this.client === 'function') {
60
+ // some builds export a constructor
61
+ this.client = new this.client({ token: this.cfg.openApiToken })
62
+ }
63
+ } catch (e) {
64
+ // If import fails, leave client null and rely on OpenAPI code paths later.
65
+ this.logger?.warn?.('node-switchbot import failed; falling back to OpenAPI when token available')
66
+ this.client = null
67
+ }
68
+ }
69
+
70
+ private async fetchWithTimeoutAndRetry(url: string, opts: any = {}, timeoutMs?: number, retries?: number, deviceId?: string) {
71
+ const to = typeof timeoutMs === 'number' ? timeoutMs : this.requestTimeout
72
+ const max = typeof retries === 'number' ? retries : this.maxRetries
73
+
74
+ // Check per-device cooldown
75
+ if (deviceId) {
76
+ const until = this.perDeviceCooldownUntil.get(deviceId) ?? 0
77
+ if (Date.now() < until) {
78
+ const ms = until - Date.now()
79
+ this.logger?.warn?.('device in cooldown, aborting fetch', { deviceId, cooldownMs: ms })
80
+ throw new Error(`device ${deviceId} in cooldown for ${ms}ms`)
81
+ }
82
+ }
83
+
84
+ let attempt = 0
85
+ while (true) {
86
+ attempt += 1
87
+ // AbortController-based timeout
88
+ const controller = new AbortController()
89
+ const timer = setTimeout(() => controller.abort(), to)
90
+ try {
91
+ this.logger?.debug?.('fetch', { url, attempt, deviceId })
92
+ const fetchOpts = Object.assign({}, opts)
93
+ try {
94
+ Object.defineProperty(fetchOpts, 'signal', { value: controller.signal, enumerable: false, configurable: true })
95
+ } catch (_e) {
96
+ // ignore environments where defineProperty may fail
97
+ }
98
+ const resp = await fetch(url, fetchOpts)
99
+ clearTimeout(timer)
100
+
101
+ // helper to safely read response body when available
102
+ const safeReadBody = async (r: any) => {
103
+ try {
104
+ if (!r) return ''
105
+ if (typeof r.text === 'function') return await r.text()
106
+ if (typeof r.json === 'function') {
107
+ const j = await r.json().catch(() => null)
108
+ return j ? JSON.stringify(j) : ''
109
+ }
110
+ return String(r)
111
+ } catch (_e) {
112
+ return ''
113
+ }
114
+ }
115
+
116
+ // Some tests/mocks provide response-like objects without numeric `status`.
117
+ // In those cases attempt to parse the body and return a Response-like
118
+ // object so callers (resp.json()) continue to work instead of forcing
119
+ // a retry path.
120
+ if (typeof (resp as any).status !== 'number') {
121
+ const bodyStr = await safeReadBody(resp)
122
+ try {
123
+ const parsed = bodyStr ? JSON.parse(bodyStr) : {}
124
+ if (deviceId) this.perDeviceRetries.set(deviceId, 0)
125
+ return { ok: true, status: 200, json: async () => parsed }
126
+ } catch (_e) {
127
+ if (deviceId) this.perDeviceRetries.set(deviceId, 0)
128
+ return { ok: true, status: 200, json: async () => ({ body: bodyStr }) }
129
+ }
130
+ }
131
+
132
+ // classify response
133
+ if (resp.ok) {
134
+ if (deviceId) this.perDeviceRetries.set(deviceId, 0)
135
+ return resp
136
+ }
137
+
138
+ // Do not retry on client errors (4xx), except 429 (rate limit)
139
+ if (resp.status >= 400 && resp.status < 500 && resp.status !== 429) {
140
+ const body = await safeReadBody(resp)
141
+ this.logger?.error?.('fetch non-retriable response', { url, status: resp.status, body })
142
+ const err = new Error(`HTTP ${resp.status}`)
143
+ ;(err as any).status = resp.status
144
+ throw err
145
+ }
146
+
147
+ // server error / rate limit: treat as retriable
148
+ const body = await safeReadBody(resp)
149
+ this.logger?.warn?.('fetch retriable response', { url, status: resp.status, body })
150
+ // throw to enter retry/catch logic below and apply backoff
151
+ throw new Error(`retriable response: ${resp.status || 'unknown'}`)
152
+ } catch (err: any) {
153
+ clearTimeout(timer)
154
+ const isAbort = err?.name === 'AbortError' || err?.message === 'The user aborted a request.' || err?.message === 'timeout'
155
+ const reason = isAbort ? 'timeout' : err?.message ?? String(err)
156
+ this.logger?.warn?.('fetch failed', { url, attempt, deviceId, reason })
157
+
158
+ // per-device retry guard
159
+ if (deviceId) {
160
+ const prev = this.perDeviceRetries.get(deviceId) ?? 0
161
+ const next = prev + 1
162
+ this.perDeviceRetries.set(deviceId, next)
163
+ if (next > this.perDeviceMaxRetries) {
164
+ this.logger?.error?.('per-device retry limit exceeded, entering cooldown', { deviceId, attempts: next })
165
+ this.perDeviceCooldownUntil.set(deviceId, Date.now() + this.perDeviceCooldownMs)
166
+ throw new Error(`per-device retry limit exceeded for ${deviceId}`)
167
+ }
168
+ }
169
+
170
+ if (attempt > max) throw err
171
+
172
+ // exponential backoff with optional jitter
173
+ let backoff = Math.min(this.baseBackoffMs * Math.pow(this.backoffFactor, attempt - 1), this.maxBackoffMs)
174
+ if (this.jitter) {
175
+ const jitterVal = Math.floor(Math.random() * backoff)
176
+ backoff = Math.floor(backoff / 2) + jitterVal
177
+ }
178
+ this.logger?.debug?.('backoff before retry', { url, attempt, backoff })
179
+ await new Promise((r) => setTimeout(r, backoff))
180
+ }
181
+ }
182
+ }
183
+
184
+ async getDevice(id: string): Promise<any> {
185
+ if (this.client && typeof this.client.getDevice === 'function') {
186
+ return this.client.getDevice(id)
187
+ }
188
+ // Fallback: call OpenAPI via HTTP using token if available.
189
+ if (this.cfg.openApiToken) {
190
+ const url = `${this.baseUrl}/devices/${id}`
191
+ const opts = { headers: { Authorization: this.cfg.openApiToken } }
192
+ const resp = await this.fetchWithTimeoutAndRetry(url, opts, undefined, undefined, id)
193
+ return resp.json()
194
+ }
195
+ throw new Error('No SwitchBot client available')
196
+ }
197
+
198
+ async setDeviceState(id: string, body: any): Promise<any> {
199
+ // If debounce is disabled do a direct write path
200
+ if (!this.writeDebounceMs || this.writeDebounceMs <= 0) {
201
+ return this._doSetDeviceState(id, body)
202
+ }
203
+
204
+ // Coalesce writes per-device within debounce window. Last write wins.
205
+ return new Promise((resolve, reject) => {
206
+ const existing = this.pendingWrites.get(id)
207
+ if (existing) {
208
+ existing.body = body
209
+ existing.resolvers.push({ resolve, reject })
210
+ // timer already scheduled
211
+ return
212
+ }
213
+
214
+ const resolvers: Array<{ resolve: (v:any)=>void; reject: (e:any)=>void }> = [{ resolve, reject }]
215
+ const timer = setTimeout(async () => {
216
+ const entry = this.pendingWrites.get(id)
217
+ if (!entry) return
218
+ this.pendingWrites.delete(id)
219
+ try {
220
+ const out = await this._doSetDeviceState(id, entry.body)
221
+ for (const r of entry.resolvers) r.resolve(out)
222
+ } catch (e) {
223
+ for (const r of entry.resolvers) r.reject(e)
224
+ }
225
+ }, this.writeDebounceMs)
226
+
227
+ this.pendingWrites.set(id, { timer, body, resolvers })
228
+ })
229
+ }
230
+
231
+ private async _doSetDeviceState(id: string, body: any): Promise<any> {
232
+ // Prefer client API
233
+ if (this.client && typeof this.client.setDeviceState === 'function') {
234
+ return this.client.setDeviceState(id, body)
235
+ }
236
+
237
+ // Try generic command methods
238
+ if (this.client && typeof this.client.sendCommand === 'function') {
239
+ return this.client.sendCommand(id, body)
240
+ }
241
+
242
+ // OpenAPI fallback
243
+ if (this.cfg.openApiToken) {
244
+ const url = `${this.baseUrl}/devices/${id}/commands`
245
+ const opts = {
246
+ method: 'POST',
247
+ headers: {
248
+ Authorization: this.cfg.openApiToken,
249
+ 'Content-Type': 'application/json',
250
+ },
251
+ body: JSON.stringify(body),
252
+ }
253
+ const resp = await this.fetchWithTimeoutAndRetry(url, opts, undefined, undefined, id)
254
+ return resp.json()
255
+ }
256
+
257
+ throw new Error('No SwitchBot client available for setDeviceState')
258
+ }
259
+
260
+ async destroy(): Promise<void> {
261
+ if (this.client && typeof this.client.destroy === 'function') {
262
+ await this.client.destroy()
263
+ }
264
+ this.client = null
265
+ }
266
+ }