@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,71 @@
1
- import { SimpleLocalConfigFlow } from '../../core/index.js';
1
+ import type { IConfigFlow, INativeConfigFlowContext, IConfigFlowStep, IDiscoveryCandidate } from '../../core/types.js';
2
+ import type { INativeAdmissionContext } from '../../core/classes.nativehomeadmission.js';
3
+ import { NativeIntegrationOwner, NativeIntegrationScope, type INativeIntegrationOwnerOptions } from '../../core/classes.nativeintegrationowner.js';
2
4
  import type { IPioneerConfig } from './pioneer.types.js';
3
- import { pioneerProfile } from './pioneer.types.js';
5
+ import { PioneerClient } from './pioneer.classes.client.js';
6
+ import { normalizePioneerConfig, pioneerConfigKeys, pioneerRecord } from './pioneer.validation.js';
4
7
 
5
- export class PioneerConfigFlow extends SimpleLocalConfigFlow<IPioneerConfig> {
6
- constructor() {
7
- super(pioneerProfile);
8
+ export class PioneerConfigFlow implements IConfigFlow<IPioneerConfig> {
9
+ private readonly owner?: NativeIntegrationOwner;
10
+ private readonly scope: NativeIntegrationScope;
11
+
12
+ public constructor(options: INativeIntegrationOwnerOptions | NativeIntegrationScope = {}) {
13
+ if (options instanceof NativeIntegrationScope) this.scope = options;
14
+ else {
15
+ this.owner = new NativeIntegrationOwner('pioneer', options);
16
+ this.scope = this.owner.createFlowScope();
17
+ }
18
+ }
19
+
20
+ public async start(input: IDiscoveryCandidate, context: INativeConfigFlowContext): Promise<IConfigFlowStep<IPioneerConfig>> {
21
+ const candidate = pioneerRecord(input);
22
+ if (candidate.integrationDomain !== 'pioneer') return { kind: 'error', error: 'Candidate does not belong to Pioneer.' };
23
+ const metadata = candidate.metadata === undefined ? {} : pioneerRecord(candidate.metadata);
24
+ const hints = Object.freeze({ host: candidate.host, expectedUdn: candidate.id, model: candidate.model, descriptionUrl: metadata.descriptionUrl });
25
+ const captured = this.scope.admit(context);
26
+ return {
27
+ kind: 'form', title: 'Connect selected Pioneer SC-95 receiver',
28
+ description: 'The host selects the owning home. Confirm the private IPv4, UPnP identity and raw owner volume ceiling. HTTP/TCP identity is unauthenticated LAN consistency. Network Standby must already be enabled when needed.',
29
+ fields: [
30
+ { name: 'host', label: 'Selected receiver IPv4', type: 'text', required: true },
31
+ { name: 'descriptionUrl', label: 'Selected UPnP description URL', type: 'text', required: true },
32
+ { name: 'expectedUdn', label: 'Expected UPnP UDN', type: 'text', required: true },
33
+ { name: 'model', label: 'Documented model', type: 'select', required: true, options: [{ label: 'SC-95', value: 'SC-95' }] },
34
+ { name: 'allowUnencryptedLan', label: 'Allow plaintext LAN control', type: 'boolean', required: true },
35
+ { name: 'maximumVolumeRaw', label: 'Owner maximum raw volume (0–185)', type: 'number', required: true },
36
+ { name: 'name', label: 'Display name', type: 'text' },
37
+ ],
38
+ submit: (values) => this.submit(hints, values, captured),
39
+ };
40
+ }
41
+
42
+ public destroy(): Promise<void> { return this.owner ? this.owner.close() : this.scope.close(); }
43
+ public retryCleanup(): Promise<void> { return this.owner ? this.owner.retryCleanup() : this.scope.retryCleanup(); }
44
+
45
+ private async submit(hints: Readonly<Record<string, unknown>>, input: unknown,
46
+ context: INativeAdmissionContext): Promise<IConfigFlowStep<IPioneerConfig>> {
47
+ this.scope.admit(context);
48
+ try {
49
+ const values = pioneerRecord(input, pioneerConfigKeys);
50
+ if (values.homeId !== undefined && values.homeId !== context.homeId) throw new Error('Pioneer form home conflicts with the host-selected home.');
51
+ const config = normalizePioneerConfig({ ...hints, ...values, homeId: context.homeId });
52
+ return await this.scope.run(context, config.homeId, async (lease) => {
53
+ const client = new PioneerClient(config, lease.context);
54
+ let cleanupStarted = false;
55
+ lease.own(() => {
56
+ const retry = cleanupStarted;
57
+ cleanupStarted = true;
58
+ return retry ? client.retryCleanup() : client.destroy();
59
+ });
60
+ await client.start(lease.signal);
61
+ lease.assertOpen();
62
+ return { kind: 'done', title: 'Selected receiver admitted', config };
63
+ });
64
+ } catch (error) {
65
+ // Cleanup failures remain actionable; the shared owner retains their handles for explicit retry.
66
+ if (error instanceof AggregateError) throw error;
67
+ this.scope.admit(context);
68
+ return { kind: 'error', title: 'Pioneer admission failed', error: 'Confirm exact home scope, SC-95 model, private IPv4 and UPnP identity, readable receiver settings and explicit raw owner volume ceiling.' };
69
+ }
8
70
  }
9
71
  }
@@ -1,23 +1,237 @@
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 type { IDeviceFeatureWriteRequest, IIntegrationEntity, IIntegrationEvent, IIntegrationRuntime, INativeIntegrationSetupContext, IServiceCallRequest, IServiceCallResult } from '../../core/types.js';
4
+ import { NativeIntegrationOwner, type INativeIntegrationOwnerOptions, type INativeSetupLease } from '../../core/classes.nativeintegrationowner.js';
2
5
  import { PioneerClient } from './pioneer.classes.client.js';
3
6
  import { PioneerConfigFlow } from './pioneer.classes.configflow.js';
4
7
  import { createPioneerDiscoveryDescriptor } from './pioneer.discovery.js';
5
- import type { IPioneerConfig } from './pioneer.types.js';
6
- import { pioneerDomain, pioneerProfile } from './pioneer.types.js';
8
+ import { PioneerMapper } from './pioneer.mapper.js';
9
+ import { normalizePioneerConfig, pioneerRecord, validatePioneerControl } from './pioneer.validation.js';
10
+ import type { IPioneerConfig, IPioneerSnapshot, TPioneerControl } from './pioneer.types.js';
11
+ import { pioneerProfile } from './pioneer.types.js';
7
12
 
8
- export class PioneerIntegration extends SimpleLocalIntegration<IPioneerConfig> {
9
- public readonly domain = pioneerDomain;
13
+ export class PioneerIntegration extends BaseIntegration<IPioneerConfig> {
14
+ public readonly domain = 'pioneer';
15
+ public readonly displayName = 'Pioneer selected SC-95 receiver';
16
+ public readonly status = 'control-runtime' as const;
10
17
  public readonly discoveryDescriptor = createPioneerDiscoveryDescriptor();
11
- public readonly configFlow = new PioneerConfigFlow();
18
+ public readonly configFlow: PioneerConfigFlow;
19
+ public readonly metadata = pioneerProfile.metadata;
20
+ private readonly owner: NativeIntegrationOwner;
12
21
 
13
- constructor() {
14
- super(pioneerProfile);
22
+ public constructor(options: INativeIntegrationOwnerOptions = {}) {
23
+ super();
24
+ this.owner = new NativeIntegrationOwner('pioneer', options);
25
+ this.configFlow = new PioneerConfigFlow(this.owner.createFlowScope());
15
26
  }
16
27
 
17
- public override async setup(configArg: IPioneerConfig, contextArg: IIntegrationSetupContext): Promise<IIntegrationRuntime> {
18
- void contextArg;
19
- return new SimpleLocalRuntime(pioneerProfile, new PioneerClient(configArg));
28
+ public setup(input: IPioneerConfig, context: INativeIntegrationSetupContext): Promise<IIntegrationRuntime> {
29
+ try {
30
+ const config = normalizePioneerConfig(input);
31
+ return this.owner.runSetup(context, config.homeId, async (lease) => {
32
+ const client = new PioneerClient(config, lease.context);
33
+ let runtime: PioneerRuntime | undefined;
34
+ let cleanupStarted = false;
35
+ lease.own(() => {
36
+ const retry = cleanupStarted;
37
+ cleanupStarted = true;
38
+ return runtime ? runtime.cleanupResources(retry) : retry ? client.retryCleanup() : client.destroy();
39
+ });
40
+ const initial = await client.start(lease.signal);
41
+ lease.assertOpen();
42
+ runtime = new PioneerRuntime(client, initial, lease);
43
+ lease.promoteToRuntime();
44
+ return runtime;
45
+ });
46
+ } catch (error) { return Promise.reject(error); }
20
47
  }
48
+
49
+ public destroy(): Promise<void> { return this.owner.close(); }
50
+ public retryCleanup(): Promise<void> { return this.owner.retryCleanup(); }
21
51
  }
22
52
 
23
53
  export class HomeAssistantPioneerIntegration extends PioneerIntegration {}
54
+
55
+ interface IPioneerSubscription {
56
+ handler: (event: IIntegrationEvent) => void;
57
+ readonly callbacks: Set<Promise<void>>;
58
+ active: boolean;
59
+ failure?: unknown;
60
+ failed: boolean;
61
+ detach(): void;
62
+ stop(): Promise<void>;
63
+ }
64
+
65
+ class PioneerRuntime implements IIntegrationRuntime {
66
+ public readonly domain = 'pioneer';
67
+ private readonly subscriptions = new Set<IPioneerSubscription>();
68
+ private readonly parentAbort: () => void;
69
+ private closePromise?: Promise<void>;
70
+ private cleanupPromise?: Promise<void>;
71
+ private closed = false;
72
+
73
+ public constructor(private readonly client: PioneerClient, private snapshot: IPioneerSnapshot,
74
+ private readonly lease: INativeSetupLease) {
75
+ // The lease retains the client and callbacks until cleanup succeeds, including explicit retries.
76
+ this.parentAbort = () => { void this.destroy().catch(() => {}); };
77
+ lease.signal.addEventListener('abort', this.parentAbort, { once: true });
78
+ if (lease.signal.aborted) this.parentAbort();
79
+ }
80
+
81
+ public isHealthy(): boolean { return !this.closed && this.client.isHealthy(); }
82
+
83
+ public async devices(signal?: AbortSignal): Promise<plugins.shxInterfaces.data.IDeviceDefinition[]> {
84
+ this.assertOpen();
85
+ const snapshot = await this.client.getSnapshot(signal);
86
+ this.publish(snapshot);
87
+ return PioneerMapper.toDevices(snapshot);
88
+ }
89
+
90
+ public async entities(): Promise<IIntegrationEntity[]> {
91
+ this.assertOpen();
92
+ const snapshot = await this.client.getSnapshot();
93
+ this.publish(snapshot);
94
+ return PioneerMapper.toEntities(snapshot);
95
+ }
96
+
97
+ public async writeFeature(input: IDeviceFeatureWriteRequest, signal?: AbortSignal): Promise<IServiceCallResult> {
98
+ this.assertOpen();
99
+ const request = pioneerRecord(input, ['device', 'feature', 'value']);
100
+ const device = pioneerRecord(request.device);
101
+ const feature = pioneerRecord(request.feature);
102
+ const canonical = PioneerMapper.toDevices(this.snapshot)[0];
103
+ if (device.id !== canonical.id || device.integrationDomain !== this.domain) throw new Error('Pioneer feature target is outside the selected home and receiver.');
104
+ const admitted = canonical.features.find((entry) => entry.id === feature.id);
105
+ if (!admitted?.writable || feature.capability !== admitted.capability) throw new Error('Pioneer feature is not writable for the selected receiver.');
106
+ return this.control(validatePioneerControl({ feature: admitted.id, value: request.value }), signal);
107
+ }
108
+
109
+ public async callService(input: IServiceCallRequest): Promise<IServiceCallResult> {
110
+ this.assertOpen();
111
+ const request = pioneerRecord(input, ['domain', 'service', 'target', 'data']);
112
+ const target = pioneerRecord(request.target, ['deviceId', 'entityId']);
113
+ const deviceId = PioneerMapper.deviceId(this.snapshot.homeId, this.snapshot.identity.udn);
114
+ const entityId = PioneerMapper.entityId(this.snapshot.homeId, this.snapshot.identity.udn);
115
+ if ((!target.deviceId && !target.entityId) || (target.deviceId !== undefined && target.deviceId !== deviceId)
116
+ || (target.entityId !== undefined && target.entityId !== entityId)) throw new Error('Pioneer service target is outside the selected home and receiver.');
117
+ if (request.domain !== 'media_player') throw new Error('Pioneer services use media_player.');
118
+ let control: TPioneerControl;
119
+ if (request.service === 'turn_on' || request.service === 'turn_off') {
120
+ pioneerRecord(request.data ?? {}, []);
121
+ control = { feature: 'power', value: request.service === 'turn_on' };
122
+ } else if (request.service === 'set_volume_raw') {
123
+ const data = pioneerRecord(request.data, ['volume_raw']);
124
+ control = validatePioneerControl({ feature: 'volume_raw', value: data.volume_raw });
125
+ } else if (request.service === 'volume_mute') {
126
+ const data = pioneerRecord(request.data, ['is_volume_muted']);
127
+ control = validatePioneerControl({ feature: 'muted', value: data.is_volume_muted });
128
+ } else if (request.service === 'select_source') {
129
+ const data = pioneerRecord(request.data, ['source']);
130
+ control = validatePioneerControl({ feature: 'input', value: data.source });
131
+ } else throw new Error('Pioneer supports explicit power, mute, raw integer volume and observed physical input controls only.');
132
+ return this.control(control);
133
+ }
134
+
135
+ /** Emits completed observations only, with no background polling or unsolicited-event claim. */
136
+ public async subscribe(handler: (event: IIntegrationEvent) => void, signal?: AbortSignal): Promise<() => Promise<void>> {
137
+ this.assertOpen();
138
+ if (typeof handler !== 'function' || (signal !== undefined && !(signal instanceof AbortSignal))) throw new TypeError('Pioneer subscription requires a callback and optional AbortSignal.');
139
+ signal?.throwIfAborted();
140
+ if (this.subscriptions.size >= 32) throw new Error('Pioneer subscription capacity reached.');
141
+ const subscription: IPioneerSubscription = {
142
+ handler, callbacks: new Set(), active: true, failed: false,
143
+ detach: () => { subscription.active = false; signal?.removeEventListener('abort', aborted); },
144
+ stop: async () => {
145
+ subscription.detach();
146
+ await Promise.all([...subscription.callbacks]);
147
+ this.subscriptions.delete(subscription);
148
+ if (subscription.failed) throw subscription.failure;
149
+ },
150
+ };
151
+ const aborted = () => {
152
+ subscription.detach();
153
+ // Allow the current invocation and its tracked callback to settle before automatic removal.
154
+ void Promise.resolve().then(async () => {
155
+ await Promise.all([...subscription.callbacks]);
156
+ if (!subscription.failed) this.subscriptions.delete(subscription);
157
+ });
158
+ };
159
+ signal?.addEventListener('abort', aborted, { once: true });
160
+ this.subscriptions.add(subscription);
161
+ if (signal?.aborted) aborted();
162
+ return subscription.stop;
163
+ }
164
+
165
+ public destroy(): Promise<void> {
166
+ if (!this.closePromise) {
167
+ this.closed = true;
168
+ this.closePromise = Promise.resolve().then(() => this.lease.close());
169
+ }
170
+ return this.closePromise;
171
+ }
172
+
173
+ public cleanupResources(retry = false): Promise<void> {
174
+ if (retry) this.cleanupPromise = undefined;
175
+ if (!this.cleanupPromise) {
176
+ this.closed = true;
177
+ this.cleanupPromise = Promise.resolve().then(async () => {
178
+ const results = await Promise.allSettled([retry ? this.client.retryCleanup() : this.client.destroy(),
179
+ ...[...this.subscriptions].map((subscription) => subscription.stop())]);
180
+ const failures = results.filter((result): result is PromiseRejectedResult => result.status === 'rejected');
181
+ if (failures.length) throw new AggregateError(failures.map((result) => result.reason as unknown), 'Pioneer runtime cleanup failed.');
182
+ });
183
+ this.lease.signal.removeEventListener('abort', this.parentAbort);
184
+ for (const subscription of this.subscriptions) subscription.detach();
185
+ }
186
+ return this.cleanupPromise;
187
+ }
188
+
189
+ private async control(control: TPioneerControl, signal?: AbortSignal): Promise<IServiceCallResult> {
190
+ try {
191
+ const result = await this.client.setControl(control, signal);
192
+ try { this.publish(result.snapshot); }
193
+ catch { return { success: false, error: 'Pioneer was closed after dispatch; its effect is indeterminate.',
194
+ data: { dispatch: result.dispatch, effectOutcome: 'indeterminate', commandAcknowledged: false, causalityConfirmed: false } }; }
195
+ return { success: result.outcome === 'observed-target', data: { dispatch: result.dispatch, effectOutcome: result.outcome,
196
+ commandAcknowledged: result.commandAcknowledged, causalityConfirmed: result.causalityConfirmed } };
197
+ } catch (error) {
198
+ return { success: false, error: 'Pioneer control was refused or its observation could not be reconciled.',
199
+ data: { effectOutcome: error instanceof plugins.ecobridgeDeviceManager.PioneerProtocolError ? error.effectOutcome : 'not-sent',
200
+ commandAcknowledged: false, causalityConfirmed: false } };
201
+ }
202
+ }
203
+
204
+ private publish(snapshot: IPioneerSnapshot): void {
205
+ this.assertOpen(); this.snapshot = snapshot;
206
+ for (const subscription of this.subscriptions) {
207
+ if (!subscription.active) continue;
208
+ if (subscription.callbacks.size >= this.client.config.maxPendingOperations) {
209
+ subscription.failed = true;
210
+ subscription.failure = new Error('Pioneer observation callback capacity reached.');
211
+ subscription.detach();
212
+ continue;
213
+ }
214
+ let complete: () => void = () => {};
215
+ let fail: (error: unknown) => void = () => {};
216
+ const invoked = new Promise<void>((resolve, reject) => { complete = resolve; fail = reject; });
217
+ const callback = invoked.catch((error: unknown) => {
218
+ subscription.failed = true; subscription.failure = error; subscription.detach();
219
+ }).finally(() => subscription.callbacks.delete(callback));
220
+ // Register before user code can synchronously abort or destroy its owner.
221
+ subscription.callbacks.add(callback);
222
+ try {
223
+ const returned: unknown = subscription.handler({ type: 'state_changed', integrationDomain: this.domain,
224
+ deviceId: PioneerMapper.deviceId(snapshot.homeId, snapshot.identity.udn),
225
+ entityId: PioneerMapper.entityId(snapshot.homeId, snapshot.identity.udn),
226
+ data: { snapshot: structuredClone(snapshot), source: 'completed-receiver-observation' }, timestamp: Date.now() });
227
+ void Promise.resolve(returned).then(complete, fail);
228
+ } catch (error) { fail(error); }
229
+ }
230
+ this.assertOpen();
231
+ }
232
+
233
+ private assertOpen(): void {
234
+ if (this.closed) throw new Error('Pioneer runtime is closed.');
235
+ this.lease.assertOpen();
236
+ }
237
+ }
@@ -1,4 +1,46 @@
1
- import { createSimpleLocalDiscoveryDescriptor } from '../../core/index.js';
2
- import { pioneerProfile } from './pioneer.types.js';
1
+ import { DiscoveryDescriptor } from '../../core/classes.discoverydescriptor.js';
2
+ import type { IDiscoveryCandidate, IDiscoveryMatch, IDiscoveryMatcher, IDiscoveryValidator } from '../../core/types.js';
3
+ import type { IPioneerManualEntry } from './pioneer.types.js';
4
+ import { pioneerDescription, pioneerHost, pioneerRecord, pioneerText, pioneerUdn } from './pioneer.validation.js';
3
5
 
4
- export const createPioneerDiscoveryDescriptor = () => createSimpleLocalDiscoveryDescriptor(pioneerProfile);
6
+ const miss = (reason: string): IDiscoveryMatch => ({ matched: false, confidence: 'low', reason });
7
+
8
+ export class PioneerManualMatcher implements IDiscoveryMatcher<IPioneerManualEntry> {
9
+ public readonly id = 'pioneer-manual-match';
10
+ public readonly source = 'manual' as const;
11
+ public readonly description = 'Selected SC-95 descriptor setup hints; native admission reads fresh identity.';
12
+
13
+ public async matches(input: IPioneerManualEntry): Promise<IDiscoveryMatch> {
14
+ try {
15
+ const record = pioneerRecord(input, ['source', 'integrationDomain', 'host', 'descriptionUrl', 'expectedUdn', 'id', 'name', 'manufacturer', 'model', 'metadata']);
16
+ if (record.source !== undefined && record.source !== 'manual') return miss('Only selected manual endpoint hints are supported.');
17
+ if (record.integrationDomain !== undefined && record.integrationDomain !== 'pioneer') return miss('Foreign integration hint.');
18
+ const metadata = record.metadata === undefined ? {} : pioneerRecord(record.metadata, ['descriptionUrl', 'identityEvidence']);
19
+ const host = pioneerHost(record.host);
20
+ const descriptionUrl = pioneerDescription(record.descriptionUrl ?? metadata.descriptionUrl, host);
21
+ const id = pioneerUdn(record.expectedUdn ?? record.id);
22
+ if (record.expectedUdn !== undefined && record.id !== undefined && pioneerUdn(record.expectedUdn) !== pioneerUdn(record.id)) return miss('Manual receiver identities conflict.');
23
+ if (record.model !== 'SC-95') return miss('Model has no selected vendor profile.');
24
+ if (record.manufacturer !== undefined && record.manufacturer !== 'Pioneer') return miss('Manufacturer does not match the selected profile.');
25
+ const name = record.name === undefined ? undefined : pioneerText(record.name, 'name', 128);
26
+ return { matched: true, confidence: 'medium', reason: 'Selected SC-95 setup hint; fresh UPnP and receiver state are required for native admission.',
27
+ normalizedDeviceId: id, candidate: { source: 'manual', integrationDomain: 'pioneer', id, host, name, manufacturer: 'Pioneer', model: 'SC-95',
28
+ metadata: { descriptionUrl, identityEvidence: 'unauthenticated-discovery-hint' } } };
29
+ } catch { return miss('Manual setup requires the selected SC-95 model, private endpoint, descriptor URL and exact UDN.'); }
30
+ }
31
+ }
32
+
33
+ export class PioneerCandidateValidator implements IDiscoveryValidator {
34
+ public readonly id = 'pioneer-candidate-validator';
35
+ public async validate(input: IDiscoveryCandidate): Promise<IDiscoveryMatch> {
36
+ try {
37
+ const record = pioneerRecord(input);
38
+ if (record.integrationDomain !== 'pioneer' || record.source !== 'manual') return miss('Candidate does not belong to selected Pioneer discovery.');
39
+ return new PioneerManualMatcher().matches(input);
40
+ } catch { return miss('Candidate must be a plain selected Pioneer record.'); }
41
+ }
42
+ }
43
+
44
+ export const createPioneerDiscoveryDescriptor = (): DiscoveryDescriptor =>
45
+ new DiscoveryDescriptor({ integrationDomain: 'pioneer', displayName: 'Pioneer selected SC-95 receiver' })
46
+ .addMatcher(new PioneerManualMatcher()).addValidator(new PioneerCandidateValidator());
@@ -1,26 +1,70 @@
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 { IPioneerConfig } from './pioneer.types.js';
1
+ import type * as plugins from '../../plugins.js';
2
+ import type { IIntegrationEntity } from '../../core/types.js';
3
+ import { SimpleLocalMapper } from '../../core/classes.simplelocalintegration.js';
4
+ import type { IPioneerOfflineConfig, IPioneerOfflineSnapshot, IPioneerSnapshot, TPioneerRawData } from './pioneer.types.js';
4
5
  import { pioneerProfile } from './pioneer.types.js';
5
6
 
6
7
  export class PioneerMapper {
7
- public static toSnapshot(optionsArg: Omit<ISimpleLocalSnapshotOptions<IPioneerConfig>, 'profile'>): ISimpleLocalSnapshot {
8
- return SimpleLocalMapper.toSnapshot({ ...optionsArg, profile: pioneerProfile });
8
+ public static deviceId(homeId: string, udn: string): string {
9
+ return `pioneer.receiver.${encodeURIComponent(homeId)}.${encodeURIComponent(udn)}`;
9
10
  }
10
11
 
11
- public static toSnapshotFromRaw(configArg: IPioneerConfig, rawDataArg: TSimpleLocalRawData): ISimpleLocalSnapshot {
12
- return SimpleLocalMapper.toSnapshot({ profile: pioneerProfile, config: configArg, rawData: rawDataArg, online: true, source: 'manual' });
12
+ public static entityId(homeId: string, udn: string): string {
13
+ return `media_player.pioneer.${encodeURIComponent(homeId)}.${encodeURIComponent(udn)}`;
13
14
  }
14
15
 
15
- public static toDevices(snapshotArg: ISimpleLocalSnapshot): shxInterfaces.data.IDeviceDefinition[] {
16
- return SimpleLocalMapper.toDevices(pioneerProfile, snapshotArg);
16
+ public static toDevices(snapshot: IPioneerSnapshot): plugins.shxInterfaces.data.IDeviceDefinition[] {
17
+ return [{
18
+ id: this.deviceId(snapshot.homeId, snapshot.identity.udn), integrationDomain: 'pioneer', name: snapshot.name,
19
+ protocol: 'tcp', manufacturer: snapshot.identity.manufacturer, model: snapshot.identity.model, online: true,
20
+ features: [
21
+ { id: 'power', capability: 'media', name: 'Main-zone power', readable: true, writable: true },
22
+ { id: 'muted', capability: 'media', name: 'Main-zone mute', readable: true, writable: true },
23
+ { id: 'volume_raw', capability: 'media', name: 'Main-zone raw volume', unit: 'raw', readable: true, writable: true },
24
+ { id: 'input', capability: 'media', name: 'Main-zone physical input', readable: true, writable: snapshot.observedInputs.length > 0 },
25
+ ],
26
+ state: [
27
+ { featureId: 'power', value: snapshot.power, updatedAt: snapshot.observedAt },
28
+ { featureId: 'muted', value: snapshot.muted, updatedAt: snapshot.observedAt },
29
+ { featureId: 'volume_raw', value: snapshot.volumeRaw, updatedAt: snapshot.observedAt },
30
+ { featureId: 'input', value: snapshot.inputId, updatedAt: snapshot.observedAt },
31
+ ],
32
+ metadata: { homeId: snapshot.homeId, udn: snapshot.identity.udn, host: snapshot.host, port: snapshot.port,
33
+ serialNumber: snapshot.identity.serialNumber, zone: 'main', observedInputs: [...snapshot.observedInputs],
34
+ maximumVolumeRaw: snapshot.maximumVolumeRaw, minimumVolumeRaw: 0, maximumReceiverVolumeRaw: 185,
35
+ identitySource: snapshot.identity.source, identityTrust: snapshot.identity.trust,
36
+ stateSource: 'receiver-observation', commandAcknowledged: false, causalityConfirmed: false },
37
+ }];
17
38
  }
18
39
 
19
- public static toEntities(snapshotArg: ISimpleLocalSnapshot): IIntegrationEntity[] {
20
- return SimpleLocalMapper.toEntities(pioneerProfile, snapshotArg);
40
+ public static toEntities(snapshot: IPioneerSnapshot): IIntegrationEntity[] {
41
+ return [{
42
+ id: this.entityId(snapshot.homeId, snapshot.identity.udn), uniqueId: this.deviceId(snapshot.homeId, snapshot.identity.udn),
43
+ integrationDomain: 'pioneer', deviceId: this.deviceId(snapshot.homeId, snapshot.identity.udn), platform: 'media_player',
44
+ name: snapshot.name, state: snapshot.power ? 'on' : 'off', available: true,
45
+ attributes: { homeId: snapshot.homeId, udn: snapshot.identity.udn, zone: 'main', power: snapshot.power,
46
+ volumeRaw: snapshot.volumeRaw, muted: snapshot.muted, source: snapshot.inputId,
47
+ observedInputs: [...snapshot.observedInputs], maximumVolumeRaw: snapshot.maximumVolumeRaw,
48
+ observedAt: snapshot.observedAt, stateSource: 'receiver-observation', identityTrust: snapshot.identity.trust,
49
+ commandAcknowledged: false, causalityConfirmed: false },
50
+ }];
51
+ }
52
+ }
53
+
54
+ /** Explicitly offline transformation; this helper never creates or admits a native runtime. */
55
+ export class PioneerOfflineMapper {
56
+ public static toSnapshotFromRaw(config: IPioneerOfflineConfig, rawData: TPioneerRawData): IPioneerOfflineSnapshot {
57
+ return this.offline(SimpleLocalMapper.toSnapshot({ profile: pioneerProfile, config: { ...config }, rawData, online: false, source: 'manual' }));
58
+ }
59
+ public static toDevices(snapshot: IPioneerOfflineSnapshot): plugins.shxInterfaces.data.IDeviceDefinition[] {
60
+ return SimpleLocalMapper.toDevices(pioneerProfile, this.offline(snapshot));
61
+ }
62
+ public static toEntities(snapshot: IPioneerOfflineSnapshot): IIntegrationEntity[] {
63
+ return SimpleLocalMapper.toEntities(pioneerProfile, this.offline(snapshot));
21
64
  }
22
65
 
23
- public static slug(valueArg: unknown): string {
24
- return SimpleLocalMapper.slug(valueArg);
66
+ private static offline(snapshot: IPioneerOfflineSnapshot): IPioneerOfflineSnapshot {
67
+ return { ...snapshot, online: false, capabilities: { localRead: true, localControl: false, liveControlRequiresExecutor: false },
68
+ entities: snapshot.entities.map((entity) => ({ ...entity, available: false, writable: false })) };
25
69
  }
26
70
  }
@@ -1,97 +1,99 @@
1
- import type { ISimpleLocalConfig, ISimpleLocalIntegrationProfile, ISimpleLocalSnapshot, TSimpleLocalRawData } from '../../core/index.js';
1
+ import type { ISimpleLocalIntegrationProfile, ISimpleLocalSnapshot, TSimpleLocalRawData } from '../../core/classes.simplelocalintegration.js';
2
2
 
3
- export const pioneerDomain = "pioneer";
4
- export const pioneerDefaultName = "Pioneer";
3
+ export const pioneerDomain = 'pioneer';
4
+ export const pioneerDefaultName = 'Pioneer';
5
5
  export const pioneerDefaultPort = 23;
6
6
  export const pioneerMaxVolume = 185;
7
- export const pioneerMaxSourceNumbers = 60;
7
+ export type TPioneerModel = 'SC-95';
8
8
 
9
- export type TPioneerRawData = TSimpleLocalRawData;
10
- export interface IPioneerSnapshot extends ISimpleLocalSnapshot {}
11
- export interface IPioneerConfig extends ISimpleLocalConfig {
12
- url?: string;
13
- macAddress?: string;
14
- deviceId?: string;
15
- sources?: Record<string, string>;
16
- sourceScanLimit?: number;
17
- commandTimeoutMs?: number;
9
+ export interface IPioneerConfig {
10
+ homeId: string;
11
+ host: string;
12
+ descriptionUrl: string;
13
+ expectedUdn: string;
14
+ model: TPioneerModel;
15
+ allowUnencryptedLan: true;
16
+ maximumVolumeRaw: number;
17
+ name?: string;
18
+ port?: number;
19
+ timeoutMs?: number;
20
+ maxPendingOperations?: number;
21
+ maxDescriptionBytes?: number;
22
+ maxFrameBytes?: number;
18
23
  }
19
24
  export interface IHomeAssistantPioneerConfig extends IPioneerConfig {}
20
25
 
26
+ export interface IPioneerIdentity {
27
+ readonly udn: string;
28
+ readonly model: TPioneerModel;
29
+ readonly manufacturer: 'Pioneer';
30
+ readonly reportedManufacturer: string;
31
+ readonly name: string;
32
+ readonly serialNumber?: string;
33
+ readonly source: 'selected-upnp-description';
34
+ readonly trust: 'unauthenticated-lan';
35
+ readonly observedAt: string;
36
+ }
37
+
38
+ export interface IPioneerSnapshot {
39
+ readonly homeId: string;
40
+ readonly host: string;
41
+ readonly port: number;
42
+ readonly name: string;
43
+ readonly identity: IPioneerIdentity;
44
+ readonly power: boolean;
45
+ readonly muted: boolean;
46
+ readonly volumeRaw: number;
47
+ readonly inputId: string;
48
+ readonly observedInputs: readonly string[];
49
+ readonly maximumVolumeRaw: number;
50
+ readonly observedAt: string;
51
+ }
52
+
53
+ export type TPioneerControl =
54
+ | { feature: 'power'; value: boolean }
55
+ | { feature: 'muted'; value: boolean }
56
+ | { feature: 'volume_raw'; value: number }
57
+ | { feature: 'input'; value: string };
58
+
59
+ export interface IPioneerEffectResult {
60
+ readonly dispatch: 'written';
61
+ readonly outcome: 'observed-target' | 'indeterminate';
62
+ readonly commandAcknowledged: false;
63
+ readonly causalityConfirmed: false;
64
+ readonly snapshot: IPioneerSnapshot;
65
+ }
66
+
67
+ export interface IPioneerManualEntry {
68
+ host?: string;
69
+ descriptionUrl?: string;
70
+ expectedUdn?: string;
71
+ id?: string;
72
+ name?: string;
73
+ manufacturer?: string;
74
+ model?: string;
75
+ metadata?: Record<string, unknown>;
76
+ }
77
+
78
+ export interface IPioneerOfflineConfig {
79
+ name?: string;
80
+ uniqueId?: string;
81
+ metadata?: Record<string, unknown>;
82
+ }
83
+ export type TPioneerRawData = TSimpleLocalRawData;
84
+ export interface IPioneerOfflineSnapshot extends ISimpleLocalSnapshot {}
85
+
21
86
  export const pioneerProfile: ISimpleLocalIntegrationProfile = {
22
- domain: pioneerDomain,
23
- displayName: "Pioneer",
24
- manufacturer: "Pioneer",
25
- model: "Pioneer local integration",
26
- defaultName: pioneerDefaultName,
27
- defaultPort: pioneerDefaultPort,
28
- defaultProtocol: 'telnet',
29
- status: "control-runtime",
30
- platforms: [
31
- "media_player",
32
- ],
33
- serviceDomains: [
34
- "media_player",
35
- ],
36
- controlServices: [
37
- "select_source",
38
- "set_volume_level",
39
- "turn_off",
40
- "turn_on",
41
- "volume_mute",
42
- "volume_down",
43
- "volume_up",
44
- ],
45
- discoverySources: [
46
- 'manual',
47
- 'custom',
48
- ],
49
- discoveryKeywords: [
50
- "pioneer",
51
- "Pioneer",
52
- ],
87
+ domain: pioneerDomain, displayName: 'Pioneer selected SC-95 receiver', manufacturer: 'Pioneer', model: 'SC-95',
88
+ defaultName: pioneerDefaultName, defaultPort: pioneerDefaultPort, defaultProtocol: 'tcp', status: 'control-runtime',
89
+ platforms: ['media_player'], serviceDomains: ['media_player'],
90
+ controlServices: ['turn_on', 'turn_off', 'volume_mute', 'set_volume_raw', 'select_source'], discoverySources: ['manual'],
91
+ discoveryKeywords: ['pioneer'],
53
92
  metadata: {
54
- "source": "home-assistant/core",
55
- "upstreamPath": "homeassistant/components/pioneer",
56
- "upstreamDomain": "pioneer",
57
- "iotClass": "local_polling",
58
- "qualityScale": "legacy",
59
- "configFlow": false,
60
- "requirements": [],
61
- "documentation": "https://www.home-assistant.io/integrations/pioneer",
62
- "runtime": {
63
- "type": "control-runtime",
64
- "services": [
65
- "snapshot",
66
- "status",
67
- "refresh",
68
- "select_source",
69
- "set_volume_level",
70
- "turn_off",
71
- "turn_on",
72
- "volume_mute",
73
- "volume_down",
74
- "volume_up",
75
- ],
76
- "platforms": [
77
- "media_player",
78
- ],
79
- "controls": "native Pioneer telnet commands for power, mute, source, and volume; injected executors remain supported",
80
- },
81
- "localApi": {
82
- "implemented": [
83
- "native Pioneer AVR Telnet/TCP polling on port 23 using ?P, ?V, ?M, ?RGBxx, and ?F",
84
- "native Pioneer AVR Telnet/TCP control using PO, PF, VU, VD, xxxVL, MO, MF, and xxFN",
85
- "manual local setup for Pioneer endpoints, snapshots, rawData, snapshotProvider, and injected native clients",
86
- "runtime mapping for Pioneer device snapshots and Home Assistant platform metadata",
87
- "safe command delegation to injected client.execute or commandExecutor",
88
- ],
89
- "explicitUnsupported": [
90
- "Pioneer pairing, subscriptions, and event streams because the Home Assistant source only documents polling Telnet commands",
91
- "media_play and media_pause because the Home Assistant Pioneer source declares features but exposes no concrete Telnet command implementation",
92
- "Home Assistant entity registry migrations and repair flows",
93
- "claiming write success for commands outside the documented Pioneer Telnet command set without injected client.execute or commandExecutor",
94
- ],
93
+ source: 'native-typescript', upstreamDomain: pioneerDomain, upstreamPath: 'homeassistant/components/pioneer',
94
+ localApi: {
95
+ implemented: ['selected SC-95/CUXJ main-zone protocol', 'exact home-scoped admission', 'absolute raw integer volume', 'receiver-observed physical input selection'],
96
+ explicitUnsupported: ['injected clients or executors', 'native runtime snapshots', 'arbitrary ASCII commands', 'toggles or relative controls', 'dB or percentage volume conversion', 'advanced zones or media playback', 'automatic retry or reconnect'],
95
97
  },
96
98
  },
97
99
  };