@willieee802/zigbee-herdsman-converters 19.44.3 → 19.45.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 (591) hide show
  1. package/CHANGELOG.md +1101 -0
  2. package/dist/converters/actions.d.ts.map +1 -1
  3. package/dist/converters/actions.js +2 -0
  4. package/dist/converters/actions.js.map +1 -1
  5. package/dist/converters/fromZigbee.d.ts +1 -150
  6. package/dist/converters/fromZigbee.d.ts.map +1 -1
  7. package/dist/converters/fromZigbee.js +183 -3044
  8. package/dist/converters/fromZigbee.js.map +1 -1
  9. package/dist/converters/toZigbee.d.ts +0 -121
  10. package/dist/converters/toZigbee.d.ts.map +1 -1
  11. package/dist/converters/toZigbee.js +289 -2386
  12. package/dist/converters/toZigbee.js.map +1 -1
  13. package/dist/devices/ITCommander.d.ts.map +1 -1
  14. package/dist/devices/ITCommander.js +2 -1
  15. package/dist/devices/ITCommander.js.map +1 -1
  16. package/dist/devices/acova.d.ts.map +1 -1
  17. package/dist/devices/acova.js +69 -2
  18. package/dist/devices/acova.js.map +1 -1
  19. package/dist/devices/adeo.d.ts.map +1 -1
  20. package/dist/devices/adeo.js +35 -3
  21. package/dist/devices/adeo.js.map +1 -1
  22. package/dist/devices/adurosmart.js +1 -1
  23. package/dist/devices/adurosmart.js.map +1 -1
  24. package/dist/devices/amina.d.ts.map +1 -1
  25. package/dist/devices/amina.js +47 -10
  26. package/dist/devices/amina.js.map +1 -1
  27. package/dist/devices/aurora_lighting.d.ts.map +1 -1
  28. package/dist/devices/aurora_lighting.js +15 -0
  29. package/dist/devices/aurora_lighting.js.map +1 -1
  30. package/dist/devices/automaton.d.ts.map +1 -1
  31. package/dist/devices/automaton.js +1 -0
  32. package/dist/devices/automaton.js.map +1 -1
  33. package/dist/devices/avatto.d.ts.map +1 -1
  34. package/dist/devices/avatto.js +29 -24
  35. package/dist/devices/avatto.js.map +1 -1
  36. package/dist/devices/awox.d.ts.map +1 -1
  37. package/dist/devices/awox.js +41 -3
  38. package/dist/devices/awox.js.map +1 -1
  39. package/dist/devices/bacchus.d.ts.map +1 -1
  40. package/dist/devices/bacchus.js +75 -0
  41. package/dist/devices/bacchus.js.map +1 -1
  42. package/dist/devices/bitron.d.ts.map +1 -1
  43. package/dist/devices/bitron.js +29 -2
  44. package/dist/devices/bitron.js.map +1 -1
  45. package/dist/devices/bosch.d.ts.map +1 -1
  46. package/dist/devices/bosch.js +70 -50
  47. package/dist/devices/bosch.js.map +1 -1
  48. package/dist/devices/bticino.d.ts.map +1 -1
  49. package/dist/devices/bticino.js +11 -1
  50. package/dist/devices/bticino.js.map +1 -1
  51. package/dist/devices/byun.d.ts.map +1 -1
  52. package/dist/devices/byun.js +40 -3
  53. package/dist/devices/byun.js.map +1 -1
  54. package/dist/devices/candeo.d.ts.map +1 -1
  55. package/dist/devices/candeo.js +262 -9
  56. package/dist/devices/candeo.js.map +1 -1
  57. package/dist/devices/centralite.d.ts +9 -0
  58. package/dist/devices/centralite.d.ts.map +1 -1
  59. package/dist/devices/centralite.js +44 -5
  60. package/dist/devices/centralite.js.map +1 -1
  61. package/dist/devices/{aubess.d.ts → cigol.d.ts} +1 -1
  62. package/dist/devices/cigol.d.ts.map +1 -0
  63. package/dist/devices/cigol.js +260 -0
  64. package/dist/devices/cigol.js.map +1 -0
  65. package/dist/devices/cleverio.js +2 -2
  66. package/dist/devices/cleverio.js.map +1 -1
  67. package/dist/devices/climax.d.ts.map +1 -1
  68. package/dist/devices/climax.js +15 -1
  69. package/dist/devices/climax.js.map +1 -1
  70. package/dist/devices/ctm.d.ts.map +1 -1
  71. package/dist/devices/ctm.js +845 -496
  72. package/dist/devices/ctm.js.map +1 -1
  73. package/dist/devices/custom_devices_diy.d.ts +183 -1
  74. package/dist/devices/custom_devices_diy.d.ts.map +1 -1
  75. package/dist/devices/custom_devices_diy.js +390 -33
  76. package/dist/devices/custom_devices_diy.js.map +1 -1
  77. package/dist/devices/daewoo.d.ts +3 -0
  78. package/dist/devices/daewoo.d.ts.map +1 -0
  79. package/dist/devices/daewoo.js +198 -0
  80. package/dist/devices/daewoo.js.map +1 -0
  81. package/dist/devices/danfoss.d.ts.map +1 -1
  82. package/dist/devices/danfoss.js +1270 -296
  83. package/dist/devices/danfoss.js.map +1 -1
  84. package/dist/devices/databyte.d.ts.map +1 -1
  85. package/dist/devices/databyte.js +47 -3
  86. package/dist/devices/databyte.js.map +1 -1
  87. package/dist/devices/datek.d.ts.map +1 -1
  88. package/dist/devices/datek.js +202 -41
  89. package/dist/devices/datek.js.map +1 -1
  90. package/dist/devices/dawon_dns.d.ts.map +1 -1
  91. package/dist/devices/dawon_dns.js +14 -1
  92. package/dist/devices/dawon_dns.js.map +1 -1
  93. package/dist/devices/develco.d.ts.map +1 -1
  94. package/dist/devices/develco.js +145 -64
  95. package/dist/devices/develco.js.map +1 -1
  96. package/dist/devices/diyruz.d.ts.map +1 -1
  97. package/dist/devices/diyruz.js +444 -20
  98. package/dist/devices/diyruz.js.map +1 -1
  99. package/dist/devices/domraem.d.ts.map +1 -1
  100. package/dist/devices/domraem.js +7 -0
  101. package/dist/devices/domraem.js.map +1 -1
  102. package/dist/devices/easyaccess.d.ts.map +1 -1
  103. package/dist/devices/easyaccess.js +22 -2
  104. package/dist/devices/easyaccess.js.map +1 -1
  105. package/dist/devices/easyiot.d.ts.map +1 -1
  106. package/dist/devices/easyiot.js +767 -5
  107. package/dist/devices/easyiot.js.map +1 -1
  108. package/dist/devices/echostar.d.ts.map +1 -1
  109. package/dist/devices/echostar.js +25 -1
  110. package/dist/devices/echostar.js.map +1 -1
  111. package/dist/devices/ecodim.d.ts.map +1 -1
  112. package/dist/devices/ecodim.js +8 -0
  113. package/dist/devices/ecodim.js.map +1 -1
  114. package/dist/devices/ecolink.d.ts.map +1 -1
  115. package/dist/devices/ecolink.js +12 -0
  116. package/dist/devices/ecolink.js.map +1 -1
  117. package/dist/devices/efekta.d.ts.map +1 -1
  118. package/dist/devices/efekta.js +1615 -60
  119. package/dist/devices/efekta.js.map +1 -1
  120. package/dist/devices/eglo.d.ts.map +1 -1
  121. package/dist/devices/eglo.js +203 -17
  122. package/dist/devices/eglo.js.map +1 -1
  123. package/dist/devices/elko.d.ts.map +1 -1
  124. package/dist/devices/elko.js +20 -22
  125. package/dist/devices/elko.js.map +1 -1
  126. package/dist/devices/engo.d.ts.map +1 -1
  127. package/dist/devices/engo.js +201 -0
  128. package/dist/devices/engo.js.map +1 -1
  129. package/dist/devices/enocean.d.ts.map +1 -1
  130. package/dist/devices/enocean.js +132 -4
  131. package/dist/devices/enocean.js.map +1 -1
  132. package/dist/devices/ensystec.d.ts +3 -0
  133. package/dist/devices/ensystec.d.ts.map +1 -0
  134. package/dist/devices/ensystec.js +1200 -0
  135. package/dist/devices/ensystec.js.map +1 -0
  136. package/dist/devices/eurotronic.d.ts +78 -1
  137. package/dist/devices/eurotronic.d.ts.map +1 -1
  138. package/dist/devices/eurotronic.js +244 -40
  139. package/dist/devices/eurotronic.js.map +1 -1
  140. package/dist/devices/ewelink.d.ts.map +1 -1
  141. package/dist/devices/ewelink.js +154 -2
  142. package/dist/devices/ewelink.js.map +1 -1
  143. package/dist/devices/fantem.js +1 -1
  144. package/dist/devices/fantem.js.map +1 -1
  145. package/dist/devices/fireangel.d.ts.map +1 -1
  146. package/dist/devices/fireangel.js +12 -1
  147. package/dist/devices/fireangel.js.map +1 -1
  148. package/dist/devices/frankever.d.ts.map +1 -1
  149. package/dist/devices/frankever.js +96 -0
  150. package/dist/devices/frankever.js.map +1 -1
  151. package/dist/devices/frient.d.ts.map +1 -1
  152. package/dist/devices/frient.js +15 -0
  153. package/dist/devices/frient.js.map +1 -1
  154. package/dist/devices/girier.js +1 -1
  155. package/dist/devices/girier.js.map +1 -1
  156. package/dist/devices/gledopto.js +1 -1
  157. package/dist/devices/gledopto.js.map +1 -1
  158. package/dist/devices/gmmts.d.ts.map +1 -1
  159. package/dist/devices/gmmts.js +59 -55
  160. package/dist/devices/gmmts.js.map +1 -1
  161. package/dist/devices/halo_smart_labs.d.ts +3 -0
  162. package/dist/devices/halo_smart_labs.d.ts.map +1 -0
  163. package/dist/devices/halo_smart_labs.js +918 -0
  164. package/dist/devices/halo_smart_labs.js.map +1 -0
  165. package/dist/devices/handshake_finland.d.ts +3 -0
  166. package/dist/devices/handshake_finland.d.ts.map +1 -0
  167. package/dist/devices/handshake_finland.js +15 -0
  168. package/dist/devices/handshake_finland.js.map +1 -0
  169. package/dist/devices/heiman.d.ts.map +1 -1
  170. package/dist/devices/heiman.js +1361 -147
  171. package/dist/devices/heiman.js.map +1 -1
  172. package/dist/devices/heimgard_technologies.d.ts.map +1 -1
  173. package/dist/devices/heimgard_technologies.js +13 -0
  174. package/dist/devices/heimgard_technologies.js.map +1 -1
  175. package/dist/devices/hive.d.ts.map +1 -1
  176. package/dist/devices/hive.js +11 -0
  177. package/dist/devices/hive.js.map +1 -1
  178. package/dist/devices/ikea.d.ts.map +1 -1
  179. package/dist/devices/ikea.js +185 -135
  180. package/dist/devices/ikea.js.map +1 -1
  181. package/dist/devices/iluminize.d.ts.map +1 -1
  182. package/dist/devices/iluminize.js +8 -7
  183. package/dist/devices/iluminize.js.map +1 -1
  184. package/dist/devices/immax.d.ts.map +1 -1
  185. package/dist/devices/immax.js +3 -1
  186. package/dist/devices/immax.js.map +1 -1
  187. package/dist/devices/index.d.ts.map +1 -1
  188. package/dist/devices/index.js +20 -2
  189. package/dist/devices/index.js.map +1 -1
  190. package/dist/devices/innr.d.ts.map +1 -1
  191. package/dist/devices/innr.js +34 -2
  192. package/dist/devices/innr.js.map +1 -1
  193. package/dist/devices/inovelli.d.ts.map +1 -1
  194. package/dist/devices/inovelli.js +41 -2348
  195. package/dist/devices/inovelli.js.map +1 -1
  196. package/dist/devices/iris.d.ts.map +1 -1
  197. package/dist/devices/iris.js +13 -1
  198. package/dist/devices/iris.js.map +1 -1
  199. package/dist/devices/javis.d.ts.map +1 -1
  200. package/dist/devices/javis.js +39 -1
  201. package/dist/devices/javis.js.map +1 -1
  202. package/dist/devices/jxuan.d.ts.map +1 -1
  203. package/dist/devices/jxuan.js +37 -2
  204. package/dist/devices/jxuan.js.map +1 -1
  205. package/dist/devices/kami.d.ts.map +1 -1
  206. package/dist/devices/kami.js +21 -2
  207. package/dist/devices/kami.js.map +1 -1
  208. package/dist/devices/keen_home.d.ts.map +1 -1
  209. package/dist/devices/keen_home.js +13 -3
  210. package/dist/devices/keen_home.js.map +1 -1
  211. package/dist/devices/klikaanklikuit.d.ts.map +1 -1
  212. package/dist/devices/klikaanklikuit.js +7 -0
  213. package/dist/devices/klikaanklikuit.js.map +1 -1
  214. package/dist/devices/kmpcil.d.ts.map +1 -1
  215. package/dist/devices/kmpcil.js +44 -5
  216. package/dist/devices/kmpcil.js.map +1 -1
  217. package/dist/devices/konke.d.ts.map +1 -1
  218. package/dist/devices/konke.js +10 -1
  219. package/dist/devices/konke.js.map +1 -1
  220. package/dist/devices/lds.d.ts.map +1 -1
  221. package/dist/devices/lds.js +7 -0
  222. package/dist/devices/lds.js.map +1 -1
  223. package/dist/devices/led_trading.d.ts.map +1 -1
  224. package/dist/devices/led_trading.js +13 -13
  225. package/dist/devices/led_trading.js.map +1 -1
  226. package/dist/devices/leedarson.d.ts.map +1 -1
  227. package/dist/devices/leedarson.js +140 -1
  228. package/dist/devices/leedarson.js.map +1 -1
  229. package/dist/devices/legrand.d.ts.map +1 -1
  230. package/dist/devices/legrand.js +73 -42
  231. package/dist/devices/legrand.js.map +1 -1
  232. package/dist/devices/lellki.d.ts.map +1 -1
  233. package/dist/devices/lellki.js +3 -1
  234. package/dist/devices/lellki.js.map +1 -1
  235. package/dist/devices/letv.d.ts.map +1 -1
  236. package/dist/devices/letv.js +16 -2
  237. package/dist/devices/letv.js.map +1 -1
  238. package/dist/devices/lidl.d.ts.map +1 -1
  239. package/dist/devices/lidl.js +26 -6
  240. package/dist/devices/lidl.js.map +1 -1
  241. package/dist/devices/lincukoo.d.ts.map +1 -1
  242. package/dist/devices/lincukoo.js +92 -31
  243. package/dist/devices/lincukoo.js.map +1 -1
  244. package/dist/devices/linkind.d.ts.map +1 -1
  245. package/dist/devices/linkind.js +14 -1
  246. package/dist/devices/linkind.js.map +1 -1
  247. package/dist/devices/linptech.d.ts.map +1 -1
  248. package/dist/devices/linptech.js +3 -1
  249. package/dist/devices/linptech.js.map +1 -1
  250. package/dist/devices/livingwise.d.ts.map +1 -1
  251. package/dist/devices/livingwise.js +2 -1
  252. package/dist/devices/livingwise.js.map +1 -1
  253. package/dist/devices/livolo.d.ts.map +1 -1
  254. package/dist/devices/livolo.js +612 -20
  255. package/dist/devices/livolo.js.map +1 -1
  256. package/dist/devices/lixee.d.ts.map +1 -1
  257. package/dist/devices/lixee.js +46 -44
  258. package/dist/devices/lixee.js.map +1 -1
  259. package/dist/devices/lonsonho.d.ts.map +1 -1
  260. package/dist/devices/lonsonho.js +18 -11
  261. package/dist/devices/lonsonho.js.map +1 -1
  262. package/dist/devices/lumi.d.ts.map +1 -1
  263. package/dist/devices/lumi.js +877 -155
  264. package/dist/devices/lumi.js.map +1 -1
  265. package/dist/devices/lytko.d.ts.map +1 -1
  266. package/dist/devices/lytko.js +205 -556
  267. package/dist/devices/lytko.js.map +1 -1
  268. package/dist/devices/makegood.d.ts.map +1 -1
  269. package/dist/devices/makegood.js +5 -1
  270. package/dist/devices/makegood.js.map +1 -1
  271. package/dist/devices/mazda.js +7 -7
  272. package/dist/devices/mazda.js.map +1 -1
  273. package/dist/devices/meazon.d.ts.map +1 -1
  274. package/dist/devices/meazon.js +82 -20
  275. package/dist/devices/meazon.js.map +1 -1
  276. package/dist/devices/megaman.d.ts +4 -0
  277. package/dist/devices/megaman.d.ts.map +1 -0
  278. package/dist/devices/megaman.js +48 -0
  279. package/dist/devices/megaman.js.map +1 -0
  280. package/dist/devices/mercator.d.ts.map +1 -1
  281. package/dist/devices/mercator.js +20 -5
  282. package/dist/devices/mercator.js.map +1 -1
  283. package/dist/devices/miboxer.d.ts.map +1 -1
  284. package/dist/devices/miboxer.js +3 -1
  285. package/dist/devices/miboxer.js.map +1 -1
  286. package/dist/devices/mill.d.ts.map +1 -1
  287. package/dist/devices/mill.js +33 -7
  288. package/dist/devices/mill.js.map +1 -1
  289. package/dist/devices/moes.d.ts.map +1 -1
  290. package/dist/devices/moes.js +89 -15
  291. package/dist/devices/moes.js.map +1 -1
  292. package/dist/devices/msh.d.ts +3 -0
  293. package/dist/devices/msh.d.ts.map +1 -0
  294. package/dist/devices/msh.js +93 -0
  295. package/dist/devices/msh.js.map +1 -0
  296. package/dist/devices/muller_licht.d.ts.map +1 -1
  297. package/dist/devices/muller_licht.js +11 -0
  298. package/dist/devices/muller_licht.js.map +1 -1
  299. package/dist/devices/multir.d.ts.map +1 -1
  300. package/dist/devices/multir.js +12 -1
  301. package/dist/devices/multir.js.map +1 -1
  302. package/dist/devices/multiterm.js +2 -2
  303. package/dist/devices/multiterm.js.map +1 -1
  304. package/dist/devices/namron.d.ts.map +1 -1
  305. package/dist/devices/namron.js +488 -128
  306. package/dist/devices/namron.js.map +1 -1
  307. package/dist/devices/neo.d.ts.map +1 -1
  308. package/dist/devices/neo.js +151 -192
  309. package/dist/devices/neo.js.map +1 -1
  310. package/dist/devices/netica.d.ts +3 -0
  311. package/dist/devices/netica.d.ts.map +1 -0
  312. package/dist/devices/netica.js +153 -0
  313. package/dist/devices/netica.js.map +1 -0
  314. package/dist/devices/niko.d.ts.map +1 -1
  315. package/dist/devices/niko.js +10 -8
  316. package/dist/devices/niko.js.map +1 -1
  317. package/dist/devices/nodon.d.ts.map +1 -1
  318. package/dist/devices/nodon.js +6 -4
  319. package/dist/devices/nodon.js.map +1 -1
  320. package/dist/devices/nous.d.ts.map +1 -1
  321. package/dist/devices/nous.js +160 -61
  322. package/dist/devices/nous.js.map +1 -1
  323. package/dist/devices/nue_3a.d.ts.map +1 -1
  324. package/dist/devices/nue_3a.js +2 -0
  325. package/dist/devices/nue_3a.js.map +1 -1
  326. package/dist/devices/onesti.d.ts +11 -1
  327. package/dist/devices/onesti.d.ts.map +1 -1
  328. package/dist/devices/onesti.js +30 -6
  329. package/dist/devices/onesti.js.map +1 -1
  330. package/dist/devices/onokom.d.ts.map +1 -1
  331. package/dist/devices/onokom.js +1152 -2309
  332. package/dist/devices/onokom.js.map +1 -1
  333. package/dist/devices/orvibo.d.ts +17 -1
  334. package/dist/devices/orvibo.d.ts.map +1 -1
  335. package/dist/devices/orvibo.js +71 -4
  336. package/dist/devices/orvibo.js.map +1 -1
  337. package/dist/devices/owon.d.ts.map +1 -1
  338. package/dist/devices/owon.js +382 -62
  339. package/dist/devices/owon.js.map +1 -1
  340. package/dist/devices/paul_neuhaus.d.ts.map +1 -1
  341. package/dist/devices/paul_neuhaus.js +9 -0
  342. package/dist/devices/paul_neuhaus.js.map +1 -1
  343. package/dist/devices/paulmann.js +2 -2
  344. package/dist/devices/paulmann.js.map +1 -1
  345. package/dist/devices/perenio.d.ts.map +1 -1
  346. package/dist/devices/perenio.js +57 -39
  347. package/dist/devices/perenio.js.map +1 -1
  348. package/dist/devices/philips.d.ts.map +1 -1
  349. package/dist/devices/philips.js +194 -53
  350. package/dist/devices/philips.js.map +1 -1
  351. package/dist/devices/plaid.d.ts.map +1 -1
  352. package/dist/devices/plaid.js +18 -1
  353. package/dist/devices/plaid.js.map +1 -1
  354. package/dist/devices/plugwise.d.ts.map +1 -1
  355. package/dist/devices/plugwise.js +307 -26
  356. package/dist/devices/plugwise.js.map +1 -1
  357. package/dist/devices/profalux.d.ts.map +1 -1
  358. package/dist/devices/profalux.js +25 -1
  359. package/dist/devices/profalux.js.map +1 -1
  360. package/dist/devices/pushok.d.ts.map +1 -1
  361. package/dist/devices/pushok.js +44 -0
  362. package/dist/devices/pushok.js.map +1 -1
  363. package/dist/devices/qa.d.ts.map +1 -1
  364. package/dist/devices/qa.js +80 -32
  365. package/dist/devices/qa.js.map +1 -1
  366. package/dist/devices/repenic_ltd.d.ts +3 -0
  367. package/dist/devices/repenic_ltd.d.ts.map +1 -0
  368. package/dist/devices/repenic_ltd.js +97 -0
  369. package/dist/devices/repenic_ltd.js.map +1 -0
  370. package/dist/devices/robb.d.ts.map +1 -1
  371. package/dist/devices/robb.js +13 -1
  372. package/dist/devices/robb.js.map +1 -1
  373. package/dist/devices/rtx.js +1 -1
  374. package/dist/devices/rtx.js.map +1 -1
  375. package/dist/devices/salus_controls.d.ts.map +1 -1
  376. package/dist/devices/salus_controls.js +44 -17
  377. package/dist/devices/salus_controls.js.map +1 -1
  378. package/dist/devices/samotech.js +2 -2
  379. package/dist/devices/samotech.js.map +1 -1
  380. package/dist/devices/sber.d.ts.map +1 -1
  381. package/dist/devices/sber.js +435 -26
  382. package/dist/devices/sber.js.map +1 -1
  383. package/dist/devices/schneider_electric.d.ts.map +1 -1
  384. package/dist/devices/schneider_electric.js +808 -252
  385. package/dist/devices/schneider_electric.js.map +1 -1
  386. package/dist/devices/securifi.d.ts.map +1 -1
  387. package/dist/devices/securifi.js +24 -1
  388. package/dist/devices/securifi.js.map +1 -1
  389. package/dist/devices/sengled.d.ts.map +1 -1
  390. package/dist/devices/sengled.js +5 -4
  391. package/dist/devices/sengled.js.map +1 -1
  392. package/dist/devices/shada.d.ts +3 -0
  393. package/dist/devices/shada.d.ts.map +1 -0
  394. package/dist/devices/{aubess.js → shada.js} +7 -20
  395. package/dist/devices/shada.js.map +1 -0
  396. package/dist/devices/shelly.d.ts.map +1 -1
  397. package/dist/devices/shelly.js +646 -61
  398. package/dist/devices/shelly.js.map +1 -1
  399. package/dist/devices/shinasystem.d.ts.map +1 -1
  400. package/dist/devices/shinasystem.js +75 -16
  401. package/dist/devices/shinasystem.js.map +1 -1
  402. package/dist/devices/siglis.d.ts.map +1 -1
  403. package/dist/devices/siglis.js +26 -0
  404. package/dist/devices/siglis.js.map +1 -1
  405. package/dist/devices/sinope.d.ts.map +1 -1
  406. package/dist/devices/sinope.js +163 -83
  407. package/dist/devices/sinope.js.map +1 -1
  408. package/dist/devices/slacky_diy.d.ts.map +1 -1
  409. package/dist/devices/slacky_diy.js +3007 -69
  410. package/dist/devices/slacky_diy.js.map +1 -1
  411. package/dist/devices/smarli.d.ts.map +1 -1
  412. package/dist/devices/smarli.js +4 -5
  413. package/dist/devices/smarli.js.map +1 -1
  414. package/dist/devices/smartthings.d.ts +25 -0
  415. package/dist/devices/smartthings.d.ts.map +1 -1
  416. package/dist/devices/smartthings.js +62 -11
  417. package/dist/devices/smartthings.js.map +1 -1
  418. package/dist/devices/somfy.d.ts.map +1 -1
  419. package/dist/devices/somfy.js +14 -1
  420. package/dist/devices/somfy.js.map +1 -1
  421. package/dist/devices/sonoff.d.ts +42 -1
  422. package/dist/devices/sonoff.d.ts.map +1 -1
  423. package/dist/devices/sonoff.js +5161 -2007
  424. package/dist/devices/sonoff.js.map +1 -1
  425. package/dist/devices/sprut.d.ts.map +1 -1
  426. package/dist/devices/sprut.js +5 -4
  427. package/dist/devices/sprut.js.map +1 -1
  428. package/dist/devices/stello.d.ts.map +1 -1
  429. package/dist/devices/stello.js +6 -24
  430. package/dist/devices/stello.js.map +1 -1
  431. package/dist/devices/stelpro.d.ts +51 -1
  432. package/dist/devices/stelpro.d.ts.map +1 -1
  433. package/dist/devices/stelpro.js +86 -23
  434. package/dist/devices/stelpro.js.map +1 -1
  435. package/dist/devices/sunricher.d.ts.map +1 -1
  436. package/dist/devices/sunricher.js +215 -29
  437. package/dist/devices/sunricher.js.map +1 -1
  438. package/dist/devices/tech.d.ts.map +1 -1
  439. package/dist/devices/tech.js +35 -35
  440. package/dist/devices/tech.js.map +1 -1
  441. package/dist/devices/terncy.d.ts.map +1 -1
  442. package/dist/devices/terncy.js +398 -2
  443. package/dist/devices/terncy.js.map +1 -1
  444. package/dist/devices/third_reality.d.ts +42 -1
  445. package/dist/devices/third_reality.d.ts.map +1 -1
  446. package/dist/devices/third_reality.js +521 -110
  447. package/dist/devices/third_reality.js.map +1 -1
  448. package/dist/devices/tuya.d.ts.map +1 -1
  449. package/dist/devices/tuya.js +3143 -815
  450. package/dist/devices/tuya.js.map +1 -1
  451. package/dist/devices/ubisys.d.ts.map +1 -1
  452. package/dist/devices/ubisys.js +11 -8
  453. package/dist/devices/ubisys.js.map +1 -1
  454. package/dist/devices/vesternet.d.ts.map +1 -1
  455. package/dist/devices/vesternet.js +7 -0
  456. package/dist/devices/vesternet.js.map +1 -1
  457. package/dist/devices/viessmann.d.ts.map +1 -1
  458. package/dist/devices/viessmann.js +107 -4
  459. package/dist/devices/viessmann.js.map +1 -1
  460. package/dist/devices/vsmart.d.ts.map +1 -1
  461. package/dist/devices/vsmart.js +11 -0
  462. package/dist/devices/vsmart.js.map +1 -1
  463. package/dist/devices/weiser.d.ts.map +1 -1
  464. package/dist/devices/weiser.js +6 -0
  465. package/dist/devices/weiser.js.map +1 -1
  466. package/dist/devices/wirenboard.d.ts.map +1 -1
  467. package/dist/devices/wirenboard.js +124 -21
  468. package/dist/devices/wirenboard.js.map +1 -1
  469. package/dist/devices/wmun.d.ts.map +1 -1
  470. package/dist/devices/wmun.js +3 -2
  471. package/dist/devices/wmun.js.map +1 -1
  472. package/dist/devices/woolley.d.ts.map +1 -1
  473. package/dist/devices/woolley.js +6 -9
  474. package/dist/devices/woolley.js.map +1 -1
  475. package/dist/devices/woox.js +2 -2
  476. package/dist/devices/woox.js.map +1 -1
  477. package/dist/devices/xyzroe.d.ts.map +1 -1
  478. package/dist/devices/xyzroe.js +16 -4
  479. package/dist/devices/xyzroe.js.map +1 -1
  480. package/dist/devices/yale.d.ts.map +1 -1
  481. package/dist/devices/yale.js +138 -40
  482. package/dist/devices/yale.js.map +1 -1
  483. package/dist/devices/yandex.d.ts.map +1 -1
  484. package/dist/devices/yandex.js +93 -11
  485. package/dist/devices/yandex.js.map +1 -1
  486. package/dist/devices/yokis.d.ts.map +1 -1
  487. package/dist/devices/yokis.js +122 -85
  488. package/dist/devices/yokis.js.map +1 -1
  489. package/dist/devices/zbeacon.d.ts.map +1 -1
  490. package/dist/devices/zbeacon.js +0 -7
  491. package/dist/devices/zbeacon.js.map +1 -1
  492. package/dist/devices/zemismart.d.ts.map +1 -1
  493. package/dist/devices/zemismart.js +148 -11
  494. package/dist/devices/zemismart.js.map +1 -1
  495. package/dist/devices/zigbeetlc.js +1 -1
  496. package/dist/devices/zigbeetlc.js.map +1 -1
  497. package/dist/index.d.ts +1 -1
  498. package/dist/index.d.ts.map +1 -1
  499. package/dist/index.js +40 -35
  500. package/dist/index.js.map +1 -1
  501. package/dist/lib/bosch.d.ts.map +1 -1
  502. package/dist/lib/bosch.js +212 -42
  503. package/dist/lib/bosch.js.map +1 -1
  504. package/dist/lib/constants.d.ts +99 -17
  505. package/dist/lib/constants.d.ts.map +1 -1
  506. package/dist/lib/constants.js +15 -2
  507. package/dist/lib/constants.js.map +1 -1
  508. package/dist/lib/develco.d.ts +11 -0
  509. package/dist/lib/develco.d.ts.map +1 -1
  510. package/dist/lib/develco.js +78 -9
  511. package/dist/lib/develco.js.map +1 -1
  512. package/dist/lib/exposes.d.ts +11 -10
  513. package/dist/lib/exposes.d.ts.map +1 -1
  514. package/dist/lib/exposes.js +7 -48
  515. package/dist/lib/exposes.js.map +1 -1
  516. package/dist/lib/heiman.d.ts.map +1 -1
  517. package/dist/lib/heiman.js +34 -14
  518. package/dist/lib/heiman.js.map +1 -1
  519. package/dist/lib/ikea.d.ts +17 -0
  520. package/dist/lib/ikea.d.ts.map +1 -1
  521. package/dist/lib/ikea.js +46 -20
  522. package/dist/lib/ikea.js.map +1 -1
  523. package/dist/lib/inovelli.d.ts +86 -0
  524. package/dist/lib/inovelli.d.ts.map +1 -0
  525. package/dist/lib/inovelli.js +2580 -0
  526. package/dist/lib/inovelli.js.map +1 -0
  527. package/dist/lib/ledvance.d.ts +4 -4
  528. package/dist/lib/ledvance.d.ts.map +1 -1
  529. package/dist/lib/ledvance.js +23 -7
  530. package/dist/lib/ledvance.js.map +1 -1
  531. package/dist/lib/legacy.d.ts +21 -2
  532. package/dist/lib/legacy.d.ts.map +1 -1
  533. package/dist/lib/legacy.js +29 -2
  534. package/dist/lib/legacy.js.map +1 -1
  535. package/dist/lib/legrand.d.ts +65 -6
  536. package/dist/lib/legrand.d.ts.map +1 -1
  537. package/dist/lib/legrand.js +188 -9
  538. package/dist/lib/legrand.js.map +1 -1
  539. package/dist/lib/light.d.ts +1 -1
  540. package/dist/lib/light.d.ts.map +1 -1
  541. package/dist/lib/light.js +2 -2
  542. package/dist/lib/light.js.map +1 -1
  543. package/dist/lib/lumi.d.ts +88 -44
  544. package/dist/lib/lumi.d.ts.map +1 -1
  545. package/dist/lib/lumi.js +1813 -59
  546. package/dist/lib/lumi.js.map +1 -1
  547. package/dist/lib/modernExtend.d.ts +19 -14
  548. package/dist/lib/modernExtend.d.ts.map +1 -1
  549. package/dist/lib/modernExtend.js +37 -35
  550. package/dist/lib/modernExtend.js.map +1 -1
  551. package/dist/lib/namron.d.ts +131 -28
  552. package/dist/lib/namron.d.ts.map +1 -1
  553. package/dist/lib/namron.js +723 -42
  554. package/dist/lib/namron.js.map +1 -1
  555. package/dist/lib/nodon.d.ts.map +1 -1
  556. package/dist/lib/nodon.js +3 -1
  557. package/dist/lib/nodon.js.map +1 -1
  558. package/dist/lib/philips.d.ts +106 -2
  559. package/dist/lib/philips.d.ts.map +1 -1
  560. package/dist/lib/philips.js +945 -44
  561. package/dist/lib/philips.js.map +1 -1
  562. package/dist/lib/sonoff.d.ts +77 -10
  563. package/dist/lib/sonoff.d.ts.map +1 -1
  564. package/dist/lib/sonoff.js +165 -34
  565. package/dist/lib/sonoff.js.map +1 -1
  566. package/dist/lib/sunricher.d.ts +1 -1
  567. package/dist/lib/sunricher.d.ts.map +1 -1
  568. package/dist/lib/sunricher.js +6 -8
  569. package/dist/lib/sunricher.js.map +1 -1
  570. package/dist/lib/tuya.d.ts +558 -13
  571. package/dist/lib/tuya.d.ts.map +1 -1
  572. package/dist/lib/tuya.js +1518 -10
  573. package/dist/lib/tuya.js.map +1 -1
  574. package/dist/lib/types.d.ts +9 -6
  575. package/dist/lib/types.d.ts.map +1 -1
  576. package/dist/lib/ubisys.d.ts +1 -1
  577. package/dist/lib/ubisys.d.ts.map +1 -1
  578. package/dist/lib/ubisys.js +60 -5
  579. package/dist/lib/ubisys.js.map +1 -1
  580. package/dist/lib/utils.d.ts +5 -8
  581. package/dist/lib/utils.d.ts.map +1 -1
  582. package/dist/lib/utils.js +30 -17
  583. package/dist/lib/utils.js.map +1 -1
  584. package/dist/lib/zosung.d.ts +69 -6
  585. package/dist/lib/zosung.d.ts.map +1 -1
  586. package/dist/lib/zosung.js +113 -1
  587. package/dist/lib/zosung.js.map +1 -1
  588. package/dist/models-index.json +1 -1
  589. package/package.json +2 -2
  590. package/dist/devices/aubess.d.ts.map +0 -1
  591. package/dist/devices/aubess.js.map +0 -1
