@smarthome.exchange/integrations 1.0.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (529) hide show
  1. package/changelog.md +84 -0
  2. package/dist_ts/00_commitinfo_data.js +1 -1
  3. package/dist_ts/core/classes.configstore.d.ts +2 -0
  4. package/dist_ts/core/classes.configstore.js +84 -27
  5. package/dist_ts/core/classes.nativehomeadmission.d.ts +19 -0
  6. package/dist_ts/core/classes.nativehomeadmission.js +84 -0
  7. package/dist_ts/core/classes.nativeintegrationowner.d.ts +81 -0
  8. package/dist_ts/core/classes.nativeintegrationowner.js +273 -0
  9. package/dist_ts/core/classes.runtimemanager.d.ts +2 -0
  10. package/dist_ts/core/classes.runtimemanager.js +11 -3
  11. package/dist_ts/core/index.d.ts +2 -0
  12. package/dist_ts/core/index.js +3 -1
  13. package/dist_ts/core/types.d.ts +16 -0
  14. package/dist_ts/integrations/braviatv/braviatv.classes.client.d.ts +23 -72
  15. package/dist_ts/integrations/braviatv/braviatv.classes.client.js +265 -625
  16. package/dist_ts/integrations/braviatv/braviatv.classes.configflow.d.ts +7 -7
  17. package/dist_ts/integrations/braviatv/braviatv.classes.configflow.js +51 -68
  18. package/dist_ts/integrations/braviatv/braviatv.classes.integration.d.ts +8 -11
  19. package/dist_ts/integrations/braviatv/braviatv.classes.integration.js +186 -135
  20. package/dist_ts/integrations/braviatv/braviatv.discovery.js +12 -11
  21. package/dist_ts/integrations/braviatv/braviatv.mapper.d.ts +6 -14
  22. package/dist_ts/integrations/braviatv/braviatv.mapper.js +37 -131
  23. package/dist_ts/integrations/braviatv/braviatv.types.d.ts +55 -133
  24. package/dist_ts/integrations/braviatv/braviatv.validation.d.ts +7 -0
  25. package/dist_ts/integrations/braviatv/braviatv.validation.js +72 -0
  26. package/dist_ts/integrations/broadlink/broadlink.actions.d.ts +2 -0
  27. package/dist_ts/integrations/broadlink/broadlink.actions.js +36 -0
  28. package/dist_ts/integrations/broadlink/broadlink.classes.client.d.ts +21 -19
  29. package/dist_ts/integrations/broadlink/broadlink.classes.client.js +185 -124
  30. package/dist_ts/integrations/broadlink/broadlink.classes.configflow.d.ts +5 -4
  31. package/dist_ts/integrations/broadlink/broadlink.classes.configflow.js +64 -83
  32. package/dist_ts/integrations/broadlink/broadlink.classes.integration.d.ts +16 -19
  33. package/dist_ts/integrations/broadlink/broadlink.classes.integration.js +114 -59
  34. package/dist_ts/integrations/broadlink/broadlink.mapper.d.ts +3 -2
  35. package/dist_ts/integrations/broadlink/broadlink.mapper.js +2 -1
  36. package/dist_ts/integrations/broadlink/broadlink.selected.mapper.d.ts +10 -0
  37. package/dist_ts/integrations/broadlink/broadlink.selected.mapper.js +41 -0
  38. package/dist_ts/integrations/broadlink/broadlink.types.d.ts +43 -7
  39. package/dist_ts/integrations/broadlink/broadlink.validation.d.ts +7 -0
  40. package/dist_ts/integrations/broadlink/broadlink.validation.js +63 -0
  41. package/dist_ts/integrations/daikin/daikin.classes.client.d.ts +10 -52
  42. package/dist_ts/integrations/daikin/daikin.classes.client.js +55 -614
  43. package/dist_ts/integrations/daikin/daikin.classes.configflow.d.ts +8 -12
  44. package/dist_ts/integrations/daikin/daikin.classes.configflow.js +77 -138
  45. package/dist_ts/integrations/daikin/daikin.classes.integration.d.ts +7 -24
  46. package/dist_ts/integrations/daikin/daikin.classes.integration.js +175 -67
  47. package/dist_ts/integrations/daikin/daikin.discovery.d.ts +11 -24
  48. package/dist_ts/integrations/daikin/daikin.discovery.js +98 -305
  49. package/dist_ts/integrations/daikin/daikin.mapper.d.ts +6 -7
  50. package/dist_ts/integrations/daikin/daikin.mapper.js +95 -155
  51. package/dist_ts/integrations/daikin/daikin.types.d.ts +24 -44
  52. package/dist_ts/integrations/daikin/daikin.types.js +1 -1
  53. package/dist_ts/integrations/daikin/daikin.validation.d.ts +5 -0
  54. package/dist_ts/integrations/daikin/daikin.validation.js +53 -0
  55. package/dist_ts/integrations/deconz/deconz.classes.client.d.ts +37 -29
  56. package/dist_ts/integrations/deconz/deconz.classes.client.js +521 -294
  57. package/dist_ts/integrations/deconz/deconz.classes.configflow.d.ts +6 -1
  58. package/dist_ts/integrations/deconz/deconz.classes.configflow.js +63 -33
  59. package/dist_ts/integrations/deconz/deconz.classes.integration.d.ts +4 -3
  60. package/dist_ts/integrations/deconz/deconz.classes.integration.js +85 -40
  61. package/dist_ts/integrations/deconz/deconz.mapper.d.ts +1 -0
  62. package/dist_ts/integrations/deconz/deconz.mapper.js +24 -6
  63. package/dist_ts/integrations/deconz/deconz.types.d.ts +43 -6
  64. package/dist_ts/integrations/deconz/deconz.validation.d.ts +7 -1
  65. package/dist_ts/integrations/deconz/deconz.validation.js +215 -4
  66. package/dist_ts/integrations/denonavr/denonavr.classes.client.d.ts +31 -40
  67. package/dist_ts/integrations/denonavr/denonavr.classes.client.js +149 -404
  68. package/dist_ts/integrations/denonavr/denonavr.classes.configflow.d.ts +7 -2
  69. package/dist_ts/integrations/denonavr/denonavr.classes.configflow.js +44 -36
  70. package/dist_ts/integrations/denonavr/denonavr.classes.integration.d.ts +6 -11
  71. package/dist_ts/integrations/denonavr/denonavr.classes.integration.js +192 -113
  72. package/dist_ts/integrations/denonavr/denonavr.discovery.d.ts +10 -18
  73. package/dist_ts/integrations/denonavr/denonavr.discovery.js +71 -193
  74. package/dist_ts/integrations/denonavr/denonavr.mapper.d.ts +5 -13
  75. package/dist_ts/integrations/denonavr/denonavr.mapper.js +35 -159
  76. package/dist_ts/integrations/denonavr/denonavr.types.d.ts +55 -90
  77. package/dist_ts/integrations/denonavr/denonavr.validation.d.ts +10 -0
  78. package/dist_ts/integrations/denonavr/denonavr.validation.js +86 -0
  79. package/dist_ts/integrations/esphome/esphome.classes.client.d.ts +19 -7
  80. package/dist_ts/integrations/esphome/esphome.classes.client.js +183 -89
  81. package/dist_ts/integrations/esphome/esphome.classes.configflow.d.ts +5 -2
  82. package/dist_ts/integrations/esphome/esphome.classes.configflow.js +43 -33
  83. package/dist_ts/integrations/esphome/esphome.classes.integration.d.ts +8 -6
  84. package/dist_ts/integrations/esphome/esphome.classes.integration.js +71 -43
  85. package/dist_ts/integrations/esphome/esphome.discovery.js +4 -12
  86. package/dist_ts/integrations/esphome/esphome.mapper.d.ts +2 -2
  87. package/dist_ts/integrations/esphome/esphome.mapper.js +6 -4
  88. package/dist_ts/integrations/esphome/esphome.types.d.ts +31 -6
  89. package/dist_ts/integrations/esphome/esphome.types.js +1 -1
  90. package/dist_ts/integrations/esphome/esphome.validation.d.ts +7 -0
  91. package/dist_ts/integrations/esphome/esphome.validation.js +66 -0
  92. package/dist_ts/integrations/homeassistant/homeassistant.classes.client.d.ts +32 -4
  93. package/dist_ts/integrations/homeassistant/homeassistant.classes.client.js +345 -116
  94. package/dist_ts/integrations/homeassistant/homeassistant.classes.integration.d.ts +8 -5
  95. package/dist_ts/integrations/homeassistant/homeassistant.classes.integration.js +34 -8
  96. package/dist_ts/integrations/homeassistant/homeassistant.classes.runtime.d.ts +7 -4
  97. package/dist_ts/integrations/homeassistant/homeassistant.classes.runtime.js +44 -56
  98. package/dist_ts/integrations/homeassistant/homeassistant.types.d.ts +12 -1
  99. package/dist_ts/integrations/hue/hue.classes.client.d.ts +6 -1
  100. package/dist_ts/integrations/hue/hue.classes.client.js +120 -45
  101. package/dist_ts/integrations/hue/hue.classes.configflow.js +16 -7
  102. package/dist_ts/integrations/hue/hue.classes.integration.d.ts +2 -0
  103. package/dist_ts/integrations/hue/hue.classes.integration.js +103 -30
  104. package/dist_ts/integrations/hue/hue.validation.d.ts +1 -0
  105. package/dist_ts/integrations/hue/hue.validation.js +14 -4
  106. package/dist_ts/integrations/kodi/kodi.classes.client.d.ts +11 -45
  107. package/dist_ts/integrations/kodi/kodi.classes.client.js +84 -310
  108. package/dist_ts/integrations/kodi/kodi.classes.configflow.d.ts +9 -8
  109. package/dist_ts/integrations/kodi/kodi.classes.configflow.js +53 -48
  110. package/dist_ts/integrations/kodi/kodi.classes.integration.d.ts +11 -11
  111. package/dist_ts/integrations/kodi/kodi.classes.integration.js +114 -171
  112. package/dist_ts/integrations/kodi/kodi.discovery.js +53 -29
  113. package/dist_ts/integrations/kodi/kodi.mapper.d.ts +7 -2
  114. package/dist_ts/integrations/kodi/kodi.mapper.js +48 -10
  115. package/dist_ts/integrations/kodi/kodi.types.d.ts +32 -28
  116. package/dist_ts/integrations/kodi/kodi.validation.d.ts +9 -0
  117. package/dist_ts/integrations/kodi/kodi.validation.js +62 -0
  118. package/dist_ts/integrations/modbus/modbus.classes.client.d.ts +15 -61
  119. package/dist_ts/integrations/modbus/modbus.classes.client.js +117 -776
  120. package/dist_ts/integrations/modbus/modbus.classes.configflow.d.ts +9 -5
  121. package/dist_ts/integrations/modbus/modbus.classes.configflow.js +70 -38
  122. package/dist_ts/integrations/modbus/modbus.classes.integration.d.ts +6 -17
  123. package/dist_ts/integrations/modbus/modbus.classes.integration.js +133 -57
  124. package/dist_ts/integrations/modbus/modbus.discovery.d.ts +5 -8
  125. package/dist_ts/integrations/modbus/modbus.discovery.js +38 -93
  126. package/dist_ts/integrations/modbus/modbus.mapper.d.ts +8 -32
  127. package/dist_ts/integrations/modbus/modbus.mapper.js +71 -431
  128. package/dist_ts/integrations/modbus/modbus.types.d.ts +82 -332
  129. package/dist_ts/integrations/modbus/modbus.validation.d.ts +10 -0
  130. package/dist_ts/integrations/modbus/modbus.validation.js +128 -0
  131. package/dist_ts/integrations/mqtt/mqtt.classes.client.d.ts +15 -2
  132. package/dist_ts/integrations/mqtt/mqtt.classes.client.js +173 -23
  133. package/dist_ts/integrations/mqtt/mqtt.classes.configflow.d.ts +5 -1
  134. package/dist_ts/integrations/mqtt/mqtt.classes.configflow.js +53 -33
  135. package/dist_ts/integrations/mqtt/mqtt.classes.integration.d.ts +4 -1
  136. package/dist_ts/integrations/mqtt/mqtt.classes.integration.js +127 -56
  137. package/dist_ts/integrations/mqtt/mqtt.classes.session.d.ts +13 -0
  138. package/dist_ts/integrations/mqtt/mqtt.classes.session.js +130 -0
  139. package/dist_ts/integrations/mqtt/mqtt.mapper.d.ts +3 -0
  140. package/dist_ts/integrations/mqtt/mqtt.mapper.js +44 -1
  141. package/dist_ts/integrations/mqtt/mqtt.types.d.ts +46 -0
  142. package/dist_ts/integrations/mqtt/mqtt.validation.d.ts +7 -0
  143. package/dist_ts/integrations/mqtt/mqtt.validation.js +180 -0
  144. package/dist_ts/integrations/nanoleaf/nanoleaf.classes.client.d.ts +12 -34
  145. package/dist_ts/integrations/nanoleaf/nanoleaf.classes.client.js +143 -231
  146. package/dist_ts/integrations/nanoleaf/nanoleaf.classes.configflow.d.ts +6 -1
  147. package/dist_ts/integrations/nanoleaf/nanoleaf.classes.configflow.js +105 -18
  148. package/dist_ts/integrations/nanoleaf/nanoleaf.classes.integration.d.ts +8 -8
  149. package/dist_ts/integrations/nanoleaf/nanoleaf.classes.integration.js +141 -155
  150. package/dist_ts/integrations/nanoleaf/nanoleaf.credentials.d.ts +9 -0
  151. package/dist_ts/integrations/nanoleaf/nanoleaf.credentials.js +35 -0
  152. package/dist_ts/integrations/nanoleaf/nanoleaf.mapper.d.ts +6 -18
  153. package/dist_ts/integrations/nanoleaf/nanoleaf.mapper.js +45 -220
  154. package/dist_ts/integrations/nanoleaf/nanoleaf.types.d.ts +33 -147
  155. package/dist_ts/integrations/nanoleaf/nanoleaf.validation.d.ts +6 -0
  156. package/dist_ts/integrations/nanoleaf/nanoleaf.validation.js +82 -0
  157. package/dist_ts/integrations/onkyo/onkyo.classes.client.d.ts +15 -20
  158. package/dist_ts/integrations/onkyo/onkyo.classes.client.js +161 -404
  159. package/dist_ts/integrations/onkyo/onkyo.classes.configflow.d.ts +9 -4
  160. package/dist_ts/integrations/onkyo/onkyo.classes.configflow.js +51 -6
  161. package/dist_ts/integrations/onkyo/onkyo.classes.integration.d.ts +22 -6
  162. package/dist_ts/integrations/onkyo/onkyo.classes.integration.js +144 -11
  163. package/dist_ts/integrations/onkyo/onkyo.discovery.d.ts +6 -1
  164. package/dist_ts/integrations/onkyo/onkyo.discovery.js +40 -4
  165. package/dist_ts/integrations/onkyo/onkyo.mapper.d.ts +7 -8
  166. package/dist_ts/integrations/onkyo/onkyo.mapper.js +45 -12
  167. package/dist_ts/integrations/onkyo/onkyo.types.d.ts +58 -8
  168. package/dist_ts/integrations/onkyo/onkyo.types.js +13 -102
  169. package/dist_ts/integrations/onkyo/onkyo.validation.d.ts +16 -0
  170. package/dist_ts/integrations/onkyo/onkyo.validation.js +77 -0
  171. package/dist_ts/integrations/panasonic_viera/panasonic_viera.classes.client.d.ts +25 -25
  172. package/dist_ts/integrations/panasonic_viera/panasonic_viera.classes.client.js +116 -360
  173. package/dist_ts/integrations/panasonic_viera/panasonic_viera.classes.configflow.d.ts +11 -3
  174. package/dist_ts/integrations/panasonic_viera/panasonic_viera.classes.configflow.js +76 -6
  175. package/dist_ts/integrations/panasonic_viera/panasonic_viera.classes.integration.d.ts +26 -4
  176. package/dist_ts/integrations/panasonic_viera/panasonic_viera.classes.integration.js +142 -9
  177. package/dist_ts/integrations/panasonic_viera/panasonic_viera.discovery.d.ts +2 -1
  178. package/dist_ts/integrations/panasonic_viera/panasonic_viera.discovery.js +31 -4
  179. package/dist_ts/integrations/panasonic_viera/panasonic_viera.mapper.d.ts +9 -9
  180. package/dist_ts/integrations/panasonic_viera/panasonic_viera.mapper.js +31 -149
  181. package/dist_ts/integrations/panasonic_viera/panasonic_viera.types.d.ts +51 -11
  182. package/dist_ts/integrations/panasonic_viera/panasonic_viera.types.js +22 -87
  183. package/dist_ts/integrations/panasonic_viera/panasonic_viera.validation.d.ts +6 -0
  184. package/dist_ts/integrations/panasonic_viera/panasonic_viera.validation.js +56 -0
  185. package/dist_ts/integrations/pioneer/pioneer.classes.client.d.ts +31 -16
  186. package/dist_ts/integrations/pioneer/pioneer.classes.client.js +167 -409
  187. package/dist_ts/integrations/pioneer/pioneer.classes.configflow.d.ts +10 -3
  188. package/dist_ts/integrations/pioneer/pioneer.classes.configflow.js +66 -6
  189. package/dist_ts/integrations/pioneer/pioneer.classes.integration.d.ts +13 -5
  190. package/dist_ts/integrations/pioneer/pioneer.classes.integration.js +239 -11
  191. package/dist_ts/integrations/pioneer/pioneer.discovery.d.ts +14 -1
  192. package/dist_ts/integrations/pioneer/pioneer.discovery.js +51 -4
  193. package/dist_ts/integrations/pioneer/pioneer.mapper.d.ts +14 -8
  194. package/dist_ts/integrations/pioneer/pioneer.mapper.js +54 -12
  195. package/dist_ts/integrations/pioneer/pioneer.types.d.ts +79 -12
  196. package/dist_ts/integrations/pioneer/pioneer.types.js +12 -76
  197. package/dist_ts/integrations/pioneer/pioneer.validation.d.ts +10 -0
  198. package/dist_ts/integrations/pioneer/pioneer.validation.js +85 -0
  199. package/dist_ts/integrations/samsungtv/samsungtv.classes.client.d.ts +4 -2
  200. package/dist_ts/integrations/samsungtv/samsungtv.classes.client.js +41 -16
  201. package/dist_ts/integrations/samsungtv/samsungtv.classes.configflow.d.ts +5 -0
  202. package/dist_ts/integrations/samsungtv/samsungtv.classes.configflow.js +20 -7
  203. package/dist_ts/integrations/samsungtv/samsungtv.classes.integration.d.ts +1 -0
  204. package/dist_ts/integrations/samsungtv/samsungtv.classes.integration.js +53 -50
  205. package/dist_ts/integrations/samsungtv/samsungtv.types.d.ts +4 -1
  206. package/dist_ts/integrations/shelly/shelly.classes.client.d.ts +26 -30
  207. package/dist_ts/integrations/shelly/shelly.classes.client.js +504 -276
  208. package/dist_ts/integrations/shelly/shelly.classes.configflow.d.ts +8 -3
  209. package/dist_ts/integrations/shelly/shelly.classes.configflow.js +43 -38
  210. package/dist_ts/integrations/shelly/shelly.classes.integration.d.ts +6 -6
  211. package/dist_ts/integrations/shelly/shelly.classes.integration.js +103 -101
  212. package/dist_ts/integrations/shelly/shelly.classes.subscription.d.ts +4 -0
  213. package/dist_ts/integrations/shelly/shelly.classes.subscription.js +24 -2
  214. package/dist_ts/integrations/shelly/shelly.mapper.d.ts +1 -2
  215. package/dist_ts/integrations/shelly/shelly.mapper.js +21 -20
  216. package/dist_ts/integrations/shelly/shelly.rpc.js +4 -1
  217. package/dist_ts/integrations/shelly/shelly.types.d.ts +42 -2
  218. package/dist_ts/integrations/shelly/shelly.types.js +11 -2
  219. package/dist_ts/integrations/shelly/shelly.validation.d.ts +7 -0
  220. package/dist_ts/integrations/shelly/shelly.validation.js +79 -0
  221. package/dist_ts/integrations/sonos/sonos.classes.client.d.ts +79 -22
  222. package/dist_ts/integrations/sonos/sonos.classes.client.js +427 -139
  223. package/dist_ts/integrations/sonos/sonos.classes.configflow.d.ts +9 -2
  224. package/dist_ts/integrations/sonos/sonos.classes.configflow.js +26 -28
  225. package/dist_ts/integrations/sonos/sonos.classes.integration.d.ts +7 -6
  226. package/dist_ts/integrations/sonos/sonos.classes.integration.js +289 -224
  227. package/dist_ts/integrations/sonos/sonos.config.d.ts +6 -1
  228. package/dist_ts/integrations/sonos/sonos.config.js +23 -2
  229. package/dist_ts/integrations/sonos/sonos.mapper.d.ts +1 -1
  230. package/dist_ts/integrations/sonos/sonos.mapper.js +14 -9
  231. package/dist_ts/integrations/sonos/sonos.matchers.js +3 -3
  232. package/dist_ts/integrations/sonos/sonos.types.d.ts +26 -1
  233. package/dist_ts/integrations/soundtouch/soundtouch.classes.client.d.ts +13 -36
  234. package/dist_ts/integrations/soundtouch/soundtouch.classes.client.js +179 -502
  235. package/dist_ts/integrations/soundtouch/soundtouch.classes.configflow.d.ts +6 -1
  236. package/dist_ts/integrations/soundtouch/soundtouch.classes.configflow.js +50 -40
  237. package/dist_ts/integrations/soundtouch/soundtouch.classes.integration.d.ts +14 -15
  238. package/dist_ts/integrations/soundtouch/soundtouch.classes.integration.js +108 -128
  239. package/dist_ts/integrations/soundtouch/soundtouch.discovery.d.ts +2 -20
  240. package/dist_ts/integrations/soundtouch/soundtouch.discovery.js +23 -113
  241. package/dist_ts/integrations/soundtouch/soundtouch.mapper.d.ts +3 -12
  242. package/dist_ts/integrations/soundtouch/soundtouch.mapper.js +35 -189
  243. package/dist_ts/integrations/soundtouch/soundtouch.types.d.ts +57 -142
  244. package/dist_ts/integrations/soundtouch/soundtouch.types.js +18 -3
  245. package/dist_ts/integrations/soundtouch/soundtouch.validation.d.ts +22 -0
  246. package/dist_ts/integrations/soundtouch/soundtouch.validation.js +65 -0
  247. package/dist_ts/integrations/tasmota/tasmota.classes.integration.d.ts +5 -0
  248. package/dist_ts/integrations/tasmota/tasmota.classes.integration.js +23 -7
  249. package/dist_ts/integrations/tasmota/tasmota.classes.runtime.d.ts +19 -5
  250. package/dist_ts/integrations/tasmota/tasmota.classes.runtime.js +115 -41
  251. package/dist_ts/integrations/tasmota/tasmota.config.js +23 -1
  252. package/dist_ts/integrations/tasmota/tasmota.credentials.d.ts +11 -0
  253. package/dist_ts/integrations/tasmota/tasmota.credentials.js +97 -0
  254. package/dist_ts/integrations/tasmota/tasmota.discovery.d.ts +7 -1
  255. package/dist_ts/integrations/tasmota/tasmota.discovery.js +108 -30
  256. package/dist_ts/integrations/tasmota/tasmota.mapper.d.ts +2 -2
  257. package/dist_ts/integrations/tasmota/tasmota.mapper.js +7 -7
  258. package/dist_ts/integrations/tasmota/tasmota.types.d.ts +41 -2
  259. package/dist_ts/integrations/tuya/tuya.classes.integration.d.ts +4 -1
  260. package/dist_ts/integrations/tuya/tuya.classes.integration.js +79 -110
  261. package/dist_ts/integrations/tuya/tuya.classes.runtime.d.ts +5 -2
  262. package/dist_ts/integrations/tuya/tuya.classes.runtime.js +73 -26
  263. package/dist_ts/integrations/tuya/tuya.mapper.js +2 -2
  264. package/dist_ts/integrations/tuya/tuya.types.d.ts +3 -0
  265. package/dist_ts/integrations/tuya/tuya.validation.d.ts +2 -2
  266. package/dist_ts/integrations/tuya/tuya.validation.js +6 -11
  267. package/dist_ts/integrations/webostv/webostv.classes.client.d.ts +6 -5
  268. package/dist_ts/integrations/webostv/webostv.classes.client.js +147 -76
  269. package/dist_ts/integrations/webostv/webostv.classes.configflow.d.ts +7 -2
  270. package/dist_ts/integrations/webostv/webostv.classes.configflow.js +36 -20
  271. package/dist_ts/integrations/webostv/webostv.classes.integration.d.ts +4 -4
  272. package/dist_ts/integrations/webostv/webostv.classes.integration.js +46 -54
  273. package/dist_ts/integrations/webostv/webostv.mapper.js +5 -5
  274. package/dist_ts/integrations/webostv/webostv.types.d.ts +16 -3
  275. package/dist_ts/integrations/webostv/webostv.types.js +1 -1
  276. package/dist_ts/integrations/webostv/webostv.validation.d.ts +3 -1
  277. package/dist_ts/integrations/webostv/webostv.validation.js +23 -1
  278. package/dist_ts/integrations/wiz/index.d.ts +1 -0
  279. package/dist_ts/integrations/wiz/index.js +2 -1
  280. package/dist_ts/integrations/wiz/wiz.classes.client.d.ts +14 -28
  281. package/dist_ts/integrations/wiz/wiz.classes.client.js +93 -229
  282. package/dist_ts/integrations/wiz/wiz.classes.configflow.d.ts +6 -4
  283. package/dist_ts/integrations/wiz/wiz.classes.configflow.js +38 -67
  284. package/dist_ts/integrations/wiz/wiz.classes.integration.d.ts +10 -21
  285. package/dist_ts/integrations/wiz/wiz.classes.integration.js +204 -44
  286. package/dist_ts/integrations/wiz/wiz.discovery.d.ts +10 -31
  287. package/dist_ts/integrations/wiz/wiz.discovery.js +48 -249
  288. package/dist_ts/integrations/wiz/wiz.mapper.d.ts +7 -51
  289. package/dist_ts/integrations/wiz/wiz.mapper.js +82 -668
  290. package/dist_ts/integrations/wiz/wiz.types.d.ts +34 -208
  291. package/dist_ts/integrations/wiz/wiz.validation.d.ts +8 -0
  292. package/dist_ts/integrations/wiz/wiz.validation.js +72 -0
  293. package/dist_ts/integrations/yamaha/index.d.ts +1 -0
  294. package/dist_ts/integrations/yamaha/index.js +2 -1
  295. package/dist_ts/integrations/yamaha/yamaha.classes.client.d.ts +30 -4
  296. package/dist_ts/integrations/yamaha/yamaha.classes.client.js +162 -6
  297. package/dist_ts/integrations/yamaha/yamaha.classes.configflow.d.ts +10 -3
  298. package/dist_ts/integrations/yamaha/yamaha.classes.configflow.js +106 -6
  299. package/dist_ts/integrations/yamaha/yamaha.classes.integration.d.ts +22 -4
  300. package/dist_ts/integrations/yamaha/yamaha.classes.integration.js +243 -8
  301. package/dist_ts/integrations/yamaha/yamaha.discovery.d.ts +13 -1
  302. package/dist_ts/integrations/yamaha/yamaha.discovery.js +57 -4
  303. package/dist_ts/integrations/yamaha/yamaha.mapper.d.ts +16 -8
  304. package/dist_ts/integrations/yamaha/yamaha.mapper.js +58 -12
  305. package/dist_ts/integrations/yamaha/yamaha.types.d.ts +73 -6
  306. package/dist_ts/integrations/yamaha/yamaha.types.js +8 -94
  307. package/dist_ts/integrations/yamaha/yamaha.validation.d.ts +12 -0
  308. package/dist_ts/integrations/yamaha/yamaha.validation.js +89 -0
  309. package/dist_ts/integrations/zigbee2mqtt/zigbee2mqtt.classes.configflow.d.ts +6 -1
  310. package/dist_ts/integrations/zigbee2mqtt/zigbee2mqtt.classes.configflow.js +18 -8
  311. package/dist_ts/integrations/zigbee2mqtt/zigbee2mqtt.classes.integration.d.ts +4 -1
  312. package/dist_ts/integrations/zigbee2mqtt/zigbee2mqtt.classes.integration.js +54 -6
  313. package/dist_ts/integrations/zigbee2mqtt/zigbee2mqtt.classes.runtime.d.ts +12 -6
  314. package/dist_ts/integrations/zigbee2mqtt/zigbee2mqtt.classes.runtime.js +73 -59
  315. package/dist_ts/integrations/zigbee2mqtt/zigbee2mqtt.mapper.d.ts +3 -2
  316. package/dist_ts/integrations/zigbee2mqtt/zigbee2mqtt.mapper.js +17 -12
  317. package/dist_ts/integrations/zigbee2mqtt/zigbee2mqtt.types.d.ts +31 -2
  318. package/dist_ts/integrations/zigbee2mqtt/zigbee2mqtt.validation.d.ts +9 -1
  319. package/dist_ts/integrations/zigbee2mqtt/zigbee2mqtt.validation.js +57 -7
  320. package/dist_ts/integrations/zwave_js/zwave_js.classes.client.d.ts +10 -4
  321. package/dist_ts/integrations/zwave_js/zwave_js.classes.client.js +167 -31
  322. package/dist_ts/integrations/zwave_js/zwave_js.classes.configflow.d.ts +6 -1
  323. package/dist_ts/integrations/zwave_js/zwave_js.classes.configflow.js +57 -35
  324. package/dist_ts/integrations/zwave_js/zwave_js.classes.integration.d.ts +3 -1
  325. package/dist_ts/integrations/zwave_js/zwave_js.classes.integration.js +59 -37
  326. package/dist_ts/integrations/zwave_js/zwave_js.discovery.js +3 -3
  327. package/dist_ts/integrations/zwave_js/zwave_js.mapper.js +41 -24
  328. package/dist_ts/integrations/zwave_js/zwave_js.types.d.ts +25 -3
  329. package/dist_ts/integrations/zwave_js/zwave_js.validation.d.ts +6 -2
  330. package/dist_ts/integrations/zwave_js/zwave_js.validation.js +52 -17
  331. package/dist_ts/plugins.d.ts +2 -1
  332. package/dist_ts/plugins.js +3 -2
  333. package/package.json +9 -9
  334. package/readme.md +539 -8
  335. package/ts/00_commitinfo_data.ts +1 -1
  336. package/ts/core/classes.configstore.ts +84 -27
  337. package/ts/core/classes.nativehomeadmission.ts +96 -0
  338. package/ts/core/classes.nativeintegrationowner.ts +302 -0
  339. package/ts/core/classes.runtimemanager.ts +11 -2
  340. package/ts/core/index.ts +2 -0
  341. package/ts/core/types.ts +18 -0
  342. package/ts/integrations/braviatv/braviatv.classes.client.ts +245 -709
  343. package/ts/integrations/braviatv/braviatv.classes.configflow.ts +47 -76
  344. package/ts/integrations/braviatv/braviatv.classes.integration.ts +167 -147
  345. package/ts/integrations/braviatv/braviatv.discovery.ts +11 -10
  346. package/ts/integrations/braviatv/braviatv.mapper.ts +39 -142
  347. package/ts/integrations/braviatv/braviatv.types.ts +53 -173
  348. package/ts/integrations/braviatv/braviatv.validation.ts +68 -0
  349. package/ts/integrations/broadlink/broadlink.actions.ts +31 -0
  350. package/ts/integrations/broadlink/broadlink.classes.client.ts +170 -144
  351. package/ts/integrations/broadlink/broadlink.classes.configflow.ts +59 -89
  352. package/ts/integrations/broadlink/broadlink.classes.integration.ts +110 -64
  353. package/ts/integrations/broadlink/broadlink.mapper.ts +5 -4
  354. package/ts/integrations/broadlink/broadlink.selected.mapper.ts +46 -0
  355. package/ts/integrations/broadlink/broadlink.types.ts +48 -8
  356. package/ts/integrations/broadlink/broadlink.validation.ts +66 -0
  357. package/ts/integrations/daikin/daikin.classes.client.ts +52 -661
  358. package/ts/integrations/daikin/daikin.classes.configflow.ts +72 -152
  359. package/ts/integrations/daikin/daikin.classes.integration.ts +166 -71
  360. package/ts/integrations/daikin/daikin.discovery.ts +94 -346
  361. package/ts/integrations/daikin/daikin.mapper.ts +83 -166
  362. package/ts/integrations/daikin/daikin.types.ts +27 -48
  363. package/ts/integrations/daikin/daikin.validation.ts +51 -0
  364. package/ts/integrations/daikin/readme.md +83 -0
  365. package/ts/integrations/deconz/deconz.classes.client.ts +348 -252
  366. package/ts/integrations/deconz/deconz.classes.configflow.ts +57 -29
  367. package/ts/integrations/deconz/deconz.classes.integration.ts +69 -37
  368. package/ts/integrations/deconz/deconz.mapper.ts +22 -5
  369. package/ts/integrations/deconz/deconz.types.ts +49 -6
  370. package/ts/integrations/deconz/deconz.validation.ts +177 -4
  371. package/ts/integrations/deconz/readme.md +15 -1
  372. package/ts/integrations/denonavr/denonavr.classes.client.ts +132 -421
  373. package/ts/integrations/denonavr/denonavr.classes.configflow.ts +44 -37
  374. package/ts/integrations/denonavr/denonavr.classes.integration.ts +171 -117
  375. package/ts/integrations/denonavr/denonavr.discovery.ts +67 -220
  376. package/ts/integrations/denonavr/denonavr.mapper.ts +36 -182
  377. package/ts/integrations/denonavr/denonavr.types.ts +48 -111
  378. package/ts/integrations/denonavr/denonavr.validation.ts +87 -0
  379. package/ts/integrations/esphome/esphome.classes.client.ts +179 -94
  380. package/ts/integrations/esphome/esphome.classes.configflow.ts +40 -33
  381. package/ts/integrations/esphome/esphome.classes.integration.ts +63 -36
  382. package/ts/integrations/esphome/esphome.discovery.ts +3 -12
  383. package/ts/integrations/esphome/esphome.mapper.ts +9 -7
  384. package/ts/integrations/esphome/esphome.types.ts +35 -6
  385. package/ts/integrations/esphome/esphome.validation.ts +66 -0
  386. package/ts/integrations/esphome/readme.md +20 -6
  387. package/ts/integrations/homeassistant/homeassistant.classes.client.ts +353 -125
  388. package/ts/integrations/homeassistant/homeassistant.classes.integration.ts +35 -18
  389. package/ts/integrations/homeassistant/homeassistant.classes.runtime.ts +50 -63
  390. package/ts/integrations/homeassistant/homeassistant.types.ts +17 -1
  391. package/ts/integrations/homeassistant/readme.md +22 -6
  392. package/ts/integrations/hue/hue.classes.client.ts +110 -41
  393. package/ts/integrations/hue/hue.classes.configflow.ts +12 -6
  394. package/ts/integrations/hue/hue.classes.integration.ts +92 -26
  395. package/ts/integrations/hue/hue.validation.ts +13 -3
  396. package/ts/integrations/hue/readme.md +3 -3
  397. package/ts/integrations/kodi/kodi.classes.client.ts +72 -352
  398. package/ts/integrations/kodi/kodi.classes.configflow.ts +52 -55
  399. package/ts/integrations/kodi/kodi.classes.integration.ts +97 -178
  400. package/ts/integrations/kodi/kodi.discovery.ts +49 -28
  401. package/ts/integrations/kodi/kodi.mapper.ts +52 -10
  402. package/ts/integrations/kodi/kodi.types.ts +33 -58
  403. package/ts/integrations/kodi/kodi.validation.ts +60 -0
  404. package/ts/integrations/modbus/modbus.classes.client.ts +100 -842
  405. package/ts/integrations/modbus/modbus.classes.configflow.ts +70 -41
  406. package/ts/integrations/modbus/modbus.classes.integration.ts +115 -60
  407. package/ts/integrations/modbus/modbus.discovery.ts +38 -106
  408. package/ts/integrations/modbus/modbus.mapper.ts +64 -467
  409. package/ts/integrations/modbus/modbus.types.ts +64 -381
  410. package/ts/integrations/modbus/modbus.validation.ts +119 -0
  411. package/ts/integrations/mqtt/mqtt.classes.client.ts +136 -19
  412. package/ts/integrations/mqtt/mqtt.classes.configflow.ts +45 -32
  413. package/ts/integrations/mqtt/mqtt.classes.integration.ts +99 -38
  414. package/ts/integrations/mqtt/mqtt.classes.session.ts +118 -0
  415. package/ts/integrations/mqtt/mqtt.mapper.ts +43 -1
  416. package/ts/integrations/mqtt/mqtt.types.ts +52 -0
  417. package/ts/integrations/mqtt/mqtt.validation.ts +157 -0
  418. package/ts/integrations/mqtt/readme.md +12 -3
  419. package/ts/integrations/nanoleaf/nanoleaf.classes.client.ts +115 -249
  420. package/ts/integrations/nanoleaf/nanoleaf.classes.configflow.ts +90 -19
  421. package/ts/integrations/nanoleaf/nanoleaf.classes.integration.ts +130 -181
  422. package/ts/integrations/nanoleaf/nanoleaf.credentials.ts +39 -0
  423. package/ts/integrations/nanoleaf/nanoleaf.mapper.ts +47 -260
  424. package/ts/integrations/nanoleaf/nanoleaf.types.ts +29 -147
  425. package/ts/integrations/nanoleaf/nanoleaf.validation.ts +77 -0
  426. package/ts/integrations/onkyo/onkyo.classes.client.ts +148 -457
  427. package/ts/integrations/onkyo/onkyo.classes.configflow.ts +52 -6
  428. package/ts/integrations/onkyo/onkyo.classes.integration.ts +121 -12
  429. package/ts/integrations/onkyo/onkyo.discovery.ts +41 -3
  430. package/ts/integrations/onkyo/onkyo.mapper.ts +46 -19
  431. package/ts/integrations/onkyo/onkyo.types.ts +55 -110
  432. package/ts/integrations/onkyo/onkyo.validation.ts +85 -0
  433. package/ts/integrations/onkyo/readme.md +126 -0
  434. package/ts/integrations/panasonic_viera/panasonic_viera.classes.client.ts +101 -398
  435. package/ts/integrations/panasonic_viera/panasonic_viera.classes.configflow.ts +69 -5
  436. package/ts/integrations/panasonic_viera/panasonic_viera.classes.integration.ts +141 -9
  437. package/ts/integrations/panasonic_viera/panasonic_viera.discovery.ts +32 -3
  438. package/ts/integrations/panasonic_viera/panasonic_viera.mapper.ts +34 -161
  439. package/ts/integrations/panasonic_viera/panasonic_viera.types.ts +52 -96
  440. package/ts/integrations/panasonic_viera/panasonic_viera.validation.ts +56 -0
  441. package/ts/integrations/pioneer/pioneer.classes.client.ts +132 -428
  442. package/ts/integrations/pioneer/pioneer.classes.configflow.ts +67 -5
  443. package/ts/integrations/pioneer/pioneer.classes.integration.ts +225 -11
  444. package/ts/integrations/pioneer/pioneer.discovery.ts +45 -3
  445. package/ts/integrations/pioneer/pioneer.mapper.ts +57 -13
  446. package/ts/integrations/pioneer/pioneer.types.ts +87 -85
  447. package/ts/integrations/pioneer/pioneer.validation.ts +84 -0
  448. package/ts/integrations/samsungtv/readme.md +11 -5
  449. package/ts/integrations/samsungtv/samsungtv.classes.client.ts +40 -15
  450. package/ts/integrations/samsungtv/samsungtv.classes.configflow.ts +21 -6
  451. package/ts/integrations/samsungtv/samsungtv.classes.integration.ts +53 -38
  452. package/ts/integrations/samsungtv/samsungtv.types.ts +4 -1
  453. package/ts/integrations/shelly/readme.md +22 -7
  454. package/ts/integrations/shelly/shelly.classes.client.ts +386 -269
  455. package/ts/integrations/shelly/shelly.classes.configflow.ts +43 -38
  456. package/ts/integrations/shelly/shelly.classes.integration.ts +92 -111
  457. package/ts/integrations/shelly/shelly.classes.subscription.ts +24 -1
  458. package/ts/integrations/shelly/shelly.mapper.ts +19 -20
  459. package/ts/integrations/shelly/shelly.rpc.ts +2 -0
  460. package/ts/integrations/shelly/shelly.types.ts +50 -2
  461. package/ts/integrations/shelly/shelly.validation.ts +76 -0
  462. package/ts/integrations/sonos/readme.md +117 -38
  463. package/ts/integrations/sonos/sonos.classes.client.ts +392 -123
  464. package/ts/integrations/sonos/sonos.classes.configflow.ts +25 -28
  465. package/ts/integrations/sonos/sonos.classes.integration.ts +211 -186
  466. package/ts/integrations/sonos/sonos.config.ts +24 -2
  467. package/ts/integrations/sonos/sonos.mapper.ts +13 -8
  468. package/ts/integrations/sonos/sonos.matchers.ts +2 -2
  469. package/ts/integrations/sonos/sonos.types.ts +30 -1
  470. package/ts/integrations/soundtouch/soundtouch.classes.client.ts +152 -571
  471. package/ts/integrations/soundtouch/soundtouch.classes.configflow.ts +47 -42
  472. package/ts/integrations/soundtouch/soundtouch.classes.integration.ts +95 -150
  473. package/ts/integrations/soundtouch/soundtouch.discovery.ts +21 -133
  474. package/ts/integrations/soundtouch/soundtouch.mapper.ts +36 -207
  475. package/ts/integrations/soundtouch/soundtouch.types.ts +50 -195
  476. package/ts/integrations/soundtouch/soundtouch.validation.ts +60 -0
  477. package/ts/integrations/tasmota/readme.md +16 -5
  478. package/ts/integrations/tasmota/tasmota.classes.integration.ts +24 -6
  479. package/ts/integrations/tasmota/tasmota.classes.runtime.ts +112 -43
  480. package/ts/integrations/tasmota/tasmota.config.ts +17 -0
  481. package/ts/integrations/tasmota/tasmota.credentials.ts +92 -0
  482. package/ts/integrations/tasmota/tasmota.discovery.ts +87 -24
  483. package/ts/integrations/tasmota/tasmota.mapper.ts +6 -6
  484. package/ts/integrations/tasmota/tasmota.types.ts +43 -2
  485. package/ts/integrations/tuya/readme.md +52 -10
  486. package/ts/integrations/tuya/tuya.classes.integration.ts +69 -98
  487. package/ts/integrations/tuya/tuya.classes.runtime.ts +70 -24
  488. package/ts/integrations/tuya/tuya.mapper.ts +1 -1
  489. package/ts/integrations/tuya/tuya.types.ts +4 -0
  490. package/ts/integrations/tuya/tuya.validation.ts +5 -8
  491. package/ts/integrations/webostv/readme.md +115 -22
  492. package/ts/integrations/webostv/webostv.classes.client.ts +123 -50
  493. package/ts/integrations/webostv/webostv.classes.configflow.ts +35 -15
  494. package/ts/integrations/webostv/webostv.classes.integration.ts +44 -37
  495. package/ts/integrations/webostv/webostv.mapper.ts +4 -4
  496. package/ts/integrations/webostv/webostv.types.ts +18 -3
  497. package/ts/integrations/webostv/webostv.validation.ts +22 -1
  498. package/ts/integrations/wiz/index.ts +1 -0
  499. package/ts/integrations/wiz/wiz.classes.client.ts +84 -254
  500. package/ts/integrations/wiz/wiz.classes.configflow.ts +39 -70
  501. package/ts/integrations/wiz/wiz.classes.integration.ts +189 -45
  502. package/ts/integrations/wiz/wiz.discovery.ts +48 -291
  503. package/ts/integrations/wiz/wiz.mapper.ts +81 -754
  504. package/ts/integrations/wiz/wiz.types.ts +24 -224
  505. package/ts/integrations/wiz/wiz.validation.ts +73 -0
  506. package/ts/integrations/yamaha/index.ts +1 -0
  507. package/ts/integrations/yamaha/yamaha.classes.client.ts +150 -6
  508. package/ts/integrations/yamaha/yamaha.classes.configflow.ts +100 -5
  509. package/ts/integrations/yamaha/yamaha.classes.integration.ts +236 -8
  510. package/ts/integrations/yamaha/yamaha.discovery.ts +52 -3
  511. package/ts/integrations/yamaha/yamaha.mapper.ts +65 -13
  512. package/ts/integrations/yamaha/yamaha.types.ts +77 -97
  513. package/ts/integrations/yamaha/yamaha.validation.ts +86 -0
  514. package/ts/integrations/zigbee2mqtt/readme.md +22 -27
  515. package/ts/integrations/zigbee2mqtt/zigbee2mqtt.classes.configflow.ts +16 -7
  516. package/ts/integrations/zigbee2mqtt/zigbee2mqtt.classes.integration.ts +53 -6
  517. package/ts/integrations/zigbee2mqtt/zigbee2mqtt.classes.runtime.ts +62 -49
  518. package/ts/integrations/zigbee2mqtt/zigbee2mqtt.mapper.ts +17 -11
  519. package/ts/integrations/zigbee2mqtt/zigbee2mqtt.types.ts +35 -2
  520. package/ts/integrations/zigbee2mqtt/zigbee2mqtt.validation.ts +53 -7
  521. package/ts/integrations/zwave_js/readme.md +42 -9
  522. package/ts/integrations/zwave_js/zwave_js.classes.client.ts +155 -31
  523. package/ts/integrations/zwave_js/zwave_js.classes.configflow.ts +55 -31
  524. package/ts/integrations/zwave_js/zwave_js.classes.integration.ts +57 -35
  525. package/ts/integrations/zwave_js/zwave_js.discovery.ts +2 -2
  526. package/ts/integrations/zwave_js/zwave_js.mapper.ts +37 -23
  527. package/ts/integrations/zwave_js/zwave_js.types.ts +26 -3
  528. package/ts/integrations/zwave_js/zwave_js.validation.ts +52 -18
  529. package/ts/plugins.ts +2 -1
