@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,9 +1,55 @@
1
- import { SimpleLocalConfigFlow } from '../../core/index.js';
2
- import type { IOnkyoConfig } from './onkyo.types.js';
3
- import { onkyoProfile } from './onkyo.types.js';
1
+ import { NativeIntegrationOwner, type NativeIntegrationScope } from '../../core/classes.nativeintegrationowner.js';
2
+ import type { IConfigFlow, IConfigFlowStep, IDiscoveryCandidate, INativeConfigFlowContext } from '../../core/types.js';
3
+ import { OnkyoClient } from './onkyo.classes.client.js';
4
+ import { createOnkyoDiscoveryDescriptor } from './onkyo.discovery.js';
5
+ import type { IOnkyoConfig, IOnkyoIntegrationOptions } from './onkyo.types.js';
6
+ import { normalizeOnkyoConfig, onkyoKeys, onkyoRecord } from './onkyo.validation.js';
4
7
 
5
- export class OnkyoConfigFlow extends SimpleLocalConfigFlow<IOnkyoConfig> {
6
- constructor() {
7
- super(onkyoProfile);
8
+ export class OnkyoConfigFlow implements IConfigFlow<IOnkyoConfig> {
9
+ readonly #scope: NativeIntegrationScope;
10
+
11
+ constructor(optionsArg: IOnkyoIntegrationOptions = {}, scopeArg?: NativeIntegrationScope) {
12
+ this.#scope = scopeArg ?? new NativeIntegrationOwner('onkyo', optionsArg).createFlowScope();
13
+ }
14
+
15
+ public async start(candidateArg: IDiscoveryCandidate, contextArg: INativeConfigFlowContext): Promise<IConfigFlowStep<IOnkyoConfig>> {
16
+ const context = this.#scope.admit(contextArg);
17
+ // The owned pure validator captures the selected candidate before yielding.
18
+ const validation = createOnkyoDiscoveryDescriptor().getValidators()[0].validate(candidateArg, {});
19
+ return this.#scope.run<IConfigFlowStep<IOnkyoConfig>>(context, undefined, async (leaseArg) => {
20
+ const matched = await validation;
21
+ leaseArg.assertOpen();
22
+ if (!matched.matched || !matched.candidate) return { kind: 'error', error: matched.reason };
23
+ const candidate = matched.candidate;
24
+ return {
25
+ kind: 'form', title: 'Connect selected Onkyo main zone',
26
+ description: 'Acknowledge the cleartext LAN protocol and set an absolute raw-volume ceiling. Home, endpoint, MAC and model are fixed by the host and selected candidate.',
27
+ fields: [
28
+ { name: 'allowUnencryptedLan', label: 'Acknowledge unauthenticated cleartext LAN', type: 'boolean', required: true },
29
+ { name: 'volumeLimitRaw', label: 'Maximum integer raw volume (0–100)', type: 'number', required: true },
30
+ { name: 'name', label: 'Name', type: 'text' },
31
+ ],
32
+ submit: async (valuesArg) => {
33
+ try {
34
+ const values = onkyoRecord(valuesArg, 'config flow values');
35
+ onkyoKeys(values, ['homeId', 'allowUnencryptedLan', 'volumeLimitRaw', 'name', 'requestTimeoutMs', 'maxPendingOperations']);
36
+ if (values.homeId !== undefined && values.homeId !== context.homeId) throw new TypeError('Onkyo submitted home must match the host-selected home.');
37
+ const config = normalizeOnkyoConfig({ ...values, homeId: context.homeId, host: candidate.host, port: candidate.port, macAddress: candidate.macAddress, model: candidate.model });
38
+ return await this.#scope.run<IConfigFlowStep<IOnkyoConfig>>(context, config.homeId, async (operationArg) => {
39
+ const client = new OnkyoClient(config, operationArg.context, operationArg.signal);
40
+ operationArg.own(() => client.destroy());
41
+ await client.getSnapshot(operationArg.signal);
42
+ operationArg.assertOpen();
43
+ return { kind: 'done', title: 'Onkyo receiver validated', config };
44
+ });
45
+ } catch (errorArg) {
46
+ return { kind: 'error', error: errorArg instanceof Error ? errorArg.message : 'Onkyo setup validation failed.' };
47
+ }
48
+ },
49
+ };
50
+ });
8
51
  }