@@ -42,19 +42,1171 @@ const exposes = __importStar(require("../lib/exposes"));
42
42
  const m = __importStar(require("../lib/modernExtend"));
43
43
  const reporting = __importStar(require("../lib/reporting"));
44
44
  const utils = __importStar(require("../lib/utils"));
45
+ const utils_1 = require("../lib/utils");
45
46
  const e = exposes.presets;
46
47
  const ea = exposes.access;
47
- const setTime = async (device) => {
48
+ const setTime = async (device, sendPolicy) => {
48
49
  const endpoint = device.getEndpoint(1);
49
- const time = Math.round((Date.now() - constants.OneJanuary2000) / 1000);
50
- // Time-master + synchronised
51
- const values = { timeStatus: 1, time: time, timeZone: new Date().getTimezoneOffset() * -1 * 60 };
52
- await endpoint.write("genTime", values);
50
+ const { time, timeZone, dstStart, dstEnd, dstShift } = (0, zigbee_herdsman_1.getTimeClusterAttributes)();
51
+ await endpoint.write("genTime", {
52
+ time,
53
+ timeStatus: 0x02, // bit 1 = synchronized (per Danfoss spec §1.2)
54
+ timeZone,
55
+ dstStart,
56
+ dstEnd,
57
+ dstShift,
58
+ }, sendPolicy ? { sendPolicy } : undefined);
59
+ };
60
+ const danfossExtend = {
61
+ addDanfossHvacThermostatCluster: () => m.deviceAddCustomCluster("hvacThermostat", {
62
+ name: "hvacThermostat",
63
+ ID: zigbee_herdsman_1.Zcl.Clusters.hvacThermostat.ID,
64
+ attributes: {
65
+ danfossWindowOpenInternal: {
66
+ name: "danfossWindowOpenInternal",
67
+ ID: 0x4000,
68
+ type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
69
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
70
+ write: true,
71
+ max: 0xff,
72
+ },
73
+ danfossWindowOpenExternal: {
74
+ name: "danfossWindowOpenExternal",
75
+ ID: 0x4003,
76
+ type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
77
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
78
+ write: true,
79
+ },
80
+ danfossDayOfWeek: {
81
+ name: "danfossDayOfWeek",
82
+ ID: 0x4010,
83
+ type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
84
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
85
+ write: true,
86
+ max: 0xff,
87
+ },
88
+ danfossTriggerTime: {
89
+ name: "danfossTriggerTime",
90
+ ID: 0x4011,
91
+ type: zigbee_herdsman_1.Zcl.DataType.UINT16,
92
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
93
+ write: true,
94
+ max: 0xffff,
95
+ },
96
+ danfossMountedModeActive: {
97
+ name: "danfossMountedModeActive",
98
+ ID: 0x4012,
99
+ type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
100
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
101
+ write: true,
102
+ },
103
+ danfossMountedModeControl: {
104
+ name: "danfossMountedModeControl",
105
+ ID: 0x4013,
106
+ type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
107
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
108
+ write: true,
109
+ },
110
+ danfossThermostatOrientation: {
111
+ name: "danfossThermostatOrientation",
112
+ ID: 0x4014,
113
+ type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
114
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
115
+ write: true,
116
+ },
117
+ danfossExternalMeasuredRoomSensor: {
118
+ name: "danfossExternalMeasuredRoomSensor",
119
+ ID: 0x4015,
120
+ type: zigbee_herdsman_1.Zcl.DataType.INT16,
121
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
122
+ write: true,
123
+ min: -32768,
124
+ max: 32767,
125
+ },
126
+ danfossRadiatorCovered: {
127
+ name: "danfossRadiatorCovered",
128
+ ID: 0x4016,
129
+ type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
130
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
131
+ write: true,
132
+ },
133
+ danfossAlgorithmScaleFactor: {
134
+ name: "danfossAlgorithmScaleFactor",
135
+ ID: 0x4020,
136
+ type: zigbee_herdsman_1.Zcl.DataType.UINT8,
137
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
138
+ write: true,
139
+ max: 0xff,
140
+ },
141
+ danfossHeatAvailable: {
142
+ name: "danfossHeatAvailable",
143
+ ID: 0x4030,
144
+ type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
145
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
146
+ write: true,
147
+ },
148
+ danfossHeatRequired: {
149
+ name: "danfossHeatRequired",
150
+ ID: 0x4031,
151
+ type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
152
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
153
+ write: true,
154
+ },
155
+ danfossLoadBalancingEnable: {
156
+ name: "danfossLoadBalancingEnable",
157
+ ID: 0x4032,
158
+ type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
159
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
160
+ write: true,
161
+ },
162
+ danfossLoadRoomMean: {
163
+ name: "danfossLoadRoomMean",
164
+ ID: 0x4040,
165
+ type: zigbee_herdsman_1.Zcl.DataType.INT16,
166
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
167
+ write: true,
168
+ min: -32768,
169
+ max: 32767,
170
+ },
171
+ danfossLoadEstimate: {
172
+ name: "danfossLoadEstimate",
173
+ ID: 0x404a,
174
+ type: zigbee_herdsman_1.Zcl.DataType.INT16,
175
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
176
+ write: true,
177
+ min: -32768,
178
+ max: 32767,
179
+ },
180
+ danfossRegulationSetpointOffset: {
181
+ name: "danfossRegulationSetpointOffset",
182
+ ID: 0x404b,
183
+ type: zigbee_herdsman_1.Zcl.DataType.INT8,
184
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
185
+ write: true,
186
+ min: -128,
187
+ max: 127,
188
+ },
189
+ danfossAdaptionRunControl: {
190
+ name: "danfossAdaptionRunControl",
191
+ ID: 0x404c,
192
+ type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
193
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
194
+ write: true,
195
+ max: 0xff,
196
+ },
197
+ danfossAdaptionRunStatus: {
198
+ name: "danfossAdaptionRunStatus",
199
+ ID: 0x404d,
200
+ type: zigbee_herdsman_1.Zcl.DataType.BITMAP8,
201
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
202
+ write: true,
203
+ },
204
+ danfossAdaptionRunSettings: {
205
+ name: "danfossAdaptionRunSettings",
206
+ ID: 0x404e,
207
+ type: zigbee_herdsman_1.Zcl.DataType.BITMAP8,
208
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
209
+ write: true,
210
+ },
211
+ danfossPreheatStatus: {
212
+ name: "danfossPreheatStatus",
213
+ ID: 0x404f,
214
+ type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
215
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
216
+ write: true,
217
+ },
218
+ danfossPreheatTime: {
219
+ name: "danfossPreheatTime",
220
+ ID: 0x4050,
221
+ type: zigbee_herdsman_1.Zcl.DataType.UINT32,
222
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
223
+ write: true,
224
+ },
225
+ danfossWindowOpenFeatureEnable: {
226
+ name: "danfossWindowOpenFeatureEnable",
227
+ ID: 0x4051,
228
+ type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
229
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
230
+ write: true,
231
+ },
232
+ danfossRoomStatusCode: {
233
+ name: "danfossRoomStatusCode",
234
+ ID: 0x4100,
235
+ type: zigbee_herdsman_1.Zcl.DataType.BITMAP16,
236
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
237
+ write: true,
238
+ },
239
+ danfossOutputStatus: {
240
+ name: "danfossOutputStatus",
241
+ ID: 0x4110,
242
+ type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
243
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
244
+ write: true,
245
+ max: 0xff,
246
+ },
247
+ danfossRoomFloorSensorMode: {
248
+ name: "danfossRoomFloorSensorMode",
249
+ ID: 0x4120,
250
+ type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
251
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
252
+ write: true,
253
+ max: 0xff,
254
+ },
255
+ danfossFloorMinSetpoint: {
256
+ name: "danfossFloorMinSetpoint",
257
+ ID: 0x4121,
258
+ type: zigbee_herdsman_1.Zcl.DataType.INT16,
259
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
260
+ write: true,
261
+ min: -32768,
262
+ max: 32767,
263
+ },
264
+ danfossFloorMaxSetpoint: {
265
+ name: "danfossFloorMaxSetpoint",
266
+ ID: 0x4122,
267
+ type: zigbee_herdsman_1.Zcl.DataType.INT16,
268
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
269
+ write: true,
270
+ min: -32768,
271
+ max: 32767,
272
+ },
273
+ danfossScheduleTypeUsed: {
274
+ name: "danfossScheduleTypeUsed",
275
+ ID: 0x4130,
276
+ type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
277
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
278
+ write: true,
279
+ max: 0xff,
280
+ },
281
+ danfossIcon2PreHeat: {
282
+ name: "danfossIcon2PreHeat",
283
+ ID: 0x4131,
284
+ type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
285
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
286
+ write: true,
287
+ max: 0xff,
288
+ },
289
+ danfossIcon2PreHeatStatus: {
290
+ name: "danfossIcon2PreHeatStatus",
291
+ ID: 0x414f,
292
+ type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
293
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
294
+ write: true,
295
+ max: 0xff,
296
+ },
297
+ },
298
+ commands: {
299
+ danfossSetpointCommand: {
300
+ name: "danfossSetpointCommand",
301
+ ID: 0x40,
302
+ parameters: [
303
+ { name: "setpointType", type: zigbee_herdsman_1.Zcl.DataType.ENUM8, max: 0xff },
304
+ { name: "setpoint", type: zigbee_herdsman_1.Zcl.DataType.INT16, min: -32768, max: 32767 },
305
+ ],
306
+ },
307
+ danfossPreHeatCommand: {
308
+ name: "danfossPreHeatCommand",
309
+ ID: 0x42,
310
+ parameters: [
311
+ { name: "type", type: zigbee_herdsman_1.Zcl.DataType.ENUM8, max: 0xff },
312
+ { name: "timestamp", type: zigbee_herdsman_1.Zcl.DataType.UINT32 },
313
+ ],
314
+ },
315
+ },
316
+ commandsResponse: {},
317
+ }),
318
+ addDanfossHvacUserInterfaceCfgCluster: () => m.deviceAddCustomCluster("hvacUserInterfaceCfg", {
319
+ name: "hvacUserInterfaceCfg",
320
+ ID: zigbee_herdsman_1.Zcl.Clusters.hvacUserInterfaceCfg.ID,
321
+ attributes: {
322
+ danfossViewingDirection: {
323
+ name: "danfossViewingDirection",
324
+ ID: 0x4000,
325
+ type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
326
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
327
+ write: true,
328
+ max: 0xff,
329
+ },
330
+ },
331
+ commands: {},
332
+ commandsResponse: {},
333
+ }),
334
+ addDanfossHaDiagnosticCluster: () => m.deviceAddCustomCluster("haDiagnostic", {
335
+ name: "haDiagnostic",
336
+ ID: zigbee_herdsman_1.Zcl.Clusters.haDiagnostic.ID,
337
+ attributes: {
338
+ danfossSystemStatusCode: {
339
+ name: "danfossSystemStatusCode",
340
+ ID: 0x4000,
341
+ type: zigbee_herdsman_1.Zcl.DataType.BITMAP16,
342
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
343
+ write: true,
344
+ },
345
+ danfossHeatSupplyRequest: {
346
+ name: "danfossHeatSupplyRequest",
347
+ ID: 0x4031,
348
+ type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
349
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
350
+ write: true,
351
+ max: 0xff,
352
+ },
353
+ danfossSystemStatusWater: {
354
+ name: "danfossSystemStatusWater",
355
+ ID: 0x4200,
356
+ type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
357
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
358
+ write: true,
359
+ max: 0xff,
360
+ },
361
+ danfossMultimasterRole: {
362
+ name: "danfossMultimasterRole",
363
+ ID: 0x4201,
364
+ type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
365
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
366
+ write: true,
367
+ max: 0xff,
368
+ },
369
+ danfossIconApplication: {
370
+ name: "danfossIconApplication",
371
+ ID: 0x4210,
372
+ type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
373
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
374
+ write: true,
375
+ max: 0xff,
376
+ },
377
+ danfossIconForcedHeatingCooling: {
378
+ name: "danfossIconForcedHeatingCooling",
379
+ ID: 0x4220,
380
+ type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
381
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
382
+ write: true,
383
+ max: 0xff,
384
+ },
385
+ },
386
+ commands: {},
387
+ commandsResponse: {},
388
+ }),
389
+ absMaxHeatSetpointLimit: (args) => m.numeric({
390
+ name: "abs_max_heat_setpoint_limit",
391
+ cluster: "hvacThermostat",
392
+ attribute: "absMaxHeatSetpointLimit",
393
+ description: "Absolute Maximum Heating Setpoint Limit.",
394
+ unit: "°C",
395
+ scale: 100,
396
+ entityCategory: "diagnostic",
397
+ access: "STATE_GET",
398
+ ...args,
399
+ }),
400
+ keypadLockout: (args) => m.enumLookup({
401
+ name: "keypad_lockout",
402
+ cluster: "hvacUserInterfaceCfg",
403
+ attribute: "keypadLockout",
404
+ description: "Enables/disables physical input on the device",
405
+ lookup: {
406
+ unlock: 0,
407
+ lock: 1,
408
+ },
409
+ access: "ALL",
410
+ entityCategory: "config",
411
+ fzConvert: (model, msg, publish, options, meta) => {
412
+ const result = {};
413
+ if ("keypadLockout" in msg.data) {
414
+ result[(0, utils_1.postfixWithEndpointName)("keypad_lockout", msg, model, meta)] = msg.data.keypadLockout > 0 ? "lock" : "unlock";
415
+ }
416
+ return result;
417
+ },
418
+ ...args,
419
+ }),
420
+ danfossMountedModeActive: (args) => m.binary({
421
+ name: "mounted_mode_active",
422
+ cluster: "hvacThermostat",
423
+ attribute: "danfossMountedModeActive",
424
+ description: "Is the unit in mounting mode. This is set to `false` for mounted (already on the radiator) or `true` for not mounted (after factory reset)",
425
+ valueOn: [true, 1],
426
+ valueOff: [false, 0],
427
+ access: "STATE_GET",
428
+ entityCategory: "diagnostic",
429
+ zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
430
+ ...args,
431
+ }),
432
+ danfossMountedModeControl: (args) => m.binary({
433
+ name: "mounted_mode_control",
434
+ cluster: "hvacThermostat",
435
+ attribute: "danfossMountedModeControl",
436
+ description: "Set the unit mounting mode. `false` Go to Mounted Mode or `true` Go to Mounting Mode",
437
+ valueOn: [true, 1],
438
+ valueOff: [false, 0],
439
+ access: "ALL",
440
+ entityCategory: "config",
441
+ zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
442
+ ...args,
443
+ }),
444
+ danfossThermostatOrientation: (args) => m.binary({
445
+ name: "thermostat_orientation",
446
+ cluster: "hvacThermostat",
447
+ attribute: "danfossThermostatOrientation",
448
+ description: "Thermostat Orientation. This is important for the PID in how it assesses temperature.",
449
+ valueOn: ["vertical", 1],
450
+ valueOff: ["horizontal", 0],
451
+ access: "ALL",
452
+ entityCategory: "config",
453
+ zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
454
+ ...args,
455
+ }),
456
+ danfossViewingDirection: (args) => m.binary({
457
+ name: "viewing_direction",
458
+ cluster: "hvacUserInterfaceCfg",
459
+ attribute: "danfossViewingDirection",
460
+ description: "Viewing/display direction",
461
+ valueOn: ["upside-down", true],
462
+ valueOff: ["normal", false],
463
+ access: "ALL",
464
+ entityCategory: "config",
465
+ zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
466
+ ...args,
467
+ }),
468
+ danfossHeatAvailable: (args) => m.binary({
469
+ name: "heat_available",
470
+ cluster: "hvacThermostat",
471
+ attribute: "danfossHeatAvailable",
472
+ description: "Not clear how this affects operation. However, it would appear that the device does not execute any " +
473
+ "motor functions if this is set to false. This may be a means to conserve battery during periods that the heating " +
474
+ "system is not energized (e.g. during summer).",
475
+ valueOn: [true, 1],
476
+ valueOff: [false, 0],
477
+ access: "ALL",
478
+ entityCategory: "config",
479
+ zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
480
+ ...args,
481
+ }),
482
+ danfossHeatRequired: (args) => m.binary({
483
+ name: "heat_required",
484
+ cluster: "hvacThermostat",
485
+ attribute: "danfossHeatRequired",
486
+ description: "Whether or not the unit needs warm water.",
487
+ valueOn: [true, 1],
488
+ valueOff: [false, 0],
489
+ access: "STATE_GET",
490
+ entityCategory: "diagnostic",
491
+ zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
492
+ ...args,
493
+ }),
494
+ setpointChangeSource: (args) => m.enumLookup({
495
+ name: "setpoint_change_source",
496
+ cluster: "hvacThermostat",
497
+ attribute: "setpointChangeSource",
498
+ description: "Values observed",
499
+ access: "STATE",
500
+ lookup: {
501
+ manual: 0,
502
+ schedule: 1,
503
+ externally: 2,
504
+ },
505
+ entityCategory: "diagnostic",
506
+ zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
507
+ ...args,
508
+ }),
509
+ occupiedHeatingSetpointScheduled: (args) => m.numeric({
510
+ name: "occupied_heating_setpoint_scheduled",
511
+ cluster: "hvacThermostat",
512
+ attribute: "occupiedHeatingSetpoint",
513
+ description: "Scheduled change of the setpoint. Alternative method for changing the setpoint. " +
514
+ "In the opposite to occupied_heating_setpoint it does not trigger an aggressive " +
515
+ "response from the actuator. (more suitable for scheduled changes)",
516
+ access: "ALL",
517
+ unit: "°C",
518
+ valueMin: 5,
519
+ valueMax: 35,
520
+ valueStep: 0.5,
521
+ scale: 100,
522
+ // fzConvert:
523
+ zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
524
+ ...args,
525
+ }),
526
+ danfossExternalMeasuredRoomSensor: (args) => m.numeric({
527
+ name: "external_measured_room_sensor",
528
+ cluster: "hvacThermostat",
529
+ attribute: "danfossExternalMeasuredRoomSensor",
530
+ description: "The temperature sensor of the TRV is — due to its design — relatively close to the heat source " +
531
+ "(i.e. the hot water in the radiator). Thus there are situations where the `local_temperature` measured by the " +
532
+ "TRV is not accurate enough: If the radiator is covered behind curtains or furniture, if the room is rather big, or " +
533
+ "if the radiator itself is big and the flow temperature is high, then the temperature in the room may easily diverge " +
534
+ "from the `local_temperature` measured by the TRV by 5°C to 8°C. In this case you might choose to use an external " +
535
+ "room sensor and send the measured value of the external room sensor to the `External_measured_room_sensor` property. " +
536
+ "The way the TRV operates on the `External_measured_room_sensor` depends on the setting of the `Radiator_covered` " +
537
+ "property: If `Radiator_covered` is `false` (Auto Offset Mode): You *must* set the `External_measured_room_sensor` " +
538
+ "property *at least* every 3 hours. After 3 hours the TRV disables this function and resets the value of the " +
539
+ "`External_measured_room_sensor` property to -8000 (disabled). You *should* set the `External_measured_room_sensor` " +
540
+ "property *at most* every 30 minutes or every 0.1°C change in measured room temperature. " +
541
+ "If `Radiator_covered` is `true` (Room Sensor Mode): You *must* set the `External_measured_room_sensor` property *at " +
542
+ "least* every 30 minutes. After 35 minutes the TRV disables this function and resets the value of the " +
543
+ "`External_measured_room_sensor` property to -8000 (disabled). You *should* set the `External_measured_room_sensor` " +
544
+ "property *at most* every 5 minutes or every 0.1°C change in measured room temperature. " +
545
+ "The unit of this value is 0.01 `°C` (so e.g. 21°C would be represented as 2100).",
546
+ valueMin: -8000,
547
+ valueMax: 3500,
548
+ zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
549
+ ...args,
550
+ }),
551
+ danfossRadiatorCovered: (args) => m.binary({
552
+ name: "radiator_covered",
553
+ cluster: "hvacThermostat",
554
+ attribute: "danfossRadiatorCovered",
555
+ description: "Controls whether the TRV should solely rely on an external room sensor or operate in offset mode. " +
556
+ "`false` = Auto Offset Mode (use this e.g. for exposed radiators) or `true` = Room Sensor Mode (use this e.g. for " +
557
+ "covered radiators). Please note that this flag only controls how the TRV operates on the value of " +
558
+ "`External_measured_room_sensor`; only setting this flag without setting the `External_measured_room_sensor` " +
559
+ "has no (noticeable?) effect.",
560
+ valueOn: [true, 1],
561
+ valueOff: [false, 0],
562
+ access: "ALL",
563
+ zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
564
+ ...args,
565
+ }),
566
+ danfossWindowOpenFeatureEnable: (args) => m.binary({
567
+ name: "window_open_feature",
568
+ cluster: "hvacThermostat",
569
+ attribute: "danfossWindowOpenFeatureEnable",
570
+ description: "Whether or not the window open feature is enabled",
571
+ valueOn: [true, 1],
572
+ valueOff: [false, 0],
573
+ access: "ALL",
574
+ entityCategory: "config",
575
+ zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
576
+ ...args,
577
+ }),
578
+ danfossWindowOpenInternal: (args) => m.enumLookup({
579
+ name: "window_open_internal",
580
+ cluster: "hvacThermostat",
581
+ attribute: "danfossWindowOpenInternal",
582
+ description: "0=Quarantine, 1=Windows are closed, 2=Hold - Windows are maybe about to open, " +
583
+ "3=Open window detected, 4=In window open state from external but detected closed locally",
584
+ lookup: {
585
+ quarantine: 0,
586
+ closed: 1,
587
+ hold: 2,
588
+ open: 3,
589
+ external_open: 4,
590
+ },
591
+ access: "STATE_GET",
592
+ entityCategory: "diagnostic",
593
+ zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
594
+ ...args,
595
+ }),
596
+ danfossWindowOpenExternal: (args) => m.binary({
597
+ name: "window_open_external",
598
+ cluster: "hvacThermostat",
599
+ attribute: "danfossWindowOpenExternal",
600
+ description: "Set if the window is open or closed. This setting will trigger a change in the internal window and heating demand.",
601
+ valueOn: [true, 1],
602
+ valueOff: [false, 0],
603
+ access: "ALL",
604
+ zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
605
+ ...args,
606
+ }),
607
+ danfossDayOfWeek: (args) => m.enumLookup({
608
+ name: "day_of_week",
609
+ cluster: "hvacThermostat",
610
+ attribute: "danfossDayOfWeek",
611
+ lookup: {
612
+ sunday: 0,
613
+ monday: 1,
614
+ tuesday: 2,
615
+ wednesday: 3,
616
+ thursday: 4,
617
+ friday: 5,
618
+ saturday: 6,
619
+ away_or_vacation: 7,
620
+ },
621
+ description: "Exercise day of week: 0=Sun...6=Sat, 7=undefined",
622
+ access: "ALL",
623
+ entityCategory: "config",
624
+ zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
625
+ ...args,
626
+ }),
627
+ danfossTriggerTime: (args) => m.numeric({
628
+ name: "trigger_time",
629
+ cluster: "hvacThermostat",
630
+ attribute: "danfossTriggerTime",
631
+ description: "Exercise trigger time. Minutes since midnight (65535=undefined). Range 0 to 1439",
632
+ valueMin: 0,
633
+ valueMax: 1439,
634
+ access: "ALL",
635
+ entityCategory: "config",
636
+ zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
637
+ ...args,
638
+ }),
639
+ danfossTriggerTime2: () => {
640
+ return {
641
+ isModernExtend: true,
642
+ exposes: [
643
+ e
644
+ .text("trigger_time", ea.ALL)
645
+ .withDescription("Exercise trigger time. Format: 'HH:MM' (e.g., '14:30'). Send 'undefined' to disable. Note: during DST, the valve may exercise earlier than configured due to a firmware limitation (the TRV uses standard time instead of wall-clock time)")
646
+ .withCategory("config"),
647
+ ],
648
+ fromZigbee: [
649
+ {
650
+ cluster: "hvacThermostat",
651
+ type: ["attributeReport", "readResponse"],
652
+ convert: (model, msg, publish, options, meta) => {
653
+ if (msg.data.danfossTriggerTime !== undefined) {
654
+ const val = msg.data.danfossTriggerTime;
655
+ if (val === 65535) {
656
+ return { trigger_time: "undefined" };
657
+ }
658
+ const hours = Math.floor(val / 60)
659
+ .toString()
660
+ .padStart(2, "0");
661
+ const mins = (val % 60).toString().padStart(2, "0");
662
+ return { trigger_time: `${hours}:${mins}` };
663
+ }
664
+ },
665
+ },
666
+ ],
667
+ toZigbee: [
668
+ {
669
+ key: ["trigger_time"],
670
+ convertSet: async (entity, key, value, meta) => {
671
+ let val = 65535; // Default to undefined (65535)
672
+ if (typeof value === "string" && value.toLowerCase() !== "undefined") {
673
+ const [hours, mins] = value.split(":").map(Number);
674
+ if (!Number.isNaN(hours) && !Number.isNaN(mins)) {
675
+ val = hours * 60 + mins;
676
+ }
677
+ else {
678
+ throw new Error(`Invalid time format for trigger_time: '${value}'. Please use 'HH:MM'.`);
679
+ }
680
+ }
681
+ await entity.write("hvacThermostat", { danfossTriggerTime: val }, { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S });
682
+ return { state: { trigger_time: value } };
683
+ },
684
+ convertGet: async (entity, key, meta) => {
685
+ await entity.read("hvacThermostat", ["danfossTriggerTime"], {
686
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
687
+ });
688
+ },
689
+ },
690
+ ],
691
+ };
692
+ },
693
+ danfossAlgorithmScaleFactor: (args) => m.numeric({
694
+ name: "algorithm_scale_factor",
695
+ cluster: "hvacThermostat",
696
+ attribute: "danfossAlgorithmScaleFactor",
697
+ description: 'Scale factor of setpoint filter timeconstant ("aggressiveness" of control algorithm) 1= Quick ... 5=Moderate ... 10=Slow',
698
+ valueMin: 1,
699
+ valueMax: 10,
700
+ access: "ALL",
701
+ zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
702
+ ...args,
703
+ }),
704
+ danfossLoadBalancingEnable: (args) => m.binary({
705
+ name: "load_balancing_enable",
706
+ cluster: "hvacThermostat",
707
+ attribute: "danfossLoadBalancingEnable",
708
+ description: "Whether or not the thermostat acts as standalone thermostat or shares load with other thermostats in the room. The gateway must update load_room_mean if enabled.",
709
+ valueOn: [true, 1],
710
+ valueOff: [false, 0],
711
+ access: "ALL",
712
+ zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
713
+ ...args,
714
+ }),
715
+ danfossLoadRoomMean: (args) => m.numeric({
716
+ name: "load_room_mean",
717
+ cluster: "hvacThermostat",
718
+ attribute: "danfossLoadRoomMean",
719
+ description: "Mean radiator load for room calculated by gateway for load balancing purposes (-8000=undefined)",
720
+ valueMin: -8000,
721
+ valueMax: 3600,
722
+ access: "ALL",
723
+ zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
724
+ ...args,
725
+ }),
726
+ danfossLoadEstimate: (args) => m.numeric({
727
+ name: "load_estimate",
728
+ cluster: "hvacThermostat",
729
+ attribute: "danfossLoadEstimate",
730
+ description: "Load estimate on this radiator",
731
+ valueMin: -8000,
732
+ valueMax: 3600,
733
+ access: "STATE_GET",
734
+ zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
735
+ ...args,
736
+ }),
737
+ danfossPreheatStatus: (args) => m.binary({
738
+ name: "preheat_status",
739
+ cluster: "hvacThermostat",
740
+ attribute: "danfossPreheatStatus",
741
+ description: "Specific for pre-heat running in Zigbee Weekly Schedule mode",
742
+ valueOn: [true, 1],
743
+ valueOff: [false, 0],
744
+ access: "STATE_GET",
745
+ zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
746
+ ...args,
747
+ }),
748
+ danfossPreheatTime: (args) => m.numeric({
749
+ name: "preheat_time",
750
+ cluster: "hvacThermostat",
751
+ attribute: "danfossPreheatTime",
752
+ description: "Timestamp of the scheduled setpoint currently being preheated to (read-only)",
753
+ access: "STATE_GET",
754
+ zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
755
+ ...args,
756
+ }),
757
+ danfossAdaptionRunStatus: (args) => m.enumLookup({
758
+ name: "adaptation_run_status",
759
+ cluster: "hvacThermostat",
760
+ attribute: "danfossAdaptionRunStatus",
761
+ description: "Status of adaptation run: None (before first run), In Progress, Valve Characteristic Found, Valve Characteristic Lost",
762
+ lookup: {
763
+ none: 0,
764
+ in_progress: 1,
765
+ found: 2,
766
+ lost: 3,
767
+ lost_in_progress: 4,
768
+ },
769
+ access: "STATE_GET",
770
+ zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
771
+ ...args,
772
+ }),
773
+ danfossAdaptionRunSettings: (args) => m.binary({
774
+ name: "adaptation_run_settings",
775
+ cluster: "hvacThermostat",
776
+ attribute: "danfossAdaptionRunSettings",
777
+ description: "Automatic adaptation run enabled (the one during the night)",
778
+ valueOn: [true, 1],
779
+ valueOff: [false, 0],
780
+ access: "ALL",
781
+ zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
782
+ ...args,
783
+ }),
784
+ danfossAdaptionRunControl: (args) => m.enumLookup({
785
+ name: "adaptation_run_control",
786
+ cluster: "hvacThermostat",
787
+ attribute: "danfossAdaptionRunControl",
788
+ description: "Adaptation run control: Initiate Adaptation Run or Cancel Adaptation Run",
789
+ lookup: {
790
+ idle: 0,
791
+ initiate_adaptation: 1,
792
+ cancel_adaptation: 2,
793
+ },
794
+ access: "ALL",
795
+ zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
796
+ ...args,
797
+ }),
798
+ danfossRegulationSetpointOffset: (args) => m.numeric({
799
+ name: "regulation_setpoint_offset",
800
+ cluster: "hvacThermostat",
801
+ attribute: "danfossRegulationSetpointOffset",
802
+ description: "Regulation SetPoint Offset in range -2.5°C to 2.5°C in steps of 0.1°C.",
803
+ valueMin: -2.5,
804
+ valueMax: 2.5,
805
+ valueStep: 0.1,
806
+ scale: 10,
807
+ unit: "°C",
808
+ access: "ALL",
809
+ entityCategory: "config",
810
+ zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
811
+ ...args,
812
+ }),
813
+ danfossThermostat: (options) => {
814
+ const extend = m.thermostat(options);
815
+ const danfossSetpointConverter = {
816
+ key: ["occupied_heating_setpoint", "occupied_heating_setpoint_scheduled"],
817
+ convertSet: async (entity, key, value, meta) => {
818
+ utils.assertNumber(value, key);
819
+ const isScheduled = key === "occupied_heating_setpoint_scheduled";
820
+ const payload = {
821
+ setpointType: isScheduled ? 0 : 1, // 0 for scheduled, 1 for aggressive
822
+ setpoint: Math.round(value * 2) * 50,
823
+ };
824
+ // Send the command
825
+ await entity.command("hvacThermostat", "danfossSetpointCommand", payload, { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S });
826
+ if (!isScheduled) {
827
+ await entity.command("hvacThermostat", "danfossSetpointCommand", payload, { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S });
828
+ }
829
+ },
830
+ convertGet: async (entity, key, meta) => {
831
+ await entity.read("hvacThermostat", ["occupiedHeatingSetpoint"]);
832
+ },
833
+ };
834
+ extend.toZigbee.unshift(danfossSetpointConverter);
835
+ const climateExpose = extend.exposes.find((exp) => typeof exp !== "function" && "type" in exp && exp.type === "climate");
836
+ if (climateExpose) {
837
+ climateExpose.withRunningState(["idle", "heat"]);
838
+ const runningStateFeature = climateExpose.features.find((f) => typeof f !== "function" && "name" in f && f.name === "running_state");
839
+ if (runningStateFeature) {
840
+ runningStateFeature.withDescription("Running state based on danfossOutputStatus and danfossHeatRequired");
841
+ }
842
+ }
843
+ extend.exposes.push(e
844
+ .numeric("occupied_heating_setpoint_scheduled", ea.ALL)
845
+ .withValueMin(5)
846
+ .withValueMax(35)
847
+ .withValueStep(0.5)
848
+ .withUnit("°C")
849
+ .withDescription("Scheduled change of the setpoint. Alternative method for changing the setpoint. In contrast to occupied heating setpoint it does not trigger an aggressive response from the actuator. (more suitable for scheduled changes)"));
850
+ extend.fromZigbee.push({
851
+ cluster: "hvacThermostat",
852
+ type: ["attributeReport", "readResponse"],
853
+ convert: (model, msg, publish, options, meta) => {
854
+ const result = {};
855
+ if ("danfossHeatRequired" in msg.data || "danfossOutputStatus" in msg.data) {
856
+ const isHeating = (msg.data.danfossOutputStatus ?? msg.data.danfossHeatRequired) === 1;
857
+ result.running_state = isHeating ? "heat" : "idle";
858
+ }
859
+ if ("occupiedHeatingSetpoint" in msg.data) {
860
+ const value = (0, utils_1.precisionRound)(msg.data.occupiedHeatingSetpoint, 2) / 100;
861
+ result[(0, utils_1.postfixWithEndpointName)("occupied_heating_setpoint", msg, model, meta)] = value;
862
+ result[(0, utils_1.postfixWithEndpointName)("occupied_heating_setpoint_scheduled", msg, model, meta)] = value;
863
+ }
864
+ return result;
865
+ },
866
+ });
867
+ extend.toZigbee.push({
868
+ key: ["running_state"],
869
+ convertGet: async (entity, key, meta) => {
870
+ await entity.read("hvacThermostat", ["danfossHeatRequired"], {
871
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
872
+ });
873
+ },
874
+ });
875
+ extend.configure.push(m.setupConfigureForReading("hvacThermostat", ["systemMode"]), m.setupConfigureForReading("hvacUserInterfaceCfg", ["keypadLockout"]), async (device, coordinatorEndpoint) => {
876
+ await setTime(device);
877
+ });
878
+ return extend;
879
+ },
880
+ danfossTimeSyncOnAnnounce: () => ({
881
+ isModernExtend: true,
882
+ onEvent: [
883
+ async (event) => {
884
+ if (event.type === "deviceAnnounce") {
885
+ await setTime(event.data.device, "queue");
886
+ }
887
+ },
888
+ ],
889
+ }),
890
+ };
891
+ const tzLocal = {
892
+ danfoss_output_status: {
893
+ key: ["output_status"],
894
+ convertGet: async (entity, key, meta) => {
895
+ await entity.read("hvacThermostat", ["danfossOutputStatus"], {
896
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
897
+ });
898
+ },
899
+ },
900
+ danfoss_room_status_code: {
901
+ key: ["room_status_code"],
902
+ convertGet: async (entity, key, meta) => {
903
+ await entity.read("hvacThermostat", ["danfossRoomStatusCode"], {
904
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
905
+ });
906
+ },
907
+ },
908
+ danfoss_floor_sensor_mode: {
909
+ key: ["room_floor_sensor_mode"],
910
+ convertGet: async (entity, key, meta) => {
911
+ await entity.read("hvacThermostat", ["danfossRoomFloorSensorMode"], {
912
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
913
+ });
914
+ },
915
+ },
916
+ danfoss_floor_min_setpoint: {
917
+ key: ["floor_min_setpoint"],
918
+ convertSet: async (entity, key, value, meta) => {
919
+ utils.assertNumber(value, key);
920
+ const danfossFloorMinSetpoint = Number((Math.round(Number((value * 2).toFixed(1))) / 2).toFixed(1)) * 100;
921
+ await entity.write("hvacThermostat", { danfossFloorMinSetpoint }, { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S });
922
+ return { state: { floor_min_setpoint: value } };
923
+ },
924
+ convertGet: async (entity, key, meta) => {
925
+ await entity.read("hvacThermostat", ["danfossFloorMinSetpoint"], {
926
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
927
+ });
928
+ },
929
+ },
930
+ danfoss_floor_max_setpoint: {
931
+ key: ["floor_max_setpoint"],
932
+ convertSet: async (entity, key, value, meta) => {
933
+ utils.assertNumber(value, key);
934
+ const danfossFloorMaxSetpoint = Number((Math.round(Number((value * 2).toFixed(1))) / 2).toFixed(1)) * 100;
935
+ await entity.write("hvacThermostat", { danfossFloorMaxSetpoint }, { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S });
936
+ return { state: { floor_max_setpoint: value } };
937
+ },
938
+ convertGet: async (entity, key, meta) => {
939
+ await entity.read("hvacThermostat", ["danfossFloorMaxSetpoint"], {
940
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
941
+ });
942
+ },
943
+ },
944
+ danfoss_schedule_type_used: {
945
+ key: ["schedule_type_used"],
946
+ convertGet: async (entity, key, meta) => {
947
+ await entity.read("hvacThermostat", ["danfossScheduleTypeUsed"], {
948
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
949
+ });
950
+ },
951
+ },
952
+ danfoss_icon2_pre_heat: {
953
+ key: ["icon2_pre_heat"],
954
+ convertGet: async (entity, key, meta) => {
955
+ await entity.read("hvacThermostat", ["danfossIcon2PreHeat"], {
956
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
957
+ });
958
+ },
959
+ },
960
+ danfoss_icon2_pre_heat_status: {
961
+ key: ["icon2_pre_heat_status"],
962
+ convertGet: async (entity, key, meta) => {
963
+ await entity.read("hvacThermostat", ["danfossIcon2PreHeatStatus"], {
964
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
965
+ });
966
+ },
967
+ },
968
+ danfoss_preheat_command: {
969
+ key: ["preheat_command"],
970
+ convertSet: async (entity, key, value, meta) => {
971
+ utils.assertObject(value);
972
+ const payload = {
973
+ type: 0x00, // Force preheat
974
+ timestamp: value.timestamp,
975
+ };
976
+ await entity.command("hvacThermostat", "danfossPreHeatCommand", payload, { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S });
977
+ },
978
+ },
979
+ danfoss_system_status_code: {
980
+ key: ["system_status_code"],
981
+ convertGet: async (entity, key, meta) => {
982
+ await entity.read("haDiagnostic", ["danfossSystemStatusCode"], {
983
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
984
+ });
985
+ },
986
+ },
987
+ danfoss_heat_supply_request: {
988
+ key: ["heat_supply_request"],
989
+ convertGet: async (entity, key, meta) => {
990
+ await entity.read("haDiagnostic", ["danfossHeatSupplyRequest"], {
991
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
992
+ });
993
+ },
994
+ },
995
+ danfoss_system_status_water: {
996
+ key: ["system_status_water"],
997
+ convertGet: async (entity, key, meta) => {
998
+ await entity.read("haDiagnostic", ["danfossSystemStatusWater"], {
999
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
1000
+ });
1001
+ },
1002
+ },
1003
+ danfoss_multimaster_role: {
1004
+ key: ["multimaster_role"],
1005
+ convertGet: async (entity, key, meta) => {
1006
+ await entity.read("haDiagnostic", ["danfossMultimasterRole"], {
1007
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
1008
+ });
1009
+ },
1010
+ },
1011
+ danfoss_icon_application: {
1012
+ key: ["icon_application"],
1013
+ convertGet: async (entity, key, meta) => {
1014
+ await entity.read("haDiagnostic", ["danfossIconApplication"], {
1015
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
1016
+ });
1017
+ },
1018
+ },
1019
+ danfoss_icon_forced_heating_cooling: {
1020
+ key: ["icon_forced_heating_cooling"],
1021
+ convertGet: async (entity, key, meta) => {
1022
+ await entity.read("haDiagnostic", ["danfossIconForcedHeatingCooling"], {
1023
+ manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
1024
+ });
1025
+ },
1026
+ },
1027
+ };
1028
+ const fzLocal = {
1029
+ danfoss_thermostat: {
1030
+ cluster: "hvacThermostat",
1031
+ type: ["attributeReport", "readResponse"],
1032
+ convert: (model, msg, publish, options, meta) => {
1033
+ const result = {};
1034
+ // Danfoss Icon Converters
1035
+ if (msg.data.danfossRoomStatusCode !== undefined) {
1036
+ result[(0, utils_1.postfixWithEndpointName)("room_status_code", msg, model, meta)] =
1037
+ constants.danfossRoomStatusCode[msg.data.danfossRoomStatusCode] !== undefined
1038
+ ? constants.danfossRoomStatusCode[msg.data.danfossRoomStatusCode]
1039
+ : msg.data.danfossRoomStatusCode;
1040
+ }
1041
+ if (msg.data.danfossOutputStatus !== undefined) {
1042
+ if (msg.data.danfossOutputStatus === 1) {
1043
+ result[(0, utils_1.postfixWithEndpointName)("output_status", msg, model, meta)] = "active";
1044
+ result[(0, utils_1.postfixWithEndpointName)("running_state", msg, model, meta)] = "heat";
1045
+ }
1046
+ else {
1047
+ result[(0, utils_1.postfixWithEndpointName)("output_status", msg, model, meta)] = "inactive";
1048
+ result[(0, utils_1.postfixWithEndpointName)("running_state", msg, model, meta)] = "idle";
1049
+ }
1050
+ }
1051
+ return result;
1052
+ },
1053
+ },
1054
+ danfoss_hvac_ui: {
1055
+ cluster: "hvacUserInterfaceCfg",
1056
+ type: ["attributeReport", "readResponse"],
1057
+ convert: (model, msg, publish, options, meta) => {
1058
+ const result = {};
1059
+ if (msg.data.danfossViewingDirection !== undefined) {
1060
+ result[(0, utils_1.postfixWithEndpointName)("viewing_direction", msg, model, meta)] = msg.data.danfossViewingDirection === 1;
1061
+ }
1062
+ return result;
1063
+ },
1064
+ },
1065
+ danfoss_icon_floor_sensor: {
1066
+ cluster: "hvacThermostat",
1067
+ type: ["attributeReport", "readResponse"],
1068
+ convert: (model, msg, publish, options, meta) => {
1069
+ const result = {};
1070
+ if (msg.data.danfossRoomFloorSensorMode !== undefined) {
1071
+ result[(0, utils_1.postfixWithEndpointName)("room_floor_sensor_mode", msg, model, meta)] =
1072
+ constants.danfossRoomFloorSensorMode[msg.data.danfossRoomFloorSensorMode] !== undefined
1073
+ ? constants.danfossRoomFloorSensorMode[msg.data.danfossRoomFloorSensorMode]
1074
+ : msg.data.danfossRoomFloorSensorMode;
1075
+ }
1076
+ if (msg.data.danfossFloorMinSetpoint !== undefined) {
1077
+ const value = (0, utils_1.precisionRound)(msg.data.danfossFloorMinSetpoint, 2) / 100;
1078
+ if (value >= -273.15) {
1079
+ result[(0, utils_1.postfixWithEndpointName)("floor_min_setpoint", msg, model, meta)] = value;
1080
+ }
1081
+ }
1082
+ if (msg.data.danfossFloorMaxSetpoint !== undefined) {
1083
+ const value = (0, utils_1.precisionRound)(msg.data.danfossFloorMaxSetpoint, 2) / 100;
1084
+ if (value >= -273.15) {
1085
+ result[(0, utils_1.postfixWithEndpointName)("floor_max_setpoint", msg, model, meta)] = value;
1086
+ }
1087
+ }
1088
+ if (msg.data.danfossScheduleTypeUsed !== undefined) {
1089
+ result[(0, utils_1.postfixWithEndpointName)("schedule_type_used", msg, model, meta)] =
1090
+ constants.danfossScheduleTypeUsed[msg.data.danfossScheduleTypeUsed] !== undefined
1091
+ ? constants.danfossScheduleTypeUsed[msg.data.danfossScheduleTypeUsed]
1092
+ : msg.data.danfossScheduleTypeUsed;
1093
+ }
1094
+ if (msg.data.danfossIcon2PreHeat !== undefined) {
1095
+ result[(0, utils_1.postfixWithEndpointName)("icon2_pre_heat", msg, model, meta)] =
1096
+ constants.danfossIcon2PreHeat[msg.data.danfossIcon2PreHeat] !== undefined
1097
+ ? constants.danfossIcon2PreHeat[msg.data.danfossIcon2PreHeat]
1098
+ : msg.data.danfossIcon2PreHeat;
1099
+ }
1100
+ if (msg.data.danfossIcon2PreHeatStatus !== undefined) {
1101
+ result[(0, utils_1.postfixWithEndpointName)("icon2_pre_heat_status", msg, model, meta)] =
1102
+ constants.danfossIcon2PreHeatStatus[msg.data.danfossIcon2PreHeatStatus] !== undefined
1103
+ ? constants.danfossIcon2PreHeatStatus[msg.data.danfossIcon2PreHeatStatus]
1104
+ : msg.data.danfossIcon2PreHeatStatus;
1105
+ }
1106
+ return result;
1107
+ },
1108
+ },
1109
+ danfoss_icon_battery: {
1110
+ cluster: "genPowerCfg",
1111
+ type: ["attributeReport", "readResponse"],
1112
+ convert: (model, msg, publish, options, meta) => {
1113
+ const result = {};
1114
+ if (msg.data.batteryPercentageRemaining !== undefined) {
1115
+ // Some devices do not comply to the ZCL and report a
1116
+ // batteryPercentageRemaining of 100 when the battery is full (should be 200).
1117
+ const dontDividePercentage = model.meta?.battery?.dontDividePercentage;
1118
+ let percentage = msg.data.batteryPercentageRemaining;
1119
+ percentage = dontDividePercentage ? percentage : percentage / 2;
1120
+ result[(0, utils_1.postfixWithEndpointName)("battery", msg, model, meta)] = (0, utils_1.precisionRound)(percentage, 2);
1121
+ }
1122
+ return result;
1123
+ },
1124
+ },
1125
+ danfoss_icon_regulator: {
1126
+ cluster: "haDiagnostic",
1127
+ type: ["attributeReport", "readResponse"],
1128
+ convert: (model, msg, publish, options, meta) => {
1129
+ const result = {};
1130
+ if (msg.data.danfossSystemStatusCode !== undefined) {
1131
+ result[(0, utils_1.postfixWithEndpointName)("system_status_code", msg, model, meta)] =
1132
+ constants.danfossSystemStatusCode[msg.data.danfossSystemStatusCode] !== undefined
1133
+ ? constants.danfossSystemStatusCode[msg.data.danfossSystemStatusCode]
1134
+ : msg.data.danfossSystemStatusCode;
1135
+ }
1136
+ if (msg.data.danfossHeatSupplyRequest !== undefined) {
1137
+ result[(0, utils_1.postfixWithEndpointName)("heat_supply_request", msg, model, meta)] =
1138
+ constants.danfossHeatsupplyRequest[msg.data.danfossHeatSupplyRequest] !== undefined
1139
+ ? constants.danfossHeatsupplyRequest[msg.data.danfossHeatSupplyRequest]
1140
+ : msg.data.danfossHeatSupplyRequest;
1141
+ }
1142
+ if (msg.data.danfossSystemStatusWater !== undefined) {
1143
+ result[(0, utils_1.postfixWithEndpointName)("system_status_water", msg, model, meta)] =
1144
+ constants.danfossSystemStatusWater[msg.data.danfossSystemStatusWater] !== undefined
1145
+ ? constants.danfossSystemStatusWater[msg.data.danfossSystemStatusWater]
1146
+ : msg.data.danfossSystemStatusWater;
1147
+ }
1148
+ if (msg.data.danfossMultimasterRole !== undefined) {
1149
+ result[(0, utils_1.postfixWithEndpointName)("multimaster_role", msg, model, meta)] =
1150
+ constants.danfossMultimasterRole[msg.data.danfossMultimasterRole] !== undefined
1151
+ ? constants.danfossMultimasterRole[msg.data.danfossMultimasterRole]
1152
+ : msg.data.danfossMultimasterRole;
1153
+ }
1154
+ if (msg.data.danfossIconApplication !== undefined) {
1155
+ result[(0, utils_1.postfixWithEndpointName)("icon_application", msg, model, meta)] =
1156
+ constants.danfossIconApplication[msg.data.danfossIconApplication] !== undefined
1157
+ ? constants.danfossIconApplication[msg.data.danfossIconApplication]
1158
+ : msg.data.danfossIconApplication;
1159
+ }
1160
+ if (msg.data.danfossIconForcedHeatingCooling !== undefined) {
1161
+ result[(0, utils_1.postfixWithEndpointName)("icon_forced_heating_cooling", msg, model, meta)] =
1162
+ constants.danfossIconForcedHeatingCooling[msg.data.danfossIconForcedHeatingCooling] !== undefined
1163
+ ? constants.danfossIconForcedHeatingCooling[msg.data.danfossIconForcedHeatingCooling]
1164
+ : msg.data.danfossIconForcedHeatingCooling;
1165
+ }
1166
+ return result;
1167
+ },
1168
+ },
1169
+ danfoss_icon_hvac_user_interface: {
1170
+ cluster: "hvacUserInterfaceCfg",
1171
+ type: ["attributeReport", "readResponse"],
1172
+ convert: (model, msg, publish, options, meta) => {
1173
+ const result = {};
1174
+ if (msg.data.keypadLockout !== undefined) {
1175
+ result[(0, utils_1.postfixWithEndpointName)("keypad_lockout", msg, model, meta)] =
1176
+ constants.keypadLockoutMode[msg.data.keypadLockout] !== undefined
1177
+ ? constants.keypadLockoutMode[msg.data.keypadLockout]
1178
+ : msg.data.keypadLockout;
1179
+ }
1180
+ if (msg.data.tempDisplayMode !== undefined) {
1181
+ result[(0, utils_1.postfixWithEndpointName)("temperature_display_mode", msg, model, meta)] =
1182
+ constants.temperatureDisplayMode[msg.data.tempDisplayMode] !== undefined
1183
+ ? constants.temperatureDisplayMode[msg.data.tempDisplayMode]
1184
+ : msg.data.tempDisplayMode;
1185
+ }
1186
+ return result;
1187
+ },
1188
+ },
1189
+ danfoss_system_status_code: {
1190
+ cluster: "haDiagnostic",
1191
+ type: ["attributeReport", "readResponse"],
1192
+ convert: (model, msg, publish, options, meta) => {
1193
+ const result = {};
1194
+ if (msg.data.danfossSystemStatusCode !== undefined) {
1195
+ const code = msg.data.danfossSystemStatusCode;
1196
+ const errors = [];
1197
+ for (const [bit, name] of Object.entries(constants.danfossAllySystemStatusCode)) {
1198
+ if (code & (1 << Number(bit))) {
1199
+ errors.push(name);
1200
+ }
1201
+ }
1202
+ result.system_status_code = errors.length > 0 ? errors.join(",") : "ok";
1203
+ }
1204
+ return result;
1205
+ },
1206
+ },
53
1207
  };
54
1208
  exports.definitions = [
55
1209
  {
56
- // eTRV0100 is the same as Hive TRV001 and Popp eT093WRO. If implementing anything, please consider
57
- // changing those two too.
58
1210
  zigbeeModel: ["eTRV0100", "eTRV0101", "eTRV0103", "TRV001", "TRV003", "eT093WRO", "eT093WRG"],
59
1211
  model: "014G2461",
60
1212
  vendor: "Danfoss",
@@ -64,277 +1216,96 @@ exports.definitions = [
64
1216
  { vendor: "Hive", model: "UK7004240", description: "Radiator valve", fingerprint: [{ modelID: "TRV001" }, { modelID: "TRV003" }] },
65
1217
  { vendor: "Popp", model: "701721", description: "Smart thermostat", fingerprint: [{ modelID: "eT093WRO" }, { modelID: "eT093WRG" }] },
66
1218
  ],
1219
+ ota: true,
67
1220
  meta: { thermostat: { dontMapPIHeatingDemand: true } },
68
- fromZigbee: [
69
- fz.battery,
70
- fz.thermostat,
71
- fz.thermostat_weekly_schedule,
72
- fz.hvac_user_interface,
73
- fz.danfoss_thermostat,
74
- fz.danfoss_hvac_ui,
75
- fz.danfoss_thermostat_setpoint_scheduled,
1221
+ extend: [
1222
+ danfossExtend.addDanfossHvacThermostatCluster(),
1223
+ danfossExtend.addDanfossHvacUserInterfaceCfgCluster(),
1224
+ danfossExtend.addDanfossHaDiagnosticCluster(),
1225
+ danfossExtend.danfossThermostat({
1226
+ setpoints: { values: { occupiedHeatingSetpoint: { min: 5, max: 35, step: 0.5 } } },
1227
+ piHeatingDemand: { values: true },
1228
+ systemMode: { values: ["heat"] },
1229
+ programmingOperationMode: { values: ["setpoint", "schedule", "schedule_with_preheat", "eco"] },
1230
+ // weeklySchedule: {values: ["heat"]}, // gives an error in test:
1231
+ // test/checks.test.ts > Check definitions > respect snake case naming conventions for exposes and options
1232
+ // Error: Definitions not using snake case for expose/option:
1233
+ // Danfoss|014G2461|expose.name=transitionTime
1234
+ // Danfoss|014G2461|expose.name=heatSetpoint
1235
+ setpointsLimit: {
1236
+ maxHeatSetpointLimit: { min: 5, max: 35, step: 0.5 },
1237
+ },
1238
+ }),
1239
+ danfossExtend.absMaxHeatSetpointLimit({
1240
+ description: "Absolute Maximum Heating Setpoint Limit for the device. Adjust the 'Max heat setpoint limit' accordingly.",
1241
+ }),
1242
+ m.battery(),
1243
+ danfossExtend.keypadLockout(),
1244
+ danfossExtend.danfossMountedModeActive(),
1245
+ danfossExtend.danfossMountedModeControl(),
1246
+ danfossExtend.danfossThermostatOrientation(),
1247
+ danfossExtend.danfossViewingDirection(),
1248
+ danfossExtend.danfossHeatAvailable(),
1249
+ danfossExtend.danfossHeatRequired(),
1250
+ danfossExtend.setpointChangeSource(),
1251
+ danfossExtend.danfossExternalMeasuredRoomSensor(),
1252
+ danfossExtend.danfossRadiatorCovered(),
1253
+ danfossExtend.danfossWindowOpenFeatureEnable(),
1254
+ danfossExtend.danfossWindowOpenInternal(),
1255
+ danfossExtend.danfossWindowOpenExternal(),
1256
+ danfossExtend.danfossDayOfWeek(),
1257
+ danfossExtend.danfossTriggerTime2(),
1258
+ danfossExtend.danfossAlgorithmScaleFactor(),
1259
+ danfossExtend.danfossLoadBalancingEnable(),
1260
+ danfossExtend.danfossLoadRoomMean(),
1261
+ danfossExtend.danfossLoadEstimate(),
1262
+ danfossExtend.danfossPreheatStatus(),
1263
+ danfossExtend.danfossPreheatTime(),
1264
+ danfossExtend.danfossAdaptionRunStatus(),
1265
+ danfossExtend.danfossAdaptionRunSettings(),
1266
+ danfossExtend.danfossAdaptionRunControl(),
1267
+ danfossExtend.danfossRegulationSetpointOffset(),
1268
+ danfossExtend.danfossTimeSyncOnAnnounce(),
1269
+ m.poll({
1270
+ key: "danfossTime",
1271
+ defaultIntervalSeconds: 60 * 60 * 24,
1272
+ poll: async (device) => {
1273
+ await setTime(device, "queue");
1274
+ },
1275
+ }),
76
1276
  ],
1277
+ exposes: [
1278
+ e
1279
+ .text("system_status_code", ea.STATE_GET)
1280
+ .withDescription("Diagnostic error codes (e.g. 'invalid_clock_information,low_battery'). 'ok' when no errors.")
1281
+ .withCategory("diagnostic"),
1282
+ ],
1283
+ fromZigbee: [fz.thermostat_weekly_schedule, fzLocal.danfoss_system_status_code],
77
1284
  toZigbee: [
78
- tz.danfoss_thermostat_occupied_heating_setpoint,
79
- tz.thermostat_local_temperature,
80
- tz.danfoss_mounted_mode_active,
81
- tz.danfoss_mounted_mode_control,
82
- tz.danfoss_thermostat_vertical_orientation,
83
- tz.danfoss_algorithm_scale_factor,
84
- tz.danfoss_heat_available,
85
- tz.danfoss_heat_required,
86
- tz.danfoss_day_of_week,
87
- tz.danfoss_trigger_time,
88
- tz.danfoss_window_open_internal,
89
- tz.danfoss_window_open_external,
90
- tz.danfoss_load_estimate,
91
- tz.danfoss_viewing_direction,
92
- tz.danfoss_external_measured_room_sensor,
93
- tz.danfoss_radiator_covered,
94
- tz.thermostat_keypad_lockout,
95
- tz.thermostat_system_mode,
96
- tz.danfoss_load_balancing_enable,
97
- tz.danfoss_load_room_mean,
98
1285
  tz.thermostat_weekly_schedule,
99
1286
  tz.thermostat_clear_weekly_schedule,
100
- tz.thermostat_programming_operation_mode,
101
- tz.danfoss_window_open_feature,
102
- tz.danfoss_preheat_status,
103
- tz.danfoss_adaptation_status,
104
- tz.danfoss_adaptation_settings,
105
- tz.danfoss_adaptation_control,
106
- tz.danfoss_regulation_setpoint_offset,
107
- tz.danfoss_thermostat_occupied_heating_setpoint_scheduled,
1287
+ tzLocal.danfoss_system_status_code,
1288
+ tzLocal.danfoss_preheat_command,
108
1289
  ],
109
- exposes: (device, options) => {
110
- const maxSetpoint = !utils.isDummyDevice(device) && ["TRV001", "TRV003"].includes(device.modelID) ? 32 : 35;
111
- return [
112
- e.battery(),
113
- e.keypad_lockout(),
114
- e.programming_operation_mode(),
115
- e
116
- .binary("mounted_mode_active", ea.STATE_GET, true, false)
117
- .withDescription("Is the unit in mounting mode. This is set to `false` for mounted (already on " +
118
- "the radiator) or `true` for not mounted (after factory reset)"),
119
- e
120
- .binary("mounted_mode_control", ea.ALL, true, false)
121
- .withDescription("Set the unit mounting mode. `false` Go to Mounted Mode or `true` Go to Mounting Mode"),
122
- e
123
- .binary("thermostat_vertical_orientation", ea.ALL, true, false)
124
- .withDescription("Thermostat Orientation. This is important for the PID in how it assesses temperature. " +
125
- "`false` Horizontal or `true` Vertical"),
126
- e.binary("viewing_direction", ea.ALL, true, false).withDescription("Viewing/display direction, `false` normal or `true` upside-down"),
127
- e
128
- .binary("heat_available", ea.ALL, true, false)
129
- .withDescription("Not clear how this affects operation. However, it would appear that the device does not execute any " +
130
- "motor functions if this is set to false. This may be a means to conserve battery during periods that the heating " +
131
- "system is not energized (e.g. during summer). `false` No Heat Available or `true` Heat Available"),
132
- e
133
- .binary("heat_required", ea.STATE_GET, true, false)
134
- .withDescription("Whether or not the unit needs warm water. `false` No Heat Request or `true` Heat Request"),
135
- e
136
- .enum("setpoint_change_source", ea.STATE, ["manual", "schedule", "externally"])
137
- .withDescription("Values observed are `0` (manual), `1` (schedule) or `2` (externally)"),
138
- e
139
- .climate()
140
- .withSetpoint("occupied_heating_setpoint", 5, maxSetpoint, 0.5)
141
- .withLocalTemperature()
142
- .withPiHeatingDemand()
143
- .withSystemMode(["heat"])
144
- .withRunningState(["idle", "heat"], ea.STATE),
145
- e
146
- .numeric("occupied_heating_setpoint_scheduled", ea.ALL)
147
- .withValueMin(5)
148
- .withValueMax(maxSetpoint)
149
- .withValueStep(0.5)
150
- .withUnit("°C")
151
- .withDescription("Scheduled change of the setpoint. Alternative method for changing the setpoint. In the opposite " +
152
- "to occupied_heating_setpoint it does not trigger an aggressive response from the actuator. " +
153
- "(more suitable for scheduled changes)"),
154
- e
155
- .numeric("external_measured_room_sensor", ea.ALL)
156
- .withDescription("The temperature sensor of the TRV is — due to its design — relatively close to the heat source " +
157
- "(i.e. the hot water in the radiator). Thus there are situations where the `local_temperature` measured by the " +
158
- "TRV is not accurate enough: If the radiator is covered behind curtains or furniture, if the room is rather big, or " +
159
- "if the radiator itself is big and the flow temperature is high, then the temperature in the room may easily diverge " +
160
- "from the `local_temperature` measured by the TRV by 5°C to 8°C. In this case you might choose to use an external " +
161
- "room sensor and send the measured value of the external room sensor to the `External_measured_room_sensor` property. " +
162
- "The way the TRV operates on the `External_measured_room_sensor` depends on the setting of the `Radiator_covered` " +
163
- "property: If `Radiator_covered` is `false` (Auto Offset Mode): You *must* set the `External_measured_room_sensor` " +
164
- "property *at least* every 3 hours. After 3 hours the TRV disables this function and resets the value of the " +
165
- "`External_measured_room_sensor` property to -8000 (disabled). You *should* set the `External_measured_room_sensor` " +
166
- "property *at most* every 30 minutes or every 0.1°C change in measured room temperature. " +
167
- "If `Radiator_covered` is `true` (Room Sensor Mode): You *must* set the `External_measured_room_sensor` property *at " +
168
- "least* every 30 minutes. After 35 minutes the TRV disables this function and resets the value of the " +
169
- "`External_measured_room_sensor` property to -8000 (disabled). You *should* set the `External_measured_room_sensor` " +
170
- "property *at most* every 5 minutes or every 0.1°C change in measured room temperature. " +
171
- "The unit of this value is 0.01 `°C` (so e.g. 21°C would be represented as 2100).")
172
- .withValueMin(-8000)
173
- .withValueMax(3500),
174
- e
175
- .binary("radiator_covered", ea.ALL, true, false)
176
- .withDescription("Controls whether the TRV should solely rely on an external room sensor or operate in offset mode. " +
177
- "`false` = Auto Offset Mode (use this e.g. for exposed radiators) or `true` = Room Sensor Mode (use this e.g. for " +
178
- "covered radiators). Please note that this flag only controls how the TRV operates on the value of " +
179
- "`External_measured_room_sensor`; only setting this flag without setting the `External_measured_room_sensor` " +
180
- "has no (noticeable?) effect."),
181
- e.binary("window_open_feature", ea.ALL, true, false).withDescription("Whether or not the window open feature is enabled"),
182
- e
183
- .enum("window_open_internal", ea.STATE_GET, ["quarantine", "closed", "hold", "open", "external_open"])
184
- .withDescription("0=Quarantine, 1=Windows are closed, 2=Hold - Windows are maybe about to open, " +
185
- "3=Open window detected, 4=In window open state from external but detected closed locally"),
186
- e
187
- .binary("window_open_external", ea.ALL, true, false)
188
- .withDescription("Set if the window is open or close. This setting will trigger a change in the internal " +
189
- "window and heating demand. `false` (windows are closed) or `true` (windows are open)"),
190
- e
191
- .enum("day_of_week", ea.ALL, ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "away_or_vacation"])
192
- .withDescription("Exercise day of week: 0=Sun...6=Sat, 7=undefined"),
193
- e
194
- .numeric("trigger_time", ea.ALL)
195
- .withValueMin(0)
196
- .withValueMax(65535)
197
- .withDescription("Exercise trigger time. Minutes since midnight (65535=undefined). Range 0 to 1439"),
198
- e
199
- .numeric("algorithm_scale_factor", ea.ALL)
200
- .withValueMin(1)
201
- .withValueMax(10)
202
- .withDescription('Scale factor of setpoint filter timeconstant ("aggressiveness" of control algorithm) ' +
203
- "1= Quick ... 5=Moderate ... 10=Slow"),
204
- e
205
- .binary("load_balancing_enable", ea.ALL, true, false)
206
- .withDescription("Whether or not the thermostat acts as standalone thermostat or shares load with other " +
207
- "thermostats in the room. The gateway must update load_room_mean if enabled."),
208
- e
209
- .numeric("load_room_mean", ea.ALL)
210
- .withDescription("Mean radiator load for room calculated by gateway for load balancing purposes (-8000=undefined)")
211
- .withValueMin(-8000)
212
- .withValueMax(3600),
213
- e.numeric("load_estimate", ea.STATE_GET).withDescription("Load estimate on this radiator").withValueMin(-8000).withValueMax(3600),
214
- e.binary("preheat_status", ea.STATE_GET, true, false).withDescription("Specific for pre-heat running in Zigbee Weekly Schedule mode"),
215
- e
216
- .enum("adaptation_run_status", ea.STATE_GET, ["none", "in_progress", "found", "lost", "lost_in_progress"])
217
- .withDescription("Status of adaptation run: None (before first run), In Progress, Valve Characteristic Found, Valve Characteristic Lost"),
218
- e
219
- .binary("adaptation_run_settings", ea.ALL, true, false)
220
- .withDescription("Automatic adaptation run enabled (the one during the night)"),
221
- e
222
- .enum("adaptation_run_control", ea.ALL, ["none", "initiate_adaptation", "cancel_adaptation"])
223
- .withDescription("Adaptation run control: Initiate Adaptation Run or Cancel Adaptation Run"),
224
- e
225
- .numeric("regulation_setpoint_offset", ea.ALL)
226
- .withDescription("Regulation SetPoint Offset in range -2.5°C to 2.5°C in steps of 0.1°C. Value 2.5°C = 25.")
227
- .withValueMin(-25)
228
- .withValueMax(25),
229
- ];
230
- },
231
- ota: true,
232
1290
  configure: async (device, coordinatorEndpoint) => {
233
1291
  const endpoint = device.getEndpoint(1);
234
1292
  const options = { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S };
235
- await reporting.bind(endpoint, coordinatorEndpoint, ["genPowerCfg", "hvacThermostat"]);
236
- // standard ZCL attributes
237
- await reporting.batteryPercentageRemaining(endpoint);
238
- await reporting.thermostatTemperature(endpoint);
239
- await reporting.thermostatPIHeatingDemand(endpoint);
240
- await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
241
- // danfoss attributes
242
- await endpoint.configureReporting("hvacThermostat", [
243
- {
244
- attribute: "danfossMountedModeActive",
245
- minimumReportInterval: constants.repInterval.MINUTE,
246
- maximumReportInterval: constants.repInterval.MAX,
247
- reportableChange: 1,
248
- },
249
- ], options);
250
- await endpoint.configureReporting("hvacThermostat", [
251
- {
252
- attribute: "danfossWindowOpenInternal",
253
- minimumReportInterval: constants.repInterval.MINUTE,
254
- maximumReportInterval: constants.repInterval.HOUR,
255
- reportableChange: 1,
256
- },
257
- ], options);
258
- await endpoint.configureReporting("hvacThermostat", [
259
- {
260
- attribute: "danfossHeatRequired",
261
- minimumReportInterval: constants.repInterval.MINUTE,
262
- maximumReportInterval: constants.repInterval.HOUR,
263
- reportableChange: 1,
264
- },
265
- ], options);
266
- await endpoint.configureReporting("hvacThermostat", [
267
- {
268
- attribute: "danfossExternalMeasuredRoomSensor",
269
- minimumReportInterval: constants.repInterval.MINUTE,
270
- maximumReportInterval: constants.repInterval.MAX,
271
- reportableChange: 1,
272
- },
273
- ], options);
274
- await endpoint.configureReporting("hvacThermostat", [
1293
+ try {
1294
+ await reporting.bind(endpoint, coordinatorEndpoint, ["haDiagnostic"]);
1295
+ }
1296
+ catch {
1297
+ // Bind may fail if already bound (Danfoss rejects duplicate binds)
1298
+ }
1299
+ await endpoint.configureReporting("haDiagnostic", [
275
1300
  {
276
- attribute: "danfossAdaptionRunStatus",
277
- minimumReportInterval: constants.repInterval.MINUTE,
1301
+ attribute: "danfossSystemStatusCode",
1302
+ minimumReportInterval: 0,
278
1303
  maximumReportInterval: constants.repInterval.HOUR,
279
1304
  reportableChange: 1,
280
1305
  },
281
1306
  ], options);
282
- try {
283
- await endpoint.configureReporting("hvacThermostat", [
284
- {
285
- attribute: "danfossPreheatStatus",
286
- minimumReportInterval: constants.repInterval.MINUTE,
287
- maximumReportInterval: constants.repInterval.MAX,
288
- reportableChange: 1,
289
- },
290
- ], options);
291
- }
292
- catch {
293
- /* not supported by all */
294
- }
295
- try {
296
- await endpoint.read("hvacThermostat", [
297
- "danfossWindowOpenFeatureEnable",
298
- "danfossWindowOpenExternal",
299
- "danfossDayOfWeek",
300
- "danfossTriggerTime",
301
- "danfossAlgorithmScaleFactor",
302
- "danfossHeatAvailable",
303
- "danfossMountedModeControl",
304
- "danfossMountedModeActive",
305
- "danfossExternalMeasuredRoomSensor",
306
- "danfossRadiatorCovered",
307
- "danfossLoadBalancingEnable",
308
- "danfossLoadRoomMean",
309
- "danfossAdaptionRunControl",
310
- "danfossAdaptionRunSettings",
311
- "danfossRegulationSetpointOffset",
312
- ], options);
313
- }
314
- catch {
315
- /* not supported by all https://github.com/Koenkk/zigbee2mqtt/issues/11872 */
316
- }
317
- // read systemMode to have an initial value
318
- await endpoint.read("hvacThermostat", ["systemMode"]);
319
- // read keypadLockout, we don't need reporting as it cannot be set physically on the device
320
- await endpoint.read("hvacUserInterfaceCfg", ["keypadLockout"]);
321
- // Seems that it is bug in Danfoss, device does not asks for the time with binding
322
- // So, we need to write time during configure (same as for HEIMAN devices)
323
- await setTime(device);
1307
+ await endpoint.read("haDiagnostic", ["danfossSystemStatusCode"], options);
324
1308
  },
325
- extend: [
326
- m.poll({
327
- key: "time_sync",
328
- defaultIntervalSeconds: 60 * 60 * 24,
329
- poll: async (device) => {
330
- // The device might have lost its time, so reset it. It would be more proper to check if
331
- // the danfossSystemStatusCode has bit 10 of the SW error code attribute (0x4000) in the
332
- // diagnostics cluster (0x0b05) is set to indicate time lost, but setting it once too many
333
- // times shouldn't hurt.
334
- await setTime(device);
335
- },
336
- }),
337
- ],
338
1309
  },
339
1310
  {
340
1311
  fingerprint: [
@@ -349,13 +1320,14 @@ exports.definitions = [
349
1320
  model: "Icon",
350
1321
  vendor: "Danfoss",
351
1322
  description: "Icon Main Controller with Zigbee Module, Room Thermostat",
1323
+ extend: [danfossExtend.addDanfossHvacThermostatCluster(), danfossExtend.addDanfossHaDiagnosticCluster()],
352
1324
  fromZigbee: [
353
- fz.danfoss_icon_battery,
1325
+ fzLocal.danfoss_icon_battery,
354
1326
  fz.thermostat,
355
- fz.danfoss_thermostat,
356
- fz.danfoss_hvac_ui,
357
- fz.danfoss_icon_regulator,
358
- fz.danfoss_icon_floor_sensor,
1327
+ fzLocal.danfoss_thermostat,
1328
+ fzLocal.danfoss_hvac_ui,
1329
+ fzLocal.danfoss_icon_regulator,
1330
+ fzLocal.danfoss_icon_floor_sensor,
359
1331
  fz.temperature,
360
1332
  ],
361
1333
  toZigbee: [
@@ -364,15 +1336,15 @@ exports.definitions = [
364
1336
  tz.thermostat_min_heat_setpoint_limit,
365
1337
  tz.thermostat_max_heat_setpoint_limit,
366
1338
  tz.thermostat_system_mode,
367
- tz.danfoss_room_status_code,
368
- tz.danfoss_output_status,
369
- tz.danfoss_floor_sensor_mode,
370
- tz.danfoss_floor_min_setpoint,
371
- tz.danfoss_floor_max_setpoint,
1339
+ tzLocal.danfoss_room_status_code,
1340
+ tzLocal.danfoss_output_status,
1341
+ tzLocal.danfoss_floor_sensor_mode,
1342
+ tzLocal.danfoss_floor_min_setpoint,
1343
+ tzLocal.danfoss_floor_max_setpoint,
372
1344
  tz.temperature,
373
- tz.danfoss_system_status_code,
374
- tz.danfoss_system_status_water,
375
- tz.danfoss_multimaster_role,
1345
+ tzLocal.danfoss_system_status_code,
1346
+ tzLocal.danfoss_system_status_water,
1347
+ tzLocal.danfoss_multimaster_role,
376
1348
  ],
377
1349
  meta: { multiEndpoint: true, thermostat: { dontMapPIHeatingDemand: true } },
378
1350
  endpoint: (device) => {
@@ -551,16 +1523,18 @@ exports.definitions = [
551
1523
  model: "Icon2",
552
1524
  vendor: "Danfoss",
553
1525
  description: "Icon2 Main Controller, Room Thermostat or Sensor",
1526
+ ota: true,
1527
+ extend: [danfossExtend.addDanfossHvacThermostatCluster(), danfossExtend.addDanfossHaDiagnosticCluster()],
554
1528
  fromZigbee: [
555
- fz.danfoss_icon_battery,
1529
+ fzLocal.danfoss_icon_battery,
556
1530
  fz.thermostat,
557
- fz.danfoss_thermostat,
558
- fz.danfoss_hvac_ui,
559
- fz.danfoss_icon_floor_sensor,
560
- fz.danfoss_icon_hvac_user_interface,
1531
+ fzLocal.danfoss_thermostat,
1532
+ fzLocal.danfoss_hvac_ui,
1533
+ fzLocal.danfoss_icon_floor_sensor,
1534
+ fzLocal.danfoss_icon_hvac_user_interface,
561
1535
  fz.temperature,
562
1536
  fz.humidity,
563
- fz.danfoss_icon_regulator,
1537
+ fzLocal.danfoss_icon_regulator,
564
1538
  ],
565
1539
  toZigbee: [
566
1540
  tz.thermostat_local_temperature,
@@ -568,23 +1542,23 @@ exports.definitions = [
568
1542
  tz.thermostat_min_heat_setpoint_limit,
569
1543
  tz.thermostat_max_heat_setpoint_limit,
570
1544
  tz.thermostat_system_mode,
571
- tz.danfoss_room_status_code,
572
- tz.danfoss_output_status,
573
- tz.danfoss_floor_sensor_mode,
574
- tz.danfoss_floor_min_setpoint,
575
- tz.danfoss_floor_max_setpoint,
576
- tz.danfoss_schedule_type_used,
577
- tz.danfoss_icon2_pre_heat,
578
- tz.danfoss_icon2_pre_heat_status,
1545
+ tzLocal.danfoss_room_status_code,
1546
+ tzLocal.danfoss_output_status,
1547
+ tzLocal.danfoss_floor_sensor_mode,
1548
+ tzLocal.danfoss_floor_min_setpoint,
1549
+ tzLocal.danfoss_floor_max_setpoint,
1550
+ tzLocal.danfoss_schedule_type_used,
1551
+ tzLocal.danfoss_icon2_pre_heat,
1552
+ tzLocal.danfoss_icon2_pre_heat_status,
579
1553
  tz.thermostat_keypad_lockout,
580
1554
  tz.temperature,
581
1555
  tz.humidity,
582
- tz.danfoss_system_status_code,
583
- tz.danfoss_heat_supply_request,
584
- tz.danfoss_system_status_water,
585
- tz.danfoss_multimaster_role,
586
- tz.danfoss_icon_application,
587
- tz.danfoss_icon_forced_heating_cooling,
1556
+ tzLocal.danfoss_system_status_code,
1557
+ tzLocal.danfoss_heat_supply_request,
1558
+ tzLocal.danfoss_system_status_water,
1559
+ tzLocal.danfoss_multimaster_role,
1560
+ tzLocal.danfoss_icon_application,
1561
+ tzLocal.danfoss_icon_forced_heating_cooling,
588
1562
  ],
589
1563
  meta: { multiEndpoint: true, thermostat: { dontMapPIHeatingDemand: true } },
590
1564
  exposes: [].concat(((endpointsCount) => {