@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,239 +1,86 @@
1
1
  import { DiscoveryDescriptor } from '../../core/classes.discoverydescriptor.js';
2
2
  import type { IDiscoveryCandidate, IDiscoveryMatch, IDiscoveryMatcher, IDiscoveryValidator } from '../../core/types.js';
3
- import type { IDenonavrManualEntry, IDenonavrMdnsRecord, IDenonavrSsdpRecord } from './denonavr.types.js';
3
+ import type { IDenonavrManualEntry, IDenonavrSsdpRecord } from './denonavr.types.js';
4
+ import { denonavrDescription, denonavrHost, denonavrModel, denonavrRecord, denonavrUdn } from './denonavr.validation.js';
4
5
 
5
- const supportedManufacturers = ['denon', 'denon professional', 'marantz'];
6
- const supportedDeviceTypes = [
7
- 'urn:schemas-upnp-org:device:mediarenderer:1',
8
- 'urn:schemas-upnp-org:device:mediaserver:1',
9
- 'urn:schemas-denon-com:device:aiosdevice:1',
10
- ];
11
- const ignoredModels = ['heos 1', 'heos 3', 'heos 5', 'heos 7'];
6
+ const miss = (reason: string): IDiscoveryMatch => ({ matched: false, confidence: 'low', reason });
12
7
 
