@smarthome.exchange/integrations 1.0.0 → 2.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 (294) hide show
  1. package/changelog.md +49 -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 +79 -0
  8. package/dist_ts/core/classes.nativeintegrationowner.js +269 -0
  9. package/dist_ts/core/index.d.ts +2 -0
  10. package/dist_ts/core/index.js +3 -1
  11. package/dist_ts/core/types.d.ts +14 -0
  12. package/dist_ts/integrations/braviatv/braviatv.classes.client.d.ts +23 -72
  13. package/dist_ts/integrations/braviatv/braviatv.classes.client.js +265 -625
  14. package/dist_ts/integrations/braviatv/braviatv.classes.configflow.d.ts +7 -7
  15. package/dist_ts/integrations/braviatv/braviatv.classes.configflow.js +51 -68
  16. package/dist_ts/integrations/braviatv/braviatv.classes.integration.d.ts +8 -11
  17. package/dist_ts/integrations/braviatv/braviatv.classes.integration.js +186 -135
  18. package/dist_ts/integrations/braviatv/braviatv.discovery.js +12 -11
  19. package/dist_ts/integrations/braviatv/braviatv.mapper.d.ts +6 -14
  20. package/dist_ts/integrations/braviatv/braviatv.mapper.js +37 -131
  21. package/dist_ts/integrations/braviatv/braviatv.types.d.ts +55 -133
  22. package/dist_ts/integrations/braviatv/braviatv.validation.d.ts +7 -0
  23. package/dist_ts/integrations/braviatv/braviatv.validation.js +72 -0
  24. package/dist_ts/integrations/broadlink/broadlink.actions.d.ts +2 -0
  25. package/dist_ts/integrations/broadlink/broadlink.actions.js +36 -0
  26. package/dist_ts/integrations/broadlink/broadlink.classes.client.d.ts +21 -19
  27. package/dist_ts/integrations/broadlink/broadlink.classes.client.js +185 -124
  28. package/dist_ts/integrations/broadlink/broadlink.classes.configflow.d.ts +5 -4
  29. package/dist_ts/integrations/broadlink/broadlink.classes.configflow.js +64 -83
  30. package/dist_ts/integrations/broadlink/broadlink.classes.integration.d.ts +16 -19
  31. package/dist_ts/integrations/broadlink/broadlink.classes.integration.js +114 -59
  32. package/dist_ts/integrations/broadlink/broadlink.mapper.d.ts +3 -2
  33. package/dist_ts/integrations/broadlink/broadlink.mapper.js +2 -1
  34. package/dist_ts/integrations/broadlink/broadlink.selected.mapper.d.ts +10 -0
  35. package/dist_ts/integrations/broadlink/broadlink.selected.mapper.js +41 -0
  36. package/dist_ts/integrations/broadlink/broadlink.types.d.ts +43 -7
  37. package/dist_ts/integrations/broadlink/broadlink.validation.d.ts +7 -0
  38. package/dist_ts/integrations/broadlink/broadlink.validation.js +63 -0
  39. package/dist_ts/integrations/daikin/daikin.classes.client.d.ts +10 -52
  40. package/dist_ts/integrations/daikin/daikin.classes.client.js +55 -614
  41. package/dist_ts/integrations/daikin/daikin.classes.configflow.d.ts +8 -12
  42. package/dist_ts/integrations/daikin/daikin.classes.configflow.js +77 -138
  43. package/dist_ts/integrations/daikin/daikin.classes.integration.d.ts +7 -24
  44. package/dist_ts/integrations/daikin/daikin.classes.integration.js +175 -67
  45. package/dist_ts/integrations/daikin/daikin.discovery.d.ts +11 -24
  46. package/dist_ts/integrations/daikin/daikin.discovery.js +98 -305
  47. package/dist_ts/integrations/daikin/daikin.mapper.d.ts +6 -7
  48. package/dist_ts/integrations/daikin/daikin.mapper.js +95 -155
  49. package/dist_ts/integrations/daikin/daikin.types.d.ts +24 -44
  50. package/dist_ts/integrations/daikin/daikin.types.js +1 -1
  51. package/dist_ts/integrations/daikin/daikin.validation.d.ts +5 -0
  52. package/dist_ts/integrations/daikin/daikin.validation.js +53 -0
  53. package/dist_ts/integrations/denonavr/denonavr.classes.client.d.ts +31 -40
  54. package/dist_ts/integrations/denonavr/denonavr.classes.client.js +149 -404
  55. package/dist_ts/integrations/denonavr/denonavr.classes.configflow.d.ts +7 -2
  56. package/dist_ts/integrations/denonavr/denonavr.classes.configflow.js +44 -36
  57. package/dist_ts/integrations/denonavr/denonavr.classes.integration.d.ts +6 -11
  58. package/dist_ts/integrations/denonavr/denonavr.classes.integration.js +192 -113
  59. package/dist_ts/integrations/denonavr/denonavr.discovery.d.ts +10 -18
  60. package/dist_ts/integrations/denonavr/denonavr.discovery.js +71 -193
  61. package/dist_ts/integrations/denonavr/denonavr.mapper.d.ts +5 -13
  62. package/dist_ts/integrations/denonavr/denonavr.mapper.js +35 -159
  63. package/dist_ts/integrations/denonavr/denonavr.types.d.ts +55 -90
  64. package/dist_ts/integrations/denonavr/denonavr.validation.d.ts +10 -0
  65. package/dist_ts/integrations/denonavr/denonavr.validation.js +86 -0
  66. package/dist_ts/integrations/kodi/kodi.classes.client.d.ts +11 -45
  67. package/dist_ts/integrations/kodi/kodi.classes.client.js +84 -310
  68. package/dist_ts/integrations/kodi/kodi.classes.configflow.d.ts +9 -8
  69. package/dist_ts/integrations/kodi/kodi.classes.configflow.js +53 -48
  70. package/dist_ts/integrations/kodi/kodi.classes.integration.d.ts +11 -11
  71. package/dist_ts/integrations/kodi/kodi.classes.integration.js +114 -171
  72. package/dist_ts/integrations/kodi/kodi.discovery.js +53 -29
  73. package/dist_ts/integrations/kodi/kodi.mapper.d.ts +7 -2
  74. package/dist_ts/integrations/kodi/kodi.mapper.js +48 -10
  75. package/dist_ts/integrations/kodi/kodi.types.d.ts +32 -28
  76. package/dist_ts/integrations/kodi/kodi.validation.d.ts +9 -0
  77. package/dist_ts/integrations/kodi/kodi.validation.js +62 -0
  78. package/dist_ts/integrations/modbus/modbus.classes.client.d.ts +15 -61
  79. package/dist_ts/integrations/modbus/modbus.classes.client.js +117 -776
  80. package/dist_ts/integrations/modbus/modbus.classes.configflow.d.ts +9 -5
  81. package/dist_ts/integrations/modbus/modbus.classes.configflow.js +70 -38
  82. package/dist_ts/integrations/modbus/modbus.classes.integration.d.ts +6 -17
  83. package/dist_ts/integrations/modbus/modbus.classes.integration.js +133 -57
  84. package/dist_ts/integrations/modbus/modbus.discovery.d.ts +5 -8
  85. package/dist_ts/integrations/modbus/modbus.discovery.js +38 -93
  86. package/dist_ts/integrations/modbus/modbus.mapper.d.ts +8 -32
  87. package/dist_ts/integrations/modbus/modbus.mapper.js +71 -431
  88. package/dist_ts/integrations/modbus/modbus.types.d.ts +82 -332
  89. package/dist_ts/integrations/modbus/modbus.validation.d.ts +10 -0
  90. package/dist_ts/integrations/modbus/modbus.validation.js +128 -0
  91. package/dist_ts/integrations/nanoleaf/nanoleaf.classes.client.d.ts +12 -34
  92. package/dist_ts/integrations/nanoleaf/nanoleaf.classes.client.js +143 -231
  93. package/dist_ts/integrations/nanoleaf/nanoleaf.classes.configflow.d.ts +6 -1
  94. package/dist_ts/integrations/nanoleaf/nanoleaf.classes.configflow.js +105 -18
  95. package/dist_ts/integrations/nanoleaf/nanoleaf.classes.integration.d.ts +8 -8
  96. package/dist_ts/integrations/nanoleaf/nanoleaf.classes.integration.js +141 -155
  97. package/dist_ts/integrations/nanoleaf/nanoleaf.credentials.d.ts +9 -0
  98. package/dist_ts/integrations/nanoleaf/nanoleaf.credentials.js +35 -0
  99. package/dist_ts/integrations/nanoleaf/nanoleaf.mapper.d.ts +6 -18
  100. package/dist_ts/integrations/nanoleaf/nanoleaf.mapper.js +45 -220
  101. package/dist_ts/integrations/nanoleaf/nanoleaf.types.d.ts +33 -147
  102. package/dist_ts/integrations/nanoleaf/nanoleaf.validation.d.ts +6 -0
  103. package/dist_ts/integrations/nanoleaf/nanoleaf.validation.js +82 -0
  104. package/dist_ts/integrations/onkyo/onkyo.classes.client.d.ts +15 -20
  105. package/dist_ts/integrations/onkyo/onkyo.classes.client.js +161 -404
  106. package/dist_ts/integrations/onkyo/onkyo.classes.configflow.d.ts +9 -4
  107. package/dist_ts/integrations/onkyo/onkyo.classes.configflow.js +51 -6
  108. package/dist_ts/integrations/onkyo/onkyo.classes.integration.d.ts +22 -6
  109. package/dist_ts/integrations/onkyo/onkyo.classes.integration.js +144 -11
  110. package/dist_ts/integrations/onkyo/onkyo.discovery.d.ts +6 -1
  111. package/dist_ts/integrations/onkyo/onkyo.discovery.js +40 -4
  112. package/dist_ts/integrations/onkyo/onkyo.mapper.d.ts +7 -8
  113. package/dist_ts/integrations/onkyo/onkyo.mapper.js +45 -12
  114. package/dist_ts/integrations/onkyo/onkyo.types.d.ts +58 -8
  115. package/dist_ts/integrations/onkyo/onkyo.types.js +13 -102
  116. package/dist_ts/integrations/onkyo/onkyo.validation.d.ts +16 -0
  117. package/dist_ts/integrations/onkyo/onkyo.validation.js +77 -0
  118. package/dist_ts/integrations/panasonic_viera/panasonic_viera.classes.client.d.ts +25 -25
  119. package/dist_ts/integrations/panasonic_viera/panasonic_viera.classes.client.js +116 -360
  120. package/dist_ts/integrations/panasonic_viera/panasonic_viera.classes.configflow.d.ts +11 -3
  121. package/dist_ts/integrations/panasonic_viera/panasonic_viera.classes.configflow.js +76 -6
  122. package/dist_ts/integrations/panasonic_viera/panasonic_viera.classes.integration.d.ts +26 -4
  123. package/dist_ts/integrations/panasonic_viera/panasonic_viera.classes.integration.js +142 -9
  124. package/dist_ts/integrations/panasonic_viera/panasonic_viera.discovery.d.ts +2 -1
  125. package/dist_ts/integrations/panasonic_viera/panasonic_viera.discovery.js +31 -4
  126. package/dist_ts/integrations/panasonic_viera/panasonic_viera.mapper.d.ts +9 -9
  127. package/dist_ts/integrations/panasonic_viera/panasonic_viera.mapper.js +31 -149
  128. package/dist_ts/integrations/panasonic_viera/panasonic_viera.types.d.ts +51 -11
  129. package/dist_ts/integrations/panasonic_viera/panasonic_viera.types.js +22 -87
  130. package/dist_ts/integrations/panasonic_viera/panasonic_viera.validation.d.ts +6 -0
  131. package/dist_ts/integrations/panasonic_viera/panasonic_viera.validation.js +56 -0
  132. package/dist_ts/integrations/pioneer/pioneer.classes.client.d.ts +31 -16
  133. package/dist_ts/integrations/pioneer/pioneer.classes.client.js +167 -409
  134. package/dist_ts/integrations/pioneer/pioneer.classes.configflow.d.ts +10 -3
  135. package/dist_ts/integrations/pioneer/pioneer.classes.configflow.js +66 -6
  136. package/dist_ts/integrations/pioneer/pioneer.classes.integration.d.ts +13 -5
  137. package/dist_ts/integrations/pioneer/pioneer.classes.integration.js +239 -11
  138. package/dist_ts/integrations/pioneer/pioneer.discovery.d.ts +14 -1
  139. package/dist_ts/integrations/pioneer/pioneer.discovery.js +51 -4
  140. package/dist_ts/integrations/pioneer/pioneer.mapper.d.ts +14 -8
  141. package/dist_ts/integrations/pioneer/pioneer.mapper.js +54 -12
  142. package/dist_ts/integrations/pioneer/pioneer.types.d.ts +79 -12
  143. package/dist_ts/integrations/pioneer/pioneer.types.js +12 -76
  144. package/dist_ts/integrations/pioneer/pioneer.validation.d.ts +10 -0
  145. package/dist_ts/integrations/pioneer/pioneer.validation.js +85 -0
  146. package/dist_ts/integrations/soundtouch/soundtouch.classes.client.d.ts +13 -36
  147. package/dist_ts/integrations/soundtouch/soundtouch.classes.client.js +179 -502
  148. package/dist_ts/integrations/soundtouch/soundtouch.classes.configflow.d.ts +6 -1
  149. package/dist_ts/integrations/soundtouch/soundtouch.classes.configflow.js +50 -40
  150. package/dist_ts/integrations/soundtouch/soundtouch.classes.integration.d.ts +14 -15
  151. package/dist_ts/integrations/soundtouch/soundtouch.classes.integration.js +108 -128
  152. package/dist_ts/integrations/soundtouch/soundtouch.discovery.d.ts +2 -20
  153. package/dist_ts/integrations/soundtouch/soundtouch.discovery.js +23 -113
  154. package/dist_ts/integrations/soundtouch/soundtouch.mapper.d.ts +3 -12
  155. package/dist_ts/integrations/soundtouch/soundtouch.mapper.js +35 -189
  156. package/dist_ts/integrations/soundtouch/soundtouch.types.d.ts +57 -142
  157. package/dist_ts/integrations/soundtouch/soundtouch.types.js +18 -3
  158. package/dist_ts/integrations/soundtouch/soundtouch.validation.d.ts +22 -0
  159. package/dist_ts/integrations/soundtouch/soundtouch.validation.js +65 -0
  160. package/dist_ts/integrations/wiz/index.d.ts +1 -0
  161. package/dist_ts/integrations/wiz/index.js +2 -1
  162. package/dist_ts/integrations/wiz/wiz.classes.client.d.ts +14 -28
  163. package/dist_ts/integrations/wiz/wiz.classes.client.js +93 -229
  164. package/dist_ts/integrations/wiz/wiz.classes.configflow.d.ts +6 -4
  165. package/dist_ts/integrations/wiz/wiz.classes.configflow.js +38 -67
  166. package/dist_ts/integrations/wiz/wiz.classes.integration.d.ts +10 -21
  167. package/dist_ts/integrations/wiz/wiz.classes.integration.js +204 -44
  168. package/dist_ts/integrations/wiz/wiz.discovery.d.ts +10 -31
  169. package/dist_ts/integrations/wiz/wiz.discovery.js +48 -249
  170. package/dist_ts/integrations/wiz/wiz.mapper.d.ts +7 -51
  171. package/dist_ts/integrations/wiz/wiz.mapper.js +82 -668
  172. package/dist_ts/integrations/wiz/wiz.types.d.ts +34 -208
  173. package/dist_ts/integrations/wiz/wiz.validation.d.ts +8 -0
  174. package/dist_ts/integrations/wiz/wiz.validation.js +72 -0
  175. package/dist_ts/integrations/yamaha/index.d.ts +1 -0
  176. package/dist_ts/integrations/yamaha/index.js +2 -1
  177. package/dist_ts/integrations/yamaha/yamaha.classes.client.d.ts +30 -4
  178. package/dist_ts/integrations/yamaha/yamaha.classes.client.js +162 -6
  179. package/dist_ts/integrations/yamaha/yamaha.classes.configflow.d.ts +10 -3
  180. package/dist_ts/integrations/yamaha/yamaha.classes.configflow.js +106 -6
  181. package/dist_ts/integrations/yamaha/yamaha.classes.integration.d.ts +22 -4
  182. package/dist_ts/integrations/yamaha/yamaha.classes.integration.js +243 -8
  183. package/dist_ts/integrations/yamaha/yamaha.discovery.d.ts +13 -1
  184. package/dist_ts/integrations/yamaha/yamaha.discovery.js +57 -4
  185. package/dist_ts/integrations/yamaha/yamaha.mapper.d.ts +16 -8
  186. package/dist_ts/integrations/yamaha/yamaha.mapper.js +58 -12
  187. package/dist_ts/integrations/yamaha/yamaha.types.d.ts +73 -6
  188. package/dist_ts/integrations/yamaha/yamaha.types.js +8 -94
  189. package/dist_ts/integrations/yamaha/yamaha.validation.d.ts +12 -0
  190. package/dist_ts/integrations/yamaha/yamaha.validation.js +89 -0
  191. package/package.json +3 -3
  192. package/readme.md +514 -2
  193. package/ts/00_commitinfo_data.ts +1 -1
  194. package/ts/core/classes.configstore.ts +84 -27
  195. package/ts/core/classes.nativehomeadmission.ts +96 -0
  196. package/ts/core/classes.nativeintegrationowner.ts +297 -0
  197. package/ts/core/index.ts +2 -0
  198. package/ts/core/types.ts +16 -0
  199. package/ts/integrations/braviatv/braviatv.classes.client.ts +245 -709
  200. package/ts/integrations/braviatv/braviatv.classes.configflow.ts +47 -76
  201. package/ts/integrations/braviatv/braviatv.classes.integration.ts +167 -147
  202. package/ts/integrations/braviatv/braviatv.discovery.ts +11 -10
  203. package/ts/integrations/braviatv/braviatv.mapper.ts +39 -142
  204. package/ts/integrations/braviatv/braviatv.types.ts +53 -173
  205. package/ts/integrations/braviatv/braviatv.validation.ts +68 -0
  206. package/ts/integrations/broadlink/broadlink.actions.ts +31 -0
  207. package/ts/integrations/broadlink/broadlink.classes.client.ts +170 -144
  208. package/ts/integrations/broadlink/broadlink.classes.configflow.ts +59 -89
  209. package/ts/integrations/broadlink/broadlink.classes.integration.ts +110 -64
  210. package/ts/integrations/broadlink/broadlink.mapper.ts +5 -4
  211. package/ts/integrations/broadlink/broadlink.selected.mapper.ts +46 -0
  212. package/ts/integrations/broadlink/broadlink.types.ts +48 -8
  213. package/ts/integrations/broadlink/broadlink.validation.ts +66 -0
  214. package/ts/integrations/daikin/daikin.classes.client.ts +52 -661
  215. package/ts/integrations/daikin/daikin.classes.configflow.ts +72 -152
  216. package/ts/integrations/daikin/daikin.classes.integration.ts +166 -71
  217. package/ts/integrations/daikin/daikin.discovery.ts +94 -346
  218. package/ts/integrations/daikin/daikin.mapper.ts +83 -166
  219. package/ts/integrations/daikin/daikin.types.ts +27 -48
  220. package/ts/integrations/daikin/daikin.validation.ts +51 -0
  221. package/ts/integrations/daikin/readme.md +83 -0
  222. package/ts/integrations/denonavr/denonavr.classes.client.ts +132 -421
  223. package/ts/integrations/denonavr/denonavr.classes.configflow.ts +44 -37
  224. package/ts/integrations/denonavr/denonavr.classes.integration.ts +171 -117
  225. package/ts/integrations/denonavr/denonavr.discovery.ts +67 -220
  226. package/ts/integrations/denonavr/denonavr.mapper.ts +36 -182
  227. package/ts/integrations/denonavr/denonavr.types.ts +48 -111
  228. package/ts/integrations/denonavr/denonavr.validation.ts +87 -0
  229. package/ts/integrations/kodi/kodi.classes.client.ts +72 -352
  230. package/ts/integrations/kodi/kodi.classes.configflow.ts +52 -55
  231. package/ts/integrations/kodi/kodi.classes.integration.ts +97 -178
  232. package/ts/integrations/kodi/kodi.discovery.ts +49 -28
  233. package/ts/integrations/kodi/kodi.mapper.ts +52 -10
  234. package/ts/integrations/kodi/kodi.types.ts +33 -58
  235. package/ts/integrations/kodi/kodi.validation.ts +60 -0
  236. package/ts/integrations/modbus/modbus.classes.client.ts +100 -842
  237. package/ts/integrations/modbus/modbus.classes.configflow.ts +70 -41
  238. package/ts/integrations/modbus/modbus.classes.integration.ts +115 -60
  239. package/ts/integrations/modbus/modbus.discovery.ts +38 -106
  240. package/ts/integrations/modbus/modbus.mapper.ts +64 -467
  241. package/ts/integrations/modbus/modbus.types.ts +64 -381
  242. package/ts/integrations/modbus/modbus.validation.ts +119 -0
  243. package/ts/integrations/nanoleaf/nanoleaf.classes.client.ts +115 -249
  244. package/ts/integrations/nanoleaf/nanoleaf.classes.configflow.ts +90 -19
  245. package/ts/integrations/nanoleaf/nanoleaf.classes.integration.ts +130 -181
  246. package/ts/integrations/nanoleaf/nanoleaf.credentials.ts +39 -0
  247. package/ts/integrations/nanoleaf/nanoleaf.mapper.ts +47 -260
  248. package/ts/integrations/nanoleaf/nanoleaf.types.ts +29 -147
  249. package/ts/integrations/nanoleaf/nanoleaf.validation.ts +77 -0
  250. package/ts/integrations/onkyo/onkyo.classes.client.ts +148 -457
  251. package/ts/integrations/onkyo/onkyo.classes.configflow.ts +52 -6
  252. package/ts/integrations/onkyo/onkyo.classes.integration.ts +121 -12
  253. package/ts/integrations/onkyo/onkyo.discovery.ts +41 -3
  254. package/ts/integrations/onkyo/onkyo.mapper.ts +46 -19
  255. package/ts/integrations/onkyo/onkyo.types.ts +55 -110
  256. package/ts/integrations/onkyo/onkyo.validation.ts +85 -0
  257. package/ts/integrations/onkyo/readme.md +126 -0
  258. package/ts/integrations/panasonic_viera/panasonic_viera.classes.client.ts +101 -398
  259. package/ts/integrations/panasonic_viera/panasonic_viera.classes.configflow.ts +69 -5
  260. package/ts/integrations/panasonic_viera/panasonic_viera.classes.integration.ts +141 -9
  261. package/ts/integrations/panasonic_viera/panasonic_viera.discovery.ts +32 -3
  262. package/ts/integrations/panasonic_viera/panasonic_viera.mapper.ts +34 -161
  263. package/ts/integrations/panasonic_viera/panasonic_viera.types.ts +52 -96
  264. package/ts/integrations/panasonic_viera/panasonic_viera.validation.ts +56 -0
  265. package/ts/integrations/pioneer/pioneer.classes.client.ts +132 -428
  266. package/ts/integrations/pioneer/pioneer.classes.configflow.ts +67 -5
  267. package/ts/integrations/pioneer/pioneer.classes.integration.ts +225 -11
  268. package/ts/integrations/pioneer/pioneer.discovery.ts +45 -3
  269. package/ts/integrations/pioneer/pioneer.mapper.ts +57 -13
  270. package/ts/integrations/pioneer/pioneer.types.ts +87 -85
  271. package/ts/integrations/pioneer/pioneer.validation.ts +84 -0
  272. package/ts/integrations/soundtouch/soundtouch.classes.client.ts +152 -571
  273. package/ts/integrations/soundtouch/soundtouch.classes.configflow.ts +47 -42
  274. package/ts/integrations/soundtouch/soundtouch.classes.integration.ts +95 -150
  275. package/ts/integrations/soundtouch/soundtouch.discovery.ts +21 -133
  276. package/ts/integrations/soundtouch/soundtouch.mapper.ts +36 -207
  277. package/ts/integrations/soundtouch/soundtouch.types.ts +50 -195
  278. package/ts/integrations/soundtouch/soundtouch.validation.ts +60 -0
  279. package/ts/integrations/wiz/index.ts +1 -0
  280. package/ts/integrations/wiz/wiz.classes.client.ts +84 -254
  281. package/ts/integrations/wiz/wiz.classes.configflow.ts +39 -70
  282. package/ts/integrations/wiz/wiz.classes.integration.ts +189 -45
  283. package/ts/integrations/wiz/wiz.discovery.ts +48 -291
  284. package/ts/integrations/wiz/wiz.mapper.ts +81 -754
  285. package/ts/integrations/wiz/wiz.types.ts +24 -224
  286. package/ts/integrations/wiz/wiz.validation.ts +73 -0
  287. package/ts/integrations/yamaha/index.ts +1 -0
  288. package/ts/integrations/yamaha/yamaha.classes.client.ts +150 -6
  289. package/ts/integrations/yamaha/yamaha.classes.configflow.ts +100 -5
  290. package/ts/integrations/yamaha/yamaha.classes.integration.ts +236 -8
  291. package/ts/integrations/yamaha/yamaha.discovery.ts +52 -3
  292. package/ts/integrations/yamaha/yamaha.mapper.ts +65 -13
  293. package/ts/integrations/yamaha/yamaha.types.ts +77 -97
  294. package/ts/integrations/yamaha/yamaha.validation.ts +86 -0
