node-red-contrib-knx-ultimate 7.1.4 → 8.0.2

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 (657) hide show
  1. package/CHANGELOG.md +20 -10
  2. package/MIGRATION.md +40 -0
  3. package/README.md +32 -6
  4. package/docs/README.md +34 -0
  5. package/docs/assets/brand/made-in-italy.svg +12 -0
  6. package/examples/Alerter - Device Alert Aggregation.json +5 -2
  7. package/examples/Auto Responder - Read Request Defaults.json +5 -2
  8. package/examples/Garage - Door Controller.json +5 -2
  9. package/examples/Global Context - Expose KNX Values.json +5 -2
  10. package/examples/KNX DateTime - Set Date and Time to Bus.json +111 -89
  11. package/examples/Load Control - Manual Shedding Mode.json +5 -2
  12. package/examples/Logger ETS File and Telegram Count.json +10 -2
  13. package/examples/Scene Controller Recall and Save.json +33 -6
  14. package/examples/Staircase - Timer, Override and Block.json +5 -2
  15. package/examples/WatchDog Connect Disconnect.json +98 -70
  16. package/nodes/commonFunctions.js +0 -587
  17. package/nodes/knxUltimate-config.html +0 -14
  18. package/nodes/knxUltimate-config.js +1 -18
  19. package/nodes/knxUltimate.html +1 -6
  20. package/nodes/knxUltimateIoTBridge.html +0 -14
  21. package/nodes/knxUltimateLegacyMigration.js +75 -0
  22. package/nodes/knxUltimateMultiRouting.html +1 -7
  23. package/nodes/knxUltimateRouterFilter.html +1 -7
  24. package/nodes/knxUltimateUtility.html +0 -6
  25. package/nodes/knxUltimateViewer.html +0 -6
  26. package/nodes/locales/de/knxUltimate-config.html +0 -8
  27. package/nodes/locales/de/knxUltimate.html +0 -8
  28. package/nodes/locales/de/knxUltimateIoTBridge.html +0 -8
  29. package/nodes/locales/de/knxUltimateMultiRouting.html +0 -8
  30. package/nodes/locales/de/knxUltimateRouterFilter.html +0 -8
  31. package/nodes/locales/de/knxUltimateUtility.html +0 -8
  32. package/nodes/locales/de/knxUltimateUtility.json +16 -1
  33. package/nodes/locales/de/knxUltimateViewer.html +0 -8
  34. package/nodes/locales/en/knxUltimate-config.html +0 -8
  35. package/nodes/locales/en/knxUltimate.html +0 -8
  36. package/nodes/locales/en/knxUltimateIoTBridge.html +0 -8
  37. package/nodes/locales/en/knxUltimateMultiRouting.html +0 -8
  38. package/nodes/locales/en/knxUltimateRouterFilter.html +0 -8
  39. package/nodes/locales/en/knxUltimateUtility.html +0 -8
  40. package/nodes/locales/en/knxUltimateUtility.json +16 -1
  41. package/nodes/locales/en/knxUltimateViewer.html +0 -8
  42. package/nodes/locales/es/knxUltimate-config.html +0 -8
  43. package/nodes/locales/es/knxUltimate.html +0 -8
  44. package/nodes/locales/es/knxUltimateIoTBridge.html +0 -8
  45. package/nodes/locales/es/knxUltimateMultiRouting.html +0 -8
  46. package/nodes/locales/es/knxUltimateRouterFilter.html +0 -8
  47. package/nodes/locales/es/knxUltimateUtility.html +0 -8
  48. package/nodes/locales/es/knxUltimateUtility.json +17 -2
  49. package/nodes/locales/es/knxUltimateViewer.html +0 -8
  50. package/nodes/locales/fr/knxUltimate-config.html +0 -8
  51. package/nodes/locales/fr/knxUltimate.html +0 -8
  52. package/nodes/locales/fr/knxUltimateIoTBridge.html +0 -8
  53. package/nodes/locales/fr/knxUltimateMultiRouting.html +0 -8
  54. package/nodes/locales/fr/knxUltimateRouterFilter.html +0 -8
  55. package/nodes/locales/fr/knxUltimateUtility.html +0 -8
  56. package/nodes/locales/fr/knxUltimateUtility.json +16 -1
  57. package/nodes/locales/fr/knxUltimateViewer.html +0 -8
  58. package/nodes/locales/it/knxUltimate-config.html +0 -8
  59. package/nodes/locales/it/knxUltimate.html +0 -8
  60. package/nodes/locales/it/knxUltimateIoTBridge.html +0 -8
  61. package/nodes/locales/it/knxUltimateMultiRouting.html +0 -8
  62. package/nodes/locales/it/knxUltimateRouterFilter.html +0 -8
  63. package/nodes/locales/it/knxUltimateUtility.html +0 -8
  64. package/nodes/locales/it/knxUltimateUtility.json +16 -1
  65. package/nodes/locales/it/knxUltimateViewer.html +0 -8
  66. package/nodes/locales/zh-CN/knxUltimate-config.html +0 -8
  67. package/nodes/locales/zh-CN/knxUltimate.html +0 -8
  68. package/nodes/locales/zh-CN/knxUltimateIoTBridge.html +0 -8
  69. package/nodes/locales/zh-CN/knxUltimateMultiRouting.html +0 -8
  70. package/nodes/locales/zh-CN/knxUltimateRouterFilter.html +0 -8
  71. package/nodes/locales/zh-CN/knxUltimateUtility.html +0 -8
  72. package/nodes/locales/zh-CN/knxUltimateUtility.json +16 -1
  73. package/nodes/locales/zh-CN/knxUltimateViewer.html +0 -8
  74. package/nodes/plugins/knxUltimate-v8-migration-recovery-plugin.html +140 -0
  75. package/package.json +22 -69
  76. package/resources/11f26b4500.js +2 -2
  77. package/resources/KNXAIChatAdapterMappings.js +2 -416
  78. package/resources/configNodeEditorSelection.js +2 -32
  79. package/resources/hueControllerEditorSelection.js +2 -32
  80. package/resources/hueControllerMigrationDialog.js +2 -254
  81. package/resources/hueControllerProfiles.js +2 -9319
  82. package/resources/knxUtilityProfiles.js +2041 -2082
  83. package/resources/legacyMigrationNotice.js +23 -111
  84. package/resources/matterQrScanner.js +2 -98
  85. package/resources/upgradeToV8.js +94 -26
  86. package/scripts/check-legacy-flows.js +142 -0
  87. package/examples/Hue Area Motion - Zone Presence.json +0 -77
  88. package/examples/Hue Battery - Level Status.json +0 -77
  89. package/examples/Hue Button - Short and Dim Commands.json +0 -83
  90. package/examples/Hue Camera Motion - Presence.json +0 -77
  91. package/examples/Hue Config - Bridge Template.json +0 -27
  92. package/examples/Hue Contact Sensor - Open Closed.json +0 -75
  93. package/examples/Hue Device Software Update - Availability.json +0 -77
  94. package/examples/Hue Humidity Sensor - Relative Humidity.json +0 -77
  95. package/examples/Hue Light - Switch and Brightness.json +0 -67
  96. package/examples/Hue Light Sensor - Lux to KNX.json +0 -77
  97. package/examples/Hue Motion - Presence Sensor.json +0 -76
  98. package/examples/Hue Plug - Switch and State.json +0 -63
  99. package/examples/Hue Scene - Recall from KNX.json +0 -63
  100. package/examples/Hue Tap Dial - Relative Dimming.json +0 -76
  101. package/examples/Hue Temperature Sensor - Celsius to KNX.json +0 -77
  102. package/examples/Hue Zigbee Connectivity - Online Status.json +0 -77
  103. package/examples/Matter Controller - Semantic Flow Input.json +0 -248
  104. package/nodes/hue-config.html +0 -378
  105. package/nodes/hue-config.js +0 -846
  106. package/nodes/icons/node-alerter-icon.png +0 -0
  107. package/nodes/icons/node-homekit-icon.png +0 -0
  108. package/nodes/icons/node-homekit-icon.svg +0 -10
  109. package/nodes/icons/node-hue-icon.svg +0 -10
  110. package/nodes/icons/node-knx-icon.png +0 -0
  111. package/nodes/icons/node-logger-icon.png +0 -0
  112. package/nodes/icons/node-logger2-icon.png +0 -0
  113. package/nodes/icons/node-logger2-icon.svg +0 -32
  114. package/nodes/icons/node-matter-bridge-icon.svg +0 -6
  115. package/nodes/icons/node-matter-controller-icon.svg +0 -6
  116. package/nodes/icons/node-matter-icon.svg +0 -12
  117. package/nodes/icons/node-scene-icon.png +0 -0
  118. package/nodes/icons/node-watchdog-icon.png +0 -0
  119. package/nodes/knxUltimateAI.html +0 -1826
  120. package/nodes/knxUltimateAI.js +0 -16797
  121. package/nodes/knxUltimateAIHomeAssistant.html +0 -54
  122. package/nodes/knxUltimateAIHomeAssistant.js +0 -152
  123. package/nodes/knxUltimateAlerter.html +0 -267
  124. package/nodes/knxUltimateAlerter.js +0 -300
  125. package/nodes/knxUltimateAutoResponder.html +0 -128
  126. package/nodes/knxUltimateAutoResponder.js +0 -264
  127. package/nodes/knxUltimateDateTime.html +0 -579
  128. package/nodes/knxUltimateDateTime.js +0 -282
  129. package/nodes/knxUltimateGarage.html +0 -337
  130. package/nodes/knxUltimateGarage.js +0 -504
  131. package/nodes/knxUltimateGlobalContext.html +0 -145
  132. package/nodes/knxUltimateGlobalContext.js +0 -208
  133. package/nodes/knxUltimateHATranslator.html +0 -85
  134. package/nodes/knxUltimateHATranslator.js +0 -83
  135. package/nodes/knxUltimateHueAreaMotion.html +0 -670
  136. package/nodes/knxUltimateHueAreaMotion.js +0 -218
  137. package/nodes/knxUltimateHueBattery.html +0 -646
  138. package/nodes/knxUltimateHueBattery.js +0 -182
  139. package/nodes/knxUltimateHueButton.html +0 -804
  140. package/nodes/knxUltimateHueButton.js +0 -292
  141. package/nodes/knxUltimateHueCameraMotion.html +0 -671
  142. package/nodes/knxUltimateHueCameraMotion.js +0 -218
  143. package/nodes/knxUltimateHueContactSensor.html +0 -609
  144. package/nodes/knxUltimateHueContactSensor.js +0 -188
  145. package/nodes/knxUltimateHueController.html +0 -1765
  146. package/nodes/knxUltimateHueController.js +0 -28
  147. package/nodes/knxUltimateHueHumiditySensor.html +0 -641
  148. package/nodes/knxUltimateHueHumiditySensor.js +0 -201
  149. package/nodes/knxUltimateHueLight.html +0 -2516
  150. package/nodes/knxUltimateHueLight.js +0 -1582
  151. package/nodes/knxUltimateHueLightSensor.html +0 -636
  152. package/nodes/knxUltimateHueLightSensor.js +0 -177
  153. package/nodes/knxUltimateHueMotion.html +0 -634
  154. package/nodes/knxUltimateHueMotion.js +0 -182
  155. package/nodes/knxUltimateHuePlug.html +0 -576
  156. package/nodes/knxUltimateHuePlug.js +0 -341
  157. package/nodes/knxUltimateHueScene.html +0 -967
  158. package/nodes/knxUltimateHueScene.js +0 -349
  159. package/nodes/knxUltimateHueTapDial.html +0 -640
  160. package/nodes/knxUltimateHueTapDial.js +0 -268
  161. package/nodes/knxUltimateHueTemperatureSensor.html +0 -639
  162. package/nodes/knxUltimateHueTemperatureSensor.js +0 -184
  163. package/nodes/knxUltimateHueZigbeeConnectivity.html +0 -648
  164. package/nodes/knxUltimateHueZigbeeConnectivity.js +0 -182
  165. package/nodes/knxUltimateHuedevice_software_update.html +0 -650
  166. package/nodes/knxUltimateHuedevice_software_update.js +0 -182
  167. package/nodes/knxUltimateLoadControl.html +0 -425
  168. package/nodes/knxUltimateLoadControl.js +0 -443
  169. package/nodes/knxUltimateLogger.html +0 -197
  170. package/nodes/knxUltimateLogger.js +0 -224
  171. package/nodes/knxUltimateMatterBridge.html +0 -689
  172. package/nodes/knxUltimateMatterBridge.js +0 -464
  173. package/nodes/knxUltimateMatterControllerDevice.html +0 -2851
  174. package/nodes/knxUltimateMatterControllerDevice.js +0 -1747
  175. package/nodes/knxUltimateSceneController.html +0 -529
  176. package/nodes/knxUltimateSceneController.js +0 -437
  177. package/nodes/knxUltimateStaircase.html +0 -346
  178. package/nodes/knxUltimateStaircase.js +0 -463
  179. package/nodes/knxUltimateWatchDog.html +0 -241
  180. package/nodes/knxUltimateWatchDog.js +0 -230
  181. package/nodes/locales/de/hue-config.html +0 -33
  182. package/nodes/locales/de/hue-config.json +0 -21
  183. package/nodes/locales/de/knxUltimateAI.html +0 -13
  184. package/nodes/locales/de/knxUltimateAI.json +0 -231
  185. package/nodes/locales/de/knxUltimateAIHomeAssistant.html +0 -11
  186. package/nodes/locales/de/knxUltimateAlerter.html +0 -159
  187. package/nodes/locales/de/knxUltimateAlerter.json +0 -27
  188. package/nodes/locales/de/knxUltimateAutoResponder.html +0 -96
  189. package/nodes/locales/de/knxUltimateAutoResponder.json +0 -8
  190. package/nodes/locales/de/knxUltimateDateTime.html +0 -45
  191. package/nodes/locales/de/knxUltimateDateTime.json +0 -32
  192. package/nodes/locales/de/knxUltimateGarage.html +0 -79
  193. package/nodes/locales/de/knxUltimateGarage.json +0 -51
  194. package/nodes/locales/de/knxUltimateGlobalContext.html +0 -76
  195. package/nodes/locales/de/knxUltimateGlobalContext.json +0 -24
  196. package/nodes/locales/de/knxUltimateHATranslator.html +0 -25
  197. package/nodes/locales/de/knxUltimateHATranslator.json +0 -8
  198. package/nodes/locales/de/knxUltimateHueAreaMotion.html +0 -44
  199. package/nodes/locales/de/knxUltimateHueAreaMotion.json +0 -31
  200. package/nodes/locales/de/knxUltimateHueBattery.html +0 -37
  201. package/nodes/locales/de/knxUltimateHueBattery.json +0 -30
  202. package/nodes/locales/de/knxUltimateHueButton.html +0 -52
  203. package/nodes/locales/de/knxUltimateHueButton.json +0 -34
  204. package/nodes/locales/de/knxUltimateHueCameraMotion.html +0 -38
  205. package/nodes/locales/de/knxUltimateHueCameraMotion.json +0 -30
  206. package/nodes/locales/de/knxUltimateHueContactSensor.html +0 -35
  207. package/nodes/locales/de/knxUltimateHueContactSensor.json +0 -26
  208. package/nodes/locales/de/knxUltimateHueController.html +0 -690
  209. package/nodes/locales/de/knxUltimateHueController.json +0 -64
  210. package/nodes/locales/de/knxUltimateHueHumiditySensor.html +0 -38
  211. package/nodes/locales/de/knxUltimateHueHumiditySensor.json +0 -30
  212. package/nodes/locales/de/knxUltimateHueLight.html +0 -121
  213. package/nodes/locales/de/knxUltimateHueLight.json +0 -94
  214. package/nodes/locales/de/knxUltimateHueLightSensor.html +0 -38
  215. package/nodes/locales/de/knxUltimateHueLightSensor.json +0 -19
  216. package/nodes/locales/de/knxUltimateHueMotion.html +0 -41
  217. package/nodes/locales/de/knxUltimateHueMotion.json +0 -27
  218. package/nodes/locales/de/knxUltimateHuePlug.html +0 -50
  219. package/nodes/locales/de/knxUltimateHuePlug.json +0 -33
  220. package/nodes/locales/de/knxUltimateHueScene.html +0 -45
  221. package/nodes/locales/de/knxUltimateHueScene.json +0 -41
  222. package/nodes/locales/de/knxUltimateHueTapDial.html +0 -40
  223. package/nodes/locales/de/knxUltimateHueTapDial.json +0 -28
  224. package/nodes/locales/de/knxUltimateHueTemperatureSensor.html +0 -38
  225. package/nodes/locales/de/knxUltimateHueTemperatureSensor.json +0 -30
  226. package/nodes/locales/de/knxUltimateHueZigbeeConnectivity.html +0 -39
  227. package/nodes/locales/de/knxUltimateHueZigbeeConnectivity.json +0 -30
  228. package/nodes/locales/de/knxUltimateHuedevice_software_update.html +0 -36
  229. package/nodes/locales/de/knxUltimateHuedevice_software_update.json +0 -30
  230. package/nodes/locales/de/knxUltimateLoadControl.html +0 -69
  231. package/nodes/locales/de/knxUltimateLoadControl.json +0 -28
  232. package/nodes/locales/de/knxUltimateLogger.html +0 -126
  233. package/nodes/locales/de/knxUltimateLogger.json +0 -31
  234. package/nodes/locales/de/knxUltimateMatterBridge.html +0 -65
  235. package/nodes/locales/de/knxUltimateMatterBridge.json +0 -123
  236. package/nodes/locales/de/knxUltimateMatterControllerDevice.html +0 -57
  237. package/nodes/locales/de/knxUltimateMatterControllerDevice.json +0 -146
  238. package/nodes/locales/de/knxUltimateSceneController.html +0 -98
  239. package/nodes/locales/de/knxUltimateSceneController.json +0 -32
  240. package/nodes/locales/de/knxUltimateStaircase.html +0 -77
  241. package/nodes/locales/de/knxUltimateStaircase.json +0 -62
  242. package/nodes/locales/de/knxUltimateWatchDog.html +0 -178
  243. package/nodes/locales/de/knxUltimateWatchDog.json +0 -27
  244. package/nodes/locales/de/matter-config.html +0 -47
  245. package/nodes/locales/de/matter-config.json +0 -47
  246. package/nodes/locales/de/matterbridge-config.html +0 -45
  247. package/nodes/locales/de/matterbridge-config.json +0 -25
  248. package/nodes/locales/en/hue-config.html +0 -31
  249. package/nodes/locales/en/hue-config.json +0 -21
  250. package/nodes/locales/en/knxUltimateAI.html +0 -13
  251. package/nodes/locales/en/knxUltimateAI.json +0 -234
  252. package/nodes/locales/en/knxUltimateAIHomeAssistant.html +0 -11
  253. package/nodes/locales/en/knxUltimateAlerter.html +0 -164
  254. package/nodes/locales/en/knxUltimateAlerter.json +0 -27
  255. package/nodes/locales/en/knxUltimateAutoResponder.html +0 -94
  256. package/nodes/locales/en/knxUltimateAutoResponder.json +0 -8
  257. package/nodes/locales/en/knxUltimateDateTime.html +0 -67
  258. package/nodes/locales/en/knxUltimateDateTime.json +0 -32
  259. package/nodes/locales/en/knxUltimateGarage.html +0 -79
  260. package/nodes/locales/en/knxUltimateGarage.json +0 -51
  261. package/nodes/locales/en/knxUltimateGlobalContext.html +0 -124
  262. package/nodes/locales/en/knxUltimateGlobalContext.json +0 -24
  263. package/nodes/locales/en/knxUltimateHATranslator.html +0 -25
  264. package/nodes/locales/en/knxUltimateHATranslator.json +0 -8
  265. package/nodes/locales/en/knxUltimateHueAreaMotion.html +0 -44
  266. package/nodes/locales/en/knxUltimateHueAreaMotion.json +0 -31
  267. package/nodes/locales/en/knxUltimateHueBattery.html +0 -37
  268. package/nodes/locales/en/knxUltimateHueBattery.json +0 -30
  269. package/nodes/locales/en/knxUltimateHueButton.html +0 -52
  270. package/nodes/locales/en/knxUltimateHueButton.json +0 -34
  271. package/nodes/locales/en/knxUltimateHueCameraMotion.html +0 -38
  272. package/nodes/locales/en/knxUltimateHueCameraMotion.json +0 -30
  273. package/nodes/locales/en/knxUltimateHueContactSensor.html +0 -35
  274. package/nodes/locales/en/knxUltimateHueContactSensor.json +0 -26
  275. package/nodes/locales/en/knxUltimateHueController.html +0 -691
  276. package/nodes/locales/en/knxUltimateHueController.json +0 -64
  277. package/nodes/locales/en/knxUltimateHueHumiditySensor.html +0 -38
  278. package/nodes/locales/en/knxUltimateHueHumiditySensor.json +0 -30
  279. package/nodes/locales/en/knxUltimateHueLight.html +0 -124
  280. package/nodes/locales/en/knxUltimateHueLight.json +0 -94
  281. package/nodes/locales/en/knxUltimateHueLightSensor.html +0 -38
  282. package/nodes/locales/en/knxUltimateHueLightSensor.json +0 -19
  283. package/nodes/locales/en/knxUltimateHueMotion.html +0 -41
  284. package/nodes/locales/en/knxUltimateHueMotion.json +0 -27
  285. package/nodes/locales/en/knxUltimateHuePlug.html +0 -50
  286. package/nodes/locales/en/knxUltimateHuePlug.json +0 -33
  287. package/nodes/locales/en/knxUltimateHueScene.html +0 -45
  288. package/nodes/locales/en/knxUltimateHueScene.json +0 -41
  289. package/nodes/locales/en/knxUltimateHueTapDial.html +0 -40
  290. package/nodes/locales/en/knxUltimateHueTapDial.json +0 -28
  291. package/nodes/locales/en/knxUltimateHueTemperatureSensor.html +0 -38
  292. package/nodes/locales/en/knxUltimateHueTemperatureSensor.json +0 -30
  293. package/nodes/locales/en/knxUltimateHueZigbeeConnectivity.html +0 -39
  294. package/nodes/locales/en/knxUltimateHueZigbeeConnectivity.json +0 -30
  295. package/nodes/locales/en/knxUltimateHuedevice_software_update.html +0 -36
  296. package/nodes/locales/en/knxUltimateHuedevice_software_update.json +0 -30
  297. package/nodes/locales/en/knxUltimateLoadControl.html +0 -76
  298. package/nodes/locales/en/knxUltimateLoadControl.json +0 -28
  299. package/nodes/locales/en/knxUltimateLogger.html +0 -161
  300. package/nodes/locales/en/knxUltimateLogger.json +0 -31
  301. package/nodes/locales/en/knxUltimateMatterBridge.html +0 -65
  302. package/nodes/locales/en/knxUltimateMatterBridge.json +0 -123
  303. package/nodes/locales/en/knxUltimateMatterControllerDevice.html +0 -57
  304. package/nodes/locales/en/knxUltimateMatterControllerDevice.json +0 -146
  305. package/nodes/locales/en/knxUltimateSceneController.html +0 -117
  306. package/nodes/locales/en/knxUltimateSceneController.json +0 -32
  307. package/nodes/locales/en/knxUltimateStaircase.html +0 -77
  308. package/nodes/locales/en/knxUltimateStaircase.json +0 -62
  309. package/nodes/locales/en/knxUltimateWatchDog.html +0 -244
  310. package/nodes/locales/en/knxUltimateWatchDog.json +0 -27
  311. package/nodes/locales/en/matter-config.html +0 -47
  312. package/nodes/locales/en/matter-config.json +0 -48
  313. package/nodes/locales/en/matterbridge-config.html +0 -45
  314. package/nodes/locales/en/matterbridge-config.json +0 -25
  315. package/nodes/locales/es/hue-config.html +0 -31
  316. package/nodes/locales/es/hue-config.json +0 -21
  317. package/nodes/locales/es/knxUltimateAI.html +0 -13
  318. package/nodes/locales/es/knxUltimateAI.json +0 -231
  319. package/nodes/locales/es/knxUltimateAIHomeAssistant.html +0 -11
  320. package/nodes/locales/es/knxUltimateAlerter.html +0 -164
  321. package/nodes/locales/es/knxUltimateAlerter.json +0 -27
  322. package/nodes/locales/es/knxUltimateAutoResponder.html +0 -81
  323. package/nodes/locales/es/knxUltimateAutoResponder.json +0 -8
  324. package/nodes/locales/es/knxUltimateDateTime.html +0 -45
  325. package/nodes/locales/es/knxUltimateDateTime.json +0 -32
  326. package/nodes/locales/es/knxUltimateGarage.html +0 -79
  327. package/nodes/locales/es/knxUltimateGarage.json +0 -51
  328. package/nodes/locales/es/knxUltimateGlobalContext.html +0 -128
  329. package/nodes/locales/es/knxUltimateGlobalContext.json +0 -24
  330. package/nodes/locales/es/knxUltimateHATranslator.html +0 -25
  331. package/nodes/locales/es/knxUltimateHATranslator.json +0 -8
  332. package/nodes/locales/es/knxUltimateHueAreaMotion.html +0 -44
  333. package/nodes/locales/es/knxUltimateHueAreaMotion.json +0 -31
  334. package/nodes/locales/es/knxUltimateHueBattery.html +0 -37
  335. package/nodes/locales/es/knxUltimateHueBattery.json +0 -30
  336. package/nodes/locales/es/knxUltimateHueButton.html +0 -52
  337. package/nodes/locales/es/knxUltimateHueButton.json +0 -34
  338. package/nodes/locales/es/knxUltimateHueCameraMotion.html +0 -38
  339. package/nodes/locales/es/knxUltimateHueCameraMotion.json +0 -30
  340. package/nodes/locales/es/knxUltimateHueContactSensor.html +0 -35
  341. package/nodes/locales/es/knxUltimateHueContactSensor.json +0 -26
  342. package/nodes/locales/es/knxUltimateHueController.html +0 -691
  343. package/nodes/locales/es/knxUltimateHueController.json +0 -64
  344. package/nodes/locales/es/knxUltimateHueHumiditySensor.html +0 -38
  345. package/nodes/locales/es/knxUltimateHueHumiditySensor.json +0 -30
  346. package/nodes/locales/es/knxUltimateHueLight.html +0 -124
  347. package/nodes/locales/es/knxUltimateHueLight.json +0 -94
  348. package/nodes/locales/es/knxUltimateHueLightSensor.html +0 -38
  349. package/nodes/locales/es/knxUltimateHueLightSensor.json +0 -19
  350. package/nodes/locales/es/knxUltimateHueMotion.html +0 -41
  351. package/nodes/locales/es/knxUltimateHueMotion.json +0 -27
  352. package/nodes/locales/es/knxUltimateHuePlug.html +0 -50
  353. package/nodes/locales/es/knxUltimateHuePlug.json +0 -33
  354. package/nodes/locales/es/knxUltimateHueScene.html +0 -45
  355. package/nodes/locales/es/knxUltimateHueScene.json +0 -41
  356. package/nodes/locales/es/knxUltimateHueTapDial.html +0 -40
  357. package/nodes/locales/es/knxUltimateHueTapDial.json +0 -28
  358. package/nodes/locales/es/knxUltimateHueTemperatureSensor.html +0 -38
  359. package/nodes/locales/es/knxUltimateHueTemperatureSensor.json +0 -30
  360. package/nodes/locales/es/knxUltimateHueZigbeeConnectivity.html +0 -39
  361. package/nodes/locales/es/knxUltimateHueZigbeeConnectivity.json +0 -30
  362. package/nodes/locales/es/knxUltimateHuedevice_software_update.html +0 -36
  363. package/nodes/locales/es/knxUltimateHuedevice_software_update.json +0 -30
  364. package/nodes/locales/es/knxUltimateLoadControl.html +0 -76
  365. package/nodes/locales/es/knxUltimateLoadControl.json +0 -28
  366. package/nodes/locales/es/knxUltimateLogger.html +0 -162
  367. package/nodes/locales/es/knxUltimateLogger.json +0 -31
  368. package/nodes/locales/es/knxUltimateMatterBridge.html +0 -65
  369. package/nodes/locales/es/knxUltimateMatterBridge.json +0 -123
  370. package/nodes/locales/es/knxUltimateMatterControllerDevice.html +0 -57
  371. package/nodes/locales/es/knxUltimateMatterControllerDevice.json +0 -146
  372. package/nodes/locales/es/knxUltimateSceneController.html +0 -115
  373. package/nodes/locales/es/knxUltimateSceneController.json +0 -32
  374. package/nodes/locales/es/knxUltimateStaircase.html +0 -77
  375. package/nodes/locales/es/knxUltimateStaircase.json +0 -62
  376. package/nodes/locales/es/knxUltimateWatchDog.html +0 -230
  377. package/nodes/locales/es/knxUltimateWatchDog.json +0 -27
  378. package/nodes/locales/es/matter-config.html +0 -47
  379. package/nodes/locales/es/matter-config.json +0 -47
  380. package/nodes/locales/es/matterbridge-config.html +0 -45
  381. package/nodes/locales/es/matterbridge-config.json +0 -25
  382. package/nodes/locales/fr/hue-config.html +0 -31
  383. package/nodes/locales/fr/hue-config.json +0 -21
  384. package/nodes/locales/fr/knxUltimateAI.html +0 -13
  385. package/nodes/locales/fr/knxUltimateAI.json +0 -231
  386. package/nodes/locales/fr/knxUltimateAIHomeAssistant.html +0 -11
  387. package/nodes/locales/fr/knxUltimateAlerter.html +0 -164
  388. package/nodes/locales/fr/knxUltimateAlerter.json +0 -27
  389. package/nodes/locales/fr/knxUltimateAutoResponder.html +0 -92
  390. package/nodes/locales/fr/knxUltimateAutoResponder.json +0 -8
  391. package/nodes/locales/fr/knxUltimateDateTime.html +0 -45
  392. package/nodes/locales/fr/knxUltimateDateTime.json +0 -32
  393. package/nodes/locales/fr/knxUltimateGarage.html +0 -79
  394. package/nodes/locales/fr/knxUltimateGarage.json +0 -51
  395. package/nodes/locales/fr/knxUltimateGlobalContext.html +0 -122
  396. package/nodes/locales/fr/knxUltimateGlobalContext.json +0 -24
  397. package/nodes/locales/fr/knxUltimateHATranslator.html +0 -25
  398. package/nodes/locales/fr/knxUltimateHATranslator.json +0 -8
  399. package/nodes/locales/fr/knxUltimateHueAreaMotion.html +0 -44
  400. package/nodes/locales/fr/knxUltimateHueAreaMotion.json +0 -31
  401. package/nodes/locales/fr/knxUltimateHueBattery.html +0 -37
  402. package/nodes/locales/fr/knxUltimateHueBattery.json +0 -30
  403. package/nodes/locales/fr/knxUltimateHueButton.html +0 -52
  404. package/nodes/locales/fr/knxUltimateHueButton.json +0 -34
  405. package/nodes/locales/fr/knxUltimateHueCameraMotion.html +0 -38
  406. package/nodes/locales/fr/knxUltimateHueCameraMotion.json +0 -30
  407. package/nodes/locales/fr/knxUltimateHueContactSensor.html +0 -35
  408. package/nodes/locales/fr/knxUltimateHueContactSensor.json +0 -26
  409. package/nodes/locales/fr/knxUltimateHueController.html +0 -691
  410. package/nodes/locales/fr/knxUltimateHueController.json +0 -64
  411. package/nodes/locales/fr/knxUltimateHueHumiditySensor.html +0 -38
  412. package/nodes/locales/fr/knxUltimateHueHumiditySensor.json +0 -30
  413. package/nodes/locales/fr/knxUltimateHueLight.html +0 -124
  414. package/nodes/locales/fr/knxUltimateHueLight.json +0 -86
  415. package/nodes/locales/fr/knxUltimateHueLightSensor.html +0 -38
  416. package/nodes/locales/fr/knxUltimateHueLightSensor.json +0 -19
  417. package/nodes/locales/fr/knxUltimateHueMotion.html +0 -41
  418. package/nodes/locales/fr/knxUltimateHueMotion.json +0 -27
  419. package/nodes/locales/fr/knxUltimateHuePlug.html +0 -50
  420. package/nodes/locales/fr/knxUltimateHuePlug.json +0 -33
  421. package/nodes/locales/fr/knxUltimateHueScene.html +0 -45
  422. package/nodes/locales/fr/knxUltimateHueScene.json +0 -41
  423. package/nodes/locales/fr/knxUltimateHueTapDial.html +0 -40
  424. package/nodes/locales/fr/knxUltimateHueTapDial.json +0 -28
  425. package/nodes/locales/fr/knxUltimateHueTemperatureSensor.html +0 -38
  426. package/nodes/locales/fr/knxUltimateHueTemperatureSensor.json +0 -30
  427. package/nodes/locales/fr/knxUltimateHueZigbeeConnectivity.html +0 -39
  428. package/nodes/locales/fr/knxUltimateHueZigbeeConnectivity.json +0 -30
  429. package/nodes/locales/fr/knxUltimateHuedevice_software_update.html +0 -36
  430. package/nodes/locales/fr/knxUltimateHuedevice_software_update.json +0 -30
  431. package/nodes/locales/fr/knxUltimateLoadControl.html +0 -76
  432. package/nodes/locales/fr/knxUltimateLoadControl.json +0 -28
  433. package/nodes/locales/fr/knxUltimateLogger.html +0 -160
  434. package/nodes/locales/fr/knxUltimateLogger.json +0 -31
  435. package/nodes/locales/fr/knxUltimateMatterBridge.html +0 -65
  436. package/nodes/locales/fr/knxUltimateMatterBridge.json +0 -123
  437. package/nodes/locales/fr/knxUltimateMatterControllerDevice.html +0 -57
  438. package/nodes/locales/fr/knxUltimateMatterControllerDevice.json +0 -146
  439. package/nodes/locales/fr/knxUltimateSceneController.html +0 -117
  440. package/nodes/locales/fr/knxUltimateSceneController.json +0 -32
  441. package/nodes/locales/fr/knxUltimateStaircase.html +0 -77
  442. package/nodes/locales/fr/knxUltimateStaircase.json +0 -62
  443. package/nodes/locales/fr/knxUltimateWatchDog.html +0 -228
  444. package/nodes/locales/fr/knxUltimateWatchDog.json +0 -27
  445. package/nodes/locales/fr/matter-config.html +0 -47
  446. package/nodes/locales/fr/matter-config.json +0 -47
  447. package/nodes/locales/fr/matterbridge-config.html +0 -45
  448. package/nodes/locales/fr/matterbridge-config.json +0 -25
  449. package/nodes/locales/it/hue-config.html +0 -33
  450. package/nodes/locales/it/hue-config.json +0 -21
  451. package/nodes/locales/it/knxUltimateAI.html +0 -13
  452. package/nodes/locales/it/knxUltimateAI.json +0 -234
  453. package/nodes/locales/it/knxUltimateAIHomeAssistant.html +0 -11
  454. package/nodes/locales/it/knxUltimateAlerter.html +0 -159
  455. package/nodes/locales/it/knxUltimateAlerter.json +0 -27
  456. package/nodes/locales/it/knxUltimateAutoResponder.html +0 -96
  457. package/nodes/locales/it/knxUltimateAutoResponder.json +0 -8
  458. package/nodes/locales/it/knxUltimateDateTime.html +0 -67
  459. package/nodes/locales/it/knxUltimateDateTime.json +0 -32
  460. package/nodes/locales/it/knxUltimateGarage.html +0 -79
  461. package/nodes/locales/it/knxUltimateGarage.json +0 -51
  462. package/nodes/locales/it/knxUltimateGlobalContext.html +0 -81
  463. package/nodes/locales/it/knxUltimateGlobalContext.json +0 -24
  464. package/nodes/locales/it/knxUltimateHATranslator.html +0 -24
  465. package/nodes/locales/it/knxUltimateHATranslator.json +0 -8
  466. package/nodes/locales/it/knxUltimateHueAreaMotion.html +0 -44
  467. package/nodes/locales/it/knxUltimateHueAreaMotion.json +0 -31
  468. package/nodes/locales/it/knxUltimateHueBattery.html +0 -37
  469. package/nodes/locales/it/knxUltimateHueBattery.json +0 -30
  470. package/nodes/locales/it/knxUltimateHueButton.html +0 -52
  471. package/nodes/locales/it/knxUltimateHueButton.json +0 -34
  472. package/nodes/locales/it/knxUltimateHueCameraMotion.html +0 -38
  473. package/nodes/locales/it/knxUltimateHueCameraMotion.json +0 -30
  474. package/nodes/locales/it/knxUltimateHueContactSensor.html +0 -35
  475. package/nodes/locales/it/knxUltimateHueContactSensor.json +0 -26
  476. package/nodes/locales/it/knxUltimateHueController.html +0 -690
  477. package/nodes/locales/it/knxUltimateHueController.json +0 -64
  478. package/nodes/locales/it/knxUltimateHueHumiditySensor 2.html +0 -11
  479. package/nodes/locales/it/knxUltimateHueHumiditySensor.html +0 -38
  480. package/nodes/locales/it/knxUltimateHueHumiditySensor.json +0 -30
  481. package/nodes/locales/it/knxUltimateHueLight.html +0 -124
  482. package/nodes/locales/it/knxUltimateHueLight.json +0 -94
  483. package/nodes/locales/it/knxUltimateHueLightSensor.html +0 -38
  484. package/nodes/locales/it/knxUltimateHueLightSensor.json +0 -19
  485. package/nodes/locales/it/knxUltimateHueMotion.html +0 -41
  486. package/nodes/locales/it/knxUltimateHueMotion.json +0 -27
  487. package/nodes/locales/it/knxUltimateHuePlug.html +0 -50
  488. package/nodes/locales/it/knxUltimateHuePlug.json +0 -33
  489. package/nodes/locales/it/knxUltimateHueScene.html +0 -45
  490. package/nodes/locales/it/knxUltimateHueScene.json +0 -41
  491. package/nodes/locales/it/knxUltimateHueTapDial.html +0 -40
  492. package/nodes/locales/it/knxUltimateHueTapDial.json +0 -28
  493. package/nodes/locales/it/knxUltimateHueTemperatureSensor.html +0 -38
  494. package/nodes/locales/it/knxUltimateHueTemperatureSensor.json +0 -30
  495. package/nodes/locales/it/knxUltimateHueZigbeeConnectivity.html +0 -39
  496. package/nodes/locales/it/knxUltimateHueZigbeeConnectivity.json +0 -30
  497. package/nodes/locales/it/knxUltimateHuedevice_software_update.html +0 -35
  498. package/nodes/locales/it/knxUltimateHuedevice_software_update.json +0 -30
  499. package/nodes/locales/it/knxUltimateLoadControl.html +0 -76
  500. package/nodes/locales/it/knxUltimateLoadControl.json +0 -28
  501. package/nodes/locales/it/knxUltimateLogger.html +0 -132
  502. package/nodes/locales/it/knxUltimateLogger.json +0 -31
  503. package/nodes/locales/it/knxUltimateMatterBridge.html +0 -65
  504. package/nodes/locales/it/knxUltimateMatterBridge.json +0 -123
  505. package/nodes/locales/it/knxUltimateMatterControllerDevice.html +0 -57
  506. package/nodes/locales/it/knxUltimateMatterControllerDevice.json +0 -146
  507. package/nodes/locales/it/knxUltimateSceneController.html +0 -101
  508. package/nodes/locales/it/knxUltimateSceneController.json +0 -32
  509. package/nodes/locales/it/knxUltimateStaircase.html +0 -77
  510. package/nodes/locales/it/knxUltimateStaircase.json +0 -62
  511. package/nodes/locales/it/knxUltimateWatchDog.html +0 -194
  512. package/nodes/locales/it/knxUltimateWatchDog.json +0 -27
  513. package/nodes/locales/it/matter-config.html +0 -47
  514. package/nodes/locales/it/matter-config.json +0 -48
  515. package/nodes/locales/it/matterbridge-config.html +0 -45
  516. package/nodes/locales/it/matterbridge-config.json +0 -25
  517. package/nodes/locales/zh-CN/hue-config.html +0 -33
  518. package/nodes/locales/zh-CN/hue-config.json +0 -21
  519. package/nodes/locales/zh-CN/knxUltimateAI.html +0 -13
  520. package/nodes/locales/zh-CN/knxUltimateAI.json +0 -231
  521. package/nodes/locales/zh-CN/knxUltimateAIHomeAssistant.html +0 -11
  522. package/nodes/locales/zh-CN/knxUltimateAlerter.html +0 -159
  523. package/nodes/locales/zh-CN/knxUltimateAlerter.json +0 -27
  524. package/nodes/locales/zh-CN/knxUltimateAutoResponder.html +0 -94
  525. package/nodes/locales/zh-CN/knxUltimateAutoResponder.json +0 -8
  526. package/nodes/locales/zh-CN/knxUltimateDateTime.html +0 -45
  527. package/nodes/locales/zh-CN/knxUltimateDateTime.json +0 -32
  528. package/nodes/locales/zh-CN/knxUltimateGarage.html +0 -79
  529. package/nodes/locales/zh-CN/knxUltimateGarage.json +0 -51
  530. package/nodes/locales/zh-CN/knxUltimateGlobalContext.html +0 -77
  531. package/nodes/locales/zh-CN/knxUltimateGlobalContext.json +0 -24
  532. package/nodes/locales/zh-CN/knxUltimateHATranslator.html +0 -25
  533. package/nodes/locales/zh-CN/knxUltimateHATranslator.json +0 -8
  534. package/nodes/locales/zh-CN/knxUltimateHueAreaMotion.html +0 -44
  535. package/nodes/locales/zh-CN/knxUltimateHueAreaMotion.json +0 -31
  536. package/nodes/locales/zh-CN/knxUltimateHueBattery.html +0 -37
  537. package/nodes/locales/zh-CN/knxUltimateHueBattery.json +0 -30
  538. package/nodes/locales/zh-CN/knxUltimateHueButton.html +0 -52
  539. package/nodes/locales/zh-CN/knxUltimateHueButton.json +0 -34
  540. package/nodes/locales/zh-CN/knxUltimateHueCameraMotion.html +0 -38
  541. package/nodes/locales/zh-CN/knxUltimateHueCameraMotion.json +0 -30
  542. package/nodes/locales/zh-CN/knxUltimateHueContactSensor.html +0 -35
  543. package/nodes/locales/zh-CN/knxUltimateHueContactSensor.json +0 -26
  544. package/nodes/locales/zh-CN/knxUltimateHueController.html +0 -693
  545. package/nodes/locales/zh-CN/knxUltimateHueController.json +0 -64
  546. package/nodes/locales/zh-CN/knxUltimateHueHumiditySensor.html +0 -38
  547. package/nodes/locales/zh-CN/knxUltimateHueHumiditySensor.json +0 -30
  548. package/nodes/locales/zh-CN/knxUltimateHueLight.html +0 -126
  549. package/nodes/locales/zh-CN/knxUltimateHueLight.json +0 -86
  550. package/nodes/locales/zh-CN/knxUltimateHueLightSensor.html +0 -38
  551. package/nodes/locales/zh-CN/knxUltimateHueLightSensor.json +0 -9
  552. package/nodes/locales/zh-CN/knxUltimateHueMotion.html +0 -41
  553. package/nodes/locales/zh-CN/knxUltimateHueMotion.json +0 -27
  554. package/nodes/locales/zh-CN/knxUltimateHuePlug.html +0 -50
  555. package/nodes/locales/zh-CN/knxUltimateHuePlug.json +0 -33
  556. package/nodes/locales/zh-CN/knxUltimateHueScene.html +0 -45
  557. package/nodes/locales/zh-CN/knxUltimateHueScene.json +0 -41
  558. package/nodes/locales/zh-CN/knxUltimateHueTapDial.html +0 -40
  559. package/nodes/locales/zh-CN/knxUltimateHueTapDial.json +0 -28
  560. package/nodes/locales/zh-CN/knxUltimateHueTemperatureSensor.html +0 -38
  561. package/nodes/locales/zh-CN/knxUltimateHueTemperatureSensor.json +0 -30
  562. package/nodes/locales/zh-CN/knxUltimateHueZigbeeConnectivity.html +0 -39
  563. package/nodes/locales/zh-CN/knxUltimateHueZigbeeConnectivity.json +0 -30
  564. package/nodes/locales/zh-CN/knxUltimateHuedevice_software_update.html +0 -36
  565. package/nodes/locales/zh-CN/knxUltimateHuedevice_software_update.json +0 -30
  566. package/nodes/locales/zh-CN/knxUltimateLoadControl.html +0 -76
  567. package/nodes/locales/zh-CN/knxUltimateLoadControl.json +0 -28
  568. package/nodes/locales/zh-CN/knxUltimateLogger.html +0 -126
  569. package/nodes/locales/zh-CN/knxUltimateLogger.json +0 -31
  570. package/nodes/locales/zh-CN/knxUltimateMatterBridge.html +0 -65
  571. package/nodes/locales/zh-CN/knxUltimateMatterBridge.json +0 -123
  572. package/nodes/locales/zh-CN/knxUltimateMatterControllerDevice.html +0 -57
  573. package/nodes/locales/zh-CN/knxUltimateMatterControllerDevice.json +0 -146
  574. package/nodes/locales/zh-CN/knxUltimateSceneController.html +0 -98
  575. package/nodes/locales/zh-CN/knxUltimateSceneController.json +0 -32
  576. package/nodes/locales/zh-CN/knxUltimateStaircase.html +0 -77
  577. package/nodes/locales/zh-CN/knxUltimateStaircase.json +0 -62
  578. package/nodes/locales/zh-CN/knxUltimateWatchDog.html +0 -178
  579. package/nodes/locales/zh-CN/knxUltimateWatchDog.json +0 -27
  580. package/nodes/locales/zh-CN/matter-config.html +0 -47
  581. package/nodes/locales/zh-CN/matter-config.json +0 -47
  582. package/nodes/locales/zh-CN/matterbridge-config.html +0 -45
  583. package/nodes/locales/zh-CN/matterbridge-config.json +0 -25
  584. package/nodes/matter-config.html +0 -578
  585. package/nodes/matter-config.js +0 -387
  586. package/nodes/matterbridge-config.html +0 -198
  587. package/nodes/matterbridge-config.js +0 -261
  588. package/nodes/plugins/knxUltimate-cerebrum-runtime-plugin.js +0 -79
  589. package/nodes/plugins/knxUltimate-migration-notice-plugin.html +0 -44
  590. package/nodes/plugins/knxUltimateAI-vue/assets/app.css +0 -1
  591. package/nodes/plugins/knxUltimateAI-vue/assets/app.js +0 -13
  592. package/nodes/plugins/knxUltimateAI-vue/assets/chunk-html2canvas.esm.js +0 -5
  593. package/nodes/plugins/knxUltimateAI-vue/assets/chunk-index.es.js +0 -5
  594. package/nodes/plugins/knxUltimateAI-vue/assets/chunk-jspdf.es.min.js +0 -79
  595. package/nodes/plugins/knxUltimateAI-vue/assets/chunk-purify.es.js +0 -3
  596. package/nodes/plugins/knxUltimateAI-vue/index.html +0 -13
  597. package/nodes/utils/HueEventStream.mjs +0 -176
  598. package/nodes/utils/colorManipulators/XYFromRGB_Supergiovane.js +0 -113
  599. package/nodes/utils/colorManipulators/hueColorConverter.js +0 -521
  600. package/nodes/utils/http.js +0 -291
  601. package/nodes/utils/hueControllerProfileAdapter.js +0 -104
  602. package/nodes/utils/hueControllerProfiles/runtime/area_motion.js +0 -221
  603. package/nodes/utils/hueControllerProfiles/runtime/button.js +0 -295
  604. package/nodes/utils/hueControllerProfiles/runtime/camera_motion.js +0 -221
  605. package/nodes/utils/hueControllerProfiles/runtime/contact.js +0 -191
  606. package/nodes/utils/hueControllerProfiles/runtime/device_power.js +0 -185
  607. package/nodes/utils/hueControllerProfiles/runtime/device_software_update.js +0 -185
  608. package/nodes/utils/hueControllerProfiles/runtime/humidity.js +0 -204
  609. package/nodes/utils/hueControllerProfiles/runtime/light.js +0 -1585
  610. package/nodes/utils/hueControllerProfiles/runtime/light_level.js +0 -180
  611. package/nodes/utils/hueControllerProfiles/runtime/motion.js +0 -185
  612. package/nodes/utils/hueControllerProfiles/runtime/plug.js +0 -344
  613. package/nodes/utils/hueControllerProfiles/runtime/relative_rotary.js +0 -271
  614. package/nodes/utils/hueControllerProfiles/runtime/scene.js +0 -352
  615. package/nodes/utils/hueControllerProfiles/runtime/temperature.js +0 -187
  616. package/nodes/utils/hueControllerProfiles/runtime/zigbee_connectivity.js +0 -185
  617. package/nodes/utils/hueControllerResourceCatalog.js +0 -71
  618. package/nodes/utils/hueEngine.mjs +0 -469
  619. package/nodes/utils/knxAiCamera.js +0 -302
  620. package/nodes/utils/knxAiCatalogRetrieval.js +0 -349
  621. package/nodes/utils/knxAiCerebrum.js +0 -406
  622. package/nodes/utils/knxAiChatContext.js +0 -496
  623. package/nodes/utils/knxAiEventHistory.js +0 -521
  624. package/nodes/utils/knxAiHomeMemory.js +0 -1021
  625. package/nodes/utils/knxAiScheduler.js +0 -445
  626. package/nodes/utils/knxAiSemanticContext.js +0 -662
  627. package/nodes/utils/knxAiTelegramVoice.js +0 -545
  628. package/nodes/utils/knxAiWebAccess.js +0 -631
  629. package/nodes/utils/lightEngines/canonicalLight.js +0 -75
  630. package/nodes/utils/lightEngines/hueLightEngine.js +0 -51
  631. package/nodes/utils/lightEngines/index.js +0 -25
  632. package/nodes/utils/lightEngines/knxLightCommand.js +0 -79
  633. package/nodes/utils/lightEngines/lightEngine.js +0 -46
  634. package/nodes/utils/lightEngines/matterHueShim.js +0 -59
  635. package/nodes/utils/lightEngines/matterLightEngine.js +0 -117
  636. package/nodes/utils/matterBridgeDeviceFactory.mjs +0 -780
  637. package/nodes/utils/matterBridgeEngine.mjs +0 -297
  638. package/nodes/utils/matterControllerCommandGate.js +0 -47
  639. package/nodes/utils/matterControllerProfiles/doorLock.js +0 -258
  640. package/nodes/utils/matterControllerProfiles/fan.js +0 -19
  641. package/nodes/utils/matterControllerProfiles/index.js +0 -34
  642. package/nodes/utils/matterControllerProfiles/mappedEndpoint.js +0 -217
  643. package/nodes/utils/matterControllerProfiles/switch.js +0 -13
  644. package/nodes/utils/matterControllerProfiles/thermostat.js +0 -19
  645. package/nodes/utils/matterControllerProfiles/universal.js +0 -462
  646. package/nodes/utils/matterControllerProfiles/windowCovering.js +0 -19
  647. package/nodes/utils/matterControllerSemanticInput.js +0 -212
  648. package/nodes/utils/matterEngine.mjs +0 -894
  649. package/nodes/utils/matterEnvironmentLock.mjs +0 -32
  650. package/nodes/utils/matterKnxConverter.js +0 -204
  651. package/nodes/utils/matterStorageBackup.js +0 -100
  652. package/resources/HA-icon.png +0 -0
  653. package/resources/dim.png +0 -0
  654. package/resources/rgb.png +0 -0
  655. package/resources/tunablewhite.png +0 -0
  656. package/resources/zxing-browser-0.2.0.min.js +0 -1
  657. package/resources/zxing-browser-LICENSE.txt +0 -21