13
- export class DenonavrSsdpMatcher implements IDiscoveryMatcher<IDenonavrSsdpRecord> {
14
- public id = 'denonavr-ssdp-match';
15
- public source = 'ssdp' as const;
16
- public description = 'Recognize Denon and Marantz AVR SSDP advertisements.';
17
-
18
- public async matches(recordArg: IDenonavrSsdpRecord): Promise<IDiscoveryMatch> {
19
- const st = header(recordArg, 'st') || recordArg.upnp?.deviceType;
20
- const usn = header(recordArg, 'usn');
21
- const location = header(recordArg, 'location');
22
- const manufacturer = upnp(recordArg, 'manufacturer');
23
- const model = cleanModel(upnp(recordArg, 'modelName'));
24
- const serialNumber = upnp(recordArg, 'serialNumber') || upnp(recordArg, 'serial');
25
- const friendlyName = upnp(recordArg, 'friendlyName');
26
- const deviceType = upnp(recordArg, 'deviceType') || st;
27
-
28
- const matchedManufacturer = isSupportedManufacturer(manufacturer);
29
- const matchedType = Boolean(deviceType && supportedDeviceTypes.includes(deviceType.toLowerCase()));
30
- const matchedUsn = Boolean(usn?.toLowerCase().includes('denon') || usn?.toLowerCase().includes('marantz'));
31
-
32
- if (!matchedManufacturer && !matchedType && !matchedUsn) {
33
- return { matched: false, confidence: 'low', reason: 'SSDP record is not a Denon/Marantz AVR.' };
34
- }
35
- if (isIgnoredModel(model)) {
36
- return { matched: false, confidence: 'low', reason: 'SSDP record is a HEOS speaker, not an AVR.' };
37
- }
38
-
39
- const url = parseUrl(location);
40
- const id = uniqueId(model, serialNumber) || stripUuid(usn);
41
- return {
42
- matched: true,
43
- confidence: id && matchedManufacturer ? 'certain' : matchedManufacturer || matchedType ? 'high' : 'medium',
44
- reason: 'SSDP record matches Denon/Marantz AVR metadata.',
45
- normalizedDeviceId: id,
46
- candidate: {
47
- source: 'ssdp',
48
- integrationDomain: 'denonavr',
49
- id,
50
- host: url?.hostname,
51
- port: url?.port ? Number(url.port) : undefined,
52
- name: friendlyName,
53
- manufacturer: normalizedManufacturer(manufacturer),
54
- model,
55
- serialNumber,
56
- metadata: { st, usn, location, deviceType },
57
- },
58
- };
59
- }
8
+ function strings(value: unknown): Record<string, unknown> {
9
+ const record = denonavrRecord(value);
10
+ if (Object.keys(record).length > 64 || Object.values(record).some((entry) => entry !== undefined && (typeof entry !== 'string' || entry.length > 2048))) throw new TypeError('DenonAVR discovery fields must be bounded strings.');
11
+ return record;
60
12
  }
61
13
 
62
- export class DenonavrMdnsMatcher implements IDiscoveryMatcher<IDenonavrMdnsRecord> {
63
- public id = 'denonavr-mdns-match';
64
- public source = 'mdns' as const;
65
- public description = 'Recognize Denon and Marantz AVR mDNS advertisements.';
66
-
67
- public async matches(recordArg: IDenonavrMdnsRecord): Promise<IDiscoveryMatch> {
68
- const name = recordArg.name || '';
69
- const type = recordArg.type || '';
70
- const manufacturer = recordArg.txt?.manufacturer || recordArg.txt?.brand || recordArg.txt?.Manufacturer;
71
- const model = cleanModel(recordArg.txt?.model || recordArg.txt?.modelName || recordArg.txt?.ModelName);
72
- const serialNumber = recordArg.txt?.serial || recordArg.txt?.serialNumber || recordArg.txt?.SerialNumber;
73
- const haystack = `${name} ${type} ${manufacturer || ''} ${model || ''}`.toLowerCase();
74
- const matched = isSupportedManufacturer(manufacturer) || haystack.includes('denon') || haystack.includes('marantz');
14
+ function field(record: Record<string, unknown>, name: string): string | undefined {
15
+ const matches = Object.keys(record).filter((key) => key.toLowerCase() === name.toLowerCase());
16
+ if (matches.length > 1) throw new TypeError('DenonAVR discovery contains duplicate fields.');
17
+ const value = matches.length ? record[matches[0]] : undefined;
18
+ return typeof value === 'string' ? value : undefined;
19
+ }
75
20
 
76
- if (!matched) {
77
- return { matched: false, confidence: 'low', reason: 'mDNS record is not a Denon/Marantz advertisement.' };
78
- }
79
- if (isIgnoredModel(model)) {
80
- return { matched: false, confidence: 'low', reason: 'mDNS record is a HEOS speaker, not an AVR.' };
81
- }
21
+ function candidate(host: unknown, description: unknown, udn: unknown, modelValue: unknown, manufacturer: unknown,
22
+ source: 'ssdp' | 'manual', name?: string): IDiscoveryMatch {
23
+ const address = denonavrHost(host);
24
+ const descriptionUrl = denonavrDescription(description, address);
25
+ const id = denonavrUdn(udn);
26
+ const model = denonavrModel(modelValue);
27
+ const expectedManufacturer = model.startsWith('AVR-') ? 'Denon' : 'Marantz';
28
+ if (manufacturer !== undefined && (typeof manufacturer !== 'string' || manufacturer.toLowerCase() !== expectedManufacturer.toLowerCase())) throw new TypeError('DenonAVR discovery manufacturer does not match the model profile.');
29
+ return { matched: true, confidence: 'medium', reason: 'Selected-receiver setup hint; fresh descriptor and receiver observations are required for admission.',
30
+ normalizedDeviceId: id, candidate: { source, integrationDomain: 'denonavr', id, host: address, name,
31
+ manufacturer: expectedManufacturer, model, metadata: { descriptionUrl, identityEvidence: 'unauthenticated-discovery-hint' } } };
32
+ }
82
33
 
83
- const id = uniqueId(model, serialNumber) || recordArg.txt?.id || name;
84
- return {
85
- matched: true,
86
- confidence: serialNumber ? 'certain' : 'medium',
87
- reason: 'mDNS record matches Denon/Marantz metadata.',
88
- normalizedDeviceId: id,
89
- candidate: {
90
- source: 'mdns',
91
- integrationDomain: 'denonavr',
92
- id,
93
- host: recordArg.host,
94
- port: recordArg.port,
95
- name,
96
- manufacturer: normalizedManufacturer(manufacturer),
97
- model,
98
- serialNumber,
99
- metadata: { mdnsName: name, mdnsType: type, txt: recordArg.txt },
100
- },
101
- };
34
+ export class DenonavrSsdpMatcher implements IDiscoveryMatcher<IDenonavrSsdpRecord> {
35
+ public readonly id = 'denonavr-ssdp-match';
36
+ public readonly source = 'ssdp' as const;
37
+ public readonly description = 'Recognize explicitly described, documented Denon/Marantz receiver setup hints.';
38
+
39
+ public async matches(input: IDenonavrSsdpRecord): Promise<IDiscoveryMatch> {
40
+ try {
41
+ const record = denonavrRecord(input, ['st', 'usn', 'location', 'headers', 'upnp']);
42
+ const headers = record.headers === undefined ? {} : strings(record.headers);
43
+ const upnp = record.upnp === undefined ? {} : strings(record.upnp);
44
+ const location = record.location ?? field(headers, 'location');
45
+ if (typeof location !== 'string') return miss('Selected descriptor URL is missing.');
46
+ const url = new URL(location);
47
+ const udn = field(upnp, 'UDN');
48
+ const usn = record.usn ?? field(headers, 'usn');
49
+ if (typeof usn === 'string' && denonavrUdn(usn.split('::')[0]) !== denonavrUdn(udn)) return miss('SSDP and descriptor identities conflict.');
50
+ return candidate(url.hostname, location, udn, field(upnp, 'modelName'), field(upnp, 'manufacturer'), 'ssdp', field(upnp, 'friendlyName'));
51
+ } catch { return miss('SSDP record lacks an exact supported model and selected descriptor identity.'); }
102
52
  }
103
53
  }
104
54
 
105
55
  export class DenonavrManualMatcher implements IDiscoveryMatcher<IDenonavrManualEntry> {
106
- public id = 'denonavr-manual-match';
107
- public source = 'manual' as const;
108
- public description = 'Recognize manual Denon/Marantz AVR setup entries.';
109
-
110
- public async matches(inputArg: IDenonavrManualEntry): Promise<IDiscoveryMatch> {
111
- const model = cleanModel(inputArg.model);
112
- const matched = Boolean(
113
- inputArg.host
114
- || isSupportedManufacturer(inputArg.manufacturer)
115
- || model?.toLowerCase().includes('denon')
116
- || model?.toLowerCase().includes('marantz')
117
- || inputArg.metadata?.denonavr
118
- );
119
- if (!matched) {
120
- return { matched: false, confidence: 'low', reason: 'Manual entry does not contain Denon AVR setup hints.' };
121
- }
122
- const id = uniqueId(model, inputArg.serialNumber) || inputArg.id;
123
- return {
124
- matched: true,
125
- confidence: inputArg.host ? 'high' : 'medium',
126
- reason: 'Manual entry can start Denon AVR setup.',
127
- normalizedDeviceId: id,
128
- candidate: {
129
- source: 'manual',
130
- integrationDomain: 'denonavr',
131
- id,
132
- host: inputArg.host,
133
- port: inputArg.port || 80,
134
- name: inputArg.name,
135
- manufacturer: normalizedManufacturer(inputArg.manufacturer),
136
- model,
137
- serialNumber: inputArg.serialNumber,
138
- metadata: inputArg.metadata,
139
- },
140
- };
56
+ public readonly id = 'denonavr-manual-match';
57
+ public readonly source = 'manual' as const;
58
+ public async matches(input: IDenonavrManualEntry): Promise<IDiscoveryMatch> {
59
+ try {
60
+ const record = denonavrRecord(input, ['host', 'descriptionUrl', 'expectedUdn', 'id', 'name', 'manufacturer', 'model', 'metadata']);
61
+ const metadata = record.metadata === undefined ? {} : denonavrRecord(record.metadata, ['descriptionUrl']);
62
+ if (record.name !== undefined && typeof record.name !== 'string') return miss('Receiver name is invalid.');
63
+ const id = record.expectedUdn ?? record.id;
64
+ if (record.expectedUdn !== undefined && record.id !== undefined && denonavrUdn(record.expectedUdn) !== denonavrUdn(record.id)) return miss('Manual receiver identities conflict.');
65
+ return candidate(record.host, record.descriptionUrl ?? metadata.descriptionUrl, id, record.model, record.manufacturer,
66
+ 'manual', typeof record.name === 'string' ? record.name : undefined);
67
+ } catch { return miss('Manual setup must select a supported model, private IP, descriptor URL and exact UDN.'); }
141
68
  }
142
69
  }
143
70
 
144
71
  export class DenonavrCandidateValidator implements IDiscoveryValidator {
145
- public id = 'denonavr-candidate-validator';
146
- public description = 'Validate Denon/Marantz AVR candidate metadata.';
147
-
148
- public async validate(candidateArg: IDiscoveryCandidate): Promise<IDiscoveryMatch> {
149
- const manufacturer = candidateArg.manufacturer?.toLowerCase() || '';
150
- const model = candidateArg.model?.toLowerCase() || '';
151
- const matched = candidateArg.integrationDomain === 'denonavr'
152
- || isSupportedManufacturer(manufacturer)
153
- || model.includes('denon')
154
- || model.includes('marantz')
155
- || model.includes('avr')
156
- || model.includes('sr');
157
- const rejected = isIgnoredModel(model);
158
-
159
- return {
160
- matched: matched && !rejected,
161
- confidence: matched && !rejected && candidateArg.host ? 'high' : matched && !rejected ? 'medium' : 'low',
162
- reason: rejected ? 'Candidate is a HEOS speaker, not an AVR.' : matched ? 'Candidate has Denon/Marantz AVR metadata.' : 'Candidate is not a Denon AVR.',
163
- candidate: matched && !rejected ? candidateArg : undefined,
164
- normalizedDeviceId: uniqueId(candidateArg.model, candidateArg.serialNumber) || candidateArg.id,
165
- };
72
+ public readonly id = 'denonavr-candidate-validator';
73
+ public async validate(input: IDiscoveryCandidate): Promise<IDiscoveryMatch> {
74
+ try {
75
+ const record = denonavrRecord(input, ['source', 'integrationDomain', 'id', 'host', 'port', 'name', 'manufacturer', 'model', 'metadata']);
76
+ if (record.integrationDomain !== 'denonavr' || (record.source !== 'manual' && record.source !== 'ssdp')) return miss('Candidate does not belong to selected DenonAVR discovery.');
77
+ const metadata = denonavrRecord(record.metadata, ['descriptionUrl', 'identityEvidence']);
78
+ return candidate(record.host, metadata.descriptionUrl, record.id, record.model, record.manufacturer, record.source,
79
+ typeof record.name === 'string' ? record.name : undefined);
80
+ } catch { return miss('Candidate cannot satisfy selected DenonAVR setup.'); }
166
81
  }
167
82
  }
168
83
 
169
- export const createDenonavrDiscoveryDescriptor = (): DiscoveryDescriptor => {
170
- return new DiscoveryDescriptor({ integrationDomain: 'denonavr', displayName: 'Denon AVR Network Receivers' })
171
- .addMatcher(new DenonavrSsdpMatcher())
172
- .addMatcher(new DenonavrMdnsMatcher())
173
- .addMatcher(new DenonavrManualMatcher())
174
- .addValidator(new DenonavrCandidateValidator());
175
- };
176
-
177
- const header = (recordArg: IDenonavrSsdpRecord, keyArg: string): string | undefined => {
178
- return recordArg[keyArg as keyof IDenonavrSsdpRecord] as string | undefined
179
- || valueForKey(recordArg.headers, keyArg);
180
- };
181
-
182
- const upnp = (recordArg: IDenonavrSsdpRecord, keyArg: string): string | undefined => {
183
- return valueForKey(recordArg.upnp, keyArg) || valueForKey(recordArg.headers, keyArg);
184
- };
185
-
186
- const valueForKey = (recordArg: Record<string, string | undefined> | undefined, keyArg: string): string | undefined => {
187
- if (!recordArg) {
188
- return undefined;
189
- }
190
- const lowerKey = keyArg.toLowerCase();
191
- for (const [key, value] of Object.entries(recordArg)) {
192
- if (key.toLowerCase() === lowerKey) {
193
- return value;
194
- }
195
- }
196
- return undefined;
197
- };
198
-
199
- const parseUrl = (valueArg: string | undefined): URL | undefined => {
200
- if (!valueArg) {
201
- return undefined;
202
- }
203
- try {
204
- return new URL(valueArg);
205
- } catch {
206
- return undefined;
207
- }
208
- };
209
-
210
- const stripUuid = (valueArg: string | undefined): string | undefined => {
211
- return valueArg?.replace(/^uuid:/i, '').split('::')[0];
212
- };
213
-
214
- const cleanModel = (valueArg: string | undefined): string | undefined => {
215
- return valueArg?.replace(/\*/g, '').trim() || undefined;
216
- };
217
-
218
- const isSupportedManufacturer = (valueArg: string | undefined): boolean => {
219
- const value = valueArg?.toLowerCase().trim();
220
- return Boolean(value && supportedManufacturers.includes(value));
221
- };
222
-
223
- const normalizedManufacturer = (valueArg: string | undefined): string | undefined => {
224
- if (!valueArg) {
225
- return undefined;
226
- }
227
- return valueArg.toLowerCase().includes('marantz') ? 'Marantz' : valueArg.toLowerCase().includes('denon') ? 'Denon' : valueArg;
228
- };
229
-
230
- const isIgnoredModel = (valueArg: string | undefined): boolean => {
231
- return Boolean(valueArg && ignoredModels.includes(valueArg.toLowerCase()));
232
- };
233
-
234
- const uniqueId = (modelArg: string | undefined, serialArg: string | undefined): string | undefined => {
235
- if (modelArg && serialArg) {
236
- return `${cleanModel(modelArg)}-${serialArg}`;
237
- }
238
- return serialArg;
239
- };
84
+ export const createDenonavrDiscoveryDescriptor = (): DiscoveryDescriptor =>
85
+ new DiscoveryDescriptor({ integrationDomain: 'denonavr', displayName: 'Denon and Marantz selected receivers' })
86
+ .addMatcher(new DenonavrSsdpMatcher()).addMatcher(new DenonavrManualMatcher()).addValidator(new DenonavrCandidateValidator());
@@ -1,193 +1,47 @@
1
- import * as plugins from '../../plugins.js';
1
+ import type * as plugins from '../../plugins.js';
2
2
  import type { IIntegrationEntity } from '../../core/types.js';
3
- import type { IDenonavrReceiverInfo, IDenonavrSnapshot, IDenonavrZoneState } from './denonavr.types.js';
3
+ import type { IDenonavrSnapshot } from './denonavr.types.js';
4
4
 
5
5
  export class DenonavrMapper {
6
- public static toDevices(snapshotArg: IDenonavrSnapshot): plugins.shxInterfaces.data.IDeviceDefinition[] {
7
- const updatedAt = new Date().toISOString();
8
- const features: plugins.shxInterfaces.data.IDeviceFeature[] = [];
9
- const state: plugins.shxInterfaces.data.IDeviceState[] = [];
10
-
11
- for (const zone of snapshotArg.zones) {
12
- const zoneSlug = this.slug(zone.zone);
13
- features.push(
14
- { id: `${zoneSlug}_power`, capability: 'media', name: `${this.zoneName(zone)} power`, readable: true, writable: true },
15
- { id: `${zoneSlug}_source`, capability: 'media', name: `${this.zoneName(zone)} source`, readable: true, writable: true },
16
- { id: `${zoneSlug}_volume`, capability: 'media', name: `${this.zoneName(zone)} volume`, readable: true, writable: true, unit: '%' },
17
- { id: `${zoneSlug}_muted`, capability: 'media', name: `${this.zoneName(zone)} muted`, readable: true, writable: true },
18
- );
19
- state.push(
20
- { featureId: `${zoneSlug}_power`, value: this.powerState(zone), updatedAt },
21
- { featureId: `${zoneSlug}_source`, value: zone.source || null, updatedAt },
22
- { featureId: `${zoneSlug}_volume`, value: typeof this.volumeLevel(zone) === 'number' ? Math.round((this.volumeLevel(zone) || 0) * 100) : null, updatedAt },
23
- { featureId: `${zoneSlug}_muted`, value: zone.muted ?? null, updatedAt },
24
- );
25
- if (zone.soundMode || zone.soundModeRaw) {
26
- features.push({ id: `${zoneSlug}_sound_mode`, capability: 'media', name: `${this.zoneName(zone)} sound mode`, readable: true, writable: true });
27
- state.push({ featureId: `${zoneSlug}_sound_mode`, value: zone.soundMode || zone.soundModeRaw || null, updatedAt });
28
- }
29
- }
30
-
31
- return [{
32
- id: this.deviceId(snapshotArg),
33
- integrationDomain: 'denonavr',
34
- name: this.receiverName(snapshotArg.receiverInfo),
35
- protocol: 'http',
36
- manufacturer: snapshotArg.receiverInfo.manufacturer || 'Denon',
37
- model: snapshotArg.receiverInfo.modelName || snapshotArg.receiverInfo.modelNumber,
38
- online: snapshotArg.zones.some((zoneArg) => zoneArg.available !== false),
39
- features,
40
- state,
41
- metadata: {
42
- host: snapshotArg.receiverInfo.host,
43
- port: snapshotArg.receiverInfo.port,
44
- serialNumber: snapshotArg.receiverInfo.serialNumber,
45
- receiverType: snapshotArg.receiverInfo.receiverType,
46
- softwareVersion: snapshotArg.receiverInfo.softwareVersion,
47
- },
48
- }];
49
- }
50
-
51
- public static toEntities(snapshotArg: IDenonavrSnapshot): IIntegrationEntity[] {
52
- const entities: IIntegrationEntity[] = [];
53
- for (const zone of snapshotArg.zones) {
54
- const zoneEntityBase = this.entityBase(snapshotArg, zone);
55
- entities.push({
56
- id: `media_player.${zoneEntityBase}`,
57
- uniqueId: `denonavr_${this.uniqueBase(snapshotArg)}_${this.slug(zone.zone)}`,
58
- integrationDomain: 'denonavr',
59
- deviceId: this.deviceId(snapshotArg),
60
- platform: 'media_player',
61
- name: this.mediaEntityName(snapshotArg.receiverInfo, zone),
62
- state: this.mediaState(zone),
63
- attributes: {
64
- deviceClass: 'receiver',
65
- zone: zone.zone,
66
- power: zone.power,
67
- volumeLevel: this.volumeLevel(zone),
68
- volumeDb: zone.volumeDb,
69
- isVolumeMuted: zone.muted,
70
- source: zone.source,
71
- sourceList: zone.sourceList,
72
- soundMode: zone.soundMode,
73
- soundModeRaw: zone.soundModeRaw,
74
- soundModeList: zone.soundModeList,
75
- mediaTitle: zone.media?.title || (!zone.media ? zone.source : undefined),
76
- mediaArtist: zone.media?.artist || zone.media?.band,
77
- mediaAlbumName: zone.media?.album || zone.media?.station,
78
- mediaImageUrl: zone.media?.imageUrl,
79
- mediaContentType: zone.media?.contentType,
80
- dynamicEq: zone.dynamicEq,
81
- ecoMode: zone.ecoMode,
82
- },
83
- available: zone.available !== false,
84
- });
85
-
86
- entities.push({
87
- id: `sensor.${zoneEntityBase}_source`,
88
- uniqueId: `denonavr_${this.uniqueBase(snapshotArg)}_${this.slug(zone.zone)}_source`,
89
- integrationDomain: 'denonavr',
90
- deviceId: this.deviceId(snapshotArg),
91
- platform: 'sensor',
92
- name: `${this.mediaEntityName(snapshotArg.receiverInfo, zone)} Source`,
93
- state: zone.source || 'unknown',
94
- attributes: { zone: zone.zone, soundMode: zone.soundMode || zone.soundModeRaw, ecoMode: zone.ecoMode },
95
- available: zone.available !== false,
96
- });
97
-
98
- if (typeof zone.muted === 'boolean') {
99
- entities.push({
100
- id: `switch.${zoneEntityBase}_mute`,
101
- uniqueId: `denonavr_${this.uniqueBase(snapshotArg)}_${this.slug(zone.zone)}_mute`,
102
- integrationDomain: 'denonavr',
103
- deviceId: this.deviceId(snapshotArg),
104
- platform: 'switch',
105
- name: `${this.mediaEntityName(snapshotArg.receiverInfo, zone)} Mute`,
106
- state: zone.muted,
107
- attributes: { zone: zone.zone },
108
- available: zone.available !== false,
109
- });
110
- }
111
-
112
- if (typeof zone.dynamicEq === 'boolean') {
113
- entities.push({
114
- id: `switch.${zoneEntityBase}_dynamic_eq`,
115
- uniqueId: `denonavr_${this.uniqueBase(snapshotArg)}_${this.slug(zone.zone)}_dynamic_eq`,
116
- integrationDomain: 'denonavr',
117
- deviceId: this.deviceId(snapshotArg),
118
- platform: 'switch',
119
- name: `${this.mediaEntityName(snapshotArg.receiverInfo, zone)} Dynamic EQ`,
120
- state: zone.dynamicEq,
121
- attributes: { zone: zone.zone },
122
- available: zone.available !== false,
123
- });
124
- }
125
- }
126
- return entities;
127
- }
128
-
129
- private static mediaState(zoneArg: IDenonavrZoneState): string {
130
- if (this.powerState(zoneArg) === 'off') {
131
- return 'off';
132
- }
133
- const state = zoneArg.state?.toLowerCase();
134
- if (state === 'playing' || state === 'paused') {
135
- return state;
136
- }
137
- if (state === 'stopped') {
138
- return 'idle';
139
- }
140
- return 'on';
6
+ public static deviceId(homeId: string, udn: string): string {
7
+ return `denonavr.receiver.${encodeURIComponent(homeId)}.${encodeURIComponent(udn)}`;
141
8
  }
142
9
 
143
- private static powerState(zoneArg: IDenonavrZoneState): string {
144
- const power = zoneArg.power?.toLowerCase();
145
- if (power === 'off' || power === 'standby') {
146
- return 'off';
147
- }
148
- if (!power && zoneArg.state?.toLowerCase() === 'off') {
149
- return 'off';
150
- }
151
- return 'on';
10
+ public static entityId(homeId: string, udn: string): string {
11
+ return `media_player.denonavr.${encodeURIComponent(homeId)}.${encodeURIComponent(udn)}`;
152
12
  }
153
13
 
154
- private static volumeLevel(zoneArg: IDenonavrZoneState): number | undefined {
155
- if (typeof zoneArg.volumeLevel === 'number') {
156
- return Math.max(0, Math.min(1, zoneArg.volumeLevel));
157
- }
158
- if (typeof zoneArg.volumeDb === 'number') {
159
- return Math.max(0, Math.min(1, (zoneArg.volumeDb + 80) / 100));
160
- }
161
- return undefined;
162
- }
163
-
164
- private static deviceId(snapshotArg: IDenonavrSnapshot): string {
165
- return `denonavr.receiver.${this.uniqueBase(snapshotArg)}`;
166
- }
167
-
168
- private static entityBase(snapshotArg: IDenonavrSnapshot, zoneArg: IDenonavrZoneState): string {
169
- const suffix = zoneArg.zone === 'Main' ? '' : `_${this.slug(zoneArg.zone)}`;
170
- return `${this.slug(this.receiverName(snapshotArg.receiverInfo))}${suffix}`;
171
- }
172
-
173
- private static uniqueBase(snapshotArg: IDenonavrSnapshot): string {
174
- return this.slug(snapshotArg.receiverInfo.serialNumber || snapshotArg.receiverInfo.modelName || snapshotArg.receiverInfo.host || this.receiverName(snapshotArg.receiverInfo));
175
- }
176
-
177
- private static receiverName(infoArg: IDenonavrReceiverInfo): string {
178
- return infoArg.name || infoArg.friendlyName || infoArg.modelName || 'Denon AVR';
179
- }
180
-
181
- private static mediaEntityName(infoArg: IDenonavrReceiverInfo, zoneArg: IDenonavrZoneState): string {
182
- const name = zoneArg.name || this.zoneName(zoneArg);
183
- return zoneArg.zone === 'Main' ? this.receiverName(infoArg) : `${this.receiverName(infoArg)} ${name}`;
184
- }
185
-
186
- private static zoneName(zoneArg: IDenonavrZoneState): string {
187
- return zoneArg.name || (zoneArg.zone === 'Main' ? 'Main Zone' : zoneArg.zone);
14
+ public static toDevices(snapshot: IDenonavrSnapshot): plugins.shxInterfaces.data.IDeviceDefinition[] {
15
+ return [{
16
+ id: this.deviceId(snapshot.homeId, snapshot.identity.udn), integrationDomain: 'denonavr', name: snapshot.name,
17
+ protocol: 'tcp', manufacturer: snapshot.identity.manufacturer, model: snapshot.identity.model, online: true,
18
+ features: [
19
+ { id: 'power', capability: 'media', name: 'Receiver power', readable: true, writable: true },
20
+ { id: 'muted', capability: 'media', name: 'Main-zone mute', readable: true, writable: true },
21
+ { id: 'volume_db', capability: 'media', name: 'Main-zone absolute volume', unit: 'dB', readable: true, writable: true },
22
+ { id: 'input', capability: 'media', name: 'Main-zone input', readable: true, writable: snapshot.observedInputs.length > 0 },
23
+ ],
24
+ state: [
25
+ { featureId: 'power', value: snapshot.power === 'on', updatedAt: snapshot.observedAt },
26
+ { featureId: 'muted', value: snapshot.muted, updatedAt: snapshot.observedAt },
27
+ { featureId: 'volume_db', value: snapshot.volumeDb, updatedAt: snapshot.observedAt },
28
+ { featureId: 'input', value: snapshot.input, updatedAt: snapshot.observedAt },
29
+ ],
30
+ metadata: { homeId: snapshot.homeId, udn: snapshot.identity.udn, host: snapshot.host, port: snapshot.port,
31
+ serialNumber: snapshot.identity.serialNumber, identitySource: snapshot.identity.source,
32
+ observedInputs: [...snapshot.observedInputs], maximumVolumeDb: snapshot.maximumVolumeDb,
33
+ stateSource: 'receiver-observation', identityAuthentication: 'unauthenticated-lan' },
34
+ }];
188
35
  }
189
36
 
190
- private static slug(valueArg: string): string {
191
- return valueArg.toLowerCase().replace(/[^a-z0-9]+/g, '_').replace(/^_+|_+$/g, '') || 'denonavr';
37
+ public static toEntities(snapshot: IDenonavrSnapshot): IIntegrationEntity[] {
38
+ return [{
39
+ id: this.entityId(snapshot.homeId, snapshot.identity.udn), uniqueId: this.deviceId(snapshot.homeId, snapshot.identity.udn),
40
+ integrationDomain: 'denonavr', deviceId: this.deviceId(snapshot.homeId, snapshot.identity.udn), platform: 'media_player',
41
+ name: snapshot.name, state: snapshot.power === 'on' ? 'on' : 'off', available: true,
42
+ attributes: { homeId: snapshot.homeId, udn: snapshot.identity.udn, zone: 'Main', power: snapshot.power,
43
+ volumeDb: snapshot.volumeDb, muted: snapshot.muted, source: snapshot.input, sourceList: [...snapshot.observedInputs],
44
+ maximumVolumeDb: snapshot.maximumVolumeDb, observedAt: snapshot.observedAt, stateSource: 'receiver-observation' },
45
+ }];
192
46
  }
193
47
  }