@@ -1,487 +1,84 @@
1
- import * as plugins from '../../plugins.js';
2
- import type { IIntegrationEntity, IIntegrationEvent, IServiceCallRequest } from '../../core/types.js';
3
- import type {
4
- IModbusCoilState,
5
- IModbusCommand,
6
- IModbusEntitySnapshot,
7
- IModbusEvent,
8
- IModbusHubSnapshot,
9
- IModbusRegisterState,
10
- IModbusSnapshot,
11
- TModbusCoilType,
12
- TModbusDataType,
13
- TModbusEntityPlatform,
14
- TModbusRegisterType,
15
- } from './modbus.types.js';
16
-
17
- const modbusDomain = 'modbus';
1
+ import type * as plugins from '../../plugins.js';
2
+ import type { IDeviceFeatureWriteRequest, IIntegrationEntity, IServiceCallRequest } from '../../core/types.js';
3
+ import type { IModbusNormalizedConfig, IModbusObservation, IModbusSnapshot, TModbusCommand } from './modbus.types.js';
4
+ import { modbusCommand, modbusRecord } from './modbus.validation.js';
18
5
 
19
6
  export class ModbusMapper {
20
- public static toDevices(snapshotArg: IModbusSnapshot): plugins.shxInterfaces.data.IDeviceDefinition[] {
21
- const updatedAt = snapshotArg.updatedAt || new Date().toISOString();
22
- const devices: plugins.shxInterfaces.data.IDeviceDefinition[] = [];
23
-
24
- for (const hub of snapshotArg.hubs) {
25
- devices.push({
26
- id: this.hubDeviceId(hub),
27
- integrationDomain: modbusDomain,
28
- name: hub.name,
29
- protocol: 'unknown',
30
- manufacturer: hub.manufacturer || 'Modbus',
31
- model: hub.model || `${hub.type.toUpperCase()} hub`,
32
- online: hub.online && !hub.unsupportedReason,
33
- features: [
34
- { id: 'connectivity', capability: 'sensor', name: 'Connectivity', readable: true, writable: false },
35
- { id: 'configured_entities', capability: 'sensor', name: 'Configured entities', readable: true, writable: false },
36
- ],
37
- state: [
38
- { featureId: 'connectivity', value: hub.online && !hub.unsupportedReason ? 'online' : 'offline', updatedAt },
39
- { featureId: 'configured_entities', value: hub.entities.length, updatedAt },
40
- ],
41
- metadata: this.cleanAttributes({
42
- type: hub.type,
43
- host: hub.host,
44
- port: hub.port,
45
- serialNumber: hub.serialNumber,
46
- unsupportedReason: hub.unsupportedReason,
47
- ...hub.metadata,
48
- }),
49
- });
50
-
51
- for (const slave of hub.slaves) {
52
- devices.push({
53
- id: this.slaveDeviceId(hub, slave.unitId),
54
- integrationDomain: modbusDomain,
55
- name: slave.name,
56
- protocol: 'unknown',
57
- manufacturer: slave.manufacturer || hub.manufacturer || 'Modbus',
58
- model: slave.model || 'Modbus slave',
59
- online: hub.online && slave.online && !hub.unsupportedReason,
60
- features: [
61
- { id: 'registers', capability: 'sensor', name: 'Configured registers', readable: true, writable: false },
62
- { id: 'coils', capability: 'sensor', name: 'Configured coils', readable: true, writable: false },
63
- ],
64
- state: [
65
- { featureId: 'registers', value: slave.registers.length, updatedAt },
66
- { featureId: 'coils', value: slave.coils.length, updatedAt },
67
- ],
68
- metadata: this.cleanAttributes({
69
- hubId: hub.id,
70
- hubName: hub.name,
71
- unitId: slave.unitId,
72
- viaDevice: this.hubDeviceId(hub),
73
- serialNumber: slave.serialNumber,
74
- ...slave.metadata,
75
- }),
76
- });
77
- }
78
- }
79
-
80
- return devices;
81
- }
82
-
83
- public static toEntities(snapshotArg: IModbusSnapshot): IIntegrationEntity[] {
84
- const usedIds = new Map<string, number>();
85
- return snapshotArg.hubs.flatMap((hubArg) => hubArg.entities.map((entityArg) => this.toEntity(hubArg, entityArg, usedIds)));
86
- }
87
-
88
- public static commandForService(snapshotArg: IModbusSnapshot, requestArg: IServiceCallRequest): IModbusCommand | undefined {
89
- const targetEntity = this.findEntity(snapshotArg, requestArg);
90
- if (requestArg.domain === modbusDomain && ['refresh', 'reload'].includes(requestArg.service)) {
91
- return { type: 'refresh', ...this.commandTarget(snapshotArg, requestArg, targetEntity) };
92
- }
93
- if (requestArg.domain === modbusDomain && requestArg.service === 'stop') {
94
- return { type: 'stop', ...this.commandTarget(snapshotArg, requestArg, targetEntity) };
95
- }
96
- if (requestArg.domain === modbusDomain && requestArg.service === 'restart') {
97
- return { type: 'restart', ...this.commandTarget(snapshotArg, requestArg, targetEntity) };
98
- }
99
-
100
- if (requestArg.domain === modbusDomain && ['read_register', 'read_holding_register', 'read_input_register'].includes(requestArg.service)) {
101
- const address = this.addressValue(requestArg, targetEntity);
102
- if (address === undefined) {
103
- return undefined;
104
- }
105
- return {
106
- type: 'read_register',
107
- ...this.commandTarget(snapshotArg, requestArg, targetEntity),
108
- address,
109
- count: this.numberData(requestArg, 'count') || targetEntity?.register?.count || 1,
110
- inputType: this.registerType(requestArg, targetEntity, requestArg.service === 'read_input_register' ? 'input' : undefined),
111
- dataType: this.dataType(requestArg, targetEntity),
112
- };
113
- }
114
-
115
- if (requestArg.domain === modbusDomain && ['read_coil', 'read_discrete_input'].includes(requestArg.service)) {
116
- const address = this.addressValue(requestArg, targetEntity);
117
- if (address === undefined) {
118
- return undefined;
119
- }
120
- return {
121
- type: 'read_coil',
122
- ...this.commandTarget(snapshotArg, requestArg, targetEntity),
123
- address,
124
- count: this.numberData(requestArg, 'count') || targetEntity?.coil?.count || 1,
125
- inputType: this.coilType(requestArg, targetEntity, requestArg.service === 'read_discrete_input' ? 'discrete_input' : undefined),
126
- };
127
- }
128
-
129
- if (requestArg.domain === modbusDomain && requestArg.service === 'write_register') {
130
- const address = this.addressValue(requestArg, targetEntity);
131
- const value = this.numberOrArrayData(requestArg, 'value');
132
- return address !== undefined && value !== undefined ? {
133
- type: 'write_register',
134
- ...this.commandTarget(snapshotArg, requestArg, targetEntity),
135
- address,
136
- value,
137
- } : undefined;
138
- }
139
-
140
- if (requestArg.domain === modbusDomain && requestArg.service === 'write_coil') {
141
- const address = this.addressValue(requestArg, targetEntity);
142
- const value = this.boolOrArrayData(requestArg, 'state') ?? this.boolOrArrayData(requestArg, 'value');
143
- return address !== undefined && value !== undefined ? {
144
- type: 'write_coil',
145
- ...this.commandTarget(snapshotArg, requestArg, targetEntity),
146
- address,
147
- value,
148
- } : undefined;
149
- }
150
-
151
- if (requestArg.domain === 'switch' && ['turn_on', 'turn_off'].includes(requestArg.service) && targetEntity?.platform === 'switch') {
152
- const commandValue = requestArg.service === 'turn_on' ? this.attributeNumber(targetEntity, 'commandOn') ?? 1 : this.attributeNumber(targetEntity, 'commandOff') ?? 0;
153
- const writeType = String(targetEntity.attributes?.writeType || 'coil');
154
- if (writeType === 'holding' || writeType === 'holdings' || targetEntity.register) {
155
- return {
156
- type: 'write_register',
157
- ...this.commandTarget(snapshotArg, requestArg, targetEntity),
158
- address: targetEntity.address,
159
- value: commandValue,
160
- };
161
- }
162
- return {
163
- type: 'write_coil',
164
- ...this.commandTarget(snapshotArg, requestArg, targetEntity),
165
- address: targetEntity.address,
166
- value: commandValue,
167
- };
168
- }
169
-
170
- if (requestArg.domain === 'number' && requestArg.service === 'set_value' && targetEntity?.platform === 'number') {
171
- const value = this.numberData(requestArg, 'value');
172
- return value !== undefined ? {
173
- type: 'write_register',
174
- ...this.commandTarget(snapshotArg, requestArg, targetEntity),
175
- address: targetEntity.address,
176
- value,
177
- } : undefined;
178
- }
179
-
180
- return undefined;
181
- }
182
-
183
- public static toIntegrationEvent(eventArg: IModbusEvent): IIntegrationEvent {
184
- return {
185
- type: eventArg.type === 'command_failed' ? 'error' : 'state_changed',
186
- integrationDomain: modbusDomain,
187
- deviceId: eventArg.deviceId,
188
- entityId: eventArg.entityId,
189
- data: eventArg,
190
- timestamp: eventArg.timestamp,
191
- };
192
- }
193
-
194
- public static hubDeviceId(hubArg: Pick<IModbusHubSnapshot, 'id'>): string {
195
- return `modbus.hub.${this.slug(hubArg.id)}`;
196
- }
197
-
198
- public static slaveDeviceId(hubArg: Pick<IModbusHubSnapshot, 'id'>, unitIdArg: number): string {
199
- return `modbus.slave.${this.slug(hubArg.id)}.${unitIdArg}`;
200
- }
201
-
202
- public static decodeRegisterValue(registerArg: IModbusRegisterState): number | string | number[] | null {
203
- if (registerArg.value !== undefined) {
204
- return registerArg.value;
205
- }
206
- const registers = registerArg.registers || [];
207
- if (!registers.length) {
208
- return null;
209
- }
210
- const dataType = this.normalizedDataType(registerArg.dataType);
211
- if (dataType === 'custom') {
212
- return registers;
213
- }
214
-
215
- const bytes = Buffer.alloc(registers.length * 2);
216
- registers.forEach((registerValueArg, indexArg) => bytes.writeUInt16BE(registerValueArg & 0xffff, indexArg * 2));
217
- let value: number | string;
218
- if (dataType === 'string') {
219
- value = bytes.toString('utf8').replace(/\0+$/g, '');
220
- } else if (dataType === 'int16') {
221
- value = bytes.readInt16BE(0);
222
- } else if (dataType === 'int32') {
223
- value = bytes.readInt32BE(0);
224
- } else if (dataType === 'uint32') {
225
- value = bytes.readUInt32BE(0);
226
- } else if (dataType === 'int64') {
227
- value = Number(bytes.readBigInt64BE(0));
228
- } else if (dataType === 'uint64') {
229
- value = Number(bytes.readBigUInt64BE(0));
230
- } else if (dataType === 'float16') {
231
- value = this.decodeFloat16(bytes.readUInt16BE(0));
232
- } else if (dataType === 'float32') {
233
- value = bytes.readFloatBE(0);
234
- } else if (dataType === 'float64') {
235
- value = bytes.readDoubleBE(0);
236
- } else {
237
- value = bytes.readUInt16BE(0);
238
- }
239
- return typeof value === 'number' ? this.processNumericValue(value, registerArg) : value;
240
- }
241
-
242
- public static registerCountForDataType(dataTypeArg: TModbusDataType | undefined): number {
243
- const dataType = this.normalizedDataType(dataTypeArg || 'int16');
244
- if (dataType === 'int32' || dataType === 'uint32' || dataType === 'float32') {
245
- return 2;
246
- }
247
- if (dataType === 'int64' || dataType === 'uint64' || dataType === 'float64') {
248
- return 4;
249
- }
250
- return 1;
251
- }
252
-
253
- private static toEntity(hubArg: IModbusHubSnapshot, entityArg: IModbusEntitySnapshot, usedIdsArg: Map<string, number>): IIntegrationEntity {
254
- const platform = entityArg.platform;
255
- const id = entityArg.id.includes('.') ? entityArg.id : this.uniqueEntityId(platform, entityArg.name, usedIdsArg);
256
- const state = this.entityState(entityArg);
257
- return {
258
- id,
259
- uniqueId: entityArg.uniqueId,
260
- integrationDomain: modbusDomain,
261
- deviceId: this.slaveDeviceId(hubArg, entityArg.unitId),
262
- platform,
263
- name: entityArg.name,
264
- state,
265
- attributes: this.cleanAttributes({
266
- hubId: hubArg.id,
267
- hubName: hubArg.name,
268
- unitId: entityArg.unitId,
269
- address: entityArg.address,
270
- writable: entityArg.writable,
271
- registerType: entityArg.register?.inputType,
272
- coilType: entityArg.coil?.inputType,
273
- dataType: entityArg.register?.dataType,
274
- count: entityArg.register?.count || entityArg.coil?.count,
275
- ...entityArg.attributes,
276
- }),
277
- available: entityArg.available && hubArg.online && !hubArg.unsupportedReason,
278
- };
279
- }
280
-
281
- private static entityState(entityArg: IModbusEntitySnapshot): unknown {
282
- if (entityArg.state !== undefined) {
283
- return entityArg.state;
284
- }
285
- if (entityArg.platform === 'sensor') {
286
- return entityArg.register ? this.decodeRegisterValue(entityArg.register) : null;
287
- }
288
- if (entityArg.platform === 'number') {
289
- const value = entityArg.register ? this.decodeRegisterValue(entityArg.register) : null;
290
- return typeof value === 'number' && Number.isFinite(value) ? value : null;
291
- }
292
- const boolValue = this.coilBoolean(entityArg.coil);
293
- return boolValue === undefined ? 'unknown' : boolValue ? 'on' : 'off';
294
- }
295
-
296
- private static coilBoolean(coilArg: IModbusCoilState | undefined): boolean | undefined {
297
- if (!coilArg) {
298
- return undefined;
299
- }
300
- if (typeof coilArg.value === 'boolean') {
301
- return coilArg.value;
302
- }
303
- if (typeof coilArg.value === 'number') {
304
- return Boolean(coilArg.value & 1);
305
- }
306
- if (coilArg.bits?.length) {
307
- return Boolean(coilArg.bits[0]);
308
- }
309
- return undefined;
310
- }
311
-
312
- private static uniqueEntityId(platformArg: TModbusEntityPlatform, nameArg: string, usedIdsArg: Map<string, number>): string {
313
- const baseId = `${platformArg}.${this.slug(nameArg)}`;
314
- const seen = usedIdsArg.get(baseId) || 0;
315
- usedIdsArg.set(baseId, seen + 1);
316
- return seen ? `${baseId}_${seen + 1}` : baseId;
317
- }
318
-
319
- private static findEntity(snapshotArg: IModbusSnapshot, requestArg: IServiceCallRequest): IModbusEntitySnapshot | undefined {
320
- const target = requestArg.target.entityId || requestArg.target.deviceId;
321
- if (!target) {
322
- return undefined;
323
- }
324
- for (const hub of snapshotArg.hubs) {
325
- const entity = hub.entities.find((entityArg) => entityArg.id === target || entityArg.uniqueId === target || this.slaveDeviceId(hub, entityArg.unitId) === target);
326
- if (entity) {
327
- return entity;
328
- }
329
- }
330
- return undefined;
331
- }
332
-
333
- private static commandTarget(snapshotArg: IModbusSnapshot, requestArg: IServiceCallRequest, entityArg?: IModbusEntitySnapshot): Pick<IModbusCommand, 'hub' | 'hubId' | 'unitId' | 'entityId' | 'deviceId' | 'uniqueId'> {
334
- const firstHub = snapshotArg.hubs[0];
335
- return {
336
- hub: this.stringData(requestArg, 'hub') || entityArg?.hubName || firstHub?.name,
337
- hubId: this.stringData(requestArg, 'hubId') || entityArg?.hubId || firstHub?.id,
338
- unitId: this.numberData(requestArg, 'unitId') ?? this.numberData(requestArg, 'unit') ?? this.numberData(requestArg, 'slave') ?? entityArg?.unitId ?? 1,
339
- entityId: requestArg.target.entityId,
340
- deviceId: requestArg.target.deviceId,
341
- uniqueId: entityArg?.uniqueId,
342
- };
343
- }
344
-
345
- private static addressValue(requestArg: IServiceCallRequest, entityArg?: IModbusEntitySnapshot): number | undefined {
346
- return this.numberData(requestArg, 'address') ?? entityArg?.address;
347
- }
348
-
349
- private static registerType(requestArg: IServiceCallRequest, entityArg?: IModbusEntitySnapshot, fallbackArg?: TModbusRegisterType): TModbusRegisterType {
350
- const value = this.stringData(requestArg, 'inputType') || this.stringData(requestArg, 'input_type') || this.stringData(requestArg, 'registerType') || this.stringData(requestArg, 'register_type') || entityArg?.register?.inputType || fallbackArg || 'holding';
351
- return value === 'input' ? 'input' : 'holding';
352
- }
353
-
354
- private static coilType(requestArg: IServiceCallRequest, entityArg?: IModbusEntitySnapshot, fallbackArg?: TModbusCoilType): TModbusCoilType {
355
- const value = this.stringData(requestArg, 'inputType') || this.stringData(requestArg, 'input_type') || this.stringData(requestArg, 'coilType') || this.stringData(requestArg, 'coil_type') || entityArg?.coil?.inputType || fallbackArg || 'coil';
356
- return value === 'discrete_input' ? 'discrete_input' : 'coil';
357
- }
358
-
359
- private static dataType(requestArg: IServiceCallRequest, entityArg?: IModbusEntitySnapshot): TModbusDataType | undefined {
360
- const value = this.stringData(requestArg, 'dataType') || this.stringData(requestArg, 'data_type') || entityArg?.register?.dataType;
361
- return value as TModbusDataType | undefined;
362
- }
363
-
364
- private static numberData(requestArg: IServiceCallRequest, keyArg: string): number | undefined {
365
- const value = requestArg.data?.[keyArg];
366
- return this.toNumber(value);
367
- }
368
-
369
- private static attributeNumber(entityArg: IModbusEntitySnapshot, keyArg: string): number | undefined {
370
- return this.toNumber(entityArg.attributes?.[keyArg]);
371
- }
372
-
373
- private static toNumber(valueArg: unknown): number | undefined {
374
- return typeof valueArg === 'number' && Number.isFinite(valueArg) ? valueArg : typeof valueArg === 'string' && valueArg.trim() && Number.isFinite(Number(valueArg)) ? Number(valueArg) : undefined;
375
- }
376
-
377
- private static stringData(requestArg: IServiceCallRequest, keyArg: string): string | undefined {
378
- const value = requestArg.data?.[keyArg];
379
- return typeof value === 'string' && value.trim() ? value.trim() : undefined;
380
- }
381
-
382
- private static numberOrArrayData(requestArg: IServiceCallRequest, keyArg: string): number | number[] | undefined {
383
- const value = requestArg.data?.[keyArg];
384
- if (Array.isArray(value)) {
385
- const values = value.map((entryArg) => this.toNumber(entryArg)).filter((entryArg): entryArg is number => entryArg !== undefined);
386
- return values.length === value.length ? values : undefined;
387
- }
388
- return this.toNumber(value);
7
+ public static deviceId(configArg: IModbusNormalizedConfig): string {
8
+ return `modbus:${encodeURIComponent(configArg.homeId)}:${configArg.address}:${configArg.port}:${configArg.unitId}`;
389
9
  }
390
10
 
391
- private static boolOrArrayData(requestArg: IServiceCallRequest, keyArg: string): boolean | boolean[] | number | number[] | undefined {
392
- const value = requestArg.data?.[keyArg];
393
- if (Array.isArray(value)) {
394
- const values = value.map((entryArg) => this.toBooleanOrNumber(entryArg)).filter((entryArg): entryArg is boolean | number => entryArg !== undefined);
395
- return values.length === value.length ? values.map((entryArg) => typeof entryArg === 'boolean' ? entryArg : Boolean(entryArg)) : undefined;
396
- }
397
- return this.toBooleanOrNumber(value);
11
+ public static entityId(configArg: IModbusNormalizedConfig, mappingIdArg: string): string {
12
+ return `${this.deviceId(configArg)}:${mappingIdArg}`;
398
13
  }
399
14
 
400
- private static toBooleanOrNumber(valueArg: unknown): boolean | number | undefined {
401
- if (typeof valueArg === 'boolean') {
402
- return valueArg;
403
- }
404
- if (typeof valueArg === 'number' && Number.isFinite(valueArg)) {
405
- return valueArg;
406
- }
407
- if (typeof valueArg === 'string') {
408
- const value = valueArg.trim().toLowerCase();
409
- if (value === 'true' || value === 'on') {
410
- return true;
411
- }
412
- if (value === 'false' || value === 'off') {
413
- return false;
414
- }
415
- if (value && Number.isFinite(Number(value))) {
416
- return Number(value);
15
+ public static toDevices(snapshotArg: IModbusSnapshot): plugins.shxInterfaces.data.IDeviceDefinition[] {
16
+ const features: plugins.shxInterfaces.data.IDeviceFeature[] = [];
17
+ const state: plugins.shxInterfaces.data.IDeviceState[] = [];
18
+ for (const observation of snapshotArg.observations) {
19
+ const mapping = observation.mapping;
20
+ for (let index = 0; index < observation.values.length; index++) {
21
+ const id = mapping.quantity === 1 ? mapping.id : `${mapping.id}:${index}`;
22
+ features.push({ id, name: mapping.quantity === 1 ? mapping.name : `${mapping.name} [${index}]`, capability: 'sensor',
23
+ readable: true, writable: mapping.quantity === 1 && this.writable(observation) });
24
+ state.push({ featureId: id, value: observation.values[index], updatedAt: observation.observedAt });
417
25
  }
418
26
  }
419
- return undefined;
27
+ return [{ id: this.deviceId(snapshotArg.config), integrationDomain: 'modbus', protocol: 'tcp',
28
+ name: snapshotArg.config.name ?? snapshotArg.identity.productCode, manufacturer: snapshotArg.identity.vendorName,
29
+ model: snapshotArg.identity.productCode, features, state, online: true, metadata: {
30
+ homeId: snapshotArg.config.homeId, address: snapshotArg.config.address, port: snapshotArg.config.port,
31
+ unitId: snapshotArg.config.unitId, revision: snapshotArg.identity.revision, observedAt: snapshotArg.observedAt,
32
+ networkAuthenticated: false, physicalEffectConfirmed: false, interpretation: 'raw-modbus-values',
33
+ } }];
420
34
  }
421
35
 
422
- private static normalizedDataType(dataTypeArg: TModbusDataType): Exclude<TModbusDataType, 'int' | 'integer' | 'uint' | 'float'> {
423
- if (dataTypeArg === 'int' || dataTypeArg === 'integer') {
424
- return 'int16';
425
- }
426
- if (dataTypeArg === 'uint') {
427
- return 'uint16';
428
- }
429
- if (dataTypeArg === 'float') {
430
- return 'float32';
431
- }
432
- return dataTypeArg;
36
+ public static toEntities(snapshotArg: IModbusSnapshot): IIntegrationEntity[] {
37
+ return snapshotArg.observations.map((observation) => {
38
+ const mapping = observation.mapping;
39
+ const bit = mapping.kind === 'coil' || mapping.kind === 'discrete_input';
40
+ const writable = this.writable(observation);
41
+ return { id: this.entityId(snapshotArg.config, mapping.id), uniqueId: this.entityId(snapshotArg.config, mapping.id),
42
+ deviceId: this.deviceId(snapshotArg.config), integrationDomain: 'modbus',
43
+ platform: bit ? writable ? 'switch' : 'binary_sensor' : writable ? 'number' : 'sensor',
44
+ name: mapping.name, state: mapping.quantity === 1 ? observation.values[0] : observation.values, available: true,
45
+ attributes: { homeId: snapshotArg.config.homeId, kind: mapping.kind, address: mapping.address, quantity: mapping.quantity,
46
+ writable, ...(mapping.kind === 'holding' && mapping.write ? { minimum: mapping.write.minimum, maximum: mapping.write.maximum } : {}),
47
+ observedAt: observation.observedAt, interpretation: 'raw-modbus-values', networkAuthenticated: false, physicalEffectConfirmed: false },
48
+ };
49
+ });
433
50
  }
434
51
 
435
- private static decodeFloat16(valueArg: number): number {
436
- const sign = (valueArg & 0x8000) ? -1 : 1;
437
- const exponent = (valueArg >> 10) & 0x1f;
438
- const fraction = valueArg & 0x03ff;
439
- if (exponent === 0) {
440
- return sign * Math.pow(2, -14) * (fraction / 1024);
441
- }
442
- if (exponent === 31) {
443
- return fraction ? Number.NaN : sign * Number.POSITIVE_INFINITY;
52
+ public static commandForService(configArg: IModbusNormalizedConfig, requestArg: IServiceCallRequest): TModbusCommand {
53
+ const request = modbusRecord(requestArg, ['domain', 'service', 'target', 'data']);
54
+ const target = modbusRecord(request.target, ['deviceId', 'entityId']);
55
+ if (target.deviceId !== undefined && target.deviceId !== this.deviceId(configArg)) throw new TypeError('Modbus service device is outside the selected home and device.');
56
+ const mapping = configArg.mappings.find((entry) => this.entityId(configArg, entry.id) === target.entityId);
57
+ if (!mapping) throw new TypeError('Modbus services require one exact mapped entity target.');
58
+ if (request.domain !== 'modbus') throw new TypeError('Modbus raw services use the modbus domain.');
59
+ if (request.service === 'read') {
60
+ if (request.data !== undefined) modbusRecord(request.data, []);
61
+ return modbusCommand({ type: 'read', mappingId: mapping.id }, configArg);
444
62
  }
445
- return sign * Math.pow(2, exponent - 15) * (1 + fraction / 1024);
63
+ const data = modbusRecord(request.data, ['value']);
64
+ return modbusCommand({ type: request.service, mappingId: mapping.id, value: data.value }, configArg);
446
65
  }
447
66
 
448
- private static processNumericValue(valueArg: number, registerArg: IModbusRegisterState): number | null {
449
- const metadata = registerArg.metadata || {};
450
- const nanValue = this.toNumberValue(metadata.nanValue) ?? this.toNumberValue(metadata.nan_value);
451
- if (nanValue !== undefined && (valueArg === nanValue || valueArg === -nanValue)) {
452
- return null;
453
- }
454
- if (Number.isNaN(valueArg)) {
455
- return null;
67
+ public static commandForFeature(configArg: IModbusNormalizedConfig, requestArg: IDeviceFeatureWriteRequest): TModbusCommand {
68
+ const request = modbusRecord(requestArg, ['device', 'feature', 'value']);
69
+ const device = modbusRecord(request.device);
70
+ const feature = modbusRecord(request.feature);
71
+ const metadata = modbusRecord(device.metadata);
72
+ if (device.id !== this.deviceId(configArg) || device.integrationDomain !== 'modbus' || metadata.homeId !== configArg.homeId) {
73
+ throw new TypeError('Modbus feature writes require the exact owned home and device.');
456
74
  }
457
- const scale = this.toNumberValue(metadata.scale) ?? 1;
458
- const offset = this.toNumberValue(metadata.offset) ?? 0;
459
- let value = valueArg * scale + offset;
460
- const min = this.toNumberValue(metadata.minValue) ?? this.toNumberValue(metadata.min_value);
461
- const max = this.toNumberValue(metadata.maxValue) ?? this.toNumberValue(metadata.max_value);
462
- const zeroSuppress = this.toNumberValue(metadata.zeroSuppress) ?? this.toNumberValue(metadata.zero_suppress);
463
- const precision = this.toNumberValue(metadata.precision);
464
- if (min !== undefined && value < min) {
465
- value = min;
466
- }
467
- if (max !== undefined && value > max) {
468
- value = max;
469
- }
470
- if (zeroSuppress !== undefined && Math.abs(value) <= zeroSuppress) {
471
- value = 0;
472
- }
473
- return precision !== undefined ? Number(value.toFixed(precision)) : value;
474
- }
475
-
476
- private static toNumberValue(valueArg: unknown): number | undefined {
477
- return typeof valueArg === 'number' && Number.isFinite(valueArg) ? valueArg : typeof valueArg === 'string' && valueArg.trim() && Number.isFinite(Number(valueArg)) ? Number(valueArg) : undefined;
478
- }
479
-
480
- private static cleanAttributes(attributesArg: Record<string, unknown>): Record<string, unknown> {
481
- return Object.fromEntries(Object.entries(attributesArg).filter(([, valueArg]) => valueArg !== undefined));
75
+ const mapping = configArg.mappings.find((entry) => entry.id === feature.id);
76
+ if (!mapping) throw new TypeError('Modbus feature is outside the explicit owner mapping.');
77
+ return modbusCommand({ type: mapping.kind === 'coil' ? 'write_coil' : 'write_register', mappingId: mapping.id, value: request.value }, configArg);
482
78
  }
483
79
 
484
- private static slug(valueArg: string): string {
485
- return valueArg.toLowerCase().replace(/[^a-z0-9]+/g, '_').replace(/^_+|_+$/g, '') || modbusDomain;
80
+ private static writable(observationArg: IModbusObservation): boolean {
81
+ const mapping = observationArg.mapping;
82
+ return mapping.kind === 'coil' && mapping.write === true || mapping.kind === 'holding' && mapping.write !== undefined;
486
83
  }
487
84
  }