52
+
53
+ public destroy(): Promise<void> { return this.#scope.close(); }
54
+ public retryCleanup(): Promise<void> { return this.#scope.retryCleanup(); }
9
55
  }
@@ -1,23 +1,132 @@
1
- import { SimpleLocalIntegration, SimpleLocalRuntime, type IIntegrationRuntime, type IIntegrationSetupContext } from '../../core/index.js';
1
+ import * as plugins from '../../plugins.js';
2
+ import { BaseIntegration } from '../../core/classes.baseintegration.js';
3
+ import { NativeIntegrationOwner } from '../../core/classes.nativeintegrationowner.js';
4
+ import type { IDeviceFeatureWriteRequest, IIntegrationEntity, IIntegrationEvent, IIntegrationRuntime, INativeIntegrationSetupContext, IServiceCallRequest, IServiceCallResult } from '../../core/types.js';
2
5
  import { OnkyoClient } from './onkyo.classes.client.js';
3
6
  import { OnkyoConfigFlow } from './onkyo.classes.configflow.js';
4
7
  import { createOnkyoDiscoveryDescriptor } from './onkyo.discovery.js';
5
- import type { IOnkyoConfig } from './onkyo.types.js';
6
- import { onkyoDomain, onkyoProfile } from './onkyo.types.js';
8
+ import { OnkyoMapper } from './onkyo.mapper.js';
9
+ import type { IOnkyoConfig, IOnkyoIntegrationOptions, IOnkyoSnapshot } from './onkyo.types.js';
10
+ import { onkyoProfile } from './onkyo.types.js';
11
+ import { normalizeOnkyoConfig, onkyoBoolean, onkyoInputId, onkyoInteger, onkyoKeys, onkyoRecord } from './onkyo.validation.js';
7
12
 
8
- export class OnkyoIntegration extends SimpleLocalIntegration<IOnkyoConfig> {
9
- public readonly domain = onkyoDomain;
13
+ export class OnkyoIntegration extends BaseIntegration<IOnkyoConfig> {
14
+ public readonly domain = 'onkyo';
15
+ public readonly displayName = 'Onkyo';
16
+ public readonly status = 'control-runtime' as const;
17
+ public readonly metadata = onkyoProfile.metadata;
10
18
  public readonly discoveryDescriptor = createOnkyoDiscoveryDescriptor();
11
- public readonly configFlow = new OnkyoConfigFlow();
19
+ public readonly configFlow: OnkyoConfigFlow;
20
+ readonly #owner: NativeIntegrationOwner;
12
21
 
13
- constructor() {
14
- super(onkyoProfile);
22
+ constructor(optionsArg: IOnkyoIntegrationOptions = {}) {
23
+ super();
24
+ this.#owner = new NativeIntegrationOwner('onkyo', optionsArg);
25
+ this.configFlow = new OnkyoConfigFlow(optionsArg, this.#owner.createFlowScope());
15
26
  }
16
27
 
17
- public async setup(configArg: IOnkyoConfig, contextArg: IIntegrationSetupContext): Promise<IIntegrationRuntime> {
18
- void contextArg;
19
- return new SimpleLocalRuntime(onkyoProfile, new OnkyoClient(configArg));
28
+ public setup(configArg: IOnkyoConfig, contextArg: INativeIntegrationSetupContext): Promise<IIntegrationRuntime> {
29
+ let config: ReturnType<typeof normalizeOnkyoConfig>;
30
+ try {
31
+ config = normalizeOnkyoConfig(configArg);
32
+ } catch (errorArg) { return Promise.reject(errorArg); }
33
+ return this.#owner.runSetup(contextArg, config.homeId, async (leaseArg) => {
34
+ const client = new OnkyoClient(config, leaseArg.context, leaseArg.signal);
35
+ leaseArg.own(() => client.destroy());
36
+ const snapshot = await client.getSnapshot(leaseArg.signal);
37
+ leaseArg.assertOpen();
38
+ const runtime = new OnkyoRuntime(client, snapshot, () => leaseArg.close());
39
+ leaseArg.promoteToRuntime();
40
+ return runtime;
41
+ });
20
42
  }
43
+ public destroy(): Promise<void> { return this.#owner.close(); }
44
+ public retryCleanup(): Promise<void> { return this.#owner.retryCleanup(); }
21
45
  }
22
-
23
46
  export class HomeAssistantOnkyoIntegration extends OnkyoIntegration {}
47
+
48
+ class OnkyoRuntime implements IIntegrationRuntime {
49
+ public readonly domain = 'onkyo';
50
+ readonly #deviceId: string;
51
+ readonly #entityId: string;
52
+ #closePromise?: Promise<void>;
53
+ constructor(private readonly client: OnkyoClient, snapshotArg: IOnkyoSnapshot, private readonly closeLease: () => Promise<void>) {
54
+ this.#deviceId = OnkyoMapper.deviceId(snapshotArg);
55
+ this.#entityId = OnkyoMapper.mediaEntityId(snapshotArg);
56
+ }
57
+ public isHealthy(): boolean { return this.client.isHealthy(); }
58
+ public async devices(signalArg?: AbortSignal): Promise<plugins.shxInterfaces.data.IDeviceDefinition[]> { return OnkyoMapper.toDevices(await this.client.getSnapshot(signalArg)); }
59
+ public async entities(): Promise<IIntegrationEntity[]> { return OnkyoMapper.toEntities(await this.client.getSnapshot()); }
60
+ public async subscribe(handlerArg: (eventArg: IIntegrationEvent) => void, signalArg?: AbortSignal): Promise<() => Promise<void>> {
61
+ if (typeof handlerArg !== 'function') throw new TypeError('Onkyo runtime subscriber must be a function.');
62
+ const unsubscribe = this.client.subscribe((eventArg) => {
63
+ const event: IIntegrationEvent = {
64
+ type: eventArg.type === 'error' ? 'error' : 'state_changed', integrationDomain: 'onkyo', deviceId: this.#deviceId,
65
+ entityId: this.#entityId, timestamp: Date.now(),
66
+ data: eventArg.type === 'snapshot' ? { snapshot: eventArg.snapshot, entity: OnkyoMapper.toEntities(eventArg.snapshot)[0] } :
67
+ eventArg.type === 'control' ? { observation: eventArg.observation } : { message: eventArg.error.message },
68
+ };
69
+ handlerArg(event);
70
+ }, signalArg);
71
+ return async () => unsubscribe();
72
+ }
73
+ public async callService(requestArg: IServiceCallRequest): Promise<IServiceCallResult> {
74
+ try {
75
+ const request = onkyoRecord(requestArg, 'service request');
76
+ onkyoKeys(request, ['domain', 'service', 'target', 'data']);
77
+ if (typeof request.domain !== 'string' || typeof request.service !== 'string') throw new TypeError('Onkyo service domain and service must be strings.');
78
+ this.#assertTarget(request.target);
79
+ const data = request.data === undefined ? {} : onkyoRecord(request.data, 'service data');
80
+ if (request.domain === 'onkyo' && ['status', 'snapshot', 'refresh'].includes(request.service)) {
81
+ onkyoKeys(data, []); return { success: true, data: await this.client.getSnapshot() };
82
+ }
83
+ if (request.domain !== 'onkyo' && request.domain !== 'media_player') throw new TypeError('Onkyo service domain is unsupported.');
84
+ if (request.service === 'set_power') {
85
+ onkyoKeys(data, ['power']); return observed(await this.client.setPower(onkyoBoolean(data.power, 'power')));
86
+ }
87
+ if (request.service === 'set_mute' || request.service === 'volume_mute') {
88
+ onkyoKeys(data, ['muted']); return observed(await this.client.setMuted(onkyoBoolean(data.muted, 'mute')));
89
+ }
90
+ if (request.service === 'set_volume_raw') {
91
+ onkyoKeys(data, ['volumeRaw']); return observed(await this.client.setVolume(onkyoInteger(data.volumeRaw, 0, 100, 'raw volume')));
92
+ }
93
+ if (request.service === 'set_input' || request.service === 'select_source') {
94
+ onkyoKeys(data, ['inputId']); return observed(await this.client.setInput(onkyoInputId(data.inputId)));
95
+ }
96
+ throw new TypeError('Onkyo service is unsupported.');
97
+ } catch (errorArg) { return failed(errorArg); }
98
+ }
99
+ public async writeFeature(requestArg: IDeviceFeatureWriteRequest, signalArg?: AbortSignal): Promise<IServiceCallResult> {
100
+ try {
101
+ const request = onkyoRecord(requestArg, 'feature write');
102
+ onkyoKeys(request, ['device', 'feature', 'value']);
103
+ const device = onkyoRecord(request.device, 'feature device');
104
+ const feature = onkyoRecord(request.feature, 'feature');
105
+ if (device.id !== this.#deviceId || device.integrationDomain !== 'onkyo') throw new TypeError('Onkyo feature device is not owned by this home runtime.');
106
+ if (typeof feature.id !== 'string') throw new TypeError('Onkyo feature id must be a string.');
107
+ const value = request.value;
108
+ if (typeof value !== 'boolean' && typeof value !== 'number' && typeof value !== 'string') throw new TypeError('Onkyo control requires an explicit primitive value.');
109
+ return observed(await this.client.writeFeature(feature.id, value, signalArg));
110
+ } catch (errorArg) { return failed(errorArg); }
111
+ }
112
+ public destroy(): Promise<void> {
113
+ this.#closePromise ??= Promise.resolve().then(() => this.closeLease());
114
+ return this.#closePromise;
115
+ }
116
+ #assertTarget(valueArg: unknown): void {
117
+ const target = onkyoRecord(valueArg, 'service target');
118
+ onkyoKeys(target, ['deviceId', 'entityId']);
119
+ if (target.deviceId === undefined && target.entityId === undefined ||
120
+ target.deviceId !== undefined && target.deviceId !== this.#deviceId ||
121
+ target.entityId !== undefined && target.entityId !== this.#entityId) throw new TypeError('Onkyo services require an exact owned device or main-zone entity target.');
122
+ }
123
+ }
124
+ function observed(observationArg: plugins.ecobridgeDeviceManager.IOnkyoControlObservation): IServiceCallResult {
125
+ return { success: true, data: { ...observationArg } };
126
+ }
127
+ function failed(errorArg: unknown): IServiceCallResult {
128
+ return { success: false, error: errorArg instanceof Error ? errorArg.message : 'Onkyo operation failed.', data: {
129
+ effectOutcome: errorArg instanceof plugins.ecobridgeDeviceManager.OnkyoProtocolError ? errorArg.effectOutcome : 'not-sent',
130
+ code: errorArg instanceof plugins.ecobridgeDeviceManager.OnkyoProtocolError ? errorArg.code : 'INVALID_OPERATION',
131
+ } };
132
+ }
@@ -1,4 +1,42 @@
1
- import { createSimpleLocalDiscoveryDescriptor } from '../../core/index.js';
2
- import { onkyoProfile } from './onkyo.types.js';
1
+ import * as plugins from '../../plugins.js';
2
+ import { DiscoveryDescriptor } from '../../core/classes.discoverydescriptor.js';
3
+ import type { IDiscoveryCandidate, IDiscoveryMatch } from '../../core/types.js';
4
+ import type { IOnkyoSelectedProbeOptions } from './onkyo.types.js';
5
+ import { onkyoHost, onkyoInteger, onkyoKeys, onkyoName, onkyoRecord, readOnkyoEndpoint } from './onkyo.validation.js';
3
6
 
4
- export const createOnkyoDiscoveryDescriptor = () => createSimpleLocalDiscoveryDescriptor(onkyoProfile);
7
+ function matchCandidate(valueArg: unknown): IDiscoveryMatch {
8
+ try {
9
+ const input = onkyoRecord(valueArg, 'discovery candidate');
10
+ if (input.source !== 'manual' && input.source !== 'custom' || input.integrationDomain !== 'onkyo') {
11
+ return { matched: false, confidence: 'low', reason: 'An explicit manual/custom Onkyo candidate is required.' };
12
+ }
13
+ const candidate: IDiscoveryCandidate = {
14
+ source: input.source, integrationDomain: 'onkyo', ...readOnkyoEndpoint(input.host, input.macAddress, input.model, input.port),
15
+ name: input.name === undefined ? undefined : onkyoName(input.name, 'candidate name'),
16
+ };
17
+ return { matched: true, confidence: 'medium', reason: 'Explicit endpoint/MAC/model binding; live identity and main zone are checked during setup.', candidate };
18
+ } catch (errorArg) {
19
+ return { matched: false, confidence: 'low', reason: errorArg instanceof Error ? errorArg.message : 'Invalid Onkyo candidate.' };
20
+ }
21
+ }
22
+
23
+ export function createOnkyoDiscoveryDescriptor(): DiscoveryDescriptor {
24
+ return new DiscoveryDescriptor({ integrationDomain: 'onkyo', displayName: 'Onkyo' })
25
+ .addMatcher({ id: 'onkyo-manual-match', source: 'manual', matches: async (inputArg) => matchCandidate(inputArg) })
26
+ .addMatcher({ id: 'onkyo-custom-match', source: 'custom', matches: async (inputArg) => matchCandidate(inputArg) })
27
+ .addValidator({ id: 'onkyo-explicit-endpoint', validate: async (candidateArg) => matchCandidate(candidateArg) });
28
+ }
29
+
30
+ /** One explicitly selected unicast UDP probe; TCP setup still validates the chosen identity. */
31
+ export async function probeSelectedOnkyo(optionsArg: IOnkyoSelectedProbeOptions): Promise<IDiscoveryCandidate> {
32
+ const options = onkyoRecord(optionsArg, 'selected probe options');
33
+ onkyoKeys(options, ['host', 'port', 'requestTimeoutMs', 'signal']);
34
+ if (options.signal !== undefined && !(options.signal instanceof AbortSignal)) throw new TypeError('Onkyo probe signal must be an AbortSignal.');
35
+ const advertisement = await plugins.ecobridgeDeviceManager.probeOnkyo({
36
+ address: onkyoHost(options.host), port: options.port === undefined ? undefined : onkyoInteger(options.port, 1, 65535, 'probe port'),
37
+ timeoutMs: options.requestTimeoutMs === undefined ? undefined : onkyoInteger(options.requestTimeoutMs, 1, 60000, 'probe deadline'),
38
+ signal: options.signal,
39
+ });
40
+ return { source: 'custom', integrationDomain: 'onkyo', host: advertisement.address, port: advertisement.port,
41
+ model: advertisement.model, macAddress: advertisement.macAddress, manufacturer: 'Onkyo', metadata: { area: advertisement.area } };
42
+ }
@@ -1,26 +1,53 @@
1
- import type * as shxInterfaces from '@smarthome.exchange/interfaces';
2
- import { SimpleLocalMapper, type IIntegrationEntity, type ISimpleLocalSnapshot, type ISimpleLocalSnapshotOptions, type TSimpleLocalRawData } from '../../core/index.js';
3
- import type { IOnkyoConfig } from './onkyo.types.js';
4
- import { onkyoProfile } from './onkyo.types.js';
1
+ import type * as plugins from '../../plugins.js';
2
+ import type { IIntegrationEntity } from '../../core/types.js';
3
+ import type { IOnkyoSnapshot } from './onkyo.types.js';
5
4
 
6
5
  export class OnkyoMapper {
7
- public static toSnapshot(optionsArg: Omit<ISimpleLocalSnapshotOptions<IOnkyoConfig>, 'profile'>): ISimpleLocalSnapshot {
8
- return SimpleLocalMapper.toSnapshot({ ...optionsArg, profile: onkyoProfile });
6
+ public static deviceId(snapshotArg: Pick<IOnkyoSnapshot, 'homeId' | 'receiver'>): string {
7
+ return `onkyo:${encodeURIComponent(snapshotArg.homeId)}:${snapshotArg.receiver.macAddress}`;
9
8
  }
10
-
11
- public static toSnapshotFromRaw(configArg: IOnkyoConfig, rawDataArg: TSimpleLocalRawData): ISimpleLocalSnapshot {
12
- return SimpleLocalMapper.toSnapshot({ profile: onkyoProfile, config: configArg, rawData: rawDataArg, online: true, source: 'manual' });
9
+ public static mediaEntityId(snapshotArg: Pick<IOnkyoSnapshot, 'homeId' | 'receiver'>): string {
10
+ return `${this.deviceId(snapshotArg)}:main`;
13
11
  }
14
-
15
- public static toDevices(snapshotArg: ISimpleLocalSnapshot): shxInterfaces.data.IDeviceDefinition[] {
16
- return SimpleLocalMapper.toDevices(onkyoProfile, snapshotArg);
12
+ public static toDevices(snapshotArg: IOnkyoSnapshot): plugins.shxInterfaces.data.IDeviceDefinition[] {
13
+ const receiver = snapshotArg.receiver;
14
+ const features: plugins.shxInterfaces.data.IDeviceFeature[] = [
15
+ { id: 'connectivity', capability: 'sensor', name: 'Connectivity', readable: true, writable: false },
16
+ { id: 'identity', capability: 'sensor', name: 'Receiver identity', readable: true, writable: false },
17
+ { id: 'inputs', capability: 'sensor', name: 'Advertised main-zone inputs', readable: true, writable: false },
18
+ ];
19
+ const state: plugins.shxInterfaces.data.IDeviceState[] = [
20
+ { featureId: 'connectivity', value: 'online', updatedAt: snapshotArg.observedAt },
21
+ { featureId: 'identity', value: { macAddress: receiver.macAddress, model: receiver.model, brand: receiver.brand }, updatedAt: snapshotArg.observedAt },
22
+ { featureId: 'inputs', value: { inputs: receiver.inputs.map((inputArg) => ({ ...inputArg })) }, updatedAt: snapshotArg.observedAt },
23
+ ];
24
+ const add = (idArg: string, nameArg: string, valueArg: boolean | number | string, writableArg: boolean, unitArg?: string): void => {
25
+ features.push({ id: idArg, capability: 'media', name: nameArg, readable: true, writable: writableArg, ...(unitArg ? { unit: unitArg } : {}) });
26
+ state.push({ featureId: idArg, value: valueArg, updatedAt: snapshotArg.observedAt });
27
+ };
28
+ if (snapshotArg.power !== undefined) add('power', 'Power', snapshotArg.power, true);
29
+ if (snapshotArg.muted !== undefined) add('mute', 'Mute', snapshotArg.muted, true);
30
+ if (snapshotArg.volumeRaw !== undefined) add('volume_raw', 'Absolute raw volume', snapshotArg.volumeRaw,
31
+ receiver.integerVolumeMaximum !== undefined && snapshotArg.volumeRaw <= receiver.integerVolumeMaximum, 'receiver raw units');
32
+ if (snapshotArg.inputId !== undefined) add('input', 'Input selector', snapshotArg.inputId, receiver.inputs.length > 0);
33
+ return [{
34
+ id: this.deviceId(snapshotArg), integrationDomain: 'onkyo', name: snapshotArg.name, manufacturer: 'Onkyo',
35
+ model: receiver.model, protocol: 'tcp', online: snapshotArg.online, features, state,
36
+ metadata: { homeId: snapshotArg.homeId, macAddress: receiver.macAddress, zone: 'main', wireProtocol: 'eiscp', lanAuthenticated: false,
37
+ inputs: receiver.inputs.map((inputArg) => ({ ...inputArg })), integerVolumeMaximum: receiver.integerVolumeMaximum,
38
+ volumeLimitRaw: snapshotArg.volumeLimitRaw,
39
+ ...(receiver.integerVolumeMaximum === undefined ? {} : { volumeRange: { minimumRaw: 0, maximumRaw: Math.min(receiver.integerVolumeMaximum, snapshotArg.volumeLimitRaw) } }),
40
+ observedAt: snapshotArg.observedAt },
41
+ }];
17
42
  }
18
-
19
- public static toEntities(snapshotArg: ISimpleLocalSnapshot): IIntegrationEntity[] {
20
- return SimpleLocalMapper.toEntities(onkyoProfile, snapshotArg);
21
- }
22
-
23
- public static slug(valueArg: unknown): string {
24
- return SimpleLocalMapper.slug(valueArg);
43
+ public static toEntities(snapshotArg: IOnkyoSnapshot): IIntegrationEntity[] {
44
+ return [{
45
+ id: this.mediaEntityId(snapshotArg), uniqueId: this.mediaEntityId(snapshotArg), deviceId: this.deviceId(snapshotArg),
46
+ integrationDomain: 'onkyo', platform: 'media_player', name: snapshotArg.name,
47
+ state: snapshotArg.power === undefined ? 'unknown' : snapshotArg.power ? 'on' : 'off', available: snapshotArg.online,
48
+ attributes: { power: snapshotArg.power, muted: snapshotArg.muted, volumeRaw: snapshotArg.volumeRaw, inputId: snapshotArg.inputId,
49
+ inputs: snapshotArg.receiver.inputs.map((inputArg) => ({ ...inputArg })), integerVolumeMaximum: snapshotArg.receiver.integerVolumeMaximum,
50
+ volumeLimitRaw: snapshotArg.volumeLimitRaw, zone: 'main', observedAt: snapshotArg.observedAt },
51
+ }];
25
52
  }
26
53
  }
@@ -1,120 +1,65 @@
1
- import type { ISimpleLocalConfig, ISimpleLocalIntegrationProfile, ISimpleLocalSnapshot, TSimpleLocalRawData } from '../../core/index.js';
1
+ import type * as plugins from '../../plugins.js';
2
2
 
3
- export const onkyoDomain = "onkyo";
4
- export const onkyoDefaultName = "Onkyo";
3
+ export const onkyoDomain = 'onkyo';
4
+ export const onkyoDefaultName = 'Onkyo';
5
5
  export const onkyoDefaultPort = 60128;
6
6
  export const onkyoDefaultTimeoutMs = 5000;
7
7
 
8
- export type TOnkyoRawData = TSimpleLocalRawData;
9
- export interface IOnkyoSnapshot extends ISimpleLocalSnapshot {}
10
- export interface IOnkyoConfig extends ISimpleLocalConfig {
11
- url?: string;
12
- macAddress?: string;
13
- deviceId?: string;
8
+ export interface IOnkyoIntegrationOptions {
9
+ /** A consistency binding; setup and flow still require explicit host home. */
10
+ readonly homeId?: string;
11
+ /** Shared pending/runtime/flow/retained-cleanup capacity; defaults to 16. */
12
+ readonly capacity?: number;
13
+ }
14
+
15
+ export interface IOnkyoConfig {
16
+ homeId: string;
17
+ host: string;
18
+ macAddress: string;
19
+ model: string;
20
+ /** The selected identity does not authenticate the cleartext LAN peer. */
21
+ allowUnencryptedLan: true;
22
+ /** Absolute integer receiver units; no percent or half-step conversion. */
23
+ volumeLimitRaw: number;
24
+ port?: number;
25
+ name?: string;
26
+ requestTimeoutMs?: number;
27
+ maxPendingOperations?: number;
14
28
  }
15
29
  export interface IHomeAssistantOnkyoConfig extends IOnkyoConfig {}
16
30
 
17
- export const onkyoProfile: ISimpleLocalIntegrationProfile = {
18
- domain: onkyoDomain,
19
- displayName: "Onkyo",
20
- manufacturer: "Onkyo",
21
- model: "Onkyo local integration",
22
- defaultName: onkyoDefaultName,
23
- defaultPort: onkyoDefaultPort,
24
- defaultProtocol: 'tcp',
25
- status: "control-runtime",
26
- platforms: [
27
- "media_player",
28
- "switch",
29
- ],
30
- serviceDomains: [
31
- "media_player",
32
- "switch",
33
- ],
34
- controlServices: [
35
- "media_pause",
36
- "media_play",
37
- "media_stop",
38
- "select_source",
39
- "toggle",
40
- "turn_off",
41
- "turn_on",
42
- "volume_down",
43
- "volume_mute",
44
- "volume_set",
45
- "volume_up",
46
- "onkyo_select_hdmi_output",
47
- ],
48
- discoverySources: [
49
- 'manual',
50
- 'custom',
51
- ],
52
- discoveryKeywords: [
53
- "onkyo",
54
- "Onkyo",
55
- ],
31
+ /** Sequential live observations, never an injectable production data source. */
32
+ export interface IOnkyoSnapshot extends plugins.ecobridgeDeviceManager.IOnkyoState {
33
+ readonly homeId: string;
34
+ readonly name: string;
35
+ readonly volumeLimitRaw: number;
36
+ readonly online: true;
37
+ }
38
+ export type TOnkyoRawData = IOnkyoSnapshot;
39
+ export type TOnkyoClientEvent =
40
+ | { type: 'snapshot'; snapshot: IOnkyoSnapshot }
41
+ | { type: 'control'; observation: plugins.ecobridgeDeviceManager.IOnkyoControlObservation }
42
+ | { type: 'error'; error: Error };
43
+
44
+ export interface IOnkyoSelectedProbeOptions {
45
+ host: string;
46
+ port?: number;
47
+ requestTimeoutMs?: number;
48
+ signal?: AbortSignal;
49
+ }
50
+
51
+ export const onkyoProfile = {
52
+ domain: onkyoDomain, displayName: onkyoDefaultName, status: 'control-runtime',
56
53
  metadata: {
57
- "source": "home-assistant/core",
58
- "upstreamPath": "homeassistant/components/onkyo",
59
- "upstreamDomain": "onkyo",
60
- "integrationType": "device",
61
- "iotClass": "local_push",
62
- "qualityScale": "bronze",
63
- "requirements": [
64
- "aioonkyo==0.4.0",
65
- ],
66
- "dependencies": [
67
- "network",
68
- ],
69
- "codeowners": [
70
- "@arturpragacz",
71
- "@eclair4151",
72
- ],
73
- "configFlow": true,
74
- "documentation": "https://www.home-assistant.io/integrations/onkyo",
75
- "loggers": [
76
- "aioonkyo",
77
- ],
78
- "runtime": {
79
- "type": "control-runtime",
80
- "services": [
81
- "snapshot",
82
- "status",
83
- "refresh",
84
- "media_pause",
85
- "media_play",
86
- "media_stop",
87
- "select_source",
88
- "toggle",
89
- "turn_off",
90
- "turn_on",
91
- "volume_down",
92
- "volume_mute",
93
- "volume_set",
94
- "volume_up",
95
- "onkyo_select_hdmi_output",
96
- ],
97
- "platforms": [
98
- "media_player",
99
- "switch",
100
- ],
101
- "controls": "native eISCP TCP commands for main-zone media controls; injected client.execute or commandExecutor remains supported",
102
- },
103
- "localApi": {
104
- "status": "Native Onkyo/Pioneer eISCP TCP polling and main-zone control are implemented for manual host/port configurations; UDP discovery/interview and persistent push subscriptions are not implemented.",
105
- "implemented": [
106
- "native eISCP TCP polling on port 60128 for main-zone power, volume, mute, input source, and listening mode status",
107
- "native eISCP TCP control for power, volume, mute, source selection, HDMI output, and NET play/pause/stop commands",
108
- "manual local setup for Onkyo endpoints, snapshots, rawData, snapshotProvider, and injected native clients",
109
- "runtime mapping for Onkyo device snapshots and Home Assistant platform metadata",
110
- "safe command delegation to injected client.execute or commandExecutor when no live eISCP host is configured",
111
- ],
112
- "explicitUnsupported": [
113
- "UDP eISCP discovery/interview broadcast semantics; use manual host configuration or external discovery metadata",
114
- "persistent local_push subscription and unsolicited status update processing; this client performs focused request/response TCP polling and commands",
115
- "multi-zone and channel-muting switch discovery beyond main-zone eISCP status/control",
116
- "Home Assistant entity registry migrations and repair flows",
117
- ],
54
+ source: 'home-assistant/core', upstreamDomain: onkyoDomain, configFlow: true,
55
+ localApi: {
56
+ status: 'Selected native Onkyo main-zone eISCP TCP through devicemanager.',
57
+ implemented: ['selected unicast UDP advertisement', 'live MAC/model and enabled main-zone admission',
58
+ 'explicit power/mute, advertised input selectors and bounded absolute integer raw volume',
59
+ 'explicit captured host home and optional actual caller-owned NoSQL store', 'events from explicit observations and joined terminal shutdown'],
60
+ explicitUnsupported: ['broadcast discovery', 'cloud access', 'injected clients and snapshots', 'other zones',
61
+ 'percentage or half-step volume conversion', 'toggle/increment/media transport/arbitrary commands',
62
+ 'automatic reconnect, effect retry or replay', 'unsolicited push subscription', 'cryptographic LAN peer authentication'],
118
63
  },
119
64
  },
120
- };
65
+ } as const;
@@ -0,0 +1,85 @@
1
+ import * as plugins from '../../plugins.js';
2
+ import type { IOnkyoConfig } from './onkyo.types.js';
3
+ import { onkyoDefaultPort, onkyoDefaultTimeoutMs } from './onkyo.types.js';
4
+
5
+ interface IOnkyoNormalizedConfig extends IOnkyoConfig {
6
+ port: number;
7
+ requestTimeoutMs: number;
8
+ maxPendingOperations: number;
9
+ }
10
+
11
+ export function onkyoRecord(valueArg: unknown, nameArg: string): Record<string, unknown> {
12
+ if (!valueArg || typeof valueArg !== 'object' || Array.isArray(valueArg) ||
13
+ ![Object.prototype, null].includes(Object.getPrototypeOf(valueArg))) {
14
+ throw new TypeError(`Onkyo ${nameArg} must be a plain data object.`);
15
+ }
16
+ const result: Record<string, unknown> = {};
17
+ for (const key of Reflect.ownKeys(valueArg)) {
18
+ const descriptor = Object.getOwnPropertyDescriptor(valueArg, key);
19
+ if (typeof key !== 'string' || !descriptor || !('value' in descriptor) || !descriptor.enumerable) {
20
+ throw new TypeError(`Onkyo ${nameArg} may not contain symbols, accessors or hidden fields.`);
21
+ }
22
+ Object.defineProperty(result, key, { value: descriptor.value, enumerable: true });
23
+ }
24
+ return result;
25
+ }
26
+
27
+ export function onkyoKeys(recordArg: Record<string, unknown>, keysArg: readonly string[]): void {
28
+ if (Object.keys(recordArg).some((keyArg) => !keysArg.includes(keyArg))) throw new TypeError('Onkyo data contains unsupported fields.');
29
+ }
30
+
31
+ export function onkyoInteger(valueArg: unknown, minimumArg: number, maximumArg: number, nameArg: string): number {
32
+ if (typeof valueArg !== 'number' || !Number.isSafeInteger(valueArg) || valueArg < minimumArg || valueArg > maximumArg) {
33
+ throw new RangeError(`Onkyo ${nameArg} must be an integer from ${minimumArg} through ${maximumArg}.`);
34
+ }
35
+ return valueArg;
36
+ }
37
+
38
+ export function onkyoName(valueArg: unknown, nameArg: string): string {
39
+ if (typeof valueArg !== 'string' || !valueArg.trim() || valueArg.length > 256 || /[\p{Cc}\p{Cs}]/u.test(valueArg)) {
40
+ throw new TypeError(`Onkyo ${nameArg} must be a non-empty string without control characters, at most 256 characters.`);
41
+ }
42
+ return valueArg;
43
+ }
44
+
45
+ export function onkyoHost(valueArg: unknown): string {
46
+ if (typeof valueArg !== 'string' || plugins.net.isIP(valueArg) !== 4) throw new TypeError('Onkyo host must be a selected unicast IPv4 address.');
47
+ const octets = valueArg.split('.').map(Number);
48
+ const local = octets[0] === 10 || octets[0] === 127 || octets[0] === 192 && octets[1] === 168 ||
49
+ octets[0] === 172 && octets[1] >= 16 && octets[1] <= 31 || octets[0] === 169 && octets[1] === 254;
50
+ if (!local || octets[3] === 255) throw new TypeError('Onkyo host must be a private, loopback or link-local unicast IPv4 address.');
51
+ return valueArg;
52
+ }
53
+
54
+ export function readOnkyoEndpoint(hostArg: unknown, macArg: unknown, modelArg: unknown, portArg?: unknown): Pick<IOnkyoNormalizedConfig, 'host' | 'macAddress' | 'model' | 'port'> {
55
+ const host = onkyoHost(hostArg);
56
+ if (typeof macArg !== 'string' || !/^[0-9a-f]{12}$/i.test(macArg) || /^(0{12}|f{12})$/i.test(macArg)) {
57
+ throw new TypeError('Onkyo macAddress must be a nonempty twelve-digit receiver MAC.');
58
+ }
59
+ if (typeof modelArg !== 'string' || !/^[A-Za-z0-9][A-Za-z0-9 ._-]{0,63}$/.test(modelArg)) throw new TypeError('Onkyo model must be the exact selected receiver model.');
60
+ return { host, macAddress: macArg.toUpperCase(), model: modelArg,
61
+ port: onkyoInteger(portArg === undefined ? onkyoDefaultPort : portArg, 1, 65535, 'port') };
62
+ }
63
+
64
+ export function normalizeOnkyoConfig(valueArg: unknown): Readonly<IOnkyoNormalizedConfig> {
65
+ const config = onkyoRecord(valueArg, 'configuration');
66
+ onkyoKeys(config, ['homeId', 'host', 'macAddress', 'model', 'allowUnencryptedLan', 'volumeLimitRaw', 'port', 'name', 'requestTimeoutMs', 'maxPendingOperations']);
67
+ if (config.allowUnencryptedLan !== true) throw new TypeError('Onkyo requires an explicit allowUnencryptedLan: true acknowledgement.');
68
+ return Object.freeze({
69
+ homeId: onkyoName(config.homeId, 'homeId'), ...readOnkyoEndpoint(config.host, config.macAddress, config.model, config.port),
70
+ allowUnencryptedLan: true, volumeLimitRaw: onkyoInteger(config.volumeLimitRaw, 0, 100, 'volumeLimitRaw'),
71
+ name: config.name === undefined ? undefined : onkyoName(config.name, 'name'),
72
+ requestTimeoutMs: onkyoInteger(config.requestTimeoutMs === undefined ? onkyoDefaultTimeoutMs : config.requestTimeoutMs, 1, 60000, 'requestTimeoutMs'),
73
+ maxPendingOperations: onkyoInteger(config.maxPendingOperations === undefined ? 16 : config.maxPendingOperations, 1, 128, 'maxPendingOperations'),
74
+ });
75
+ }
76
+
77
+ export function onkyoBoolean(valueArg: unknown, nameArg: string): boolean {
78
+ if (typeof valueArg !== 'boolean') throw new TypeError(`Onkyo ${nameArg} requires an explicit boolean.`);
79
+ return valueArg;
80
+ }
81
+
82
+ export function onkyoInputId(valueArg: unknown): string {
83
+ if (typeof valueArg !== 'string' || !/^[0-9a-f]{2}$/i.test(valueArg)) throw new TypeError('Onkyo input requires an advertised two-digit selector ID.');
84
+ return valueArg.toUpperCase();
85
+ }