@@ -1,1747 +0,0 @@
1
- /* eslint-disable no-param-reassign */
2
- /* eslint-disable camelcase */
3
- /* eslint-disable max-len */
4
- /* eslint-disable no-lonely-if */
5
- /* eslint-disable no-case-declarations */
6
- /* eslint-disable no-unused-vars */
7
- const cloneDeep = require('lodash/cloneDeep')
8
- const dptlib = require('knxultimate').dptlib
9
- const hueColorConverter = require('./utils/colorManipulators/hueColorConverter')
10
- const { createLightEngine } = require('./utils/lightEngines')
11
- const { hueStateToCanonical, matterEventToHuePatch } = require('./utils/lightEngines/matterHueShim')
12
- const { setupMatterControllerProfile } = require('./utils/matterControllerProfiles')
13
- const { setupMatterControllerCommandGate } = require('./utils/matterControllerCommandGate')
14
-
15
- let matterCommandGateEndpointRegistered = false
16
-
17
- module.exports = function (RED) {
18
- if (!matterCommandGateEndpointRegistered) {
19
- RED.httpAdmin.post('/KNXUltimateMatterControllerEnable', RED.auth.needsPermission('matter-config.write'), (req, res) => {
20
- try {
21
- const nodeId = String(req.body?.nodeId || '').trim()
22
- if (nodeId === '') {
23
- res.status(400).json({ error: 'Missing Matter Controller node id' })
24
- return
25
- }
26
- const targetNode = RED.nodes.getNode(nodeId)
27
- if (!targetNode || typeof targetNode.clearMatterCommandBlock !== 'function') {
28
- // New or not-yet-deployed editor nodes have no runtime counterpart.
29
- res.json({ status: 'not-deployed', cleared: false })
30
- return
31
- }
32
- const cleared = targetNode.clearMatterCommandBlock('editor')
33
- res.json({ status: 'ok', cleared })
34
- } catch (error) {
35
- res.status(500).json({ error: error.message || 'Unable to enable Matter commands' })
36
- }
37
- })
38
- matterCommandGateEndpointRegistered = true
39
- }
40
-
41
- function knxUltimateMatterControllerDevice (config) {
42
- RED.nodes.createNode(this, config)
43
- const node = this
44
- node.serverKNX = RED.nodes.getNode(config.server) || undefined
45
- node.serverMatter = RED.nodes.getNode(config.serverMatter) || undefined
46
- node.matterNodeId = config.matterNodeId !== undefined ? String(config.matterNodeId) : ''
47
- node.matterEndpointId = config.matterEndpointId !== undefined ? Number(config.matterEndpointId) : 1
48
- node.matterDeviceName = config.matterDeviceName !== undefined ? String(config.matterDeviceName) : ''
49
- setupMatterControllerCommandGate(node)
50
-
51
- let matterCapabilities = {}
52
- try { matterCapabilities = JSON.parse(config.matterDeviceCapabilities || '{}') } catch (error) { /* empty */ }
53
- // Non-light endpoints are handled by isolated profiles. A successful profile setup
54
- // owns the complete node lifecycle and deliberately bypasses the legacy light path.
55
- // Keeping this boundary here prevents new device types from changing established
56
- // light behaviour or its saved configuration contract.
57
- if (setupMatterControllerProfile(matterCapabilities.profile, RED, node, config)) return
58
-
59
- // Matter engine (adapter). The manager is resolved lazily at each write, because
60
- // matter-config creates its matterManager asynchronously after the deploy.
61
- node.lightEngine = createLightEngine('matter', {
62
- deviceId: node.matterNodeId,
63
- nodeId: node.matterNodeId,
64
- endpointId: node.matterEndpointId
65
- })
66
-
67
- // Facade impersonating the hue-config node. The entire light logic below was born
68
- // in the Hue Light node and is kept UNCHANGED: it speaks Hue-native state objects,
69
- // and this boundary translates them to the Matter engine (strategy/adapter).
70
- node.serverHue = {
71
- get linkStatus () { return node.serverMatter ? node.serverMatter.linkStatus : 'disconnected' },
72
- hueManager: {
73
- writeHueQueueAdd: (_lightID, _state, _operation) => {
74
- try {
75
- if (node.matterCommandBlocked === true) return
76
- if (!node.lightEngine) return
77
- const patch = hueStateToCanonical(_state)
78
- if (!patch) return
79
- node.lightEngine.manager = node.serverMatter ? node.serverMatter.matterManager : undefined
80
- node.lightEngine.applyState(patch)
81
- } catch (error) {
82
- RED.log.error('knxUltimateMatterControllerDevice: writeHueQueueAdd shim: ' + (error && error.message))
83
- }
84
- },
85
- deleteHueQueue: () => { }
86
- },
87
- addClient: (_node) => { try { if (node.serverMatter) node.serverMatter.addClient(_node) } catch (error) { /* empty */ } },
88
- removeClient: (_node) => { if (node.serverMatter) { try { node.serverMatter.removeClient(_node) } catch (error) { /* empty */ } } },
89
- getAllLightsBelongingToTheGroup: async () => [],
90
- getHueResourceSnapshot: async () => node.currentHUEDevice,
91
- getAverageColorsXYBrightnessAndTemperature: async () => undefined
92
- }
93
-
94
- // Convert for backward compatibility
95
- if (config.nameLightKelvinDIM === undefined) {
96
- config.nameLightKelvinDIM = config.nameLightHSV
97
- config.GALightKelvinDIM = config.GALightHSV
98
- config.dptLightKelvinDIM = config.dptLightHSV
99
-
100
- config.nameLightKelvinPercentage = config.nameLightHSVPercentage
101
- config.GALightKelvinPercentage = config.GALightHSVPercentage
102
- config.dptLightKelvinPercentage = config.dptLightHSVPercentage
103
-
104
- config.nameLightKelvinPercentageState = config.nameLightHSVState
105
- config.GALightKelvinPercentageState = config.GALightHSVState
106
- config.dptLightKelvinPercentageState = config.dptLightHSVState
107
- }
108
-
109
- node.name = config.name || node.matterDeviceName || 'Control Matter from KNX'
110
- node.topic = node.name
111
- node.outputtopic = node.name
112
- node.dpt = ''
113
- node.notifyreadrequest = true
114
- node.notifyreadrequestalsorespondtobus = 'false'
115
- node.notifyreadrequestalsorespondtobusdefaultvalueifnotinitialized = ''
116
- node.notifyresponse = false
117
- node.notifywrite = true
118
- node.initialread = true
119
- node.listenallga = true // Don't remove
120
- node.outputtype = 'write'
121
- node.outputRBE = 'false' // Apply or not RBE to the output (Messages coming from flow)
122
- node.inputRBE = 'false' // Apply or not RBE to the input (Messages coming from BUS)
123
- node.currentPayload = '' // Current value for the RBE input and for the .previouspayload msg
124
- node.passthrough = 'no'
125
- node.formatmultiplyvalue = 1
126
- node.formatnegativevalue = 'leave'
127
- node.formatdecimalsvalue = 2
128
- node.knxUltimateAcceptedGAs = [
129
- config.GALightSwitch,
130
- config.GALightState,
131
- config.GALightDIM,
132
- config.GALightColor,
133
- config.GALightColorState,
134
- config.GALightHSV_H_DIM,
135
- config.GALightHSV_H_State,
136
- config.GALightHSV_S_DIM,
137
- config.GALightHSV_S_State,
138
- config.GALightKelvinDIM,
139
- config.GALightKelvinPercentage,
140
- config.GALightKelvinPercentageState,
141
- config.GALightKelvin,
142
- config.GALightKelvinState,
143
- config.GALightBrightness,
144
- config.GALightBrightnessState,
145
- config.GALightBlink,
146
- config.GALightColorCycle,
147
- config.GADaylightSensor
148
- ].map((ga) => String(ga || '').trim()).filter((ga) => ga !== '')
149
- const isConfiguredKNXGA = (ga) => node.knxUltimateAcceptedGAs.includes(String(ga || '').trim())
150
- // Synthetic current-device compatibility state, kept in sync from Matter attribute
151
- // reports. It lets the established light logic run untouched on a Matter light.
152
- node.currentHUEDevice = {
153
- id: node.matterNodeId,
154
- type: 'light',
155
- on: { on: false },
156
- dimming: { brightness: 100, min_dim_level: 0 },
157
- color: { xy: { x: 0.3127, y: 0.329 }, gamut: undefined, gamut_type: undefined },
158
- color_temperature: { mirek: 333, mirek_valid: true, mirek_schema: { mirek_minimum: 153, mirek_maximum: 500 } }
159
- }
160
- node.HUEDeviceWhileDaytime = null// This retains the HUE device status while daytime, to be restored after nighttime elapsed.
161
- node.HUELightsBelongingToGroupWhileDaytime = null // Array contains all light belonging to the grouped_light (if grouped_light is selected)
162
- node.DayTime = true
163
- node.isGrouped_light = false // No grouped lights on Matter
164
- node.hueDevice = node.matterNodeId
165
- node.initializingAtStart = (config.readStatusAtStartup === undefined || config.readStatusAtStartup === 'yes')
166
- config.specifySwitchOnBrightness = (config.specifySwitchOnBrightness === undefined || config.specifySwitchOnBrightness === '') ? 'temperature' : config.specifySwitchOnBrightness
167
- config.specifySwitchOnBrightnessNightTime = (config.specifySwitchOnBrightnessNightTime === undefined || config.specifySwitchOnBrightnessNightTime === '') ? 'no' : config.specifySwitchOnBrightnessNightTime
168
- config.colorAtSwitchOnDayTime = (config.colorAtSwitchOnDayTime === '' || config.colorAtSwitchOnDayTime === undefined) ? '{ "kelvin":3000, "brightness":100 }' : config.colorAtSwitchOnDayTime
169
- config.colorAtSwitchOnNightTime = (config.colorAtSwitchOnNightTime === '' || config.colorAtSwitchOnNightTime === undefined) ? '{ "kelvin":2700, "brightness":20 }' : config.colorAtSwitchOnNightTime
170
- config.colorAtSwitchOnDayTime = config.colorAtSwitchOnDayTime.replace('geen', 'green')
171
- config.colorAtSwitchOnNightTime = config.colorAtSwitchOnNightTime.replace('geen', 'green')
172
- config.dimSpeed = (config.dimSpeed === undefined || config.dimSpeed === '') ? 5000 : Number(config.dimSpeed)
173
- config.HSVDimSpeed = (config.HSVDimSpeed === undefined || config.HSVDimSpeed === '') ? 5000 : Number(config.HSVDimSpeed)
174
- config.invertDimTunableWhiteDirection = config.invertDimTunableWhiteDirection !== undefined
175
- config.restoreDayMode = config.restoreDayMode === undefined ? 'no' : config.restoreDayMode // no or setDayByFastSwitchLightSingle or setDayByFastSwitchLightALL
176
- config.updateLocalStateFromKNXWrite = config.updateLocalStateFromKNXWrite === true || config.updateLocalStateFromKNXWrite === 'true' // Starting from v 4.1.31
177
- node.timerCheckForFastLightSwitch = null
178
- config.invertDayNight = config.invertDayNight === undefined ? false : config.invertDayNight
179
- node.HSVObject = null // { h, s, v };// Store the current light calculated HSV
180
-
181
- // Transform HEX in RGB and stringified json in json oblects.
182
- if (config.colorAtSwitchOnDayTime.indexOf('#') !== -1) {
183
- // Transform to rgb.
184
- try {
185
- config.colorAtSwitchOnDayTime = hueColorConverter.ColorConverter.hexRgb(config.colorAtSwitchOnDayTime.replace('#', ''))
186
- } catch (error) {
187
- config.colorAtSwitchOnDayTime = { kelvin: 3000, brightness: 100 }
188
- }
189
- } else {
190
- try {
191
- config.colorAtSwitchOnDayTime = JSON.parse(config.colorAtSwitchOnDayTime)
192
- } catch (error) {
193
- RED.log.error(`knxUltimateMatterControllerDevice: config.colorAtSwitchOnDayTime = JSON.parse(config.colorAtSwitchOnDayTime): ${error.message} : ${error.stack || ''} `)
194
- config.colorAtSwitchOnDayTime = ''
195
- }
196
- }
197
- // Same thing, but with night color
198
- if (config.colorAtSwitchOnNightTime.indexOf('#') !== -1) {
199
- // Transform to rgb.
200
- try {
201
- config.colorAtSwitchOnNightTime = hueColorConverter.ColorConverter.hexRgb(config.colorAtSwitchOnNightTime.replace('#', ''))
202
- } catch (error) {
203
- config.colorAtSwitchOnNightTime = { kelvin: 2700, brightness: 20 }
204
- }
205
- } else {
206
- try {
207
- config.colorAtSwitchOnNightTime = JSON.parse(config.colorAtSwitchOnNightTime)
208
- } catch (error) {
209
- RED.log.error(`knxUltimateMatterControllerDevice: config.colorAtSwitchOnDayTime = JSON.parse(config.colorAtSwitchOnNightTime): ${error.message} : ${error.stack || ''} `)
210
- config.colorAtSwitchOnNightTime = ''
211
- }
212
- }
213
-
214
- const formatTs = (date) => {
215
- const d = date instanceof Date ? date : new Date(date)
216
- const provider = node.serverKNX
217
- if (provider && typeof provider.formatStatusTimestamp === 'function') return provider.formatStatusTimestamp(d)
218
- return `${d.getDate()}, ${d.toLocaleTimeString()}`
219
- }
220
-
221
- node.syncCurrentHUEDeviceFromKNXState = function syncCurrentHUEDeviceFromKNXState (_state) { // Starting from v 4.1.31
222
- if (config.updateLocalStateFromKNXWrite !== true) return // Starting from v 4.1.31
223
- if (_state === undefined || _state === null || typeof _state !== 'object') return // Starting from v 4.1.31
224
- if (node.currentHUEDevice === undefined || node.currentHUEDevice === null) return // Starting from v 4.1.31
225
- if (_state.on !== undefined && typeof _state.on.on === 'boolean') { // Starting from v 4.1.31
226
- if (node.currentHUEDevice.on === undefined || node.currentHUEDevice.on === null) node.currentHUEDevice.on = {} // Starting from v 4.1.31
227
- node.currentHUEDevice.on.on = _state.on.on // Starting from v 4.1.31
228
- } // Starting from v 4.1.31
229
- if (_state.dimming !== undefined && _state.dimming !== null && _state.dimming.brightness !== undefined) { // Starting from v 4.1.31
230
- if (node.currentHUEDevice.dimming === undefined || node.currentHUEDevice.dimming === null) node.currentHUEDevice.dimming = {} // Starting from v 4.1.31
231
- node.currentHUEDevice.dimming.brightness = _state.dimming.brightness // Starting from v 4.1.31
232
- } // Starting from v 4.1.31
233
- if (_state.color !== undefined && _state.color !== null && _state.color.xy !== undefined) { // Starting from v 4.1.31
234
- if (node.currentHUEDevice.color === undefined || node.currentHUEDevice.color === null) node.currentHUEDevice.color = {} // Starting from v 4.1.31
235
- node.currentHUEDevice.color.xy = cloneDeep(_state.color.xy) // Starting from v 4.1.31
236
- } // Starting from v 4.1.31
237
- if (_state.color_temperature !== undefined && _state.color_temperature !== null && _state.color_temperature.mirek !== undefined) { // Starting from v 4.1.31
238
- if (node.currentHUEDevice.color_temperature === undefined || node.currentHUEDevice.color_temperature === null) node.currentHUEDevice.color_temperature = {} // Starting from v 4.1.31
239
- node.currentHUEDevice.color_temperature.mirek = _state.color_temperature.mirek // Starting from v 4.1.31
240
- } // Starting from v 4.1.31
241
- } // Starting from v 4.1.31
242
-
243
- // Used to call the status update from the config node.
244
- node.setNodeStatus = ({
245
- fill, shape, text, payload
246
- }) => {
247
- try {
248
- if (node.matterCommandBlocked === true) return
249
- if (node.currentHUEDevice?.on?.on === true) { fill = 'blue'; shape = 'dot' } else { fill = 'blue'; shape = 'ring' };
250
- if (payload === undefined) payload = ''
251
- const dDate = new Date()
252
- payload = typeof payload === 'object' ? JSON.stringify(payload) : payload.toString()
253
- node.sKNXNodeStatusText = `|KNX: ${text} ${payload} (${formatTs(dDate)})`
254
- node.status({ fill, shape, text: (node.sHUENodeStatusText || '') + ' ' + (node.sKNXNodeStatusText || '') })
255
- } catch (error) { }
256
- }
257
- // Compatibility callback used to update the Matter node status.
258
- node.setNodeStatusHue = ({ fill, shape, text, payload }) => {
259
- try {
260
- if (node.matterCommandBlocked === true) return
261
- if (node.currentHUEDevice?.on?.on === true) { fill = 'blue'; shape = 'dot' } else { fill = 'blue'; shape = 'ring' };
262
- if (payload === undefined) payload = ''
263
- const dDate = new Date()
264
- payload = typeof payload === 'object' ? JSON.stringify(payload) : payload.toString()
265
- node.sHUENodeStatusText = `|Matter: ${text} ${payload} (${formatTs(dDate)})`
266
- node.status({ fill, shape, text: node.sHUENodeStatusText + ' ' + (node.sKNXNodeStatusText || '') })
267
- } catch (error) { }
268
- }
269
-
270
- node.writeHueState = function writeHueState (_state) {
271
- if (node.matterCommandBlocked === true) return
272
- const defaultOperation = node.isGrouped_light === false ? 'setLight' : 'setGroupedLight'
273
- const isGroupedLightOff = node.isGrouped_light === true && node.currentHUEDevice?.on?.on === false
274
- const stateKeys = _state && typeof _state === 'object' ? Object.keys(_state) : []
275
- const presetKeys = ['dimming', 'color', 'color_temperature', 'gradient']
276
- const actionableKeys = ['dimming', ...presetKeys]
277
- const hasActionablePayload = stateKeys.some((key) => actionableKeys.includes(key))
278
- const mustPresetGroupedLightChildren = isGroupedLightOff &&
279
- stateKeys.some((key) => presetKeys.includes(key))
280
-
281
- if (!mustPresetGroupedLightChildren) {
282
- node.serverHue.hueManager.writeHueQueueAdd(node.hueDevice, _state, defaultOperation)
283
- return
284
- }
285
-
286
- (async () => {
287
- try {
288
- const groupLights = await node.serverHue.getAllLightsBelongingToTheGroup(node.hueDevice, false)
289
- RED.log.debug(`knxUltimateMatterControllerDevice: preset grouped_light children before group on. Group=${node.hueDevice} lights=${Array.isArray(groupLights) ? groupLights.length : 0}`)
290
- let hasWrittenAtLeastOneLight = false
291
- for (let index = 0; index < groupLights.length; index++) {
292
- const light = groupLights[index]
293
- if (!light?.id) continue
294
- const lightState = {}
295
- let hasActionableStateForLight = false
296
-
297
- if (_state.dimming !== undefined && light.dimming !== undefined) {
298
- lightState.dimming = cloneDeep(_state.dimming)
299
- hasActionableStateForLight = true
300
- }
301
- if (_state.color !== undefined && light.color !== undefined) {
302
- lightState.color = cloneDeep(_state.color)
303
- hasActionableStateForLight = true
304
- }
305
- if (_state.color_temperature !== undefined && light.color_temperature !== undefined) {
306
- lightState.color_temperature = cloneDeep(_state.color_temperature)
307
- hasActionableStateForLight = true
308
- }
309
- if (_state.gradient !== undefined && light.gradient !== undefined) {
310
- lightState.gradient = cloneDeep(_state.gradient)
311
- hasActionableStateForLight = true
312
- }
313
-
314
- if (!hasActionableStateForLight) continue
315
- node.serverHue.hueManager.writeHueQueueAdd(light.id, lightState, 'setLight')
316
- hasWrittenAtLeastOneLight = true
317
- }
318
-
319
- if (!hasWrittenAtLeastOneLight || !hasActionablePayload) {
320
- node.serverHue.hueManager.writeHueQueueAdd(node.hueDevice, _state, defaultOperation)
321
- return
322
- }
323
-
324
- if (_state?.on?.on !== true) return
325
-
326
- const groupedLightState = { on: cloneDeep(_state.on) }
327
- if (_state.dynamics !== undefined) groupedLightState.dynamics = cloneDeep(_state.dynamics)
328
- RED.log.debug(`knxUltimateMatterControllerDevice: turning on grouped_light after children preset. Group=${node.hueDevice}`)
329
- node.serverHue.hueManager.writeHueQueueAdd(node.hueDevice, groupedLightState, defaultOperation)
330
- } catch (error) {
331
- RED.log.debug(`knxUltimateMatterControllerDevice: node.writeHueState fallback to grouped_light write: ${error.message}`)
332
- node.serverHue.hueManager.writeHueQueueAdd(node.hueDevice, _state, defaultOperation)
333
- }
334
- })()
335
- }
336
-
337
- node.deleteHueStateQueue = function deleteHueStateQueue () {
338
- node.serverHue.hueManager.deleteHueQueue(node.hueDevice)
339
- if (node.isGrouped_light !== true) return;
340
-
341
- (async () => {
342
- try {
343
- const groupLights = await node.serverHue.getAllLightsBelongingToTheGroup(node.hueDevice, false)
344
- for (let index = 0; index < groupLights.length; index++) {
345
- const light = groupLights[index]
346
- if (!light?.id) continue
347
- node.serverHue.hueManager.deleteHueQueue(light.id)
348
- }
349
- } catch (error) {
350
- RED.log.debug(`knxUltimateMatterControllerDevice: node.deleteHueStateQueue: ${error.message}`)
351
- }
352
- })()
353
- }
354
-
355
- function getRandomIntInclusive (min, max) {
356
- min = Math.ceil(min)
357
- max = Math.floor(max)
358
- return Math.floor(Math.random() * (max - min + 1) + min) // The maximum is inclusive and the minimum is inclusive
359
- }
360
-
361
- // Compatibility callback invoked by the Matter controller adapter.
362
- node.handleSend = (msg) => {
363
- if (!msg || !msg.knx || !isConfiguredKNXGA(msg.knx.destination)) return
364
- if (node.matterCommandBlocked === true) return
365
- if (node.currentHUEDevice === undefined && node.serverHue.linkStatus === 'connected') {
366
- node.setNodeStatusHue({
367
- fill: 'yellow',
368
- shape: 'ring',
369
- text: 'Initializing. Please wait.',
370
- payload: ''
371
- })
372
- return
373
- }
374
- if (msg.knx.event !== 'GroupValue_Read' && node.currentHUEDevice !== undefined) {
375
- let state = {}
376
- try {
377
- switch (msg.knx.destination) {
378
- case config.GALightSwitch:
379
- msg.payload = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptLightSwitch))
380
-
381
- // 15/05/2024 Supergiovane: check the Override to Day option
382
- // config.restoreDayMode can be: no or setDayByFastSwitchLightSingle or setDayByFastSwitchLightALL
383
- // ----------------------------------------------------------
384
- if (config.restoreDayMode === 'setDayByFastSwitchLightSingle' || config.restoreDayMode === 'setDayByFastSwitchLightALL') {
385
- if (node.DayTime === false) {
386
- if (msg.payload === true) {
387
- if (node.timerCheckForFastLightSwitch === null) {
388
- node.timerCheckForFastLightSwitch = setTimeout(() => {
389
- node.DayTime = false
390
- RED.log.debug('knxUltimateMatterControllerDevice: node.timerCheckForFastLightSwitch: set daytime to false after node.timerCheckForFastLightSwitch elapsed')
391
- node.timerCheckForFastLightSwitch = null
392
- }, 10000) // 10 seconds
393
- } else {
394
- if (config.restoreDayMode === 'setDayByFastSwitchLightALL') {
395
- // Turn off the Day/Night group address
396
- if (config.GADaylightSensor !== undefined && config.GADaylightSensor !== '') {
397
- if (node.timerCheckForFastLightSwitch !== null) { clearTimeout(node.timerCheckForFastLightSwitch); node.timerCheckForFastLightSwitch = null }
398
- RED.log.debug(`knxUltimateMatterControllerDevice: node.timerCheckForFastLightSwitch: set daytime the group address ${config.GADaylightSensor}`)
399
- node.serverKNX.sendKNXTelegramToKNXEngine({
400
- grpaddr: config.GADaylightSensor,
401
- payload: config.invertDayNight === false,
402
- dpt: config.dptDaylightSensor,
403
- outputtype: 'write',
404
- nodecallerid: node.id
405
- })
406
- }
407
- }
408
- node.DayTime = true
409
- RED.log.debug('knxUltimateMatterControllerDevice: node.timerCheckForFastLightSwitch: set daytime to true')
410
- }
411
- }
412
- }
413
- }
414
- // ----------------------------------------------------------
415
-
416
- if (msg.payload === true) {
417
- // From HUE Api core concepts:
418
- // If you try and control multiple conflicting parameters at once e.g. {"color": {"xy": {"x":0.5,"y":0.5}}, "color_temperature": {"mirek": 250}}
419
- // the lights can only physically do one, for this we apply the rule that xy beats ct. Simple.
420
- // color_temperature.mirek: color temperature in mirek is null when the light color is not in the ct spectrum
421
- if ((node.DayTime === true && config.specifySwitchOnBrightness === 'no') && ((node.isGrouped_light === false && node.HUEDeviceWhileDaytime !== null) || (node.isGrouped_light === true && node.HUELightsBelongingToGroupWhileDaytime !== null))) {
422
- if (node.isGrouped_light === false && node.HUEDeviceWhileDaytime !== null) {
423
- // The DayNight has switched into day, so restore the previous light status
424
- state = { on: { on: true }, dimming: node.HUEDeviceWhileDaytime.dimming, color: node.HUEDeviceWhileDaytime.color, color_temperature: node.HUEDeviceWhileDaytime.color_temperature }
425
- if (node.HUEDeviceWhileDaytime.color_temperature !== undefined && node.HUEDeviceWhileDaytime.color_temperature.mirek === null) delete state.color_temperature // Otherwise the lamp will not turn on due to an error. color_temperature.mirek: color temperature in mirek is null when the light color is not in the ct spectrum
426
- node.writeHueState(state)
427
- node.setNodeStatusHue({
428
- fill: 'green',
429
- shape: 'dot',
430
- text: 'KNX->Matter',
431
- payload: 'Restore light status'
432
- })
433
- node.HUEDeviceWhileDaytime = null // Nullize the object.
434
- } else if (node.isGrouped_light === true && node.HUELightsBelongingToGroupWhileDaytime !== null) {
435
- // The DayNight has switched into day, so restore the previous light state, belonging to the group
436
- let bAtLeastOneIsOn = false
437
- for (let index = 0; index < node.HUELightsBelongingToGroupWhileDaytime.length; index++) { // Ensure, at least 1 lamp was on, otherwise turn all lamps on
438
- const element = node.HUELightsBelongingToGroupWhileDaytime[index].light[0]
439
- if (element.on.on === true) {
440
- bAtLeastOneIsOn = true
441
- break
442
- }
443
- }
444
- for (let index = 0; index < node.HUELightsBelongingToGroupWhileDaytime.length; index++) {
445
- const element = node.HUELightsBelongingToGroupWhileDaytime[index].light[0]
446
- if (bAtLeastOneIsOn === true) {
447
- state = { on: element.on, dimming: element.dimming, color: element.color, color_temperature: element.color_temperature }
448
- } else {
449
- // Failsafe all on
450
- state = { on: { on: true }, dimming: element.dimming, color: element.color, color_temperature: element.color_temperature }
451
- }
452
- if (element.color_temperature !== undefined && element.color_temperature.mirek === null) delete state.color_temperature // Otherwise the lamp will not turn on due to an error. color_temperature.mirek: color temperature in mirek is null when the light color is not in the ct spectrum
453
- node.serverHue.hueManager.writeHueQueueAdd(element.id, state, 'setLight')
454
- }
455
- node.setNodeStatusHue({
456
- fill: 'green',
457
- shape: 'dot',
458
- text: 'KNX->Matter',
459
- payload: "Resuming all group's light"
460
- })
461
- node.HUELightsBelongingToGroupWhileDaytime = null // Nullize the object.
462
- return
463
- }
464
- } else {
465
- let colorChoosen
466
- let temperatureChoosen
467
- let brightnessChoosen
468
- // The light must support the temperature (in this case, colorAtSwitchOnNightTime is an object {kelvin:xx, brightness:yy})
469
- if (node.currentHUEDevice.color_temperature !== undefined) {
470
- if (node.DayTime === true && config.specifySwitchOnBrightness === 'temperature') {
471
- temperatureChoosen = config.colorAtSwitchOnDayTime.kelvin
472
- } else if (node.DayTime === false && config.enableDayNightLighting === 'temperature') {
473
- temperatureChoosen = config.colorAtSwitchOnNightTime.kelvin
474
- }
475
- }
476
- if (node.currentHUEDevice.dimming !== undefined) {
477
- // Check wether the user selected specific brightness at switch on (in this case, colorAtSwitchOnNightTime is an object {kelvin:xx, brightness:yy})
478
- if (node.DayTime === true && config.specifySwitchOnBrightness === 'temperature') {
479
- brightnessChoosen = config.colorAtSwitchOnDayTime.brightness
480
- } else if (node.DayTime === false && config.enableDayNightLighting === 'temperature') {
481
- brightnessChoosen = config.colorAtSwitchOnNightTime.brightness
482
- }
483
- }
484
- if (node.currentHUEDevice.color !== undefined) {
485
- // Check wether the user selected specific color at switch on (in this case, colorAtSwitchOnDayTime is a text with HTML web color)
486
- if (node.DayTime === true && config.specifySwitchOnBrightness === 'yes') {
487
- colorChoosen = config.colorAtSwitchOnDayTime
488
- } else if (node.DayTime === false && config.enableDayNightLighting === 'yes') {
489
- colorChoosen = config.colorAtSwitchOnNightTime
490
- }
491
- }
492
- // Create the HUE command
493
- if (colorChoosen !== undefined) {
494
- // Now we have a jColorChoosen. Proceed illuminating the light
495
- let gamut = null
496
- if (node.currentHUEDevice.color.gamut !== undefined) {
497
- gamut = node.currentHUEDevice.color.gamut
498
- }
499
- const dretXY = hueColorConverter.ColorConverter.calculateXYFromRGB(colorChoosen.red, colorChoosen.green, colorChoosen.blue, gamut)
500
- const dbright = hueColorConverter.ColorConverter.getBrightnessFromRGBOrHex(colorChoosen.red, colorChoosen.green, colorChoosen.blue)
501
- node.currentHUEDevice.dimming.brightness = Math.round(dbright, 0)
502
- if (node.currentHUEDevice.color !== undefined) node.currentHUEDevice.color.xy = dretXY // 26/03/2024
503
- node.updateKNXBrightnessState(node.currentHUEDevice.dimming.brightness)
504
- state = dbright > 0 ? { on: { on: true }, dimming: { brightness: dbright }, color: { xy: dretXY } } : { on: { on: false } }
505
- // state = { on: { on: true }, dimming: { brightness: dbright }, color: { xy: dretXY } };
506
- } else if (temperatureChoosen !== undefined) {
507
- // Kelvin
508
- const mirek = hueColorConverter.ColorConverter.kelvinToMirek(temperatureChoosen)
509
- node.currentHUEDevice.color_temperature.mirek = mirek
510
- node.currentHUEDevice.dimming.brightness = brightnessChoosen
511
- node.updateKNXBrightnessState(node.currentHUEDevice.dimming.brightness)
512
- // Kelvin temp
513
- state = brightnessChoosen > 0 ? { on: { on: true }, dimming: { brightness: brightnessChoosen }, color_temperature: { mirek } } : { on: { on: false } }
514
- // state = { on: { on: true }, dimming: { brightness: brightnessChoosen }, color_temperature: { mirek: mirek } };
515
- } else if (brightnessChoosen !== undefined) {
516
- state = brightnessChoosen > 0 ? { on: { on: true }, dimming: { brightness: brightnessChoosen } } : { on: { on: false } }
517
- // state = { on: { on: true }, dimming: { brightness: brightnessChoosen } };
518
- } else {
519
- state = { on: { on: true } }
520
- }
521
- }
522
- } else {
523
- // Stop color cycle
524
- if (node.timerColorCycle !== undefined) clearInterval(node.timerColorCycle)
525
- // Stop Blinking
526
- if (node.timerBlink !== undefined) clearInterval(node.timerBlink)
527
- state = { on: { on: false } }
528
- }
529
-
530
- node.syncCurrentHUEDeviceFromKNXState(state) // Starting from v 4.1.31
531
- node.writeHueState(state)
532
- node.setNodeStatusHue({
533
- fill: 'green',
534
- shape: 'dot',
535
- text: 'KNX->Matter',
536
- payload: state
537
- })
538
- break
539
- case config.GALightDIM:
540
- // { decr_incr: 1, data: 1 } : Start increasing until { decr_incr: 0, data: 0 } is received.
541
- // { decr_incr: 0, data: 1 } : Start decreasing until { decr_incr: 0, data: 0 } is received.
542
- msg.payload = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptLightDIM))
543
- node.hueDimming(msg.payload.decr_incr, msg.payload.data, config.dimSpeed)
544
- node.setNodeStatusHue({
545
- fill: 'green', shape: 'dot', text: 'KNX->Matter', payload: JSON.stringify(msg.payload)
546
- })
547
- break
548
- case config.GALightHSV_H_DIM:
549
- // { decr_incr: 1, data: 1 } : Start increasing until { decr_incr: 0, data: 0 } is received.
550
- // { decr_incr: 0, data: 1 } : Start decreasing until { decr_incr: 0, data: 0 } is received.
551
- msg.payload = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptLightDIM))
552
- node.hueDimmingHSV_H(msg.payload.decr_incr, msg.payload.data, config.HSVDimSpeed)
553
- node.setNodeStatusHue({
554
- fill: 'green', shape: 'dot', text: 'KNX->Matter', payload: JSON.stringify(msg.payload)
555
- })
556
- break
557
- case config.GALightHSV_S_DIM:
558
- // { decr_incr: 1, data: 1 } : Start increasing until { decr_incr: 0, data: 0 } is received.
559
- // { decr_incr: 0, data: 1 } : Start decreasing until { decr_incr: 0, data: 0 } is received.
560
- msg.payload = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptLightDIM))
561
- node.hueDimmingHSV_S(msg.payload.decr_incr, msg.payload.data, config.HSVDimSpeed)
562
- node.setNodeStatusHue({
563
- fill: 'green', shape: 'dot', text: 'KNX->Matter', payload: JSON.stringify(msg.payload)
564
- })
565
- break
566
- case config.GALightKelvin:
567
- let retMirek
568
- let kelvinValue = 0
569
- msg.payload = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptLightKelvin))
570
- if (config.dptLightKelvin === '7.600') {
571
- if (msg.payload > 6535) msg.payload = 6535
572
- if (msg.payload < 2000) msg.payload = 2000
573
- kelvinValue = msg.payload// hueColorConverter.ColorConverter.scale(msg.payload, [0, 65535], [2000, 6535]);
574
- retMirek = hueColorConverter.ColorConverter.kelvinToMirek(kelvinValue)
575
- } else if (config.dptLightKelvin === '9.002') {
576
- // Relative temperature in Kelvin. Use HUE scale.
577
- if (msg.payload > 6535) msg.payload = 6535
578
- if (msg.payload < 2000) msg.payload = 2000
579
- retMirek = hueColorConverter.ColorConverter.kelvinToMirek(msg.payload)
580
- }
581
- state = { color_temperature: { mirek: retMirek } }
582
- node.syncCurrentHUEDeviceFromKNXState(state) // Starting from v 4.1.31
583
- node.writeHueState(state)
584
- node.setNodeStatusHue({
585
- fill: 'green',
586
- shape: 'dot',
587
- text: 'KNX->Matter',
588
- payload: kelvinValue
589
- })
590
- break
591
- case config.GADaylightSensor:
592
- node.DayTime = Boolean(dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptDaylightSensor)))
593
- if (config.invertDayNight === true) node.DayTime = !node.DayTime
594
- if (config.specifySwitchOnBrightness === 'no') {
595
- // This retains the HUE device status while daytime, to be restored after nighttime elapsed. https://github.com/Supergiovane/node-red-contrib-knx-ultimate/issues/298
596
- if (node.DayTime === false) {
597
- if (node.isGrouped_light === false) node.HUEDeviceWhileDaytime = cloneDeep(node.currentHUEDevice) // DayTime has switched to false: save the currentHUEDevice into the HUEDeviceWhileDaytime
598
- if (node.isGrouped_light === true) {
599
- (async () => {
600
- try {
601
- const retLights = await node.serverHue.getAllLightsBelongingToTheGroup(node.hueDevice, false)
602
- node.HUELightsBelongingToGroupWhileDaytime = cloneDeep(retLights) // DayTime has switched to false: save the lights belonging to the group into the HUELightsBelongingToGroupWhileDaytime array
603
- } catch (error) { /* empty */ }
604
- })()
605
- }
606
- }
607
- } else {
608
- node.HUEDeviceWhileDaytime = null
609
- node.HUELightsBelongingToGroupWhileDaytime = null
610
- }
611
- node.setNodeStatusHue({
612
- fill: 'green',
613
- shape: 'dot',
614
- text: 'KNX->Matter Daytime',
615
- payload: node.DayTime
616
- })
617
-
618
- break
619
- case config.GALightKelvinDIM:
620
- if (config.dptLightKelvinDIM === '3.007') {
621
- // MDT smartbutton will dim the color temperature
622
- // { decr_incr: 1, data: 1 } : Start increasing until { decr_incr: 0, data: 0 } is received.
623
- // { decr_incr: 0, data: 1 } : Start decreasing until { decr_incr: 0, data: 0 } is received.
624
- msg.payload = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptLightKelvinDIM))
625
- node.hueDimmingTunableWhite(msg.payload.decr_incr, msg.payload.data, 5000)
626
- node.setNodeStatusHue({
627
- fill: 'green', shape: 'dot', text: 'KNX->Matter', payload: JSON.stringify(msg.payload)
628
- })
629
- }
630
- break
631
- case config.GALightKelvinPercentage:
632
- if (config.dptLightKelvinPercentage === '5.001') {
633
- // 0-100% tunable white
634
- msg.payload = 100 - dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptLightKelvinPercentage))
635
- // msg.payload = msg.payload <= 0 ? 1 : msg.payload
636
- const retMirek = hueColorConverter.ColorConverter.scale(msg.payload, [0, 100], [153, 500])
637
- msg.payload = retMirek
638
- state = { color_temperature: { mirek: msg.payload } }
639
- node.syncCurrentHUEDeviceFromKNXState(state) // Starting from v 4.1.31
640
- node.writeHueState(state)
641
- node.setNodeStatusHue({
642
- fill: 'green',
643
- shape: 'dot',
644
- text: 'KNX->Matter',
645
- payload: state
646
- })
647
- }
648
- break
649
- case config.GALightBrightness:
650
- msg.payload = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptLightBrightness))
651
- if (typeof msg.payload !== 'number' || Number.isNaN(msg.payload)) throw new Error('Invalid KNX brightness payload')
652
- state = { dimming: { brightness: msg.payload } }
653
- if (msg.payload === 0) {
654
- state.on = { on: false }
655
- } else if (node.currentHUEDevice !== undefined && node.currentHUEDevice.on?.on === true) {
656
- state.on = { on: true }
657
- }
658
- node.syncCurrentHUEDeviceFromKNXState(state) // Starting from v 4.1.31
659
- node.writeHueState(state)
660
- node.setNodeStatusHue({
661
- fill: 'green',
662
- shape: 'dot',
663
- text: 'KNX->Matter',
664
- payload: state
665
- })
666
- break
667
- case config.GALightColor:
668
- msg.payload = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptLightColor))
669
- let gamut = null
670
- if (
671
- node.currentHUEDevice !== undefined &&
672
- node.currentHUEDevice.color !== undefined &&
673
- node.currentHUEDevice.color.gamut !== undefined
674
- ) {
675
- gamut = node.currentHUEDevice.color.gamut
676
- }
677
- const retXY = hueColorConverter.ColorConverter.calculateXYFromRGB(msg.payload.red, msg.payload.green, msg.payload.blue, gamut)
678
- const bright = hueColorConverter.ColorConverter.getBrightnessFromRGBOrHex(msg.payload.red, msg.payload.green, msg.payload.blue)
679
- state = { dimming: { brightness: bright }, color: { xy: retXY } }
680
- if (node.currentHUEDevice === undefined) {
681
- // Grouped light
682
- state.on = { on: bright > 0 }
683
- } else {
684
- // Light
685
- if (node.currentHUEDevice.on.on === false && bright > 0) state.on = { on: true }
686
- if (node.currentHUEDevice.on.on === true && bright === 0) state = { on: { on: false }, dimming: { brightness: bright } }
687
- }
688
- node.syncCurrentHUEDeviceFromKNXState(state) // Starting from v 4.1.31
689
- node.writeHueState(state)
690
- node.setNodeStatusHue({
691
- fill: 'green',
692
- shape: 'dot',
693
- text: 'KNX->Matter',
694
- payload: state
695
- })
696
- break
697
- case config.GALightBlink:
698
- const gaVal = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptLightBlink))
699
- if (gaVal) {
700
- node.timerBlink = setInterval(() => {
701
- if (node.blinkValue === undefined) node.blinkValue = true
702
- node.blinkValue = !node.blinkValue
703
- msg.payload = node.blinkValue
704
- // state = msg.payload === true ? { on: { on: true } } : { on: { on: false } }
705
- state = msg.payload === true
706
- ? { on: { on: true }, dimming: { brightness: 100 }, dynamics: { duration: 0 } }
707
- : { on: { on: false }, dimming: { brightness: 0 }, dynamics: { duration: 0 } }
708
- node.writeHueState(state)
709
- }, 1500)
710
- } else {
711
- if (node.timerBlink !== undefined) clearInterval(node.timerBlink)
712
- node.writeHueState({ on: { on: false } })
713
- }
714
- node.setNodeStatusHue({
715
- fill: 'green',
716
- shape: 'dot',
717
- text: 'KNX->Matter',
718
- payload: gaVal
719
- })
720
- break
721
- case config.GALightColorCycle:
722
- {
723
- if (node.timerColorCycle !== undefined) clearInterval(node.timerColorCycle)
724
- const gaValColorCycle = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptLightColorCycle))
725
- if (gaValColorCycle === true) {
726
- node.writeHueState({ on: { on: true } })
727
- node.timerColorCycle = setInterval(() => {
728
- try {
729
- const red = getRandomIntInclusive(0, 255)
730
- const green = getRandomIntInclusive(0, 255)
731
- const blue = getRandomIntInclusive(0, 255)
732
- let gamut = null
733
- if (
734
- node.currentHUEDevice !== undefined &&
735
- node.currentHUEDevice.color !== undefined &&
736
- node.currentHUEDevice.color.gamut !== undefined
737
- ) {
738
- gamut = node.currentHUEDevice.color.gamut
739
- }
740
- const retXY = hueColorConverter.ColorConverter.calculateXYFromRGB(red, green, blue, gamut)
741
- const bright = hueColorConverter.ColorConverter.getBrightnessFromRGBOrHex(red, green, blue)
742
- state = bright > 0 ? { on: { on: true }, dimming: { brightness: bright }, color: { xy: retXY } } : { on: { on: false } }
743
- node.writeHueState(state)
744
- } catch (error) { }
745
- }, 10000)
746
- } else {
747
- if (node.timerColorCycle !== undefined) clearInterval(node.timerColorCycle)
748
- node.writeHueState({ on: { on: false } })
749
- }
750
- node.setNodeStatusHue({
751
- fill: 'green',
752
- shape: 'dot',
753
- text: 'KNX->Matter',
754
- payload: gaValColorCycle
755
- })
756
- }
757
- break
758
- default:
759
- break
760
- }
761
- } catch (error) {
762
- node.status({
763
- fill: 'red',
764
- shape: 'dot',
765
- text: `KNX->Matter errorRead ${error.message} (${formatTs(new Date())})`
766
- })
767
- RED.log.error(`knxUltimateMatterControllerDevice: node.handleSend: if (msg.knx.event !== "GroupValue_Read"): ${error.message} : ${error.stack || ''} `)
768
- }
769
- }
770
-
771
- // I must respond to query requests (read request) sent from the KNX BUS
772
- try {
773
- if (msg.knx.event === 'GroupValue_Read' && node.currentHUEDevice !== undefined) {
774
- const zeroBrightnessWhenOff = (config.updateKNXBrightnessStatusOnHUEOnOff === undefined || config.updateKNXBrightnessStatusOnHUEOnOff === 'onhueoff')
775
- let ret
776
- switch (msg.knx.destination) {
777
- case config.GALightState:
778
- ret = node.currentHUEDevice.on.on
779
- if (ret !== undefined) node.updateKNXLightState(ret, 'response')
780
- break
781
- case config.GALightColorState:
782
- ret = node.currentHUEDevice.color.xy
783
- if (ret !== undefined) node.updateKNXLightColorState(node.currentHUEDevice.color, 'response')
784
- break
785
- case config.GALightKelvinPercentageState:
786
- // The kelvin level belongs to the group defice, so i don't need to get the first light in the collection (if the device is a grouped_light)
787
- ret = node.currentHUEDevice.color_temperature.mirek
788
- if (ret !== undefined) node.updateKNXLightKelvinPercentageState(ret, 'response')
789
- // if (node.isGrouped_light === false) {
790
- // ret = node.currentHUEDevice.color_temperature.mirek;
791
- // if (ret !== undefined) node.updateKNXLightKelvinPercentageState(ret, "response");
792
- // } else {
793
- // (async () => {
794
- // try {
795
- // // Find the first light in the collection, having the color_temperature capabilities
796
- // const devices = await node.serverHue.getAllLightsBelongingToTheGroup(node.hueDevice, false);
797
- // for (let index = 0; index < devices.length; index++) {
798
- // const element = devices[index];
799
- // if (element.light[0].color_temperature !== undefined) {
800
- // ret = element.light[0].color_temperature.mirek;
801
- // break;
802
- // }
803
- // }
804
- // if (ret !== undefined) node.updateKNXLightKelvinPercentageState(ret, "response");
805
- // } catch (error) { /* empty */ }
806
- // })();
807
- // }
808
- break
809
- case config.GALightBrightnessState:
810
- // Hue keeps the last brightness even when the light is OFF. If the user enabled "brightness status -> 0 on HUE off",
811
- // keep returning 0 while OFF to avoid the KNX status jumping back to the last/start value after some time/read-requests.
812
- if (zeroBrightnessWhenOff === true && node.currentHUEDevice?.on?.on === false) {
813
- ret = 0
814
- } else {
815
- ret = node.currentHUEDevice.dimming.brightness
816
- }
817
- if (ret !== undefined) node.updateKNXBrightnessState(ret, 'response')
818
- break
819
- case config.GALightKelvinState:
820
- // The kelvin level belongs to the group defice, so i don't need to get the first light in the collection (if the device is a grouped_light)
821
- ret = node.currentHUEDevice.color_temperature.mirek
822
- if (ret !== undefined) node.updateKNXLightKelvinState(ret, 'response')
823
- // if (node.isGrouped_light === false) {
824
- // ret = node.currentHUEDevice.color_temperature.mirek;
825
- // if (ret !== undefined) node.updateKNXLightKelvinState(ret, "response");
826
- // } else {
827
- // (async () => {
828
- // try {
829
- // // Find the first light in the collection, having the color_temperature capabilities
830
- // const devices = await node.serverHue.getAllLightsBelongingToTheGroup(node.hueDevice, false);
831
- // for (let index = 0; index < devices.length; index++) {
832
- // const element = devices[index];
833
- // if (element.light[0].color_temperature !== undefined) {
834
- // ret = element.light[0].color_temperature.mirek;
835
- // break;
836
- // }
837
- // }
838
- // if (ret !== undefined) node.updateKNXLightKelvinState(ret, "response");
839
- // } catch (error) { /* empty */ }
840
- // })();
841
- // }
842
- break
843
- default:
844
- break
845
- }
846
- }
847
- } catch (error) {
848
- node.status({
849
- fill: 'red',
850
- shape: 'dot',
851
- text: `KNX->Matter error :-( ${error.message} (${formatTs(new Date())})`
852
- })
853
- RED.log.error(`knxUltimateMatterControllerDevice: node.handleSend: if (msg.knx.event === "GroupValue_Read" && node.currentHUEDevice !== undefined): ${error.message} : ${error.stack || ''} `)
854
- }
855
- }
856
-
857
- // Start dimming
858
- // ***********************************************************
859
- node.hueDimming = function hueDimming (_KNXaction, _KNXbrightness_Direction, _dimSpeedInMillisecs = undefined) {
860
- // 31/10/2023 after many attempts to use dimming_delta function of the HueApeV2, loosing days of my life, without a decent success, will use the standard dimming calculations
861
- // i decide to go to the "step brightness" way.
862
- try {
863
- let hueTelegram = {}
864
- let numStep = 10 // Steps from 0 to 100 by 10
865
- const extendedConf = {}
866
-
867
- if (_KNXbrightness_Direction === 0 && _KNXaction === 0) {
868
- // STOP DIM
869
- if (node.timerStepDim !== undefined) clearInterval(node.timerStepDim)
870
- node.brightnessStep = null
871
- node.deleteHueStateQueue() // Clear dimming queue.
872
- return
873
- }
874
-
875
- // 26/03/2024 set the extended configuration as well, because the light was off (so i've been unable to set it up elsewhere)
876
- if (node.currentHUEDevice.on !== undefined && node.currentHUEDevice.on.on === false) {
877
- // if (node.currentHUEDevice.color !== undefined) extendedConf.color = { xy: node.currentHUEDevice.color.xy }; // DO NOT ADD THE COLOR, BECAUSE THE COLOR HAS ALSO THE BRIGHTNESS, SO ALL THE DATA NEEDED TO BE SWITCHED ON CORRECLY
878
- if (node.currentHUEDevice.color_temperature !== undefined) extendedConf.color_temperature = { mirek: node.currentHUEDevice.color_temperature.mirek }
879
- }
880
-
881
- // If i'm dimming up while the light is off, start the dim with the initial brightness set to zero
882
- if (_KNXbrightness_Direction > 0 && _KNXaction === 1 && node.currentHUEDevice.on !== undefined && node.currentHUEDevice.on.on === false) {
883
- node.brightnessStep = null
884
- node.currentHUEDevice.dimming.brightness = 0
885
- }
886
-
887
- // Set the actual brightness to start with
888
- if (node.brightnessStep === null || node.brightnessStep === undefined) node.brightnessStep = node.currentHUEDevice.dimming.brightness !== undefined ? node.currentHUEDevice.dimming.brightness : 50
889
- node.brightnessStep = Math.ceil(Number(node.brightnessStep))
890
-
891
- // We have also minDimLevelLight and maxDimLevelLight to take care of.
892
- let minDimLevelLight
893
- if (config.minDimLevelLight === undefined) {
894
- minDimLevelLight = 10
895
- } else if (config.minDimLevelLight === 'useHueLightLevel') {
896
- minDimLevelLight = node.currentHUEDevice.dimming.min_dim_level === undefined ? 10 : node.currentHUEDevice.dimming.min_dim_level
897
- } else {
898
- minDimLevelLight = Number(config.minDimLevelLight)
899
- }
900
- const maxDimLevelLight = config.maxDimLevelLight === undefined ? 100 : Number(config.maxDimLevelLight)
901
-
902
- // Set the speed
903
- _dimSpeedInMillisecs /= numStep
904
- numStep = Math.round((maxDimLevelLight - minDimLevelLight) / numStep, 0)
905
-
906
- if (_KNXbrightness_Direction > 0 && _KNXaction === 1) {
907
- // DIM UP
908
- if (node.timerStepDim !== undefined) clearInterval(node.timerStepDim)
909
- node.timerStepDim = setInterval(() => {
910
- node.updateKNXBrightnessState(node.brightnessStep) // Unnecessary, but necessary to set the KNX Status in real time.
911
- node.brightnessStep += numStep
912
- if (node.brightnessStep > maxDimLevelLight) node.brightnessStep = maxDimLevelLight
913
- hueTelegram = { dimming: { brightness: node.brightnessStep }, dynamics: { duration: _dimSpeedInMillisecs + 500 } } // + is to avoid ladder effect
914
- // Switch on the light if off
915
- if (node.currentHUEDevice.on !== undefined && node.currentHUEDevice.on.on === false) {
916
- hueTelegram.on = { on: true }
917
- Object.assign(hueTelegram, extendedConf) // 26/03/2024 add extended conf
918
- }
919
- // console.log(hueTelegram)
920
- node.writeHueState(hueTelegram)
921
- if (node.brightnessStep >= maxDimLevelLight) clearInterval(node.timerStepDim)
922
- }, _dimSpeedInMillisecs)
923
- }
924
- if (_KNXbrightness_Direction > 0 && _KNXaction === 0) {
925
- if (node.currentHUEDevice.on.on === false) return // Don't dim down, if the light is already off.
926
- // DIM DOWN
927
- if (node.timerStepDim !== undefined) clearInterval(node.timerStepDim)
928
- node.timerStepDim = setInterval(() => {
929
- node.updateKNXBrightnessState(node.brightnessStep) // Unnecessary, but necessary to set the KNX Status in real time.
930
- node.brightnessStep -= numStep
931
- if (node.brightnessStep < minDimLevelLight) node.brightnessStep = minDimLevelLight
932
- hueTelegram = { dimming: { brightness: node.brightnessStep }, dynamics: { duration: _dimSpeedInMillisecs + 500 } }// + 100 is to avoid ladder effect
933
- // Switch off the light if on
934
- if (node.currentHUEDevice.on !== undefined && node.currentHUEDevice.on.on === true && node.brightnessStep === 0) {
935
- hueTelegram.on = { on: false }
936
- }
937
- node.writeHueState(hueTelegram)
938
- if (node.brightnessStep <= minDimLevelLight) clearInterval(node.timerStepDim)
939
- }, _dimSpeedInMillisecs)
940
- }
941
- } catch (error) { }
942
- }
943
- // ***********************************************************
944
-
945
- // Start dimming tunable white
946
- // mirek: required(integer minimum: 153, maximum: 500)
947
- // ***********************************************************
948
- node.hueDimmingTunableWhite = function hueDimmingTunableWhite (_KNXaction, _KNXbrightness_DirectionTunableWhite, _dimSpeedInMillisecsTunableWhite = undefined) {
949
- // 23/23/2023 after many attempts to use dimming_delta function of the HueApeV2, loosing days of my life, without a decent success, will use the standard dimming calculations
950
- // i decide to go to the "step brightness" way.
951
- try {
952
- if (_KNXbrightness_DirectionTunableWhite === 0 && _KNXaction === 0) {
953
- // STOP DIM
954
- if (node.timerStepDimTunableWhite !== undefined) clearInterval(node.timerStepDimTunableWhite)
955
- node.brightnessStepTunableWhite = null
956
- node.deleteHueStateQueue() // Clear dimming queue.
957
- return
958
- }
959
-
960
- let numStepTunableWhite = 10 // Steps from 153 to 500
961
- if (config.invertDimTunableWhiteDirection === true) {
962
- if (_KNXaction === 1) { _KNXaction = 0 } else { _KNXaction = 1 }
963
- }
964
-
965
- // Set the actual brightness to start with
966
- if (node.brightnessStepTunableWhite === null || node.brightnessStepTunableWhite === undefined) node.brightnessStepTunableWhite = node.currentHUEDevice.color_temperature.mirek || 372
967
- node.brightnessStepTunableWhite = Math.ceil(Number(node.brightnessStepTunableWhite))
968
-
969
- // Set the speed
970
- _dimSpeedInMillisecsTunableWhite = Math.ceil(_dimSpeedInMillisecsTunableWhite / numStepTunableWhite)
971
-
972
- const minDimLevelLightTunableWhite = 153
973
- const maxDimLevelLightTunableWhite = 500
974
- // numStepTunableWhite = hueColorConverter.ColorConverter.scale(numStepTunableWhite, [0, 100], [minDimLevelLightTunableWhite, maxDimLevelLightTunableWhite]);
975
- // numStepTunableWhite = hueColorConverter.ColorConverter.scale(numStepTunableWhite, [node.brightnessStepTunableWhite, maxDimLevelLightTunableWhite], [node.brightnessStepTunableWhite, maxDimLevelLightTunableWhite]);
976
- numStepTunableWhite = Math.round((maxDimLevelLightTunableWhite - minDimLevelLightTunableWhite) / numStepTunableWhite, 0)
977
-
978
- if (_KNXbrightness_DirectionTunableWhite > 0 && _KNXaction === 1) {
979
- // DIM UP
980
- if (node.timerStepDimTunableWhite !== undefined) clearInterval(node.timerStepDimTunableWhite)
981
- node.timerStepDimTunableWhite = setInterval(() => {
982
- node.updateKNXLightKelvinPercentageState(node.brightnessStepTunableWhite) // Unnecessary, but necessary to set the KNX Status in real time.
983
- node.brightnessStepTunableWhite += numStepTunableWhite // *2 to speed up the things
984
- if (node.brightnessStepTunableWhite > maxDimLevelLightTunableWhite) node.brightnessStepTunableWhite = maxDimLevelLightTunableWhite
985
- const hueTelegram = { color_temperature: { mirek: node.brightnessStepTunableWhite }, dynamics: { duration: _dimSpeedInMillisecsTunableWhite } }
986
- // Switch on the light if off
987
- if (node.currentHUEDevice.on !== undefined && node.currentHUEDevice.on.on === false) {
988
- hueTelegram.on = { on: true }
989
- }
990
- node.writeHueState(hueTelegram)
991
- if (node.brightnessStepTunableWhite >= maxDimLevelLightTunableWhite) clearInterval(node.timerStepDimTunableWhite)
992
- }, _dimSpeedInMillisecsTunableWhite)
993
- }
994
- if (_KNXbrightness_DirectionTunableWhite > 0 && _KNXaction === 0) {
995
- if (node.currentHUEDevice.on.on === false) return // Don't dim down, if the light is already off.
996
- // DIM DOWN
997
- if (node.timerStepDimTunableWhite !== undefined) clearInterval(node.timerStepDimTunableWhite)
998
- node.timerStepDimTunableWhite = setInterval(() => {
999
- node.updateKNXLightKelvinPercentageState(node.brightnessStepTunableWhite) // Unnecessary, but necessary to set the KNX Status in real time.
1000
- node.brightnessStepTunableWhite -= numStepTunableWhite // *2 to speed up the things
1001
- if (node.brightnessStepTunableWhite < minDimLevelLightTunableWhite) node.brightnessStepTunableWhite = minDimLevelLightTunableWhite
1002
- const hueTelegram = { color_temperature: { mirek: node.brightnessStepTunableWhite }, dynamics: { duration: _dimSpeedInMillisecsTunableWhite } }
1003
- // Switch off the light if on
1004
- if (node.currentHUEDevice.on !== undefined && node.currentHUEDevice.on.on === true && node.brightnessStepTunableWhite === 0) {
1005
- hueTelegram.on = { on: false }
1006
- }
1007
- node.writeHueState(hueTelegram)
1008
- if (node.brightnessStepTunableWhite <= minDimLevelLightTunableWhite) clearInterval(node.timerStepDimTunableWhite)
1009
- }, _dimSpeedInMillisecsTunableWhite)
1010
- }
1011
- } catch (error) { }
1012
- }
1013
- // ***********************************************************
1014
-
1015
- /**
1016
- * Starts dimming / stop dimming of the HUE
1017
- * @param {number} _KNXaction 1 for start, 0 for stop
1018
- * @param {number} _KNXbrightness_DirectionHSV_H 1 for up, 0 for down
1019
- * @param {number} _dimSpeedInMillisecsHSV Speed time in milliseconds
1020
- * @returns {}
1021
- */
1022
- node.hueDimmingHSV_H = function hueDimmingHSV_H (_KNXaction, _KNXbrightness_DirectionHSV_H, _dimSpeedInMillisecsHSV = undefined) {
1023
- // After many attempts to use dimming_delta function of the HueApiV2, loosing days of my life, without a decent success, will use the standard dimming calculations
1024
- // i decide to go to the "step brightness" way.
1025
- try {
1026
- if (_KNXbrightness_DirectionHSV_H === 0 && _KNXaction === 0) {
1027
- // STOP DIM
1028
- if (node.timerStepDimHSV_H !== undefined) clearInterval(node.timerStepDimHSV_H)
1029
- node.deleteHueStateQueue() // Clear dimming queue.
1030
- return
1031
- }
1032
-
1033
- let xyBrightnessToHsv
1034
- if (node.currentHUEDevice.color !== undefined && node.currentHUEDevice.color.xy !== undefined) {
1035
- // Get the XY + brightness from the lamp and transform it into HSV
1036
- // xyBrightnessToHsv = hueColorConverter.ColorConverter.xyBrightnessToHsv(node.currentHUEDevice.color.xy.x, node.currentHUEDevice.color.xy.y, node.currentHUEDevice.dimming.brightness);
1037
- xyBrightnessToHsv = hueColorConverter.ColorConverter.xyBrightnessToHsv(hueColorConverter.ColorConverter.scale(node.currentHUEDevice.color.xy.x, [0, 1], [0, 100]), hueColorConverter.ColorConverter.scale(node.currentHUEDevice.color.xy.y, [0, 1], [0, 100]), node.currentHUEDevice.dimming.brightness)
1038
- } else {
1039
- return // Something wrong here.
1040
- }
1041
- let numStepHSV_H = 10 // Steps from 0 to 100
1042
-
1043
- // Set the actual brightness to start with
1044
- if (node.brightnessStepHSV_H === null || node.brightnessStepHSV_H === undefined) node.brightnessStepHSV_H = node.currentHUEDevice.dimming.brightness
1045
- node.brightnessStepHSV_H = Math.ceil(Number(node.brightnessStepHSV_H))
1046
-
1047
- const minDimLevelLightHSV_H = 1
1048
- const maxDimLevelLightHSV_H = 100
1049
- numStepHSV_H = Math.round((maxDimLevelLightHSV_H - minDimLevelLightHSV_H) / numStepHSV_H, 0)
1050
- // Set the speed
1051
- _dimSpeedInMillisecsHSV = Math.ceil(_dimSpeedInMillisecsHSV / (maxDimLevelLightHSV_H / numStepHSV_H))
1052
-
1053
- if (_KNXbrightness_DirectionHSV_H > 0 && _KNXaction === 1) {
1054
- // DIM UP
1055
- if (node.timerStepDimHSV_H !== undefined) clearInterval(node.timerStepDimHSV_H)
1056
- node.timerStepDimHSV_H = setInterval(() => {
1057
- node.deleteHueStateQueue() // Clear dimming queue.
1058
- node.brightnessStepHSV_H += numStepHSV_H
1059
- if (node.brightnessStepHSV_H > maxDimLevelLightHSV_H) node.brightnessStepHSV_H = maxDimLevelLightHSV_H
1060
- // node.updateKNXLightHSV_H_State(node.brightnessStepHSV_H); // Unnecessary, but necessary to set the KNX Status in real time.
1061
- xyBrightnessToHsv.h = node.brightnessStepHSV_H
1062
- const hsvToXYBri = hueColorConverter.ColorConverter.hsvToxyBrightness(xyBrightnessToHsv, node.currentHUEDevice.color.gamut)
1063
- const hueTelegram = { color: { xy: { x: hsvToXYBri.x, y: hsvToXYBri.y } }, dynamics: { duration: _dimSpeedInMillisecsHSV + 500 } } // Add some ms, to prevent the "ladder" step effect.
1064
- // Switch on the light if off
1065
- if (node.currentHUEDevice.on !== undefined && node.currentHUEDevice.on.on === false) {
1066
- hueTelegram.on = { on: true }
1067
- }
1068
- node.currentHUEDevice.color.xy = hsvToXYBri// Unnecessary, but necessary to set the KNX Status in real time.
1069
- node.updateKNXLightColorState(node.currentHUEDevice.color)
1070
- node.writeHueState(hueTelegram)
1071
- if (node.brightnessStepHSV_H >= maxDimLevelLightHSV_H) {
1072
- if (node.timerStepDimHSV_H !== undefined) clearInterval(node.timerStepDimHSV_H)
1073
- }
1074
- }, _dimSpeedInMillisecsHSV)
1075
- }
1076
- if (_KNXbrightness_DirectionHSV_H > 0 && _KNXaction === 0) {
1077
- if (node.currentHUEDevice.on.on === false) return // Don't dim down, if the light is already off.
1078
- // DIM DOWN
1079
- if (node.timerStepDimHSV_H !== undefined) clearInterval(node.timerStepDimHSV_H)
1080
- node.timerStepDimHSV_H = setInterval(() => {
1081
- node.deleteHueStateQueue() // Clear dimming queue.
1082
- node.brightnessStepHSV_H -= numStepHSV_H // *2 to speed up the things
1083
- if (node.brightnessStepHSV_H < minDimLevelLightHSV_H) node.brightnessStepHSV_H = minDimLevelLightHSV_H
1084
- // node.updateKNXLightHSV_H_State(node.brightnessStepHSV_H); // Unnecessary, but necessary to set the KNX Status in real time.
1085
- // Produco l'RGB
1086
- xyBrightnessToHsv.h = node.brightnessStepHSV_H
1087
- const hsvToXYBri = hueColorConverter.ColorConverter.hsvToxyBrightness(xyBrightnessToHsv, node.currentHUEDevice.color.gamut)
1088
- const hueTelegram = { color: { xy: { x: hsvToXYBri.x, y: hsvToXYBri.y } }, dynamics: { duration: _dimSpeedInMillisecsHSV + 500 } }
1089
- // Switch off the light if on
1090
- if (node.currentHUEDevice.on !== undefined && node.currentHUEDevice.on.on === true && node.brightnessStepHSV_H === 0) {
1091
- hueTelegram.on = { on: false }
1092
- }
1093
- node.currentHUEDevice.color.xy = hsvToXYBri// Unnecessary, but necessary to set the KNX Status in real time.
1094
- node.updateKNXLightColorState(node.currentHUEDevice.color)
1095
- node.writeHueState(hueTelegram)
1096
- if (node.brightnessStepHSV_H <= minDimLevelLightHSV_H) {
1097
- if (node.timerStepDimHSV_H !== undefined) clearInterval(node.timerStepDimHSV_H)
1098
- }
1099
- }, _dimSpeedInMillisecsHSV)
1100
- }
1101
- } catch (error) { /* empty */ }
1102
- }
1103
- /**
1104
- * Starts dimming / stop dimming of the Saturation
1105
- * @param {number} _KNXaction 1 for start, 0 for stop
1106
- * @param {number} _KNXbrightness_DirectionHSV_S 1 for up, 0 for down
1107
- * @param {number} _dimSpeedInMillisecsHSV Speed time in milliseconds
1108
- * @returns {}
1109
- */
1110
- node.hueDimmingHSV_S = function hueDimmingHSV_S (_KNXaction, _KNXbrightness_DirectionHSV_S, _dimSpeedInMillisecsHSV = undefined) {
1111
- // After many attempts to use dimming_delta function of the HueApiV2, loosing days of my life, without a decent success, will use the standard dimming calculations
1112
- // i decide to go to the "step brightness" way.
1113
- try {
1114
- if (_KNXbrightness_DirectionHSV_S === 0 && _KNXaction === 0) {
1115
- // STOP DIM
1116
- if (node.timerStepDimHSV_S !== undefined) clearInterval(node.timerStepDimHSV_S)
1117
- node.deleteHueStateQueue() // Clear dimming queue.
1118
- return
1119
- }
1120
-
1121
- let xyBrightnessToHsv
1122
- if (node.currentHUEDevice.color !== undefined && node.currentHUEDevice.color.xy !== undefined) {
1123
- // Get the XY + brightness from the lamp and transform it into HSV
1124
- xyBrightnessToHsv = hueColorConverter.ColorConverter.xyBrightnessToHsv(hueColorConverter.ColorConverter.scale(node.currentHUEDevice.color.xy.x, [0, 1], [0, 100]), hueColorConverter.ColorConverter.scale(node.currentHUEDevice.color.xy.y, [0, 1], [0, 100]), node.currentHUEDevice.dimming.brightness)
1125
- } else {
1126
- return // Something wrong here.
1127
- }
1128
- let numStepHSV_S = 10 // Steps from 0 to 100
1129
-
1130
- // Set the actual brightness to start with
1131
- if (node.brightnessStepHSV_S === null || node.brightnessStepHSV_S === undefined) node.brightnessStepHSV_S = node.currentHUEDevice.dimming.brightness
1132
- node.brightnessStepHSV_S = Math.ceil(Number(node.brightnessStepHSV_S))
1133
-
1134
- const minDimLevelLightHSV_S = 1
1135
- const maxDimLevelLightHSV_S = 100
1136
- numStepHSV_S = Math.round((maxDimLevelLightHSV_S - minDimLevelLightHSV_S) / numStepHSV_S, 0)
1137
- // Set the speed
1138
- _dimSpeedInMillisecsHSV = Math.ceil(_dimSpeedInMillisecsHSV / (maxDimLevelLightHSV_S / numStepHSV_S))
1139
-
1140
- if (_KNXbrightness_DirectionHSV_S > 0 && _KNXaction === 1) {
1141
- // DIM UP
1142
- if (node.timerStepDimHSV_S !== undefined) clearInterval(node.timerStepDimHSV_S)
1143
- node.timerStepDimHSV_S = setInterval(() => {
1144
- node.deleteHueStateQueue() // Clear dimming queue.
1145
- node.brightnessStepHSV_S += numStepHSV_S
1146
- if (node.brightnessStepHSV_S > maxDimLevelLightHSV_S) node.brightnessStepHSV_S = maxDimLevelLightHSV_S
1147
- // node.updateKNXLightHSV_S_State(node.brightnessStepHSV_S); // Unnecessary, but necessary to set the KNX Status in real time.
1148
- xyBrightnessToHsv.s = node.brightnessStepHSV_S
1149
- const hsvToXYBri = hueColorConverter.ColorConverter.hsvToxyBrightness(xyBrightnessToHsv, node.currentHUEDevice.color.gamut)
1150
- const hueTelegram = { color: { xy: { x: hsvToXYBri.x, y: hsvToXYBri.y } }, dynamics: { duration: _dimSpeedInMillisecsHSV + 500 } } // Add some ms, to prevent the "ladder" step effect.
1151
- // Switch on the light if off
1152
- if (node.currentHUEDevice.on !== undefined && node.currentHUEDevice.on.on === false) {
1153
- hueTelegram.on = { on: true }
1154
- }
1155
- node.currentHUEDevice.color.xy = cloneDeep(hsvToXYBri)// Unnecessary, but necessary to set the KNX Status in real time.
1156
- node.updateKNXLightColorState(node.currentHUEDevice.color)
1157
- node.writeHueState(hueTelegram)
1158
- if (node.brightnessStepHSV_S >= maxDimLevelLightHSV_S) {
1159
- if (node.timerStepDimHSV_S !== undefined) clearInterval(node.timerStepDimHSV_S)
1160
- }
1161
- }, _dimSpeedInMillisecsHSV)
1162
- }
1163
- if (_KNXbrightness_DirectionHSV_S > 0 && _KNXaction === 0) {
1164
- if (node.currentHUEDevice.on.on === false) return // Don't dim down, if the light is already off.
1165
- // DIM DOWN
1166
- if (node.timerStepDimHSV_S !== undefined) clearInterval(node.timerStepDimHSV_S)
1167
- node.timerStepDimHSV_S = setInterval(() => {
1168
- node.deleteHueStateQueue() // Clear dimming queue.
1169
- node.brightnessStepHSV_S -= numStepHSV_S // *2 to speed up the things
1170
- if (node.brightnessStepHSV_S < minDimLevelLightHSV_S) node.brightnessStepHSV_S = minDimLevelLightHSV_S
1171
- // node.updateKNXLightHSV_S_State(node.brightnessStepHSV_S); // Unnecessary, but necessary to set the KNX Status in real time.
1172
- // Produco l'RGB
1173
- xyBrightnessToHsv.s = node.brightnessStepHSV_S
1174
- const hsvToXYBri = hueColorConverter.ColorConverter.hsvToxyBrightness(xyBrightnessToHsv, node.currentHUEDevice.color.gamut)
1175
- const hueTelegram = { color: { xy: { x: hsvToXYBri.x, y: hsvToXYBri.y } }, dynamics: { duration: _dimSpeedInMillisecsHSV + 500 } }
1176
- // Switch off the light if on
1177
- if (node.currentHUEDevice.on !== undefined && node.currentHUEDevice.on.on === true && node.brightnessStepHSV_S === 0) {
1178
- hueTelegram.on = { on: false }
1179
- }
1180
- node.currentHUEDevice.color.xy = cloneDeep(hsvToXYBri)// Unnecessary, but necessary to set the KNX Status in real time.
1181
- node.updateKNXLightColorState(node.currentHUEDevice.color)
1182
- node.writeHueState(hueTelegram)
1183
- if (node.brightnessStepHSV_S <= minDimLevelLightHSV_S) {
1184
- if (node.timerStepDimHSV_S !== undefined) clearInterval(node.timerStepDimHSV_S)
1185
- }
1186
- }, _dimSpeedInMillisecsHSV)
1187
- }
1188
- } catch (error) { /* empty */ }
1189
- }
1190
- // ***********************************************************
1191
-
1192
- node.handleSendHUE = async (_event) => {
1193
- if (_event === undefined) return
1194
- if (_event.type !== 'grouped_light' && _event.type !== 'light') return
1195
-
1196
- // !!!! >>> if the node is a grouped_light, the only values required, thus present, by HUE apis are "on" and "dimming".
1197
- // !!!! >>> For all others properties like for example color and tunable white, i must get the data from one of the child lights.
1198
-
1199
- // (async () => {
1200
- try {
1201
- if (node.currentHUEDevice === undefined || node.serverHue === null || node.serverHue === undefined) {
1202
- node.setNodeStatusHue({
1203
- fill: 'red',
1204
- shape: 'ring',
1205
- text: "Rejected Matter light settings. I'm still not ready...",
1206
- payload: ''
1207
- })
1208
- return
1209
- }
1210
-
1211
- const receivedHUEObject = cloneDeep(_event)
1212
-
1213
- // #region "CALCULATE COLOR AND COLOR TEMPERATURE OF THE LIGHTS BELONGING TO THE GROUPED_LIGHT"
1214
- // Check wether the incoming _event belongs to a light belonging to the group_light
1215
- if (node.isGrouped_light === true && receivedHUEObject.type === 'light') {
1216
- // Handling of not by HUE handled Color Temperature and ColorXY
1217
- let modifiedLight
1218
- const groupChilds = []
1219
- let AverageColorsXYBrightnessAndTemperature // Average color xy and color temp if the node is a grouped light.
1220
- // If the current node is a grouped lights, i must check wether the receivedHUEObject (containing a light) belongs to the node lights collection.
1221
- // Find all the lights in the collection, having the color_temperature capabilities, belonging to the group.
1222
- const devices = await node.serverHue.getAllLightsBelongingToTheGroup(node.hueDevice, false)
1223
- if (devices.length === 0) {
1224
- devices.push(receivedHUEObject)
1225
- }
1226
-
1227
- for (let index = 0; index < devices.length; index++) {
1228
- const element = devices[index]
1229
- if (receivedHUEObject.id === element.id) {
1230
- modifiedLight = element
1231
- // The dimming is not necessary, beacause the HUE API already sends a group_light event with the average brightness //if (receivedHUEObject.dimming !== undefined) modifiedLight.dimming = { brightness: receivedHUEObject.dimming.brightness };
1232
- if (receivedHUEObject.color !== undefined && receivedHUEObject.color.xy !== undefined) modifiedLight.color = receivedHUEObject.color
1233
- if (receivedHUEObject.color_temperature !== undefined) modifiedLight.color_temperature = receivedHUEObject.color_temperature
1234
- groupChilds.push(modifiedLight)
1235
- } else {
1236
- // Simply append the light
1237
- if ((element.color_temperature !== undefined && element.color_temperature.mirek !== undefined) ||
1238
- (element.color !== undefined && element.color.xy !== undefined)) {
1239
- groupChilds.push(element)
1240
- }
1241
- }
1242
- }
1243
-
1244
- // Use the arithmetic average of color xy, brightness and color temperature "averageColorXYandKelvinOfGroupedLights"
1245
- if (groupChilds !== undefined) AverageColorsXYBrightnessAndTemperature = await node.serverHue.getAverageColorsXYBrightnessAndTemperature(groupChilds)
1246
-
1247
- // Set the new values based on average calculated above
1248
- // CHECK FIRST THE COLOR_TEMPERATURE, because it can be undefined, because the current selected color
1249
- // is out of the mirek range, so it cannot be represented with the colore temperature.
1250
- if (receivedHUEObject.color_temperature !== undefined && AverageColorsXYBrightnessAndTemperature.mirek !== undefined && receivedHUEObject.color_temperature.mirel_valid === true) {
1251
- receivedHUEObject.color_temperature.mirek = AverageColorsXYBrightnessAndTemperature.mirek
1252
- node.currentHUEDevice.color_temperature = { mirek: AverageColorsXYBrightnessAndTemperature.mirek }
1253
- node.updateKNXLightKelvinPercentageState(receivedHUEObject.color_temperature.mirek)
1254
- node.updateKNXLightKelvinState(receivedHUEObject.color_temperature.mirek)
1255
- } else if (receivedHUEObject.color !== undefined && receivedHUEObject.color.xy !== undefined && AverageColorsXYBrightnessAndTemperature.x !== undefined) {
1256
- receivedHUEObject.color.xy.x = AverageColorsXYBrightnessAndTemperature.x
1257
- receivedHUEObject.color.xy.y = AverageColorsXYBrightnessAndTemperature.y
1258
- node.currentHUEDevice.color = { xy: { x: AverageColorsXYBrightnessAndTemperature.x, y: AverageColorsXYBrightnessAndTemperature.y } }
1259
- node.updateKNXLightColorState(receivedHUEObject.color)
1260
- }
1261
- // The dimming is not necessary, beacause the HUE API already sends a group_light event with the average brightness
1262
- // if (receivedHUEObject.dimming !== undefined && AverageColorsXYBrightnessAndTemperature.brightness !== undefined) {
1263
- // receivedHUEObject.dimming = { brightness: AverageColorsXYBrightnessAndTemperature.brightness };
1264
- // }
1265
- // --------------------------------------------------------------------------------------------------
1266
- if (modifiedLight !== undefined && modifiedLight.metadata !== undefined && modifiedLight.metadata.name !== undefined) {
1267
- receivedHUEObject.lightName = modifiedLight.metadata.name
1268
- }
1269
- node.send(receivedHUEObject)
1270
- return
1271
- }
1272
- // #endregion
1273
-
1274
- if (receivedHUEObject.id === node.hueDevice) {
1275
- // Output the msg to the flow
1276
- node.send(receivedHUEObject)
1277
-
1278
- // // DEBUG testing enable/disable HTML UI Tabs
1279
- // delete _event.dimming;
1280
- // delete _event.color;
1281
- // delete _event.color_temperature;
1282
- // delete _event.color_temperature_delta;
1283
-
1284
- if (receivedHUEObject.on !== undefined) {
1285
- node.updateKNXLightState(receivedHUEObject.on.on)
1286
- // In case of switch off, set the dim to zero
1287
- if (receivedHUEObject.on.on === false && (config.updateKNXBrightnessStatusOnHUEOnOff === undefined || config.updateKNXBrightnessStatusOnHUEOnOff === 'onhueoff')) {
1288
- node.updateKNXBrightnessState(0)
1289
- if (receivedHUEObject.dimming !== undefined) delete receivedHUEObject.dimming // Remove event.dimming, because has beem handled by this function and i don't want the function below to take care of it.
1290
- } else if (receivedHUEObject.on.on === true && node.currentHUEDevice.on.on === false) {
1291
- // Turn on: update the dimming KNX Status value as well, but only if we have a reliable value.
1292
- // For grouped_light, the bridge exposes an aggregated brightness value via /resource/grouped_light/{id}.
1293
- let brightVal
1294
- if (receivedHUEObject.dimming !== undefined && receivedHUEObject.dimming.brightness !== undefined) {
1295
- brightVal = receivedHUEObject.dimming.brightness
1296
- } else if (node.isGrouped_light === true && typeof node.serverHue?.getHueResourceSnapshot === 'function' && config.GALightBrightnessState) {
1297
- try {
1298
- const snapshot = await node.serverHue.getHueResourceSnapshot(node.hueDevice, { forceRefresh: true })
1299
- if (snapshot?.dimming?.brightness !== undefined) brightVal = snapshot.dimming.brightness
1300
- } catch (error) { /* empty */ }
1301
- } else if (node.currentHUEDevice.dimming !== undefined && node.currentHUEDevice.dimming.brightness !== undefined) {
1302
- brightVal = node.currentHUEDevice.dimming.brightness
1303
- }
1304
- if (brightVal !== undefined) node.updateKNXBrightnessState(brightVal)
1305
- }
1306
- node.currentHUEDevice.on.on = receivedHUEObject.on.on
1307
- }
1308
-
1309
- if (receivedHUEObject.color !== undefined && receivedHUEObject.color.xy !== undefined) { // fixed https://github.com/Supergiovane/node-red-contrib-knx-ultimate/issues/287
1310
- node.updateKNXLightColorState(receivedHUEObject.color)
1311
- node.currentHUEDevice.color = receivedHUEObject.color
1312
- }
1313
-
1314
- if (receivedHUEObject.dimming !== undefined && receivedHUEObject.dimming.brightness !== undefined) {
1315
- const zeroBrightnessWhenOff = (config.updateKNXBrightnessStatusOnHUEOnOff === undefined || config.updateKNXBrightnessStatusOnHUEOnOff === 'onhueoff')
1316
- // Once upon n a time, the light transmit the brightness value of 0.39.
1317
- // To avoid wrongly turn light state on, exit
1318
- if (receivedHUEObject.dimming.brightness < 1) receivedHUEObject.dimming.brightness = 0
1319
- // If the light is OFF and the user wants KNX brightness status to stay 0 while OFF,
1320
- // don't propagate Hue's cached brightness (usually the last/boot brightness) back to KNX.
1321
- if (zeroBrightnessWhenOff === true && node.currentHUEDevice?.on?.on === false && (receivedHUEObject.on === undefined || receivedHUEObject.on.on === false)) {
1322
- if (node.currentHUEDevice.dimming !== undefined) node.currentHUEDevice.dimming.brightness = receivedHUEObject.dimming.brightness
1323
- } else if (node.currentHUEDevice.on !== undefined && node.currentHUEDevice.on.on === false && receivedHUEObject.dimming.brightness === 0) {
1324
- // Do nothing, because the light is off and the dimming also is 0
1325
- } else {
1326
- if (node.currentHUEDevice.on !== undefined && node.currentHUEDevice.on.on === false && (receivedHUEObject.on === undefined || (receivedHUEObject.on !== undefined && receivedHUEObject.on.on === true))) node.updateKNXLightState(receivedHUEObject.dimming.brightness > 0)
1327
- node.updateKNXBrightnessState(receivedHUEObject.dimming.brightness)
1328
- // If the brightness reaches zero, the hue lamp "on" property must be set to zero as well
1329
- if (receivedHUEObject.dimming.brightness === 0 && node.currentHUEDevice.on !== undefined && node.currentHUEDevice.on.on === true) {
1330
- node.writeHueState({ on: { on: false } })
1331
- node.currentHUEDevice.on.on = false
1332
- }
1333
- node.currentHUEDevice.dimming.brightness = receivedHUEObject.dimming.brightness
1334
- }
1335
- }
1336
-
1337
- if (receivedHUEObject.color_temperature !== undefined && receivedHUEObject.color_temperature.mirek !== undefined) {
1338
- node.updateKNXLightKelvinPercentageState(receivedHUEObject.color_temperature.mirek)
1339
- node.updateKNXLightKelvinState(receivedHUEObject.color_temperature.mirek)
1340
- node.currentHUEDevice.color_temperature.mirek = receivedHUEObject.color_temperature.mirek
1341
- }
1342
- }
1343
- } catch (error) {
1344
- node.status({
1345
- fill: 'red',
1346
- shape: 'dot',
1347
- text: `Matter->KNX error ${node.id} ${error.message}. Seee Log`
1348
- })
1349
- RED.log.error(`knxUltimateMatterControllerDevice: node.handleSendHUE = (_event): ${error.stack}`)
1350
- }
1351
- // })();
1352
- }
1353
-
1354
- // Leave the name after "function", to avoid <anonymous function> in the stack trace, in caso of errors.
1355
- // ---- Matter -> KNX feedback (replaces the Hue event stream) -----------------
1356
- // Applies a feedback patch from the shim: updates the synthetic currentHUEDevice
1357
- // and reuses the very same updateKNX* writers of the Hue-born logic below.
1358
- node.applyMatterFeedback = function applyMatterFeedback (patch, _outputtype = 'write') {
1359
- if (!patch || node.currentHUEDevice === undefined) return
1360
- const dev = node.currentHUEDevice
1361
- const zeroBrightnessWhenOff = (config.updateKNXBrightnessStatusOnHUEOnOff === undefined || config.updateKNXBrightnessStatusOnHUEOnOff === 'onhueoff')
1362
- if (patch.on !== undefined) {
1363
- dev.on.on = !!patch.on
1364
- node.updateKNXLightState(dev.on.on, _outputtype)
1365
- if (zeroBrightnessWhenOff) node.updateKNXBrightnessState(dev.on.on ? dev.dimming.brightness : 0, _outputtype)
1366
- }
1367
- if (patch.brightnessPct !== undefined) {
1368
- dev.dimming.brightness = Number(patch.brightnessPct)
1369
- if (dev.on.on === true || !zeroBrightnessWhenOff) node.updateKNXBrightnessState(dev.dimming.brightness, _outputtype)
1370
- }
1371
- if (patch.mirek !== undefined) {
1372
- dev.color_temperature.mirek = patch.mirek
1373
- node.updateKNXLightKelvinState(patch.mirek, _outputtype)
1374
- node.updateKNXLightKelvinPercentageState(patch.mirek, _outputtype)
1375
- }
1376
- if (patch.xyX !== undefined) dev.color.xy.x = patch.xyX
1377
- if (patch.xyY !== undefined) dev.color.xy.y = patch.xyY
1378
- if (patch.xyX !== undefined || patch.xyY !== undefined) node.updateKNXLightColorState({ xy: { x: dev.color.xy.x, y: dev.color.xy.y } }, _outputtype)
1379
- }
1380
-
1381
- // Called by matter-config on every attribute report of the subscription.
1382
- node.handleSendMatter = (_event) => {
1383
- try {
1384
- if (_event === undefined || _event.attributeName === undefined) return
1385
- if (String(_event.nodeId) !== String(node.matterNodeId)) return
1386
- if (Number(_event.endpointId) !== Number(node.matterEndpointId)) return
1387
- const patch = matterEventToHuePatch(_event)
1388
- if (patch) node.applyMatterFeedback(patch)
1389
- } catch (error) {
1390
- RED.log.error(`knxUltimateMatterControllerDevice: node.handleSendMatter: ${error.message}`)
1391
- }
1392
- }
1393
- node.handleMatterClusterEvent = () => { }
1394
- node.handleMatterNodeInitialized = () => { }
1395
-
1396
- node.updateKNXBrightnessState = function updateKNXBrightnessState (_value, _outputtype = 'write') {
1397
- if (config.GALightBrightnessState !== undefined && config.GALightBrightnessState !== '') {
1398
- const knxMsgPayload = {}
1399
- knxMsgPayload.topic = config.GALightBrightnessState
1400
- knxMsgPayload.dpt = config.dptLightBrightnessState
1401
- knxMsgPayload.payload = _value
1402
- // Send to KNX bus
1403
- if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) {
1404
- if (node.serverKNX !== null && node.serverKNX !== undefined) {
1405
- node.serverKNX.sendKNXTelegramToKNXEngine({
1406
- grpaddr: knxMsgPayload.topic,
1407
- payload: knxMsgPayload.payload,
1408
- dpt: knxMsgPayload.dpt,
1409
- outputtype: _outputtype,
1410
- nodecallerid: node.id
1411
- })
1412
- }
1413
- }
1414
- node.setNodeStatusHue({
1415
- fill: 'blue',
1416
- shape: 'ring',
1417
- text: 'Matter->KNX Bright',
1418
- payload: knxMsgPayload.payload
1419
- })
1420
- }
1421
- }
1422
-
1423
- node.updateKNXLightState = function updateKNXLightState (_value, _outputtype = 'write') {
1424
- try {
1425
- const knxMsgPayload = {}
1426
- knxMsgPayload.topic = config.GALightState
1427
- knxMsgPayload.dpt = config.dptLightState
1428
- knxMsgPayload.payload = _value
1429
- if (config.GALightState !== undefined && config.GALightState !== '') {
1430
- // Check not to have already sent the value
1431
- // Send to KNX bus
1432
- if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) {
1433
- if (node.serverKNX !== null && node.serverKNX !== undefined) {
1434
- node.serverKNX.sendKNXTelegramToKNXEngine({
1435
- grpaddr: knxMsgPayload.topic,
1436
- payload: knxMsgPayload.payload,
1437
- dpt: knxMsgPayload.dpt,
1438
- outputtype: _outputtype,
1439
- nodecallerid: node.id
1440
- })
1441
- }
1442
- }
1443
- node.setNodeStatusHue({
1444
- fill: 'blue',
1445
- shape: 'ring',
1446
- text: 'Matter->KNX On/Off',
1447
- payload: knxMsgPayload.payload
1448
- })
1449
- }
1450
- } catch (error) {
1451
- /* empty */
1452
- }
1453
- }
1454
-
1455
- node.updateKNXLightKelvinPercentageState = function updateKNXLightKelvinPercentageState (_value, _outputtype = 'write') {
1456
- if (config.GALightKelvinPercentageState !== undefined && config.GALightKelvinPercentageState !== '') {
1457
- const knxMsgPayload = {}
1458
- knxMsgPayload.topic = config.GALightKelvinPercentageState
1459
- knxMsgPayload.dpt = config.dptLightKelvinPercentageState
1460
- if (config.dptLightKelvinPercentageState === '5.001') {
1461
- const retPercent = hueColorConverter.ColorConverter.scale(_value, [153, 500], [0, 100])
1462
- knxMsgPayload.payload = 100 - retPercent
1463
- }
1464
- // Send to KNX bus
1465
- if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) {
1466
- if (node.serverKNX !== null && node.serverKNX !== undefined) {
1467
- node.serverKNX.sendKNXTelegramToKNXEngine({
1468
- grpaddr: knxMsgPayload.topic,
1469
- payload: knxMsgPayload.payload,
1470
- dpt: knxMsgPayload.dpt,
1471
- outputtype: _outputtype,
1472
- nodecallerid: node.id
1473
- })
1474
- }
1475
- }
1476
- node.setNodeStatusHue({
1477
- fill: 'blue',
1478
- shape: 'ring',
1479
- text: 'Matter->KNX Tunable White',
1480
- payload: knxMsgPayload.payload
1481
- })
1482
- }
1483
- }
1484
-
1485
- // /**
1486
- // * Update the internal HSV variable status and send the valuge in % to the KNX BUS
1487
- // * @param {number} _value 0-100%
1488
- // * @param {string} _outputtype "write" is the default KNX command
1489
- // * * @returns {}
1490
- // */
1491
- // node.updateKNXLightHSV_H_State = function updateKNXLightHSV_H_State(_value, _outputtype = "write") {
1492
- // if (config.GALightHSV_H_State !== undefined && config.GALightHSV_H_State !== "") {
1493
- // const knxMsgPayload = {};
1494
- // knxMsgPayload.topic = config.GALightHSV_H_State;
1495
- // knxMsgPayload.dpt = config.dptLightHSV_H_State;
1496
- // if (config.dptLightHSV_H_State === "5.001") {
1497
- // knxMsgPayload.payload = 100 - _value;
1498
- // }
1499
- // // Send to KNX bus
1500
- // if (knxMsgPayload.topic !== "" && knxMsgPayload.topic !== undefined) {
1501
- // if (node.serverKNX !== null && node.serverKNX !== undefined) {
1502
- // node.serverKNX.sendKNXTelegramToKNXEngine({
1503
- // grpaddr: knxMsgPayload.topic,
1504
- // payload: knxMsgPayload.payload,
1505
- // dpt: knxMsgPayload.dpt,
1506
- // outputtype: _outputtype || "write",
1507
- // nodecallerid: node.id,
1508
- // });
1509
- // }
1510
- // }
1511
- // node.setNodeStatusHue({
1512
- // fill: "blue",
1513
- // shape: "ring",
1514
- // text: "Matter->KNX HSV (H)",
1515
- // payload: knxMsgPayload.payload,
1516
- // });
1517
- // }
1518
- // };
1519
-
1520
- // /**
1521
- // * Update the internal HSV variable status and send the valuge in % to the KNX BUS
1522
- // * @param {number} _value 0-100%
1523
- // * @param {string} _outputtype "write" is the default KNX command
1524
- // * @returns {}
1525
- // */
1526
- // node.updateKNXLightHSV_S_State = function updateKNXLightHSV_S_State(_value, _outputtype = "write") {
1527
- // if (config.GALightHSV_S_State !== undefined && config.GALightHSV_S_State !== "") {
1528
- // const knxMsgPayload = {};
1529
- // knxMsgPayload.topic = config.GALightHSV_S_State;
1530
- // knxMsgPayload.dpt = config.dptLightHSV_S_State;
1531
- // if (config.dptLightHSV_S_State === "5.001") {
1532
- // knxMsgPayload.payload = _value;
1533
- // }
1534
- // // Send to KNX bus
1535
- // if (knxMsgPayload.topic !== "" && knxMsgPayload.topic !== undefined) {
1536
- // if (node.serverKNX !== null && node.serverKNX !== undefined) {
1537
- // node.serverKNX.sendKNXTelegramToKNXEngine({
1538
- // grpaddr: knxMsgPayload.topic,
1539
- // payload: knxMsgPayload.payload,
1540
- // dpt: knxMsgPayload.dpt,
1541
- // outputtype: _outputtype || "write",
1542
- // nodecallerid: node.id,
1543
- // });
1544
- // }
1545
- // }
1546
- // node.setNodeStatusHue({
1547
- // fill: "blue",
1548
- // shape: "ring",
1549
- // text: "Matter->KNX HSV (H)",
1550
- // payload: knxMsgPayload.payload,
1551
- // });
1552
- // }
1553
- // };
1554
-
1555
- /**
1556
- * Update the KNC colors and HSV states group addresses
1557
- * @param {object} _value {xy:{x,y}} in 0-1 scale
1558
- * @param {string} _outputtype "write" is the default KNX command
1559
- * @returns {}
1560
- */
1561
- node.updateKNXLightColorState = function updateKNXLightColorState (_value, _outputtype = 'write') {
1562
- if (config.GALightColorState !== undefined && config.GALightColorState !== '') {
1563
- if (_value.xy === undefined || _value.xy.x === undefined) return
1564
- const knxMsgPayload = {}
1565
- knxMsgPayload.topic = config.GALightColorState
1566
- knxMsgPayload.dpt = config.dptLightColorState
1567
- try {
1568
- knxMsgPayload.payload = hueColorConverter.ColorConverter.xyBriToRgb(
1569
- _value.xy.x,
1570
- _value.xy.y,
1571
- node.currentHUEDevice !== undefined && node.currentHUEDevice.dimming !== undefined && node.currentHUEDevice.dimming.brightness === undefined ? node.currentHUEDevice.dimming.brightness : 100
1572
- )
1573
- knxMsgPayload.payload = { red: knxMsgPayload.payload.r, green: knxMsgPayload.payload.g, blue: knxMsgPayload.payload.b }
1574
- // Send to KNX bus
1575
- if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) {
1576
- if (node.serverKNX !== null && node.serverKNX !== undefined) {
1577
- node.serverKNX.sendKNXTelegramToKNXEngine({
1578
- grpaddr: knxMsgPayload.topic,
1579
- payload: knxMsgPayload.payload,
1580
- dpt: knxMsgPayload.dpt,
1581
- outputtype: _outputtype,
1582
- nodecallerid: node.id
1583
- })
1584
- }
1585
- }
1586
- node.setNodeStatusHue({
1587
- fill: 'blue',
1588
- shape: 'ring',
1589
- text: 'Matter->KNX Color',
1590
- payload: knxMsgPayload.payload
1591
- })
1592
- } catch (error) { }
1593
- }
1594
- if (config.GALightHSV_S_State !== undefined && config.GALightHSV_S_State !== '') {
1595
- const knxMsgPayload = {}
1596
- knxMsgPayload.topic = config.GALightHSV_S_State
1597
- knxMsgPayload.dpt = config.dptLightHSV_S_State
1598
- if (config.dptLightHSV_S_State === '5.001') {
1599
- knxMsgPayload.payload = hueColorConverter.ColorConverter.xyBrightnessToHsv(_value.xy.x, _value.xy.y, node.currentHUEDevice !== undefined && node.currentHUEDevice.dimming !== undefined && node.currentHUEDevice.dimming.brightness === undefined ? node.currentHUEDevice.dimming.brightness : 100, false)
1600
- knxMsgPayload.payload = knxMsgPayload.payload.s
1601
- }
1602
- // Send to KNX bus
1603
- if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) {
1604
- if (node.serverKNX !== null && node.serverKNX !== undefined) {
1605
- node.serverKNX.sendKNXTelegramToKNXEngine({
1606
- grpaddr: knxMsgPayload.topic,
1607
- payload: knxMsgPayload.payload,
1608
- dpt: knxMsgPayload.dpt,
1609
- outputtype: _outputtype || 'write',
1610
- nodecallerid: node.id
1611
- })
1612
- }
1613
- }
1614
- node.setNodeStatusHue({
1615
- fill: 'blue',
1616
- shape: 'ring',
1617
- text: 'Matter->KNX HSV (S)',
1618
- payload: knxMsgPayload.payload
1619
- })
1620
- }
1621
- if (config.GALightHSV_H_State !== undefined && config.GALightHSV_H_State !== '') {
1622
- const knxMsgPayload = {}
1623
- knxMsgPayload.topic = config.GALightHSV_H_State
1624
- knxMsgPayload.dpt = config.dptLightHSV_H_State
1625
- if (config.dptLightHSV_H_State === '5.001') {
1626
- knxMsgPayload.payload = hueColorConverter.ColorConverter.xyBrightnessToHsv(_value.xy.x, _value.xy.y, node.currentHUEDevice !== undefined && node.currentHUEDevice.dimming !== undefined && node.currentHUEDevice.dimming.brightness === undefined ? node.currentHUEDevice.dimming.brightness : 100, false)
1627
- knxMsgPayload.payload = 100 - knxMsgPayload.payload.h
1628
- }
1629
- // Send to KNX bus
1630
- if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) {
1631
- if (node.serverKNX !== null && node.serverKNX !== undefined) {
1632
- node.serverKNX.sendKNXTelegramToKNXEngine({
1633
- grpaddr: knxMsgPayload.topic,
1634
- payload: knxMsgPayload.payload,
1635
- dpt: knxMsgPayload.dpt,
1636
- outputtype: _outputtype || 'write',
1637
- nodecallerid: node.id
1638
- })
1639
- }
1640
- }
1641
- node.setNodeStatusHue({
1642
- fill: 'blue',
1643
- shape: 'ring',
1644
- text: 'Matter->KNX HSV (H)',
1645
- payload: knxMsgPayload.payload
1646
- })
1647
- }
1648
- }
1649
-
1650
- node.updateKNXLightKelvinState = function updateKNXLightKelvinState (_value, _outputtype = 'write') {
1651
- if (config.GALightKelvinState !== undefined && config.GALightKelvinState !== '') {
1652
- const knxMsgPayload = {}
1653
- const kelvinValue = 0
1654
- knxMsgPayload.topic = config.GALightKelvinState
1655
- knxMsgPayload.dpt = config.dptLightKelvinState
1656
- if (config.dptLightKelvinState === '7.600') {
1657
- knxMsgPayload.payload = hueColorConverter.ColorConverter.mirekToKelvin(_value)
1658
- // knxMsgPayload.payload = hueColorConverter.ColorConverter.scale(kelvinValue, [2000, 6535], [0, 65535]);
1659
- } else if (config.dptLightKelvinState === '9.002') {
1660
- knxMsgPayload.payload = hueColorConverter.ColorConverter.mirekToKelvin(_value)
1661
- }
1662
- // Send to KNX bus
1663
- if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) {
1664
- if (node.serverKNX !== null && node.serverKNX !== undefined) {
1665
- node.serverKNX.sendKNXTelegramToKNXEngine({
1666
- grpaddr: knxMsgPayload.topic,
1667
- payload: knxMsgPayload.payload,
1668
- dpt: knxMsgPayload.dpt,
1669
- outputtype: _outputtype,
1670
- nodecallerid: node.id
1671
- })
1672
- }
1673
-
1674
- node.setNodeStatusHue({
1675
- fill: 'blue',
1676
- shape: 'ring',
1677
- text: 'Matter->KNX Kelvin',
1678
- payload: knxMsgPayload.payload
1679
- })
1680
- }
1681
- }
1682
- }
1683
-
1684
- // On each deploy, unsubscribe+resubscribe
1685
- if (node.serverKNX) {
1686
- node.serverKNX.removeClient(node)
1687
- node.serverKNX.addClient(node)
1688
- } else {
1689
- node.setNodeStatus({
1690
- fill: 'yellow',
1691
- shape: 'ring',
1692
- text: 'No KNX gateway selected',
1693
- payload: ''
1694
- })
1695
- }
1696
- if (node.serverHue) {
1697
- try {
1698
- node.serverHue.removeClient(node)
1699
- node.serverHue.addClient(node)
1700
- } catch (error) {
1701
- RED.log.error('knxUltimateMatterControllerDevice: if (node.serverKNX): ' + error.message)
1702
- }
1703
- }
1704
-
1705
- node.on('input', (msg, send, done) => {
1706
- if (node.matterCommandBlocked === true) {
1707
- const error = new Error(node.matterCommandBlockReason || 'Matter device unavailable')
1708
- if (done) done(error); else node.error(error, msg)
1709
- return
1710
- }
1711
- try {
1712
- const state = RED.util.cloneMessage(msg)
1713
- node.writeHueState(state)
1714
- node.setNodeStatusHue({
1715
- fill: 'green',
1716
- shape: 'dot',
1717
- text: '->Matter',
1718
- payload: 'Flow msg.'
1719
- })
1720
- } catch (error) {
1721
- node.setNodeStatusHue({
1722
- fill: 'red',
1723
- shape: 'dot',
1724
- text: '->Matter',
1725
- payload: error.message
1726
- })
1727
- }
1728
- // Once finished, call 'done'.
1729
- // This call is wrapped in a check that 'done' exists
1730
- // so the node will work in earlier versions of Node-RED (<1.0)
1731
- if (done) {
1732
- done()
1733
- }
1734
- })
1735
-
1736
- node.on('close', (done) => {
1737
- if (node.serverKNX) {
1738
- node.serverKNX.removeClient(node)
1739
- }
1740
- if (node.serverHue) {
1741
- node.serverHue.removeClient(node)
1742
- }
1743
- done()
1744
- })
1745
- }
1746
- RED.nodes.registerType('knxUltimateMatterControllerDevice', knxUltimateMatterControllerDevice)
1747
- }