@@ -1,168 +1,88 @@
1
- import * as plugins from '../../plugins.js';
2
1
  import type { IConfigFlow, IConfigFlowContext, IConfigFlowStep, IDiscoveryCandidate } from '../../core/types.js';
3
- import type { IDaikinConfig, IDaikinRawData, IDaikinSnapshot, IDaikinValueMap, TDaikinApiVariant } from './daikin.types.js';
4
- import { daikinDefaultHttpPort, daikinDefaultHttpsPort, daikinDefaultTimeoutMs, daikinSkyFiPort } from './daikin.types.js';
2
+ import { NativeIntegrationOwner, type NativeIntegrationScope } from '../../core/classes.nativeintegrationowner.js';
3
+ import { DaikinClient } from './daikin.classes.client.js';
4
+ import type { IDaikinIntegrationOptions, IDaikinNativeConfig } from './daikin.types.js';
5
+ import { daikinKeys, daikinObject, normalizeDaikinConfig } from './daikin.validation.js';
5
6
 
6
- export class DaikinConfigFlow implements IConfigFlow<IDaikinConfig> {
7
- public async start(candidateArg: IDiscoveryCandidate, contextArg: IConfigFlowContext): Promise<IConfigFlowStep<IDaikinConfig>> {
8
- void contextArg;
7
+ export class DaikinConfigFlow implements IConfigFlow<IDaikinNativeConfig> {
8
+ readonly #scope: NativeIntegrationScope;
9
+
10
+ constructor(optionsArg: IDaikinIntegrationOptions = {}, scopeArg?: NativeIntegrationScope) {
11
+ this.#scope = scopeArg ?? new NativeIntegrationOwner('daikin', optionsArg).createFlowScope();
12
+ }
13
+
14
+ public destroy(): Promise<void> { return this.#scope.close(); }
15
+ public retryCleanup(): Promise<void> { return this.#scope.retryCleanup(); }
16
+
17
+ public async start(candidateArg: IDiscoveryCandidate, contextArg: IConfigFlowContext): Promise<IConfigFlowStep<IDaikinNativeConfig>> {
18
+ const context = this.#scope.admit(contextArg);
19
+ const candidate = daikinObject(candidateArg, 'Daikin candidate');
20
+ const metadata = candidate.metadata === undefined ? {} : daikinObject(candidate.metadata, 'Daikin candidate metadata');
21
+ const host = typeof candidate.host === 'string' ? candidate.host : undefined;
22
+ const expectedMac = typeof candidate.macAddress === 'string' ? candidate.macAddress.replace(/:/g, '') : typeof metadata.expectedMac === 'string' ? metadata.expectedMac : undefined;
9
23
  return {
10
- kind: 'form',
11
- title: 'Configure Daikin AC',
12
- description: 'Configure a local Daikin endpoint, or use snapshot/manual data from the discovery candidate. Use either API key or SkyFi password, not both.',
24
+ kind: 'form', title: 'Connect selected Daikin BRP069',
25
+ description: 'Select a private IPv4 address and exact 12-digit adapter MAC for the host-selected home. Setup verifies basic, model and current control observations. BRP069 LAN HTTP is unauthenticated. No credentials are accepted.',
13
26
  fields: [
14
- { name: 'host', label: 'Host', type: 'text' },
15
- { name: 'port', label: 'Port', type: 'number' },
16
- { name: 'apiVariant', label: 'API variant', type: 'select', options: [
17
- { label: 'Auto / BRP069 local HTTP', value: 'auto' },
18
- { label: 'BRP069 local HTTP', value: 'brp069' },
19
- { label: 'BRP072C HTTPS with API key', value: 'brp072c' },
20
- { label: 'AirBase / skyfi path prefix', value: 'airbase' },
21
- { label: 'SkyFi password API', value: 'skyfi' },
22
- { label: 'BRP084 dsiot read-only', value: 'brp084' },
23
- ] },
24
- { name: 'ssl', label: 'Use HTTPS', type: 'boolean' },
25
- { name: 'verifySsl', label: 'Verify TLS certificate', type: 'boolean' },
26
- { name: 'apiKey', label: 'API key', type: 'password' },
27
- { name: 'uuid', label: 'Terminal UUID', type: 'text' },
28
- { name: 'password', label: 'SkyFi password', type: 'password' },
27
+ { name: 'host', label: 'Selected private IPv4', type: 'text', required: true },
28
+ { name: 'expectedMac', label: 'Exact adapter MAC (12 hex digits)', type: 'text', required: true },
29
+ { name: 'apiVariant', label: 'Controller family', type: 'select', required: true, options: [{ label: 'Selected BRP069', value: 'brp069' }] },
30
+ { name: 'allowPlaintext', label: 'Allow unauthenticated plaintext LAN HTTP', type: 'boolean', required: true },
31
+ { name: 'port', label: 'HTTP port (80)', type: 'number' },
29
32
  { name: 'name', label: 'Name', type: 'text' },
30
33
  ],
31
- submit: async (valuesArg) => this.submit(candidateArg, valuesArg),
34
+ submit: async (valuesArg) => {
35
+ let config: Readonly<IDaikinNativeConfig>;
36
+ try {
37
+ const values = daikinObject(valuesArg, 'Daikin configuration form');
38
+ daikinKeys(values, ['homeId', 'host', 'expectedMac', 'apiVariant', 'allowPlaintext', 'port', 'name']);
39
+ if (values.homeId !== undefined && values.homeId !== context.homeId) throw new TypeError('Daikin submitted home must match the independently selected host home.');
40
+ config = normalizeDaikinConfig({
41
+ homeId: context.homeId,
42
+ host: formText(values.host, host),
43
+ expectedMac: formText(values.expectedMac, expectedMac),
44
+ apiVariant: selectedVariant(values.apiVariant), allowPlaintext: selectedPlaintext(values.allowPlaintext), port: formPort(values.port, candidate.port),
45
+ name: values.name === undefined ? undefined : formText(values.name),
46
+ });
47
+ this.#scope.admit(context, config.homeId);
48
+ } catch (errorArg) {
49
+ return { kind: 'error', title: 'Daikin verification failed', error: errorArg instanceof Error ? errorArg.message : 'Daikin configuration is invalid.' };
50
+ }
51
+ return this.#scope.run(context, config.homeId, async (leaseArg): Promise<IConfigFlowStep<IDaikinNativeConfig>> => {
52
+ const client = new DaikinClient(config, leaseArg.context);
53
+ leaseArg.own(() => client.destroy());
54
+ try {
55
+ await client.getSnapshot(leaseArg.signal);
56
+ leaseArg.assertOpen();
57
+ return { kind: 'done', title: 'Verified selected Daikin BRP069', config };
58
+ } catch (errorArg) {
59
+ return { kind: 'error', title: 'Daikin verification failed', error: errorArg instanceof Error ? errorArg.message : 'Daikin verification failed.' };
60
+ }
61
+ });
62
+ },
32
63
  };
33
64
  }
34
-
35
- private async submit(candidateArg: IDiscoveryCandidate, valuesArg: Record<string, unknown>): Promise<IConfigFlowStep<IDaikinConfig>> {
36
- const metadata = candidateArg.metadata || {};
37
- const parsed = parseEndpoint(this.stringValue(valuesArg.host) || this.stringValue(metadata.url));
38
- const snapshot = snapshotValue(metadata.snapshot);
39
- const rawData = rawDataValue(metadata.rawData);
40
- const apiKey = this.stringValue(valuesArg.apiKey) || this.stringMetadata(metadata, 'apiKey');
41
- const password = this.stringValue(valuesArg.password) || this.stringMetadata(metadata, 'password');
42
- const apiVariant = this.apiVariant(this.stringValue(valuesArg.apiVariant) || this.stringMetadata(metadata, 'apiVariant'), apiKey, password);
43
- const host = parsed?.host || this.stringValue(valuesArg.host) || candidateArg.host || snapshot?.device.host;
44
- const ssl = this.booleanValue(valuesArg.ssl) ?? this.booleanMetadata(metadata, 'ssl') ?? parsed?.ssl ?? snapshot?.device.ssl ?? apiVariant === 'brp072c';
45
- const port = this.numberValue(valuesArg.port) || candidateArg.port || parsed?.port || snapshot?.device.port || this.defaultPort(apiVariant, ssl);
46
- const hasManualData = Boolean(snapshot || rawData || metadata.values || metadata.client);
47
-
48
- if (apiKey && password) {
49
- return { kind: 'error', title: 'Daikin setup failed', error: 'Invalid authentication: use either API key or password, not both.' };
50
- }
51
- if (!host && !hasManualData) {
52
- return { kind: 'error', title: 'Daikin setup failed', error: 'Daikin host, injected client, snapshot, or manual data is required.' };
53
- }
54
- if (!this.validPort(port)) {
55
- return { kind: 'error', title: 'Daikin setup failed', error: 'Daikin port must be between 1 and 65535.' };
56
- }
57
-
58
- const config: IDaikinConfig = {
59
- host,
60
- port,
61
- ssl,
62
- verifySsl: this.booleanValue(valuesArg.verifySsl) ?? this.booleanMetadata(metadata, 'verifySsl') ?? false,
63
- apiKey,
64
- uuid: this.stringValue(valuesArg.uuid) || this.stringMetadata(metadata, 'uuid') || (apiKey ? plugins.crypto.randomUUID().replace(/-/g, '') : undefined),
65
- password,
66
- apiVariant,
67
- timeoutMs: daikinDefaultTimeoutMs,
68
- name: this.stringValue(valuesArg.name) || candidateArg.name || snapshot?.device.name || this.stringMetadata(metadata, 'name'),
69
- manufacturer: candidateArg.manufacturer || snapshot?.device.manufacturer || 'Daikin',
70
- model: candidateArg.model || snapshot?.device.model,
71
- uniqueId: candidateArg.id || snapshot?.device.id || snapshot?.device.macAddress || (host ? `${host}:${port}` : undefined),
72
- macAddress: candidateArg.macAddress || snapshot?.device.macAddress,
73
- snapshot,
74
- rawData,
75
- values: valueMapValue(metadata.values),
76
- client: metadata.client as IDaikinConfig['client'],
77
- commandExecutor: metadata.commandExecutor as IDaikinConfig['commandExecutor'],
78
- };
79
-
80
- return { kind: 'done', title: 'Daikin configured', config };
81
- }
82
-
83
- private apiVariant(valueArg: string | undefined, apiKeyArg: string | undefined, passwordArg: string | undefined): TDaikinApiVariant {
84
- if (passwordArg) {
85
- return 'skyfi';
86
- }
87
- if (apiKeyArg) {
88
- return 'brp072c';
89
- }
90
- const allowed: TDaikinApiVariant[] = ['auto', 'brp069', 'brp072c', 'airbase', 'skyfi', 'brp084'];
91
- return allowed.includes(valueArg as TDaikinApiVariant) ? valueArg as TDaikinApiVariant : 'auto';
92
- }
93
-
94
- private defaultPort(apiVariantArg: TDaikinApiVariant, sslArg: boolean): number {
95
- if (apiVariantArg === 'skyfi') {
96
- return daikinSkyFiPort;
97
- }
98
- return sslArg ? daikinDefaultHttpsPort : daikinDefaultHttpPort;
99
- }
100
-
101
- private stringValue(valueArg: unknown): string | undefined {
102
- return typeof valueArg === 'string' && valueArg.trim() ? valueArg.trim().replace(/\/$/, '') : undefined;
103
- }
104
-
105
- private numberValue(valueArg: unknown): number | undefined {
106
- if (typeof valueArg === 'number' && Number.isFinite(valueArg)) {
107
- return Math.round(valueArg);
108
- }
109
- if (typeof valueArg === 'string' && valueArg.trim()) {
110
- const parsed = Number(valueArg);
111
- return Number.isFinite(parsed) ? Math.round(parsed) : undefined;
112
- }
113
- return undefined;
114
- }
115
-
116
- private booleanValue(valueArg: unknown): boolean | undefined {
117
- if (typeof valueArg === 'boolean') {
118
- return valueArg;
119
- }
120
- if (typeof valueArg === 'string') {
121
- const normalized = valueArg.trim().toLowerCase();
122
- if (['true', 'yes', 'on', '1'].includes(normalized)) {
123
- return true;
124
- }
125
- if (['false', 'no', 'off', '0'].includes(normalized)) {
126
- return false;
127
- }
128
- }
129
- return undefined;
130
- }
131
-
132
- private stringMetadata(metadataArg: Record<string, unknown>, keyArg: string): string | undefined {
133
- return this.stringValue(metadataArg[keyArg]);
134
- }
135
-
136
- private booleanMetadata(metadataArg: Record<string, unknown>, keyArg: string): boolean | undefined {
137
- const value = metadataArg[keyArg];
138
- return typeof value === 'boolean' ? value : undefined;
139
- }
140
-
141
- private validPort(valueArg: number): boolean {
142
- return Number.isInteger(valueArg) && valueArg > 0 && valueArg <= 65535;
143
- }
144
65
  }
145
66
 
146
- const parseEndpoint = (valueArg: string | undefined): { host: string; port?: number; ssl: boolean } | undefined => {
147
- if (!valueArg || !/^[a-z][a-z0-9+.-]*:\/\//i.test(valueArg)) {
148
- return undefined;
149
- }
150
- try {
151
- const url = new URL(valueArg);
152
- return { host: url.hostname, port: url.port ? Number(url.port) : undefined, ssl: url.protocol === 'https:' };
153
- } catch {
154
- return undefined;
155
- }
67
+ const selectedVariant = (valueArg: unknown): 'brp069' => {
68
+ if (valueArg !== 'brp069') throw new TypeError('Select the BRP069 controller family explicitly.');
69
+ return valueArg;
156
70
  };
157
-
158
- const snapshotValue = (valueArg: unknown): IDaikinSnapshot | undefined => {
159
- return valueArg && typeof valueArg === 'object' && 'device' in valueArg && 'climate' in valueArg ? valueArg as IDaikinSnapshot : undefined;
71
+ const formPort = (valueArg: unknown, hintArg: unknown): number | undefined => {
72
+ const value = valueArg === undefined || valueArg === '' ? hintArg : valueArg;
73
+ if (value === undefined) return undefined;
74
+ if (typeof value === 'number') return value;
75
+ if (typeof value === 'string' && /^\d{1,5}$/.test(value)) return Number(value);
76
+ throw new TypeError('Daikin port must be an integer.');
160
77
  };
161
78
 
162
- const rawDataValue = (valueArg: unknown): Partial<IDaikinRawData> | undefined => {
163
- return valueArg && typeof valueArg === 'object' && !Array.isArray(valueArg) ? valueArg as Partial<IDaikinRawData> : undefined;
79
+ const selectedPlaintext = (valueArg: unknown): true => {
80
+ if (valueArg !== true) throw new TypeError('Explicitly allow unauthenticated plaintext LAN HTTP.');
81
+ return valueArg;
164
82
  };
165
83
 
166
- const valueMapValue = (valueArg: unknown): IDaikinValueMap | undefined => {
167
- return valueArg && typeof valueArg === 'object' && !Array.isArray(valueArg) ? valueArg as IDaikinValueMap : undefined;
84
+ const formText = (valueArg: unknown, hintArg?: string): string => {
85
+ if (valueArg === undefined) return hintArg ?? '';
86
+ if (typeof valueArg !== 'string') throw new TypeError('Daikin text fields must be strings.');
87
+ return valueArg;
168
88
  };
@@ -1,107 +1,202 @@
1
- import type * as shxInterfaces from '@smarthome.exchange/interfaces';
1
+ import * as plugins from '../../plugins.js';
2
2
  import { BaseIntegration } from '../../core/classes.baseintegration.js';
3
- import type { IIntegrationEntity, IIntegrationRuntime, IIntegrationSetupContext, IServiceCallRequest, IServiceCallResult } from '../../core/types.js';
3
+ import { NativeIntegrationOwner, type INativeSetupLease } from '../../core/classes.nativeintegrationowner.js';
4
+ import type { IDeviceFeatureWriteRequest, IIntegrationEntity, IIntegrationEvent, IIntegrationRuntime, IIntegrationSetupContext, ILogger, IServiceCallRequest, IServiceCallResult } from '../../core/types.js';
4
5
  import { DaikinClient } from './daikin.classes.client.js';
5
6
  import { DaikinConfigFlow } from './daikin.classes.configflow.js';
6
7
  import { createDaikinDiscoveryDescriptor } from './daikin.discovery.js';
7
8
  import { DaikinMapper } from './daikin.mapper.js';
8
- import type { IDaikinConfig } from './daikin.types.js';
9
- import { daikinDisplayName, daikinDomain } from './daikin.types.js';
9
+ import type { IDaikinIntegrationOptions, IDaikinNativeConfig, IDaikinSnapshot } from './daikin.types.js';
10
+ import { normalizeDaikinConfig } from './daikin.validation.js';
10
11
 
11
- export class DaikinIntegration extends BaseIntegration<IDaikinConfig> {
12
- public readonly domain = daikinDomain;
13
- public readonly displayName = daikinDisplayName;
12
+ const failure = (errorArg: unknown): IServiceCallResult => ({
13
+ success: false, error: errorArg instanceof Error ? errorArg.message : 'Daikin operation failed.',
14
+ data: errorArg instanceof plugins.ecobridgeDeviceManager.DaikinProtocolError
15
+ ? { code: errorArg.code, effectOutcome: errorArg.effectOutcome }
16
+ : { effectOutcome: 'not-sent' },
17
+ });
18
+
19
+ export class DaikinIntegration extends BaseIntegration<IDaikinNativeConfig> {
20
+ public readonly domain = 'daikin';
21
+ public readonly displayName = 'Daikin BRP069';
14
22
  public readonly status = 'control-runtime' as const;
15
23
  public readonly discoveryDescriptor = createDaikinDiscoveryDescriptor();
16
- public readonly configFlow = new DaikinConfigFlow();
24
+ public readonly configFlow: DaikinConfigFlow;
17
25
  public readonly metadata = {
18
- source: 'home-assistant/core',
19
- upstreamPath: 'homeassistant/components/daikin',
20
- upstreamDomain: daikinDomain,
21
- integrationType: 'device',
22
- iotClass: 'local_polling',
23
- requirements: ['pydaikin==2.17.2'],
24
- dependencies: [] as string[],
25
- afterDependencies: [] as string[],
26
- codeowners: ['@fredrike'],
27
- configFlow: true,
28
- documentation: 'https://www.home-assistant.io/integrations/daikin',
29
- zeroconf: ['_dkapi._tcp.local.'],
30
- discovery: {
31
- zeroconf: '_dkapi._tcp.local.',
32
- udp: 'DAIKIN_UDP/common/basic_info broadcast on UDP 30050 from source port 30000.',
33
- http: 'Manual HTTP candidates for /common/basic_info, /aircon/*, /skyfi/*, and /dsiot/* are recognized.',
34
- manual: true,
35
- },
36
- runtime: {
37
- type: 'control-runtime',
38
- polling: 'local Daikin HTTP key/value APIs plus SkyFi and BRP084 dsiot read modeling',
39
- services: ['snapshot', 'status', 'refresh', 'climate controls', 'power switch', 'zone switch', 'streamer', 'holiday/advanced modes when represented by local endpoints'],
40
- controls: true,
41
- },
26
+ source: '@ecobridge.xyz/devicemanager', upstreamDomain: 'daikin', integrationType: 'device', iotClass: 'local_polling',
42
27
  localApi: {
43
- implemented: [
44
- 'BRP069-style key/value local HTTP reads and set_control_info writes',
45
- 'BRP072C register_terminal/API-key request modeling when HTTPS is usable by the runtime',
46
- 'AirBase skyfi-prefixed reads plus zone setting writes',
47
- 'SkyFi password API reads and set.cgi/setzone.cgi writes',
48
- 'BRP084 dsiot snapshot reads',
49
- 'snapshot/manual-data and injected client/executor operation',
50
- ],
51
- explicitUnsupported: [
52
- 'BRP084 dsiot control writes without an injected commandExecutor',
53
- 'faking command success for snapshot/manual-only configurations',
54
- 'forcing TLS certificate bypass for BRP072C self-signed devices through Node fetch',
55
- ],
28
+ implemented: ['selected BRP069 fresh identity/model/control observations', 'explicit power', 'integer target in observed cool or heat mode', 'independent readback'],
29
+ explicitUnsupported: ['automatic family selection', 'mode/humidity/fan/direction changes', 'other controller-family effects', 'cloud', 'retries', 'optimistic state', 'injected effect executors'],
56
30
  },
57
31
  };
32
+ readonly #owner: NativeIntegrationOwner;
33
+
34
+ constructor(optionsArg: IDaikinIntegrationOptions = {}) {
35
+ super();
36
+ this.#owner = new NativeIntegrationOwner(this.domain, optionsArg);
37
+ this.configFlow = new DaikinConfigFlow({}, this.#owner.createFlowScope());
38
+ }
58
39
 
59
- public async setup(configArg: IDaikinConfig, contextArg: IIntegrationSetupContext): Promise<IIntegrationRuntime> {
60
- void contextArg;
61
- return new DaikinRuntime(new DaikinClient(configArg));
40
+ public async setup(configArg: IDaikinNativeConfig, contextArg: IIntegrationSetupContext): Promise<IIntegrationRuntime> {
41
+ const config = normalizeDaikinConfig(configArg);
42
+ return this.#owner.runSetup(contextArg, config.homeId, async (leaseArg) => {
43
+ const client = new DaikinClient(config, leaseArg.context);
44
+ let runtime: DaikinRuntime | undefined;
45
+ leaseArg.own(() => runtime ? runtime.cleanupOwnedResource() : client.destroy());
46
+ const identity = await client.getSnapshot(leaseArg.signal);
47
+ leaseArg.assertOpen();
48
+ runtime = new DaikinRuntime(client, identity, leaseArg, leaseArg.context.logger);
49
+ leaseArg.promoteToRuntime();
50
+ return runtime;
51
+ });
62
52
  }
63
53
 
64
- public async destroy(): Promise<void> {}
54
+ public destroy(): Promise<void> { return this.#owner.close(); }
55
+ public retryCleanup(): Promise<void> { return this.#owner.retryCleanup(); }
65
56
  }
66
57
 
67
58
  export class HomeAssistantDaikinIntegration extends DaikinIntegration {}
68
59
 
60
+ interface IDaikinSubscriber {
61
+ handler: (eventArg: IIntegrationEvent) => void;
62
+ cleanup: () => void;
63
+ }
64
+
69
65
  class DaikinRuntime implements IIntegrationRuntime {
70
- public domain = daikinDomain;
66
+ public readonly domain = 'daikin';
67
+ readonly #identity: IDaikinSnapshot;
68
+ readonly #subscriptions = new Set<IDaikinSubscriber>();
69
+ #entities: IIntegrationEntity[];
70
+ #available = true;
71
+ #destroy?: Promise<void>;
72
+ #removeAbort: () => void = () => undefined;
71
73
 
72
- constructor(private readonly client: DaikinClient) {}
74
+ constructor(private readonly client: DaikinClient, identityArg: IDaikinSnapshot, private readonly lease: INativeSetupLease,
75
+ private readonly logger?: ILogger) {
76
+ this.#identity = structuredClone(identityArg);
77
+ this.#entities = DaikinMapper.toEntities(identityArg);
78
+ // The lease retains failed cleanup; destroy() and the owner expose its stable rejection.
79
+ const aborted = (): void => { void this.destroy().catch(() => undefined); };
80
+ lease.signal.addEventListener('abort', aborted, { once: true });
81
+ this.#removeAbort = () => lease.signal.removeEventListener('abort', aborted);
82
+ if (lease.signal.aborted) aborted();
83
+ }
73
84
 
74
- public async devices(): Promise<shxInterfaces.data.IDeviceDefinition[]> {
75
- return DaikinMapper.toDevices(await this.client.getSnapshot());
85
+ public isHealthy(): boolean { return !this.#destroy && this.client.isHealthy(); }
86
+ public async devices(signalArg?: AbortSignal): Promise<plugins.shxInterfaces.data.IDeviceDefinition[]> {
87
+ return DaikinMapper.toDevices(await this.#snapshot(signalArg));
76
88
  }
89
+ public async entities(): Promise<IIntegrationEntity[]> { return DaikinMapper.toEntities(await this.#snapshot()); }
77
90
 
78
- public async entities(): Promise<IIntegrationEntity[]> {
79
- return DaikinMapper.toEntities(await this.client.getSnapshot());
91
+ public async subscribe(handlerArg: (eventArg: IIntegrationEvent) => void, signalArg?: AbortSignal): Promise<() => Promise<void>> {
92
+ this.#assertOpen();
93
+ if (typeof handlerArg !== 'function') throw new TypeError('Daikin subscriber must be a function.');
94
+ if (signalArg !== undefined && !(signalArg instanceof AbortSignal)) throw new TypeError('Daikin subscriber signal must be an AbortSignal.');
95
+ signalArg?.throwIfAborted();
96
+ if (this.#subscriptions.size >= 128) throw new Error('Daikin subscriber capacity is exhausted.');
97
+ const subscriber: IDaikinSubscriber = { handler: handlerArg, cleanup: () => {
98
+ this.#subscriptions.delete(subscriber);
99
+ signalArg?.removeEventListener('abort', subscriber.cleanup);
100
+ } };
101
+ this.#subscriptions.add(subscriber);
102
+ signalArg?.addEventListener('abort', subscriber.cleanup, { once: true });
103
+ if (signalArg?.aborted) subscriber.cleanup();
104
+ return async () => subscriber.cleanup();
80
105
  }
81
106
 
82
107
  public async callService(requestArg: IServiceCallRequest): Promise<IServiceCallResult> {
83
108
  try {
84
- if (requestArg.domain === daikinDomain && (requestArg.service === 'snapshot' || requestArg.service === 'status')) {
85
- return { success: true, data: await this.client.getSnapshot() };
86
- }
87
- if (requestArg.domain === daikinDomain && requestArg.service === 'refresh') {
88
- const result = await this.client.refresh();
89
- return { success: result.success, error: result.error, data: result.snapshot || result.data };
109
+ this.#assertOpen();
110
+ const control = DaikinMapper.controlForService(this.#identity, requestArg);
111
+ if (control === 'snapshot') {
112
+ const snapshot = await this.client.getSnapshot();
113
+ this.#observe(snapshot);
114
+ return { success: true, data: snapshot };
90
115
  }
116
+ return this.#result(await this.client.setControl(control));
117
+ } catch (errorArg) { this.#report(errorArg); return failure(errorArg); }
118
+ }
119
+
120
+ public async writeFeature(requestArg: IDeviceFeatureWriteRequest, signalArg?: AbortSignal): Promise<IServiceCallResult> {
121
+ try {
122
+ this.#assertOpen();
123
+ return this.#result(await this.client.setControl(DaikinMapper.controlForFeature(this.#identity, requestArg), signalArg));
124
+ } catch (errorArg) { this.#report(errorArg); return failure(errorArg); }
125
+ }
126
+
127
+ public destroy(): Promise<void> {
128
+ this.#destroy ??= Promise.resolve().then(() => this.lease.close());
129
+ return this.#destroy;
130
+ }
91
131
 
92
- const snapshot = await this.client.getSnapshot();
93
- const command = DaikinMapper.commandForService(snapshot, requestArg);
94
- if (!command) {
95
- return { success: false, error: `Unsupported Daikin service: ${requestArg.domain}.${requestArg.service}` };
132
+ /** One adapter resource groups its client and subscriptions; every sibling must settle. */
133
+ public async cleanupOwnedResource(): Promise<void> {
134
+ const results = await Promise.allSettled([
135
+ Promise.resolve().then(() => this.#removeAbort()),
136
+ ...[...this.#subscriptions].map((subscriberArg) => Promise.resolve().then(() => subscriberArg.cleanup())),
137
+ Promise.resolve().then(() => this.client.destroy()),
138
+ ]);
139
+ const errors = results.filter((resultArg): resultArg is PromiseRejectedResult => resultArg.status === 'rejected').map((resultArg) => resultArg.reason as unknown);
140
+ if (errors.length) throw new AggregateError(errors, 'Daikin runtime resource cleanup failed.');
141
+ }
142
+
143
+ async #snapshot(signalArg?: AbortSignal): Promise<IDaikinSnapshot> {
144
+ this.#assertOpen();
145
+ try {
146
+ const snapshot = await this.client.getSnapshot(signalArg);
147
+ this.#observe(snapshot);
148
+ return snapshot;
149
+ } catch (errorArg) { this.#report(errorArg); throw errorArg; }
150
+ }
151
+
152
+ #result(dataArg: plugins.ecobridgeDeviceManager.IDaikinControlResult): IServiceCallResult {
153
+ this.#observe(DaikinMapper.fromState(this.client.config, dataArg.observed));
154
+ return { success: dataArg.effectOutcome === 'confirmed', data: dataArg,
155
+ error: dataArg.effectOutcome === 'confirmed' ? undefined : 'Daikin setter was accepted but requested state was not confirmed by observation.' };
156
+ }
157
+
158
+ #observe(snapshotArg: IDaikinSnapshot): void {
159
+ const entities = DaikinMapper.toEntities(snapshotArg);
160
+ if (!this.#available) this.#emit({ type: 'availability_changed', data: { available: true } });
161
+ this.#available = true;
162
+ for (const entity of entities) {
163
+ const previous = this.#entities.find((entryArg) => entryArg.id === entity.id);
164
+ if (!previous || JSON.stringify([previous.state, previous.attributes]) !== JSON.stringify([entity.state, entity.attributes])) {
165
+ this.#emit({ type: 'state_changed', entityId: entity.id, data: entity });
96
166
  }
97
- const data = await this.client.execute(command);
98
- return { success: true, data: data ?? command };
99
- } catch (errorArg) {
100
- return { success: false, error: errorArg instanceof Error ? errorArg.message : String(errorArg) };
101
167
  }
168
+ this.#entities = entities;
169
+ }
170
+
171
+ #report(errorArg: unknown): void {
172
+ if (!this.client.isHealthy() && this.#available) {
173
+ this.#available = false;
174
+ this.#emit({ type: 'availability_changed', data: { available: false } });
175
+ }
176
+ this.#emit({ type: 'error', data: failure(errorArg) });
177
+ }
178
+
179
+ #emit(eventArg: Pick<IIntegrationEvent, 'type' | 'data'> & { entityId?: string }): void {
180
+ if (this.#destroy) return;
181
+ const event: IIntegrationEvent = { ...eventArg, integrationDomain: this.domain,
182
+ deviceId: DaikinMapper.deviceId(this.#identity), timestamp: Date.now() };
183
+ for (const subscriber of [...this.#subscriptions]) {
184
+ if (!this.#subscriptions.has(subscriber)) continue;
185
+ try {
186
+ const returned: unknown = subscriber.handler(structuredClone(event));
187
+ if (returned instanceof Promise) void returned.catch(() => this.#subscriberFailed(subscriber));
188
+ } catch { this.#subscriberFailed(subscriber); }
189
+ }
190
+ }
191
+
192
+ #subscriberFailed(subscriberArg: IDaikinSubscriber): void {
193
+ subscriberArg.cleanup();
194
+ this.logger?.log('error', 'Daikin event subscriber failed.');
195
+ this.#emit({ type: 'error', data: { error: 'Daikin event subscriber failed.' } });
102
196
  }
103
197
 
104
- public async destroy(): Promise<void> {
105
- await this.client.destroy();
198
+ #assertOpen(): void {
199
+ if (this.#destroy) throw new Error('Daikin runtime is destroyed.');
200
+ this.lease.assertOpen();
106
201
  }
107
202
  }