@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,764 +1,91 @@
1
1
  import * as plugins from '../../plugins.js';
2
- import type { IIntegrationEntity, IIntegrationEvent, IServiceCallRequest, TEntityPlatform } from '../../core/types.js';
3
- import type {
4
- IWizButtonRecord,
5
- IWizClientCommand,
6
- IWizConfig,
7
- IWizDeviceFeatures,
8
- IWizDeviceInfo,
9
- IWizEntityRecord,
10
- IWizEvent,
11
- IWizManualEntry,
12
- IWizPilotPatch,
13
- IWizPilotState,
14
- IWizSensorRecord,
15
- IWizSnapshot,
16
- IWizSnapshotDevice,
17
- } from './wiz.types.js';
18
- import { wizDefaultPort } from './wiz.types.js';
19
-
20
- const wizScenes: Array<{ id: number; name: string }> = [
21
- { id: 35, name: 'Alarm' },
22
- { id: 10, name: 'Bedtime' },
23
- { id: 29, name: 'Candlelight' },
24
- { id: 27, name: 'Christmas' },
25
- { id: 6, name: 'Cozy' },
26
- { id: 13, name: 'Cool white' },
27
- { id: 26, name: 'Club' },
28
- { id: 12, name: 'Daylight' },
29
- { id: 33, name: 'Diwali' },
30
- { id: 23, name: 'Deep dive' },
31
- { id: 22, name: 'Fall' },
32
- { id: 5, name: 'Fireplace' },
33
- { id: 7, name: 'Forest' },
34
- { id: 15, name: 'Focus' },
35
- { id: 30, name: 'Golden white' },
36
- { id: 28, name: 'Halloween' },
37
- { id: 24, name: 'Jungle' },
38
- { id: 25, name: 'Mojito' },
39
- { id: 14, name: 'Night light' },
40
- { id: 1, name: 'Ocean' },
41
- { id: 4, name: 'Party' },
42
- { id: 31, name: 'Pulse' },
43
- { id: 8, name: 'Pastel colors' },
44
- { id: 19, name: 'Plantgrowth' },
45
- { id: 2, name: 'Romance' },
46
- { id: 16, name: 'Relax' },
47
- { id: 36, name: 'Snowy sky' },
48
- { id: 3, name: 'Sunset' },
49
- { id: 20, name: 'Spring' },
50
- { id: 21, name: 'Summer' },
51
- { id: 32, name: 'Steampunk' },
52
- { id: 17, name: 'True colors' },
53
- { id: 18, name: 'TV time' },
54
- { id: 34, name: 'White' },
55
- { id: 9, name: 'Wake-up' },
56
- { id: 11, name: 'Warm white' },
57
- { id: 1000, name: 'Rhythm' },
58
- ];
59
-
60
- const wizSceneNamesById = new Map(wizScenes.map((sceneArg) => [sceneArg.id, sceneArg.name]));
61
- const wizSceneIdsByName = new Map(wizScenes.map((sceneArg) => [sceneArg.name.toLowerCase(), sceneArg.id]));
62
-
63
- const wizButtonSources: Record<string, string> = {
64
- wfa1: 'on',
65
- wfa2: 'off',
66
- wfa3: 'night',
67
- wfa8: 'decrease_brightness',
68
- wfa9: 'increase_brightness',
69
- wfa16: '1',
70
- wfa17: '2',
71
- wfa18: '3',
72
- wfa19: '4',
73
- };
74
-
75
- const pilotPatchKeys = new Set(['state', 'sceneId', 'temp', 'dimming', 'r', 'g', 'b', 'c', 'w', 'speed', 'ratio', 'fanState', 'fanMode', 'fanSpeed', 'fanRevrs']);
2
+ import type { IDeviceFeatureWriteRequest, IIntegrationEntity, IServiceCallRequest } from '../../core/types.js';
3
+ import type { IWizSnapshot, TWizControl } from './wiz.types.js';
4
+ import { wizControl, wizRecord } from './wiz.validation.js';
76
5
 
77
6
  export class WizMapper {
78
- public static readonly sceneNames = wizScenes.map((sceneArg) => sceneArg.name);
79
-
80
- public static toSnapshot(configArg: IWizConfig, connectedArg?: boolean, eventsArg: IWizEvent[] = []): IWizSnapshot {
81
- const source = configArg.snapshot;
82
- const devices: IWizSnapshotDevice[] = [
83
- ...(source?.devices || []),
84
- ...(configArg.devices || []),
85
- ];
86
-
87
- for (const entry of configArg.manualEntries || []) {
88
- if (entry.snapshot) {
89
- devices.push(...entry.snapshot.devices);
90
- } else {
91
- devices.push(this.deviceFromManualEntry(entry));
92
- }
93
- }
94
-
95
- if (!devices.length && (configArg.host || configArg.mac || configArg.name || configArg.deviceInfo || configArg.pilot)) {
96
- devices.push({
97
- host: configArg.host,
98
- port: configArg.port || wizDefaultPort,
99
- mac: configArg.mac || configArg.deviceInfo?.mac || configArg.pilot?.mac,
100
- name: configArg.name || configArg.deviceInfo?.name,
101
- deviceInfo: configArg.deviceInfo,
102
- pilot: configArg.pilot,
103
- available: connectedArg ?? Boolean(configArg.pilot || source?.connected),
104
- });
105
- }
106
-
107
- return {
108
- connected: connectedArg ?? source?.connected ?? false,
109
- host: configArg.host || source?.host,
110
- port: configArg.port || source?.port || wizDefaultPort,
111
- devices,
112
- events: [...(source?.events || []), ...(configArg.events || []), ...eventsArg],
113
- };
114
- }
7
+ public static deviceId(snapshotArg: IWizSnapshot): string { return `wiz:${encodeURIComponent(snapshotArg.homeId)}:${snapshotArg.info.macAddress}`; }
8
+ public static entityId(snapshotArg: IWizSnapshot): string { return `${this.deviceId(snapshotArg)}:control`; }
115
9
 
116
10
  public static toDevices(snapshotArg: IWizSnapshot): plugins.shxInterfaces.data.IDeviceDefinition[] {
117
- const updatedAt = new Date().toISOString();
118
- return snapshotArg.devices.map((deviceArg) => this.toDevice(deviceArg, updatedAt));
119
- }
120
-
121
- public static toEntities(snapshotArg: IWizSnapshot): IIntegrationEntity[] {
122
- const entities: IIntegrationEntity[] = [];
123
- const usedIds = new Map<string, number>();
124
-
125
- for (const device of snapshotArg.devices) {
126
- const info = this.deviceInfo(device);
127
- const pilot = device.pilot || {};
128
- const features = this.features(device);
129
- const deviceId = this.deviceId(device);
130
- const baseName = this.deviceName(device);
131
- const isSocket = this.isSocket(device);
132
- const hasLight = !isSocket && features.light !== false;
133
-
134
- if (hasLight) {
135
- entities.push(this.entity('light', baseName, deviceId, this.uniqueId('light', device), pilot.state ? 'on' : 'off', usedIds, {
136
- ...this.baseAttributes(device),
137
- brightness: pilot.dimming,
138
- brightness255: this.percentToByte(pilot.dimming),
139
- colorTemperatureKelvin: pilot.temp,
140
- rgbColor: this.rgb(pilot),
141
- sceneId: this.sceneId(pilot),
142
- effect: this.sceneName(pilot),
143
- effectList: this.sceneNames,
144
- writable: true,
145
- }, device.available !== false));
146
- }
147
-
148
- if (isSocket || features.switch) {
149
- entities.push(this.entity('switch', baseName, deviceId, this.uniqueId('switch', device), pilot.state ? 'on' : 'off', usedIds, {
150
- ...this.baseAttributes(device),
151
- writable: true,
152
- }, device.available !== false));
153
- }
154
-
155
- if (features.fan || pilot.fanState !== undefined) {
156
- entities.push(this.entity('fan', `${baseName} Fan`, deviceId, this.uniqueId('fan', device), pilot.fanState ? 'on' : 'off', usedIds, {
157
- ...this.baseAttributes(device),
158
- percentage: this.fanPercentage(device, pilot),
159
- fanMode: pilot.fanMode,
160
- fanSpeed: pilot.fanSpeed,
161
- fanReverse: pilot.fanRevrs,
162
- writable: true,
163
- }, device.available !== false));
164
- }
165
-
166
- if (typeof pilot.rssi === 'number') {
167
- entities.push(this.sensorEntity(device, { key: 'rssi', name: `${baseName} RSSI`, value: pilot.rssi, unit: 'dBm', deviceClass: 'signal_strength' }, usedIds));
168
- }
169
- if (typeof pilot.pc === 'number' || features.power) {
170
- entities.push(this.sensorEntity(device, { key: 'power', name: `${baseName} Power`, value: typeof pilot.pc === 'number' ? pilot.pc / 1000 : undefined, unit: 'W', deviceClass: 'power' }, usedIds));
171
- }
172
- if (features.occupancy || pilot.src === 'pir') {
173
- entities.push(this.sensorEntity(device, { key: 'occupancy', name: `${baseName} Occupancy`, platform: 'binary_sensor', value: pilot.src === 'pir' ? pilot.state : undefined, deviceClass: 'occupancy' }, usedIds));
174
- }
175
-
176
- for (const sensor of device.sensors || []) {
177
- entities.push(this.sensorEntity(device, sensor, usedIds));
178
- }
179
-
180
- if (features.effect || pilot.speed !== undefined) {
181
- entities.push(this.numberEntity(device, 'effect_speed', `${baseName} Effect Speed`, pilot.speed, usedIds, { min: 10, max: 200, step: 1, wizPilotKey: 'speed' }));
182
- }
183
- if (features.dualHead || pilot.ratio !== undefined) {
184
- entities.push(this.numberEntity(device, 'dual_head_ratio', `${baseName} Dual Head Ratio`, pilot.ratio, usedIds, { min: 0, max: 100, step: 1, wizPilotKey: 'ratio' }));
185
- }
186
- if (features.effect || this.sceneId(pilot) !== undefined) {
187
- entities.push(this.entity('select', `${baseName} Effect`, deviceId, `${this.uniqueId('select', device)}_effect`, this.sceneName(pilot) || 'None', usedIds, {
188
- ...this.baseAttributes(device),
189
- options: this.sceneNames,
190
- wizPilotKey: 'sceneId',
191
- writable: true,
192
- }, device.available !== false));
193
- }
194
-
195
- for (const button of this.buttons(device)) {
196
- entities.push(this.buttonEntity(device, button, usedIds));
197
- }
198
-
199
- for (const entity of device.entities || []) {
200
- entities.push(this.explicitEntity(device, entity, usedIds));
201
- }
202
- }
203
-
204
- return entities;
205
- }
206
-
207
- public static toIntegrationEvent(eventArg: IWizEvent): IIntegrationEvent {
208
- return {
209
- type: eventArg.type === 'command_failed' || eventArg.type === 'error' ? 'error' : 'state_changed',
210
- integrationDomain: 'wiz',
211
- deviceId: eventArg.deviceId,
212
- entityId: eventArg.entityId,
213
- data: eventArg,
214
- timestamp: eventArg.timestamp || Date.now(),
215
- };
216
- }
217
-
218
- public static commandForService(snapshotArg: IWizSnapshot, requestArg: IServiceCallRequest): IWizClientCommand | undefined {
219
- if (requestArg.domain === 'wiz' && requestArg.service === 'set_pilot' && this.isRecord(requestArg.data?.payload)) {
220
- const targetEntity = this.findTargetEntity(snapshotArg, requestArg);
221
- return {
222
- type: 'setPilot',
223
- service: requestArg.service,
224
- deviceId: targetEntity?.deviceId || requestArg.target.deviceId,
225
- entityId: targetEntity?.id || requestArg.target.entityId,
226
- payload: requestArg.data.payload as IWizPilotPatch,
227
- target: requestArg.target,
228
- };
229
- }
230
-
231
- const target = this.findTargetEntity(snapshotArg, requestArg);
232
- if (!target) {
233
- return undefined;
234
- }
235
- const device = snapshotArg.devices.find((deviceArg) => this.deviceId(deviceArg) === target.deviceId);
236
- const payload = this.payloadForService(target, requestArg, device);
237
- if (!payload || !Object.keys(payload).length) {
238
- return undefined;
239
- }
240
- return {
241
- type: 'setPilot',
242
- service: requestArg.service,
243
- deviceId: target.deviceId,
244
- entityId: target.id,
245
- payload,
246
- target: requestArg.target,
247
- };
248
- }
249
-
250
- public static sceneIdFromName(valueArg: string): number | undefined {
251
- return wizSceneIdsByName.get(valueArg.toLowerCase());
252
- }
253
-
254
- private static toDevice(deviceArg: IWizSnapshotDevice, updatedAtArg: string): plugins.shxInterfaces.data.IDeviceDefinition {
255
- const info = this.deviceInfo(deviceArg);
256
- const pilot = deviceArg.pilot || {};
257
- const featuresInfo = this.features(deviceArg);
258
- const features: plugins.shxInterfaces.data.IDeviceFeature[] = [
259
- { id: 'availability', capability: 'sensor', name: 'Availability', readable: true, writable: false },
260
- ];
261
- const state: plugins.shxInterfaces.data.IDeviceState[] = [
262
- { featureId: 'availability', value: deviceArg.available === false ? 'offline' : 'online', updatedAt: updatedAtArg },
263
- ];
264
- const isSocket = this.isSocket(deviceArg);
265
- const hasLight = !isSocket && featuresInfo.light !== false;
266
-
267
- if (hasLight) {
268
- features.push({ id: 'on', capability: 'light', name: 'Power', readable: true, writable: true });
269
- this.pushDeviceState(state, 'on', pilot.state ?? false, updatedAtArg);
270
- if (featuresInfo.brightness !== false || typeof pilot.dimming === 'number') {
271
- features.push({ id: 'brightness', capability: 'light', name: 'Brightness', readable: true, writable: true, unit: '%' });
272
- this.pushDeviceState(state, 'brightness', pilot.dimming, updatedAtArg);
273
- }
274
- if (featuresInfo.colorTemp || typeof pilot.temp === 'number') {
275
- features.push({ id: 'color_temperature', capability: 'light', name: 'Color Temperature', readable: true, writable: true, unit: 'K' });
276
- this.pushDeviceState(state, 'color_temperature', pilot.temp, updatedAtArg);
277
- }
278
- if (featuresInfo.color || this.rgb(pilot)) {
279
- features.push({ id: 'rgb', capability: 'light', name: 'RGB Color', readable: true, writable: true });
280
- this.pushDeviceState(state, 'rgb', this.rgbRecord(pilot), updatedAtArg);
281
- }
282
- if (featuresInfo.effect || this.sceneId(pilot) !== undefined) {
283
- features.push({ id: 'effect', capability: 'light', name: 'Effect', readable: true, writable: true });
284
- this.pushDeviceState(state, 'effect', this.sceneName(pilot) || null, updatedAtArg);
285
- }
286
- }
287
-
288
- if (isSocket || featuresInfo.switch) {
289
- features.push({ id: 'switch', capability: 'switch', name: 'Power', readable: true, writable: true });
290
- this.pushDeviceState(state, 'switch', pilot.state ?? false, updatedAtArg);
291
- }
292
-
293
- if (featuresInfo.fan || pilot.fanState !== undefined) {
294
- features.push({ id: 'fan', capability: 'fan', name: 'Fan', readable: true, writable: true });
295
- this.pushDeviceState(state, 'fan', Boolean(pilot.fanState), updatedAtArg);
296
- features.push({ id: 'fan_speed', capability: 'fan', name: 'Fan Speed', readable: true, writable: true, unit: '%' });
297
- this.pushDeviceState(state, 'fan_speed', this.fanPercentage(deviceArg, pilot), updatedAtArg);
298
- }
299
-
300
- if (typeof pilot.rssi === 'number') {
301
- features.push({ id: 'rssi', capability: 'sensor', name: 'RSSI', readable: true, writable: false, unit: 'dBm' });
302
- this.pushDeviceState(state, 'rssi', pilot.rssi, updatedAtArg);
303
- }
304
- if (typeof pilot.pc === 'number' || featuresInfo.power) {
305
- features.push({ id: 'power', capability: 'energy', name: 'Power', readable: true, writable: false, unit: 'W' });
306
- this.pushDeviceState(state, 'power', typeof pilot.pc === 'number' ? pilot.pc / 1000 : undefined, updatedAtArg);
307
- }
308
- if (featuresInfo.occupancy || pilot.src === 'pir') {
309
- features.push({ id: 'occupancy', capability: 'sensor', name: 'Occupancy', readable: true, writable: false });
310
- this.pushDeviceState(state, 'occupancy', pilot.src === 'pir' ? Boolean(pilot.state) : undefined, updatedAtArg);
311
- }
312
-
313
- for (const sensor of deviceArg.sensors || []) {
314
- features.push({ id: sensor.key, capability: 'sensor', name: sensor.name || this.title(sensor.key), readable: true, writable: Boolean(sensor.writable), unit: sensor.unit });
315
- this.pushDeviceState(state, sensor.key, this.deviceStateValue(sensor.value), updatedAtArg);
316
- }
317
- for (const button of this.buttons(deviceArg)) {
318
- features.push({ id: `button_${button.key}`, capability: 'switch', name: button.name || this.title(button.key), readable: true, writable: true });
319
- this.pushDeviceState(state, `button_${button.key}`, String(button.value ?? button.lastPressedAt ?? 'idle'), updatedAtArg);
320
- }
321
-
322
- return {
323
- id: this.deviceId(deviceArg),
324
- integrationDomain: 'wiz',
325
- name: this.deviceName(deviceArg),
326
- protocol: 'unknown',
327
- manufacturer: info.manufacturer || 'WiZ',
328
- model: info.model || info.moduleName || String(info.bulbType || 'WiZ device'),
329
- online: deviceArg.available !== false,
330
- features,
331
- state,
332
- metadata: {
333
- ...deviceArg.metadata,
334
- protocol: 'wiz-udp-json',
335
- host: deviceArg.host || info.host,
336
- port: deviceArg.port || info.port || wizDefaultPort,
337
- mac: this.mac(deviceArg),
338
- moduleName: info.moduleName,
339
- fwVersion: info.fwVersion,
340
- typeId: info.typeId,
341
- features: featuresInfo,
342
- },
343
- };
344
- }
345
-
346
- private static payloadForService(entityArg: IIntegrationEntity, requestArg: IServiceCallRequest, deviceArg?: IWizSnapshotDevice): IWizPilotPatch | undefined {
347
- if (requestArg.service === 'turn_off') {
348
- return entityArg.platform === 'fan' || requestArg.domain === 'fan' ? { fanState: 0 } : { state: false };
349
- }
350
- if (requestArg.service === 'turn_on') {
351
- const payload: IWizPilotPatch = entityArg.platform === 'fan' || requestArg.domain === 'fan' ? { fanState: 1 } : { state: true };
352
- this.applyServiceData(payload, requestArg, entityArg, deviceArg);
353
- return payload;
354
- }
355
- if (requestArg.service === 'set_percentage' || requestArg.service === 'set_brightness') {
356
- const percentage = this.percentageFromData(requestArg.data, requestArg.service);
357
- if (percentage === undefined) {
358
- return undefined;
359
- }
360
- if (entityArg.platform === 'fan' || requestArg.domain === 'fan') {
361
- return percentage <= 0 ? { fanState: 0 } : { fanState: 1, fanSpeed: this.percentageToFanSpeed(deviceArg, percentage) };
362
- }
363
- return percentage <= 0 ? { state: false } : { state: true, dimming: this.clamp(Math.round(percentage), 10, 100) };
364
- }
365
- if (requestArg.service === 'set_value') {
366
- return this.setValuePayload(entityArg, requestArg);
367
- }
368
- if (requestArg.service === 'select_option' || requestArg.service === 'select_effect') {
369
- const option = this.stringFromData(requestArg.data, ['option', 'effect', 'value']);
370
- const sceneId = typeof option === 'string' ? this.sceneIdFromName(option) : undefined;
371
- return sceneId === undefined ? undefined : { state: true, sceneId };
372
- }
373
- if (requestArg.domain === 'fan') {
374
- if (requestArg.service === 'set_direction') {
375
- const direction = this.stringFromData(requestArg.data, ['direction']);
376
- return direction ? { fanRevrs: direction === 'reverse' ? 1 : 0 } : undefined;
377
- }
378
- if (requestArg.service === 'set_preset_mode') {
379
- const presetMode = this.stringFromData(requestArg.data, ['preset_mode', 'presetMode']);
380
- return presetMode === 'breeze' ? { fanMode: 2 } : undefined;
381
- }
382
- }
383
- return undefined;
384
- }
385
-
386
- private static applyServiceData(payloadArg: IWizPilotPatch, requestArg: IServiceCallRequest, entityArg: IIntegrationEntity, deviceArg?: IWizSnapshotDevice): void {
387
- const brightness = this.percentageFromData(requestArg.data, 'turn_on');
388
- if (brightness !== undefined && entityArg.platform !== 'fan' && requestArg.domain !== 'fan') {
389
- payloadArg.dimming = this.clamp(Math.round(brightness), 10, 100);
390
- }
391
- if (brightness !== undefined && (entityArg.platform === 'fan' || requestArg.domain === 'fan')) {
392
- payloadArg.fanSpeed = this.percentageToFanSpeed(deviceArg, brightness);
393
- }
394
- const kelvin = this.kelvinFromData(requestArg.data);
395
- if (kelvin !== undefined) {
396
- payloadArg.temp = kelvin;
397
- }
398
- const rgb = this.rgbFromData(requestArg.data, 'rgb_color') || this.rgbFromData(requestArg.data, 'rgb');
399
- if (rgb) {
400
- payloadArg.r = rgb[0];
401
- payloadArg.g = rgb[1];
402
- payloadArg.b = rgb[2];
403
- }
404
- const rgbw = this.rgbFromData(requestArg.data, 'rgbw_color');
405
- if (rgbw) {
406
- payloadArg.r = rgbw[0];
407
- payloadArg.g = rgbw[1];
408
- payloadArg.b = rgbw[2];
409
- payloadArg.w = rgbw[3];
410
- }
411
- const rgbww = this.rgbFromData(requestArg.data, 'rgbww_color');
412
- if (rgbww) {
413
- payloadArg.r = rgbww[0];
414
- payloadArg.g = rgbww[1];
415
- payloadArg.b = rgbww[2];
416
- payloadArg.c = rgbww[3];
417
- payloadArg.w = rgbww[4];
418
- }
419
- const effect = this.stringFromData(requestArg.data, ['effect', 'option']);
420
- const sceneId = effect ? this.sceneIdFromName(effect) : this.numberFromData(requestArg.data, ['sceneId', 'scene_id']);
421
- if (sceneId !== undefined) {
422
- payloadArg.sceneId = sceneId;
423
- }
424
- const speed = this.numberFromData(requestArg.data, ['speed']);
425
- if (speed !== undefined) {
426
- payloadArg.speed = this.clamp(Math.round(speed), 10, 200);
427
- }
428
- }
429
-
430
- private static setValuePayload(entityArg: IIntegrationEntity, requestArg: IServiceCallRequest): IWizPilotPatch | undefined {
431
- const value = this.valueFromData(requestArg.data, ['value', 'state']);
432
- const field = this.stringFromData(requestArg.data, ['field', 'attribute', 'key']) || (typeof entityArg.attributes?.wizPilotKey === 'string' ? entityArg.attributes.wizPilotKey : undefined);
433
- if (value === undefined || !field || !pilotPatchKeys.has(field)) {
434
- return undefined;
435
- }
436
- if (field === 'speed') {
437
- return typeof value === 'number' ? { speed: this.clamp(Math.round(value), 10, 200) } : undefined;
438
- }
439
- if (field === 'ratio') {
440
- return typeof value === 'number' ? { ratio: this.clamp(Math.round(value), 0, 100) } : undefined;
441
- }
442
- if (field === 'sceneId' && typeof value === 'string') {
443
- const sceneId = this.sceneIdFromName(value);
444
- return sceneId === undefined ? undefined : { state: true, sceneId };
445
- }
446
- return { [field]: value } as IWizPilotPatch;
447
- }
448
-
449
- private static findTargetEntity(snapshotArg: IWizSnapshot, requestArg: IServiceCallRequest): IIntegrationEntity | undefined {
450
- const entities = this.toEntities(snapshotArg);
451
- if (requestArg.target.entityId) {
452
- return entities.find((entityArg) => entityArg.id === requestArg.target.entityId || entityArg.uniqueId === requestArg.target.entityId);
453
- }
454
- if (requestArg.target.deviceId) {
455
- return entities.find((entityArg) => entityArg.deviceId === requestArg.target.deviceId && entityArg.platform === requestArg.domain)
456
- || entities.find((entityArg) => entityArg.deviceId === requestArg.target.deviceId && Boolean(entityArg.attributes?.writable))
457
- || entities.find((entityArg) => entityArg.deviceId === requestArg.target.deviceId);
458
- }
459
- return entities.find((entityArg) => entityArg.platform === requestArg.domain && Boolean(entityArg.attributes?.writable));
460
- }
461
-
462
- private static deviceFromManualEntry(entryArg: IWizManualEntry): IWizSnapshotDevice {
463
- return {
464
- id: entryArg.id,
465
- host: entryArg.host,
466
- port: entryArg.port || wizDefaultPort,
467
- mac: entryArg.mac || entryArg.macAddress || entryArg.deviceInfo?.mac,
468
- name: entryArg.name || entryArg.deviceInfo?.name,
469
- deviceInfo: {
470
- ...entryArg.deviceInfo,
471
- host: entryArg.host,
472
- port: entryArg.port || wizDefaultPort,
473
- mac: entryArg.mac || entryArg.macAddress || entryArg.deviceInfo?.mac,
474
- name: entryArg.name || entryArg.deviceInfo?.name,
475
- manufacturer: entryArg.manufacturer || entryArg.deviceInfo?.manufacturer,
476
- model: entryArg.model || entryArg.deviceInfo?.model,
477
- },
478
- pilot: entryArg.pilot,
479
- available: Boolean(entryArg.pilot),
480
- metadata: entryArg.metadata,
11
+ const pilot = snapshotArg.info.observedState;
12
+ const capabilities = snapshotArg.info.capabilities;
13
+ const features: plugins.shxInterfaces.data.IDeviceFeature[] = [];
14
+ const state: plugins.shxInterfaces.data.IDeviceState[] = [];
15
+ const add = (idArg: string, nameArg: string, capabilityArg: plugins.shxInterfaces.data.TDeviceCapability,
16
+ valueArg: plugins.shxInterfaces.data.TDeviceStateValue | undefined, writableArg: boolean, unitArg?: string): void => {
17
+ if (valueArg === undefined) return;
18
+ features.push({ id: idArg, name: nameArg, capability: capabilityArg, readable: true, writable: writableArg, unit: unitArg });
19
+ state.push({ featureId: idArg, value: valueArg, updatedAt: snapshotArg.observedAt });
481
20
  };
21
+ add('power', 'Power', 'switch', pilot.power, capabilities.power);
22
+ add('brightness', 'Brightness', 'light', pilot.brightness, capabilities.brightness, '%');
23
+ add('rgb', 'RGB', 'light', pilot.rgb ? `${pilot.rgb.red},${pilot.rgb.green},${pilot.rgb.blue}` : undefined, capabilities.rgb);
24
+ add('color_temperature', 'Observed colour temperature', 'sensor', pilot.colorTemperature, false, 'K');
25
+ add('scene_id', 'Observed scene ID', 'sensor', pilot.sceneId, false);
26
+ return [{ id: this.deviceId(snapshotArg), integrationDomain: 'wiz', protocol: 'udp', manufacturer: 'WiZ',
27
+ name: snapshotArg.name ?? snapshotArg.info.moduleName ?? 'WiZ', model: snapshotArg.info.moduleName,
28
+ features, state, online: true, metadata: {
29
+ homeId: snapshotArg.homeId, macAddress: snapshotArg.info.macAddress, host: snapshotArg.host, port: snapshotArg.port,
30
+ firmwareVersion: snapshotArg.info.firmwareVersion, deviceClass: snapshotArg.info.deviceClass,
31
+ observedAt: snapshotArg.observedAt, networkAuthenticated: false, physicalStateConfirmed: false,
32
+ } }];
482
33
  }
483
34
 
484
- private static explicitEntity(deviceArg: IWizSnapshotDevice, entityArg: IWizEntityRecord, usedIdsArg: Map<string, number>): IIntegrationEntity {
485
- const platform = this.corePlatform(entityArg.platform);
486
- const name = entityArg.name || this.deviceName(deviceArg);
487
- return this.entity(platform, name, this.deviceId(deviceArg), entityArg.uniqueId || `${this.uniqueId(platform, deviceArg)}_${entityArg.key || this.slug(name)}`, this.entityState(entityArg.state, platform), usedIdsArg, {
488
- ...this.baseAttributes(deviceArg),
489
- ...entityArg.attributes,
490
- wizPilotKey: entityArg.key,
491
- writable: entityArg.writable,
492
- }, entityArg.available !== false && deviceArg.available !== false, entityArg.entityId);
493
- }
494
-
495
- private static sensorEntity(deviceArg: IWizSnapshotDevice, sensorArg: IWizSensorRecord, usedIdsArg: Map<string, number>): IIntegrationEntity {
496
- const platform = sensorArg.platform || 'sensor';
497
- const state = platform === 'binary_sensor' ? sensorArg.value ? 'on' : 'off' : sensorArg.value ?? 'unknown';
498
- return this.entity(platform, sensorArg.name || `${this.deviceName(deviceArg)} ${this.title(sensorArg.key)}`, this.deviceId(deviceArg), `${this.uniqueId(platform, deviceArg)}_${this.slug(sensorArg.key)}`, state, usedIdsArg, {
499
- ...this.baseAttributes(deviceArg),
500
- wizSensorKey: sensorArg.key,
501
- wizPilotKey: sensorArg.writable ? sensorArg.key : undefined,
502
- deviceClass: sensorArg.deviceClass,
503
- unit: sensorArg.unit,
504
- writable: sensorArg.writable,
505
- }, sensorArg.available !== false && deviceArg.available !== false);
506
- }
507
-
508
- private static numberEntity(deviceArg: IWizSnapshotDevice, keyArg: string, nameArg: string, valueArg: unknown, usedIdsArg: Map<string, number>, attributesArg: Record<string, unknown>): IIntegrationEntity {
509
- return this.entity('number', nameArg, this.deviceId(deviceArg), `${this.uniqueId('number', deviceArg)}_${this.slug(keyArg)}`, valueArg ?? 'unknown', usedIdsArg, {
510
- ...this.baseAttributes(deviceArg),
511
- ...attributesArg,
512
- writable: true,
513
- }, deviceArg.available !== false);
514
- }
515
-
516
- private static buttonEntity(deviceArg: IWizSnapshotDevice, buttonArg: IWizButtonRecord, usedIdsArg: Map<string, number>): IIntegrationEntity {
517
- const name = buttonArg.name || `${this.deviceName(deviceArg)} ${this.title(buttonArg.key)}`;
518
- return this.entity('button', name, this.deviceId(deviceArg), `${this.uniqueId('button', deviceArg)}_${this.slug(buttonArg.key)}`, buttonArg.value ?? 'idle', usedIdsArg, {
519
- ...this.baseAttributes(deviceArg),
520
- wizButtonKey: buttonArg.key,
521
- lastPressedAt: buttonArg.lastPressedAt,
522
- writable: true,
523
- }, buttonArg.available !== false && deviceArg.available !== false);
524
- }
525
-
526
- private static entity(platformArg: TEntityPlatform, nameArg: string, deviceIdArg: string, uniqueIdArg: string, stateArg: unknown, usedIdsArg: Map<string, number>, attributesArg: Record<string, unknown>, availableArg: boolean, explicitEntityIdArg?: string): IIntegrationEntity {
527
- return {
528
- id: explicitEntityIdArg || this.entityId(platformArg, nameArg, usedIdsArg),
529
- uniqueId: uniqueIdArg,
530
- integrationDomain: 'wiz',
531
- deviceId: deviceIdArg,
532
- platform: platformArg,
533
- name: nameArg,
534
- state: stateArg,
535
- attributes: attributesArg,
536
- available: availableArg,
537
- };
538
- }
539
-
540
- private static buttons(deviceArg: IWizSnapshotDevice): IWizButtonRecord[] {
541
- const buttons = [...(deviceArg.buttons || [])];
542
- const source = typeof deviceArg.pilot?.src === 'string' ? deviceArg.pilot.src : undefined;
543
- if (source && wizButtonSources[source]) {
544
- buttons.push({ key: wizButtonSources[source], name: `${this.deviceName(deviceArg)} Button ${this.title(wizButtonSources[source])}`, value: source });
545
- }
546
- return buttons;
547
- }
548
-
549
- private static deviceInfo(deviceArg: IWizSnapshotDevice): IWizDeviceInfo {
550
- return {
551
- ...deviceArg.deviceInfo,
552
- id: deviceArg.deviceInfo?.id || deviceArg.id,
553
- host: deviceArg.host || deviceArg.deviceInfo?.host,
554
- port: deviceArg.port || deviceArg.deviceInfo?.port || wizDefaultPort,
555
- mac: deviceArg.mac || deviceArg.deviceInfo?.mac || deviceArg.pilot?.mac,
556
- name: deviceArg.name || deviceArg.deviceInfo?.name,
557
- };
558
- }
559
-
560
- private static features(deviceArg: IWizSnapshotDevice): IWizDeviceFeatures {
561
- const info = this.deviceInfo(deviceArg);
562
- const pilot = deviceArg.pilot || {};
563
- const lowerType = String(info.bulbType || info.model || info.moduleName || '').toLowerCase();
564
- const isSocket = this.isSocket(deviceArg);
565
- return {
566
- light: !isSocket,
567
- switch: isSocket,
568
- brightness: typeof pilot.dimming === 'number' || !isSocket,
569
- color: ['r', 'g', 'b'].every((keyArg) => typeof pilot[keyArg] === 'number') || lowerType.includes('rgb'),
570
- colorTemp: typeof pilot.temp === 'number' || lowerType.includes('tw') || lowerType.includes('tunable'),
571
- effect: typeof pilot.sceneId === 'number' || typeof pilot.schdPsetId === 'number' || info.features?.effect,
572
- fan: typeof pilot.fanState === 'number' || info.features?.fan,
573
- power: typeof pilot.pc === 'number' || info.powerMonitoring || info.features?.power,
574
- occupancy: pilot.src === 'pir' || info.features?.occupancy,
575
- button: Boolean(deviceArg.buttons?.length) || Boolean(pilot.src && wizButtonSources[String(pilot.src)]) || info.features?.button,
576
- dualHead: typeof pilot.ratio === 'number' || info.features?.dualHead,
577
- ...info.features,
578
- };
579
- }
580
-
581
- private static isSocket(deviceArg: IWizSnapshotDevice): boolean {
582
- const info = this.deviceInfo(deviceArg);
583
- const text = [info.bulbType, info.model, info.moduleName, info.typeId].filter((valueArg) => valueArg !== undefined).join(' ').toLowerCase();
584
- return info.isSocket === true || info.features?.switch === true || text.includes('socket') || text.includes('plug');
585
- }
586
-
587
- private static deviceId(deviceArg: IWizSnapshotDevice): string {
588
- return `wiz.device.${this.slug(deviceArg.id || this.mac(deviceArg) || deviceArg.host || this.deviceName(deviceArg))}`;
589
- }
590
-
591
- private static uniqueId(platformArg: string, deviceArg: IWizSnapshotDevice): string {
592
- return `wiz_${platformArg}_${this.slug(this.mac(deviceArg) || deviceArg.id || deviceArg.host || this.deviceName(deviceArg))}`;
593
- }
594
-
595
- private static deviceName(deviceArg: IWizSnapshotDevice): string {
596
- const info = this.deviceInfo(deviceArg);
597
- return info.name || deviceArg.name || (this.mac(deviceArg) ? `WiZ ${this.shortMac(this.mac(deviceArg))}` : 'WiZ device');
598
- }
599
-
600
- private static mac(deviceArg: IWizSnapshotDevice): string | undefined {
601
- return this.normalizeMac(deviceArg.mac || deviceArg.deviceInfo?.mac || deviceArg.pilot?.mac);
602
- }
603
-
604
- private static baseAttributes(deviceArg: IWizSnapshotDevice): Record<string, unknown> {
605
- const info = this.deviceInfo(deviceArg);
606
- return {
607
- wizDeviceId: this.deviceId(deviceArg),
608
- wizHost: info.host,
609
- wizPort: info.port || wizDefaultPort,
610
- wizMac: this.mac(deviceArg),
611
- moduleName: info.moduleName,
612
- fwVersion: info.fwVersion,
613
- model: info.model,
614
- };
615
- }
616
-
617
- private static sceneId(pilotArg: IWizPilotState): number | undefined {
618
- if (typeof pilotArg.schdPsetId === 'number') {
619
- return 1000;
620
- }
621
- return typeof pilotArg.sceneId === 'number' && pilotArg.sceneId > 0 ? pilotArg.sceneId : undefined;
622
- }
623
-
624
- private static sceneName(pilotArg: IWizPilotState): string | undefined {
625
- const sceneId = this.sceneId(pilotArg);
626
- return sceneId === undefined ? undefined : wizSceneNamesById.get(sceneId) || `Scene ${sceneId}`;
627
- }
628
-
629
- private static fanPercentage(deviceArg: IWizSnapshotDevice, pilotArg: IWizPilotState): number | undefined {
630
- if (typeof pilotArg.fanSpeed !== 'number') {
631
- return undefined;
632
- }
633
- const max = this.deviceInfo(deviceArg).fanSpeedRange || 6;
634
- return this.clamp(Math.round(pilotArg.fanSpeed / max * 100), 0, 100);
635
- }
636
-
637
- private static percentageToFanSpeed(deviceArg: IWizSnapshotDevice | undefined, percentageArg: number): number {
638
- const max = deviceArg ? this.deviceInfo(deviceArg).fanSpeedRange || 6 : 6;
639
- return this.clamp(Math.ceil(this.clamp(percentageArg, 0, 100) / 100 * max), 1, max);
640
- }
641
-
642
- private static percentToByte(valueArg: unknown): number | undefined {
643
- return typeof valueArg === 'number' ? this.clamp(Math.round(valueArg / 100 * 255), 0, 255) : undefined;
644
- }
645
-
646
- private static percentageFromData(dataArg: Record<string, unknown> | undefined, serviceArg: string): number | undefined {
647
- const pct = this.numberFromData(dataArg, ['percentage', 'brightness_pct']);
648
- if (pct !== undefined) {
649
- return this.clamp(pct, 0, 100);
650
- }
651
- const brightness = this.numberFromData(dataArg, serviceArg === 'set_brightness' ? ['brightness', 'value'] : ['brightness']);
652
- return brightness === undefined ? undefined : this.clamp(Math.round(brightness / 255 * 100), 0, 100);
653
- }
654
-
655
- private static kelvinFromData(dataArg: Record<string, unknown> | undefined): number | undefined {
656
- const direct = this.numberFromData(dataArg, ['color_temp_kelvin', 'kelvin', 'temp', 'color_temperature']);
657
- if (direct !== undefined) {
658
- return Math.round(direct);
659
- }
660
- const mired = this.numberFromData(dataArg, ['color_temp', 'color_temp_mired']);
661
- return mired && mired > 0 ? Math.round(1000000 / mired) : undefined;
662
- }
663
-
664
- private static rgb(pilotArg: IWizPilotState): number[] | undefined {
665
- return typeof pilotArg.r === 'number' && typeof pilotArg.g === 'number' && typeof pilotArg.b === 'number'
666
- ? [pilotArg.r, pilotArg.g, pilotArg.b]
667
- : undefined;
668
- }
669
-
670
- private static rgbRecord(pilotArg: IWizPilotState): Record<string, unknown> | undefined {
671
- const rgb = this.rgb(pilotArg);
672
- return rgb ? { r: rgb[0], g: rgb[1], b: rgb[2], c: pilotArg.c, w: pilotArg.w } : undefined;
673
- }
674
-
675
- private static rgbFromData(dataArg: Record<string, unknown> | undefined, keyArg: string): number[] | undefined {
676
- const value = dataArg?.[keyArg];
677
- if (!Array.isArray(value) || value.length < 3) {
678
- return undefined;
679
- }
680
- const numbers = value.map((valueArg) => typeof valueArg === 'number' && Number.isFinite(valueArg) ? this.clamp(Math.round(valueArg), 0, 255) : undefined);
681
- return numbers.every((valueArg) => valueArg !== undefined) ? numbers as number[] : undefined;
682
- }
683
-
684
- private static valueFromData(dataArg: Record<string, unknown> | undefined, keysArg: string[]): unknown {
685
- for (const key of keysArg) {
686
- if (dataArg && key in dataArg) {
687
- return dataArg[key];
688
- }
689
- }
690
- return undefined;
691
- }
692
-
693
- private static numberFromData(dataArg: Record<string, unknown> | undefined, keysArg: string[]): number | undefined {
694
- const value = this.valueFromData(dataArg, keysArg);
695
- return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
696
- }
697
-
698
- private static stringFromData(dataArg: Record<string, unknown> | undefined, keysArg: string[]): string | undefined {
699
- const value = this.valueFromData(dataArg, keysArg);
700
- return typeof value === 'string' && value.trim() ? value.trim() : undefined;
701
- }
702
-
703
- private static corePlatform(platformArg: TEntityPlatform | string): TEntityPlatform {
704
- const platform = platformArg.toLowerCase();
705
- const allowed: TEntityPlatform[] = ['light', 'switch', 'sensor', 'binary_sensor', 'button', 'climate', 'cover', 'fan', 'media_player', 'number', 'select', 'text', 'update'];
706
- return allowed.includes(platform as TEntityPlatform) ? platform as TEntityPlatform : 'sensor';
707
- }
708
-
709
- private static entityState(valueArg: unknown, platformArg: TEntityPlatform): unknown {
710
- if (platformArg === 'light' || platformArg === 'switch' || platformArg === 'fan' || platformArg === 'binary_sensor') {
711
- return typeof valueArg === 'boolean' ? valueArg ? 'on' : 'off' : valueArg ?? 'unknown';
712
- }
713
- return valueArg ?? 'unknown';
714
- }
715
-
716
- private static pushDeviceState(stateArg: plugins.shxInterfaces.data.IDeviceState[], featureIdArg: string, valueArg: unknown, updatedAtArg: string): void {
717
- if (valueArg === undefined) {
718
- return;
719
- }
720
- stateArg.push({ featureId: featureIdArg, value: this.deviceStateValue(valueArg), updatedAt: updatedAtArg });
721
- }
722
-
723
- private static deviceStateValue(valueArg: unknown): plugins.shxInterfaces.data.TDeviceStateValue {
724
- if (typeof valueArg === 'string' || typeof valueArg === 'number' || typeof valueArg === 'boolean' || valueArg === null || this.isRecord(valueArg)) {
725
- return valueArg;
726
- }
727
- return valueArg === undefined ? null : String(valueArg);
728
- }
729
-
730
- private static entityId(platformArg: TEntityPlatform, nameArg: string, usedIdsArg: Map<string, number>): string {
731
- const base = `${platformArg}.${this.slug(nameArg)}`;
732
- const count = usedIdsArg.get(base) || 0;
733
- usedIdsArg.set(base, count + 1);
734
- return count ? `${base}_${count + 1}` : base;
735
- }
736
-
737
- private static shortMac(valueArg?: string): string {
738
- return (valueArg || '').replace(/[^a-fA-F0-9]/g, '').slice(-6).toUpperCase();
739
- }
740
-
741
- private static normalizeMac(valueArg?: string): string | undefined {
742
- if (!valueArg) {
743
- return undefined;
744
- }
745
- const compact = valueArg.replace(/[^a-fA-F0-9]/g, '').toLowerCase();
746
- return compact.length === 12 ? compact.match(/.{1,2}/g)?.join(':') : valueArg.toLowerCase();
747
- }
748
-
749
- private static title(valueArg: string): string {
750
- return valueArg.replace(/_/g, ' ').replace(/\b\w/g, (matchArg) => matchArg.toUpperCase());
751
- }
752
-
753
- private static slug(valueArg: string): string {
754
- return valueArg.toLowerCase().replace(/[^a-z0-9]+/g, '_').replace(/^_+|_+$/g, '') || 'wiz';
755
- }
756
-
757
- private static clamp(valueArg: number, minArg: number, maxArg: number): number {
758
- return Math.max(minArg, Math.min(maxArg, valueArg));
759
- }
760
-
761
- private static isRecord(valueArg: unknown): valueArg is Record<string, unknown> {
762
- return typeof valueArg === 'object' && valueArg !== null && !Array.isArray(valueArg);
35
+ public static toEntities(snapshotArg: IWizSnapshot): IIntegrationEntity[] {
36
+ const pilot = snapshotArg.info.observedState;
37
+ return [{ id: this.entityId(snapshotArg), uniqueId: this.entityId(snapshotArg), deviceId: this.deviceId(snapshotArg), integrationDomain: 'wiz',
38
+ platform: snapshotArg.info.deviceClass === 'socket' ? 'switch' : snapshotArg.info.deviceClass === 'unknown' ? 'sensor' : 'light',
39
+ name: snapshotArg.name ?? snapshotArg.info.moduleName ?? 'WiZ', state: pilot.power === undefined ? null : pilot.power ? 'on' : 'off', available: true,
40
+ attributes: { homeId: snapshotArg.homeId, writable: Object.values(snapshotArg.info.capabilities).some(Boolean),
41
+ capabilities: snapshotArg.info.capabilities, brightness: pilot.brightness, rgb: pilot.rgb,
42
+ colorTemperature: pilot.colorTemperature, sceneId: pilot.sceneId, observedAt: snapshotArg.observedAt,
43
+ networkAuthenticated: false, physicalStateConfirmed: false },
44
+ }];
45
+ }
46
+
47
+ public static controlForService(snapshotArg: IWizSnapshot, requestArg: IServiceCallRequest): TWizControl {
48
+ const request = wizRecord(requestArg, ['domain', 'service', 'target', 'data']);
49
+ const target = wizRecord(request.target, ['deviceId', 'entityId']);
50
+ if (target.deviceId === undefined && target.entityId === undefined ||
51
+ target.deviceId !== undefined && target.deviceId !== this.deviceId(snapshotArg) ||
52
+ target.entityId !== undefined && target.entityId !== this.entityId(snapshotArg)) throw new TypeError('WiZ requires an exact owned home/device/entity target.');
53
+ const domain = snapshotArg.info.deviceClass === 'socket' ? 'switch' : 'light';
54
+ if (request.domain !== domain) throw new TypeError('WiZ service domain must match the observed device class.');
55
+ if (request.service === 'turn_on' || request.service === 'turn_off') {
56
+ if (request.data !== undefined) wizRecord(request.data, []);
57
+ return this.requireCapability(snapshotArg, wizControl({ feature: 'power', value: request.service === 'turn_on' }));
58
+ }
59
+ if (request.service === 'set_brightness') {
60
+ const data = wizRecord(request.data, ['brightness']);
61
+ return this.requireCapability(snapshotArg, wizControl({ feature: 'brightness', value: data.brightness }));
62
+ }
63
+ if (request.service === 'set_rgb') {
64
+ const data = wizRecord(request.data, ['rgb']);
65
+ return this.requireCapability(snapshotArg, wizControl({ feature: 'rgb', value: data.rgb }));
66
+ }
67
+ throw new TypeError('WiZ supports only explicit power, brightness and RGB services.');
68
+ }
69
+
70
+ public static controlForFeature(snapshotArg: IWizSnapshot, requestArg: IDeviceFeatureWriteRequest): TWizControl {
71
+ const request = wizRecord(requestArg, ['device', 'feature', 'value']);
72
+ const device = wizRecord(request.device);
73
+ const feature = wizRecord(request.feature);
74
+ const metadata = wizRecord(device.metadata);
75
+ if (device.id !== this.deviceId(snapshotArg) || device.integrationDomain !== 'wiz' || metadata.homeId !== snapshotArg.homeId) {
76
+ throw new TypeError('WiZ feature write must target the exact configured home and device.');
77
+ }
78
+ let value = request.value;
79
+ if (feature.id === 'rgb') {
80
+ if (typeof value !== 'string' || !/^(0|[1-9]\d{0,2}),(0|[1-9]\d{0,2}),(0|[1-9]\d{0,2})$/.test(value)) throw new TypeError('WiZ RGB features require three exact decimal bytes.');
81
+ const channels = value.split(',').map(Number);
82
+ value = { red: channels[0], green: channels[1], blue: channels[2] };
83
+ }
84
+ return this.requireCapability(snapshotArg, wizControl({ feature: feature.id, value }));
85
+ }
86
+
87
+ private static requireCapability(snapshotArg: IWizSnapshot, controlArg: TWizControl): TWizControl {
88
+ if (!snapshotArg.info.capabilities[controlArg.feature]) throw new TypeError('WiZ control is unsupported by the observed device.');
89
+ return controlArg;
763
90
  }
764
91
  }