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,780 +0,0 @@
1
- /* eslint-disable max-len */
2
- // Factory of the bridged Matter endpoints exposed by knxUltimateMatterBridge.
3
- // Each KNX "virtual device" definition becomes a Matter endpoint under the aggregator.
4
- import { Endpoint } from '@matter/main'
5
- import { BridgedDeviceBasicInformationServer } from '@matter/main/behaviors/bridged-device-basic-information'
6
- import { OnOffServer } from '@matter/main/behaviors/on-off'
7
- import { LevelControlServer } from '@matter/main/behaviors/level-control'
8
- import { OnOffLightDevice } from '@matter/main/devices/on-off-light'
9
- import { DimmableLightDevice } from '@matter/main/devices/dimmable-light'
10
- import { OnOffPlugInUnitDevice } from '@matter/main/devices/on-off-plug-in-unit'
11
- import { TemperatureSensorDevice } from '@matter/main/devices/temperature-sensor'
12
- import { HumiditySensorDevice } from '@matter/main/devices/humidity-sensor'
13
- import { LightSensorDevice } from '@matter/main/devices/light-sensor'
14
- import { OccupancySensorDevice } from '@matter/main/devices/occupancy-sensor'
15
- import { OccupancySensingServer } from '@matter/main/behaviors/occupancy-sensing'
16
- import { ContactSensorDevice } from '@matter/main/devices/contact-sensor'
17
- import { WindowCoveringDevice } from '@matter/main/devices/window-covering'
18
- import { MovementDirection, MovementType, WindowCoveringServer } from '@matter/main/behaviors/window-covering'
19
- import { ThermostatDevice } from '@matter/main/devices/thermostat'
20
- import { ThermostatServer } from '@matter/main/behaviors/thermostat'
21
- import { ExtendedColorLightDevice } from '@matter/main/devices/extended-color-light'
22
- import { ColorTemperatureLightDevice } from '@matter/main/devices/color-temperature-light'
23
- import { ColorControlServer } from '@matter/main/behaviors/color-control'
24
- import { SmokeCoAlarmDevice } from '@matter/main/devices/smoke-co-alarm'
25
- import { SmokeCoAlarmServer } from '@matter/main/behaviors/smoke-co-alarm'
26
- import { WaterLeakDetectorDevice } from '@matter/main/devices/water-leak-detector'
27
- import { AirQualitySensorDevice } from '@matter/main/devices/air-quality-sensor'
28
- import { AirQualityServer } from '@matter/main/behaviors/air-quality'
29
- import { CarbonDioxideConcentrationMeasurementServer } from '@matter/main/behaviors/carbon-dioxide-concentration-measurement'
30
- import { FanDevice } from '@matter/main/devices/fan'
31
- import { FanControlServer } from '@matter/main/behaviors/fan-control'
32
- import { RoomAirConditionerDevice } from '@matter/main/devices/room-air-conditioner'
33
- import { DoorLockDevice } from '@matter/main/devices/door-lock'
34
- import { DoorLockServer } from '@matter/main/behaviors/door-lock'
35
- import { DoorLock } from '@matter/main/clusters/door-lock'
36
- import { RoboticVacuumCleanerDevice } from '@matter/main/devices/robotic-vacuum-cleaner'
37
- import { RvcRunModeServer } from '@matter/main/behaviors/rvc-run-mode'
38
- import { RvcOperationalStateServer } from '@matter/main/behaviors/rvc-operational-state'
39
- import { ModeUtils } from '@matter/main/behaviors/mode-base'
40
- import hueColorConverter from './colorManipulators/hueColorConverter.js'
41
-
42
- const { ColorConverter } = hueColorConverter
43
- const clamp = (v, min, max) => Math.min(max, Math.max(min, v))
44
- const truthy = (v) => v === true || v === 1 || v === '1' || v === 'true' || v === 'on'
45
-
46
- // Catalog of the supported virtual device types.
47
- // - functions: the abstract functions the KNX node can feed/receive ('onoff', 'level', 'temperature', ...)
48
- // - commandFunctions: the subset that flows Matter -> KNX (commands from Alexa & Co.)
49
- const BRIDGE_TYPES = {
50
- onofflight: { device: OnOffLightDevice, functions: ['onoff'], commandFunctions: ['onoff'] },
51
- onoffplug: { device: OnOffPlugInUnitDevice, functions: ['onoff'], commandFunctions: ['onoff'] },
52
- dimmablelight: { device: DimmableLightDevice, functions: ['onoff', 'level'], commandFunctions: ['onoff', 'level'] },
53
- temperaturesensor: { device: TemperatureSensorDevice, functions: ['temperature'], commandFunctions: [] },
54
- humiditysensor: { device: HumiditySensorDevice, functions: ['humidity'], commandFunctions: [] },
55
- lightsensor: { device: LightSensorDevice, functions: ['illuminance'], commandFunctions: [] },
56
- occupancysensor: { device: OccupancySensorDevice, functions: ['occupancy'], commandFunctions: [] },
57
- contactsensor: { device: ContactSensorDevice, functions: ['contact'], commandFunctions: [] },
58
- // Custom construction (dedicated server behaviors), handled in createBridgedEndpoint
59
- windowcovering: { device: null, functions: ['position'], commandFunctions: [] },
60
- thermostat: { device: null, functions: ['currenttemp', 'setpoint', 'coolingsetpoint'], commandFunctions: [] },
61
- roomairconditioner: { device: null, functions: ['onoff', 'currenttemp', 'setpoint', 'coolingsetpoint', 'fanspeed'], commandFunctions: [] },
62
- doorlock: { device: null, functions: ['lock'], commandFunctions: [] },
63
- rgblight: { device: null, functions: ['onoff', 'level', 'rgb'], commandFunctions: ['onoff', 'level'] },
64
- colortemperaturelight: { device: null, functions: ['onoff', 'level', 'colortemp'], commandFunctions: ['onoff', 'level'] },
65
- smokecoalarm: { device: null, functions: ['smoke', 'co'], commandFunctions: [] },
66
- waterleakdetector: { device: WaterLeakDetectorDevice, functions: ['leak'], commandFunctions: [] },
67
- airqualitysensor: { device: null, functions: ['co2'], commandFunctions: [] },
68
- fan: { device: null, functions: ['fanspeed'], commandFunctions: [] },
69
- robotvacuum: { device: null, functions: ['rvcstate', 'rvcmode'], commandFunctions: [] } // Flow-only (node PINs)
70
- }
71
-
72
- // CO2 ppm -> Matter AirQuality classification (1 Good ... 6 ExtremelyPoor)
73
- function co2ToAirQuality (ppm) {
74
- if (ppm < 800) return 1
75
- if (ppm < 1000) return 2
76
- if (ppm < 1400) return 3
77
- if (ppm < 2000) return 4
78
- if (ppm < 3000) return 5
79
- return 6
80
- }
81
-
82
- // RVC operational states (Matter enum values, incl. the RVC specific ones)
83
- const RVC_OP_STATES = { stopped: 0, running: 1, paused: 2, error: 3, seekingcharger: 0x40, charging: 0x41, docked: 0x42 }
84
-
85
- // KNX payload (decoded DPT value) -> Matter attribute patch for endpoint.set()
86
- function knxValueToMatterPatch (def, fn, value) {
87
- switch (fn) {
88
- case 'position': {
89
- // KNX 5.001 position: 0% = open, 100% = closed (invert flag flips it).
90
- // Matter lift percent100ths: 0 = open, 10000 = closed.
91
- let percent = Number(value)
92
- if (Number.isNaN(percent)) return undefined
93
- const invert = (def.invertPosition === true) !== (def.coverSwapOpenClose === true)
94
- if (invert) percent = 100 - percent
95
- return { windowCovering: { currentPositionLiftPercent100ths: clamp(Math.round(percent * 100), 0, 10000) } }
96
- }
97
- case 'rgb': {
98
- // KNX DPT 232.600 payload: { red, green, blue } 0-255 -> Matter hue/saturation (0-254)
99
- if (value === null || typeof value !== 'object') return undefined
100
- const red = Number(value.red); const green = Number(value.green); const blue = Number(value.blue)
101
- if (Number.isNaN(red) || Number.isNaN(green) || Number.isNaN(blue)) return undefined
102
- const hsv = ColorConverter.rgbToHsv(clamp(red, 0, 255), clamp(green, 0, 255), clamp(blue, 0, 255)) // h,s,v in percent 0-100
103
- return {
104
- colorControl: {
105
- currentHue: clamp(Math.round(hsv.h * 254 / 100), 0, 254),
106
- currentSaturation: clamp(Math.round(hsv.s * 254 / 100), 0, 254)
107
- }
108
- }
109
- }
110
- case 'colortemp': {
111
- // KNX DPT 7.600 carries Kelvin -> Matter mireds (accept mireds too for values < 1000)
112
- const numeric = Number(value)
113
- if (Number.isNaN(numeric) || numeric <= 0) return undefined
114
- const mireds = numeric >= 1000 ? Math.round(1000000 / numeric) : Math.round(numeric)
115
- return { colorControl: { colorTemperatureMireds: clamp(mireds, 153, 500) } }
116
- }
117
- case 'currenttemp': {
118
- const t = Number(value)
119
- if (Number.isNaN(t)) return undefined
120
- return { thermostat: { localTemperature: Math.round(t * 100) } }
121
- }
122
- case 'setpoint': {
123
- const t = Number(value)
124
- if (Number.isNaN(t)) return undefined
125
- return { thermostat: { occupiedHeatingSetpoint: clamp(Math.round(t * 100), 700, 3000) } } // 7-30°C
126
- }
127
- case 'coolingsetpoint': {
128
- const t = Number(value)
129
- if (Number.isNaN(t)) return undefined
130
- return { thermostat: { occupiedCoolingSetpoint: clamp(Math.round(t * 100), 1600, 3200) } } // 16-32°C
131
- }
132
- case 'onoff':
133
- return { onOff: { onOff: truthy(value) } }
134
- case 'lock':
135
- return { doorLock: { lockState: truthy(value) ? DoorLock.LockState.Locked : DoorLock.LockState.Unlocked } }
136
- case 'level': {
137
- const percent = Number(value)
138
- if (Number.isNaN(percent)) return undefined
139
- // KNX 0-100% -> Matter level 1-254 (0 is not a valid "on" level for lighting)
140
- const level = clamp(Math.round(percent * 254 / 100), 1, 254)
141
- return { levelControl: { currentLevel: level } }
142
- }
143
- case 'temperature': {
144
- const t = Number(value)
145
- if (Number.isNaN(t)) return undefined
146
- return { temperatureMeasurement: { measuredValue: Math.round(t * 100) } } // °C -> centi-°C
147
- }
148
- case 'humidity': {
149
- const h = Number(value)
150
- if (Number.isNaN(h)) return undefined
151
- return { relativeHumidityMeasurement: { measuredValue: clamp(Math.round(h * 100), 0, 10000) } }
152
- }
153
- case 'illuminance': {
154
- const lux = Number(value)
155
- if (Number.isNaN(lux)) return undefined
156
- // Matter: measuredValue = 10000 * log10(lux) + 1 (0 = "too low to measure")
157
- const measured = lux <= 0 ? 0 : clamp(Math.round(10000 * Math.log10(lux) + 1), 0, 65534)
158
- return { illuminanceMeasurement: { measuredValue: measured } }
159
- }
160
- case 'occupancy':
161
- return { occupancySensing: { occupancy: { occupied: truthy(value) } } }
162
- case 'contact':
163
- return { booleanState: { stateValue: truthy(value) } }
164
- case 'leak':
165
- return { booleanState: { stateValue: truthy(value) } } // true = leak detected
166
- case 'smoke': {
167
- const alarm = truthy(value)
168
- return { smokeCoAlarm: { smokeState: alarm ? 2 : 0, expressedState: alarm ? 1 : 0 } } // 2 = critical
169
- }
170
- case 'co': {
171
- const alarm = truthy(value)
172
- return { smokeCoAlarm: { coState: alarm ? 2 : 0, expressedState: alarm ? 2 : 0 } }
173
- }
174
- case 'co2': {
175
- const ppm = Number(value)
176
- if (Number.isNaN(ppm) || ppm < 0) return undefined
177
- return {
178
- carbonDioxideConcentrationMeasurement: { measuredValue: Math.round(ppm) },
179
- airQuality: { airQuality: co2ToAirQuality(ppm) }
180
- }
181
- }
182
- case 'fanspeed': {
183
- const percent = Number(value)
184
- if (Number.isNaN(percent)) return undefined
185
- const p = clamp(Math.round(percent), 0, 100)
186
- return { fanControl: { percentCurrent: p, percentSetting: p, fanMode: p > 0 ? 3 : 0 } } // 3 = High, 0 = Off
187
- }
188
- case 'rvcstate': {
189
- // 'docked' | 'charging' | 'running' | 'paused' | 'stopped' | 'seekingcharger' | 'error' (or the numeric Matter value)
190
- const key = value !== null && value !== undefined ? value.toString().toLowerCase().trim() : ''
191
- const state = RVC_OP_STATES[key] !== undefined ? RVC_OP_STATES[key] : Number(value)
192
- if (Number.isNaN(state)) return undefined
193
- return { rvcOperationalState: { operationalState: state } }
194
- }
195
- case 'rvcmode': {
196
- const key = value !== null && value !== undefined ? value.toString().toLowerCase().trim() : ''
197
- if (key !== 'idle' && key !== 'cleaning') return undefined
198
- return { rvcRunMode: { currentMode: key === 'cleaning' ? 1 : 0 } }
199
- }
200
- default:
201
- return undefined
202
- }
203
- }
204
-
205
- // Builds a ColorControlServer that captures color commands AT THE COMMAND BOUNDARY
206
- // (like RawOnOffServer/RawLevelControlServer), instead of listening for attribute
207
- // changes: repeated commands (e.g. "set to red" twice) are still forwarded every time,
208
- // not just the first. This is possible for color because Matter controllers always
209
- // change color via cluster COMMANDS (MoveToHue, MoveToSaturation, MoveToHueAndSaturation,
210
- // MoveToColor) - unlike e.g. Thermostat/FanControl, where absolute values are set via a
211
- // plain ATTRIBUTE WRITE with no command-level hook to intercept (verified against
212
- // @matter/node's ThermostatServer/FanControlServer: only relative Move/Step-style
213
- // commands exist there, not the absolute "set to X" interaction voice assistants use).
214
- //
215
- // Controllers set the color as hue+saturation OR as X+Y, sometimes as two separate
216
- // commands (MoveToHue then MoveToSaturation): a short debounce merges those two into a
217
- // single KNX RGB command. A combined MoveToHueAndSaturation/MoveToColor command already
218
- // carries both values, so it flushes immediately with no debounce.
219
- function createRawColorControlServer (def, onCommand) {
220
- const tracker = { hue: 0, sat: 0, x: undefined, y: undefined, mode: 0, level: 254, timer: null }
221
-
222
- const flush = () => {
223
- if (tracker.timer !== null) { clearTimeout(tracker.timer); tracker.timer = null }
224
- try {
225
- const v01 = clamp((tracker.level === null || tracker.level === undefined ? 254 : Number(tracker.level)) / 254, 0, 1)
226
- let rgb
227
- if (tracker.mode === 1 && tracker.x !== undefined && tracker.y !== undefined) {
228
- // XY color mode (Matter x/y are 0..65536 for 0..1)
229
- rgb = ColorConverter.xyBriToRgb(tracker.x / 65536, tracker.y / 65536, Math.max(1, Math.round(v01 * 100)))
230
- } else {
231
- // Hue/Saturation mode (Matter 0..254 -> 0..1)
232
- rgb = ColorConverter.hsvToRgb(clamp(tracker.hue / 254, 0, 1), clamp(tracker.sat / 254, 0, 1), Math.max(0.01, v01))
233
- }
234
- if (!rgb) return
235
- onCommand({
236
- deviceId: def.id,
237
- fn: 'rgb',
238
- value: { red: clamp(Math.round(rgb.r), 0, 255), green: clamp(Math.round(rgb.g), 0, 255), blue: clamp(Math.round(rgb.b), 0, 255) }
239
- })
240
- } catch (error) { /* empty */ }
241
- }
242
-
243
- const schedule = () => {
244
- if (tracker.timer !== null) clearTimeout(tracker.timer)
245
- tracker.timer = setTimeout(flush, 250)
246
- }
247
-
248
- class RawColorControlServer extends ColorControlServer.with('HueSaturation', 'Xy') {
249
- async moveToHue (request) {
250
- await super.moveToHue(request)
251
- tracker.hue = Number(request.hue)
252
- tracker.mode = 0
253
- schedule()
254
- }
255
-
256
- async moveToSaturation (request) {
257
- await super.moveToSaturation(request)
258
- tracker.sat = Number(request.saturation)
259
- tracker.mode = 0
260
- schedule()
261
- }
262
-
263
- async moveToHueAndSaturation (request) {
264
- await super.moveToHueAndSaturation(request)
265
- tracker.hue = Number(request.hue)
266
- tracker.sat = Number(request.saturation)
267
- tracker.mode = 0
268
- flush() // atomic: both values already known, no need to wait for a second command
269
- }
270
-
271
- async moveToColor (request) {
272
- await super.moveToColor(request)
273
- tracker.x = Number(request.colorX)
274
- tracker.y = Number(request.colorY)
275
- tracker.mode = 1
276
- flush()
277
- }
278
- }
279
-
280
- // Track the brightness (for the RGB computation only: the level command has its own GA).
281
- // Passive bookkeeping, not a command to forward raw, so an attribute listener is fine here.
282
- const attachLevelTracker = (endpoint) => {
283
- endpoint.events.levelControl.currentLevel$Changed.on((value) => {
284
- try {
285
- if (value !== null && value !== undefined) tracker.level = Number(value)
286
- } catch (error) { /* empty */ }
287
- })
288
- }
289
-
290
- return { RawColorControlServer, attachLevelTracker }
291
- }
292
-
293
- function configureThermostatState (initialState, def, fallbackMode) {
294
- let hasHeating = def.hasHeatingSetpoint === true
295
- let hasCooling = def.hasCoolingSetpoint === true
296
- // The Thermostat cluster cannot be composed without at least one operating feature.
297
- // Preserve the historical heating default for the standalone Thermostat; a Room Air
298
- // Conditioner with no setpoint GA configured defaults to cooling, its primary use case.
299
- if (!hasHeating && !hasCooling) {
300
- hasHeating = fallbackMode === 'heating'
301
- hasCooling = fallbackMode === 'cooling'
302
- }
303
- const features = []
304
- if (hasHeating) features.push('Heating')
305
- if (hasCooling) features.push('Cooling')
306
- initialState.thermostat = {
307
- localTemperature: null,
308
- // CoolingOnly=0, HeatingOnly=2, CoolingAndHeating=4 (ControlSequenceOfOperation).
309
- controlSequenceOfOperation: hasHeating && hasCooling ? 4 : (hasCooling ? 0 : 2),
310
- // Cool=3, Heat=4 (SystemMode). A dual-mode device starts in Heat.
311
- systemMode: hasCooling && !hasHeating ? 3 : 4
312
- }
313
- if (hasHeating) initialState.thermostat.occupiedHeatingSetpoint = 2000 // 20°C
314
- if (hasCooling) initialState.thermostat.occupiedCoolingSetpoint = 2400 // 24°C
315
- return { features, hasHeating, hasCooling }
316
- }
317
-
318
- function attachThermostatCommandHandlers (endpoint, def, onCommand, capabilities) {
319
- // Absolute thermostat targets are Matter attribute writes, not commands. The offline
320
- // context marks KNX/flow state synchronization and prevents a feedback write to KNX.
321
- if (capabilities.hasHeating) {
322
- endpoint.events.thermostat.occupiedHeatingSetpoint$Changed.on((value, oldValue, context) => {
323
- try {
324
- if (context?.offline === true || value === null || value === undefined) return
325
- onCommand({ deviceId: def.id, fn: 'setpoint', value: Math.round(Number(value)) / 100 })
326
- } catch (error) { /* empty */ }
327
- })
328
- }
329
- if (capabilities.hasCooling) {
330
- endpoint.events.thermostat.occupiedCoolingSetpoint$Changed.on((value, oldValue, context) => {
331
- try {
332
- if (context?.offline === true || value === null || value === undefined) return
333
- onCommand({ deviceId: def.id, fn: 'coolingsetpoint', value: Math.round(Number(value)) / 100 })
334
- } catch (error) { /* empty */ }
335
- })
336
- }
337
- }
338
-
339
- function configureFanState (initialState) {
340
- initialState.fanControl = {
341
- fanMode: 0, // Off
342
- fanModeSequence: 0, // Off/Low/Med/High (Auto requires the AUT feature)
343
- percentSetting: 0,
344
- percentCurrent: 0
345
- }
346
- }
347
-
348
- function attachFanCommandHandlers (endpoint, def, onCommand) {
349
- endpoint.events.fanControl.percentSetting$Changed.on((value, oldValue, context) => {
350
- try {
351
- if (context?.offline === true || value === null || value === undefined) return
352
- onCommand({ deviceId: def.id, fn: 'fanspeed', value: clamp(Math.round(Number(value)), 0, 100) })
353
- } catch (error) { /* empty */ }
354
- })
355
- endpoint.events.fanControl.fanMode$Changed.on((value, oldValue, context) => {
356
- try {
357
- if (context?.offline === true) return
358
- if (Number(value) === 0) onCommand({ deviceId: def.id, fn: 'fanspeed', value: 0 })
359
- } catch (error) { /* empty */ }
360
- })
361
- }
362
-
363
- /**
364
- * Creates the bridged Matter endpoint for a virtual device definition.
365
- * @param {object} def - { id, type, name }
366
- * @param {string} serialPrefix - stable prefix for serial numbers
367
- * @param {function} onCommand - callback({ deviceId, fn, value }) for commands coming from Matter controllers.
368
- * 'value' is already KNX friendly (boolean for onoff, 0-100 for level).
369
- * @returns {Endpoint}
370
- */
371
- function createBridgedEndpoint (def, serialPrefix, onCommand) {
372
- const typeInfo = BRIDGE_TYPES[def.type]
373
- if (typeInfo === undefined) throw new Error(`Unsupported Matter bridge device type: ${def.type}`)
374
- const name = (def.name || def.type).toString().slice(0, 32)
375
-
376
- const stableSerial = `${serialPrefix}-${def.id}`.slice(0, 32)
377
- const initialState = {
378
- id: `knx-${def.id}`.slice(0, 32),
379
- bridgedDeviceBasicInformation: {
380
- nodeLabel: name, // This is the name Alexa/Google/Apple show and use
381
- productName: name,
382
- productLabel: name,
383
- serialNumber: stableSerial,
384
- // Optional but recommended: some controllers (notably Apple Home) use UniqueID,
385
- // rather than the endpoint number alone, as the stable cross-reset device identity.
386
- // It never changes for a given def.id, matching the endpoint's own persisted 'id'.
387
- uniqueId: stableSerial,
388
- reachable: true
389
- }
390
- }
391
- // Non nullable attributes need a sane initial value
392
- if (def.type === 'contactsensor') initialState.booleanState = { stateValue: false }
393
- if (def.type === 'occupancysensor') initialState.occupancySensing = { occupancy: { occupied: false } }
394
- // Although Matter permits an unknown (null) position, some controllers (including
395
- // Alexa) then expose only Open/Close instead of percentage positioning. Start with
396
- // a valid position; KNX or flow feedback replaces it as soon as it is available.
397
- if (def.type === 'windowcovering') {
398
- initialState.windowCovering = {
399
- currentPositionLiftPercent100ths: 0,
400
- targetPositionLiftPercent100ths: 0
401
- }
402
- }
403
-
404
- let endpoint
405
-
406
- // Emit controller commands at the command boundary instead of observing attribute
407
- // changes. This makes the node output raw: a controller re-sending a command (for
408
- // example Off while already off) is still forwarded, unlike attribute-change tracking
409
- // which would swallow the no-op.
410
- //
411
- // The one exception is a DUPLICATE burst from a single request. Just like the
412
- // WindowCovering RangeController quirk handled below, Alexa maps lights to its generic
413
- // Alexa.PowerController / Alexa.BrightnessController and a single "turn on" / "set to
414
- // 50%" voice request can arrive here as up to two IDENTICAL cluster commands (two On, or
415
- // moveToLevelWithOnOff + moveToLevel with the same level) instead of one - which made the
416
- // node emit duplicate raw msgs, discussions/516. A short leading-edge dedup collapses
417
- // that: the FIRST command is forwarded immediately (no added latency, unlike the cover's
418
- // trailing debounce - lights must react instantly), and a command identical to the one
419
- // just emitted for the same function is dropped only if it lands within the window. Any
420
- // change of value (a real On->Off, or a different brightness) always passes through at
421
- // once, so this suppresses only the spurious duplicate, never a genuine command.
422
- // Configurable per device via the editor's Advanced tab (def.commandDedupMs): 0 disables
423
- // it entirely (every command forwarded raw), a missing value uses the 1200ms default.
424
- const rawDedupMs = Number(def.commandDedupMs)
425
- const COMMAND_DEDUP_MS = Number.isFinite(rawDedupMs) && rawDedupMs >= 0 ? rawDedupMs : 1200
426
- const lastEmittedCommand = new Map() // fn -> { value, at }
427
- const isDuplicateCommand = (fn, value) => {
428
- const now = Date.now()
429
- const prev = lastEmittedCommand.get(fn)
430
- if (prev !== undefined && prev.value === value && (now - prev.at) < COMMAND_DEDUP_MS) return true
431
- lastEmittedCommand.set(fn, { value, at: now })
432
- return false
433
- }
434
-
435
- const RawOnOffBase = def.type === 'onoffplug'
436
- ? OnOffServer
437
- : def.type === 'roomairconditioner' ? OnOffServer.with('DeadFrontBehavior') : OnOffServer.with('Lighting')
438
- class RawOnOffServer extends RawOnOffBase {
439
- async on () {
440
- await super.on()
441
- if (isDuplicateCommand('onoff', true)) return
442
- onCommand({ deviceId: def.id, fn: 'onoff', value: true, matterCommand: { cluster: 'OnOff', command: 'on' } })
443
- }
444
-
445
- async off () {
446
- await super.off()
447
- if (isDuplicateCommand('onoff', false)) return
448
- onCommand({ deviceId: def.id, fn: 'onoff', value: false, matterCommand: { cluster: 'OnOff', command: 'off' } })
449
- }
450
- }
451
-
452
- class RawLevelControlServer extends LevelControlServer.with('Lighting', 'OnOff') {
453
- async moveToLevel (request) {
454
- await super.moveToLevel(request)
455
- const value = clamp(Math.round(Number(request.level) * 100 / 254), 0, 100)
456
- if (isDuplicateCommand('level', value)) return
457
- onCommand({ deviceId: def.id, fn: 'level', value, matterCommand: { cluster: 'LevelControl', command: 'moveToLevel', request } })
458
- }
459
-
460
- async moveToLevelWithOnOff (request) {
461
- await super.moveToLevelWithOnOff(request)
462
- const value = clamp(Math.round(Number(request.level) * 100 / 254), 0, 100)
463
- if (isDuplicateCommand('level', value)) return
464
- onCommand({ deviceId: def.id, fn: 'level', value, matterCommand: { cluster: 'LevelControl', command: 'moveToLevelWithOnOff', request } })
465
- }
466
- }
467
-
468
- if (def.type === 'windowcovering') {
469
- // The WindowCoveringServer requires the movement logic: we forward it to the KNX bus.
470
- // Position feedback comes back from the KNX status GA, so we do NOT call the default
471
- // implementation (which would fake the movement by jumping to the target).
472
- // KNX DPT 5.001 already follows Matter's cover convention. `invertPosition`
473
- // provides the Home Assistant/Alexa-friendly opposite percentage convention;
474
- // swapping Open/Close also reverses percentage commands and reports, symmetrically.
475
- const swapOpenClose = def.coverSwapOpenClose === true
476
- const invert = (def.invertPosition === true) !== swapOpenClose
477
-
478
- // Alexa DOES support the Matter WindowCovering device type - per Amazon's own docs
479
- // (developer.amazon.com/.../supported-matter-device-categories.html, Closure category) -
480
- // but maps it to its generic Alexa.RangeController interface, not a dedicated cover
481
- // controller (unlike lights, which get Alexa.ColorController, or locks, which get
482
- // Alexa.LockController). RangeController's generic "set/adjust range value" directive
483
- // model plausibly explains why a single "open/close the blind" voice request can arrive
484
- // here as a BURST of several GoToLiftPercentage commands stepping toward the final target,
485
- // instead of one UpOrOpen/DownOrClose/GoToLiftPercentage(final) call. Forwarding every
486
- // step to KNX makes the physical cover move in jerky stop-start motion. A short debounce -
487
- // the same coalescing technique already used for RGB colors elsewhere in this file, and
488
- // the fix independently validated in production by a very similar bridge - collapses a
489
- // burst into one KNX command using only the LAST target. This adds an imperceptible delay
490
- // for a single legitimate command (covers take many seconds to physically travel), and
491
- // StopMotion always bypasses it below.
492
- // https://github.com/Luligu/matterbridge-hass/issues/196
493
- // Match Home Assistant Matter Hub's cover slider handling: the first command in a
494
- // sequence waits 400 ms and subsequent rapid updates wait 150 ms. A per-node value
495
- // above zero replaces both windows. `movementDebounceMs` remains as a test/backward
496
- // compatibility alias for definitions created outside the Node-RED editor.
497
- const configuredDebounce = Number(def.coverSliderDebounceMs) > 0
498
- ? Number(def.coverSliderDebounceMs)
499
- : Number(def.movementDebounceMs) > 0 ? Number(def.movementDebounceMs) : 0
500
- const DEBOUNCE_INITIAL_MS = 400
501
- const DEBOUNCE_SUBSEQUENT_MS = 150
502
- const COMMAND_SEQUENCE_THRESHOLD_MS = 600
503
- let lastMovementCommandAt = 0
504
- let movementTimer = null
505
- let pendingMovementCommand = null
506
- const flushMovement = () => {
507
- movementTimer = null
508
- if (pendingMovementCommand === null) return
509
- const command = pendingMovementCommand
510
- pendingMovementCommand = null
511
- onCommand(command)
512
- }
513
- const scheduleMovement = (command) => {
514
- const now = Date.now()
515
- const firstInSequence = now - lastMovementCommandAt > COMMAND_SEQUENCE_THRESHOLD_MS
516
- lastMovementCommandAt = now
517
- const debounceMs = configuredDebounce > 0
518
- ? configuredDebounce
519
- : firstInSequence ? DEBOUNCE_INITIAL_MS : DEBOUNCE_SUBSEQUENT_MS
520
- pendingMovementCommand = command
521
- if (movementTimer !== null) clearTimeout(movementTimer)
522
- movementTimer = setTimeout(flushMovement, debounceMs)
523
- }
524
-
525
- class KnxCoverServer extends WindowCoveringServer.with('Lift', 'PositionAwareLift') {
526
- async handleMovement (type, reversed, direction, targetPercent100ths) {
527
- try {
528
- if (type !== MovementType.Lift) return
529
- const matterDiagnostic = {
530
- handler: 'handleMovement',
531
- movementType: type,
532
- reversed: reversed === true,
533
- direction,
534
- directionName: direction === MovementDirection.DefinedByPosition
535
- ? 'DefinedByPosition'
536
- : direction === MovementDirection.Open ? 'Open' : direction === MovementDirection.Close ? 'Close' : 'Unknown',
537
- targetPercent100ths: targetPercent100ths ?? null
538
- }
539
- if (targetPercent100ths === undefined || targetPercent100ths === null) return
540
- // NOTE: 'direction' is NOT a usable signal here. matter.js's WindowCoveringServer
541
- // resolves MovementDirection.DefinedByPosition (the direction goToLiftPercentage()
542
- // actually passes) into a concrete Open/Close BEFORE calling handleMovement,
543
- // by comparing targetPercent100ths against the current position (see
544
- // #prepareMovement in @matter/node's WindowCoveringServer.ts). Since this bridge
545
- // always starts with a known (non-null) position, handleMovement never receives
546
- // DefinedByPosition in practice - every percentage command looked exactly like a
547
- // plain Open/Close command. targetPercent100ths, on the other hand, is always
548
- // populated when PositionAwareLift is supported (0/10000 for plain Up/Down too),
549
- // so classify on that instead. Credit: till69, github.com/Supergiovane/
550
- // node-red-contrib-knx-ultimate/discussions/516#discussioncomment-17633430
551
- const target = Number(targetPercent100ths)
552
- if (target <= 0 || target >= 10000) {
553
- // Full travel: KNX DPT 1.008 (0 = up/open, 1 = down/close). Not affected by
554
- // invertPosition, which only rescales the percentage GA convention.
555
- const downOrClose = target >= 10000
556
- scheduleMovement({ deviceId: def.id, fn: 'updown', value: swapOpenClose ? !downOrClose : downOrClose, matterDiagnostic })
557
- } else {
558
- let percent = Math.round(target / 100)
559
- if (invert) percent = 100 - percent
560
- scheduleMovement({ deviceId: def.id, fn: 'position', value: clamp(percent, 0, 100), matterDiagnostic })
561
- }
562
- } catch (error) { /* empty */ }
563
- }
564
-
565
- async handleStopMovement () {
566
- try {
567
- // Stop is always immediate: drop any pending debounced movement so a stale queued
568
- // command from before the stop cannot fire afterwards.
569
- if (movementTimer !== null) { clearTimeout(movementTimer); movementTimer = null }
570
- pendingMovementCommand = null
571
- onCommand({
572
- deviceId: def.id,
573
- fn: 'stop',
574
- value: true,
575
- matterDiagnostic: { handler: 'handleStopMovement' }
576
- })
577
- } catch (error) { /* empty */ }
578
- return super.handleStopMovement()
579
- }
580
- }
581
- endpoint = new Endpoint(WindowCoveringDevice.with(KnxCoverServer, BridgedDeviceBasicInformationServer), initialState)
582
- return endpoint
583
- }
584
-
585
- if (def.type === 'thermostat') {
586
- // Heating/Cooling capability is auto-detected from which setpoint GA(s) the KNX node
587
- // has configured (see knxUltimateMatterBridge.js#getMatterDef). Leaving both flags
588
- // unset keeps the original heating-only behavior, so existing flows are unaffected.
589
- const thermostat = configureThermostatState(initialState, def, 'heating')
590
- endpoint = new Endpoint(ThermostatDevice.with(ThermostatServer.with(...thermostat.features), BridgedDeviceBasicInformationServer), initialState)
591
- attachThermostatCommandHandlers(endpoint, def, onCommand, thermostat)
592
- // NOTE: SystemMode (Heat/Cool/Off/Auto) changes from a controller are accepted by the
593
- // cluster but not forwarded to KNX yet: there is no single KNX DPT for HVAC mode that
594
- // fits every actuator. Track it via the node's optional input PIN if you need it today.
595
- return endpoint
596
- }
597
-
598
- if (def.type === 'roomairconditioner') {
599
- // Matter Room Air Conditioner (0x0072) requires OnOff with DeadFrontBehavior and a
600
- // feature-selected Thermostat server. FanControl is optional in the specification,
601
- // but included here so the former on/off + thermostat + fan trio becomes one endpoint.
602
- const thermostat = configureThermostatState(initialState, def, 'cooling')
603
- configureFanState(initialState)
604
- endpoint = new Endpoint(RoomAirConditionerDevice.with(
605
- RawOnOffServer,
606
- ThermostatServer.with(...thermostat.features),
607
- FanControlServer,
608
- BridgedDeviceBasicInformationServer
609
- ), initialState)
610
- attachThermostatCommandHandlers(endpoint, def, onCommand, thermostat)
611
- attachFanCommandHandlers(endpoint, def, onCommand)
612
- return endpoint
613
- }
614
-
615
- if (def.type === 'doorlock') {
616
- initialState.doorLock = {
617
- lockState: DoorLock.LockState.Unlocked,
618
- lockType: DoorLock.LockType.Other,
619
- actuatorEnabled: true,
620
- operatingMode: DoorLock.OperatingMode.Normal,
621
- // matter.js currently defaults these constrained base attributes to 0, which is
622
- // outside their Matter-defined 1..255 range and prevents endpoint initialization.
623
- wrongCodeEntryLimit: 3,
624
- userCodeTemporaryDisableTime: 10
625
- }
626
- class KnxDoorLockServer extends DoorLockServer {
627
- async lockDoor (request) {
628
- await super.lockDoor(request)
629
- onCommand({ deviceId: def.id, fn: 'lock', value: true, matterCommand: { cluster: 'DoorLock', command: 'lockDoor' } })
630
- }
631
-
632
- async unlockDoor (request) {
633
- await super.unlockDoor(request)
634
- onCommand({ deviceId: def.id, fn: 'lock', value: false, matterCommand: { cluster: 'DoorLock', command: 'unlockDoor' } })
635
- }
636
- }
637
- endpoint = new Endpoint(DoorLockDevice.with(KnxDoorLockServer, BridgedDeviceBasicInformationServer), initialState)
638
- return endpoint
639
- }
640
-
641
- if (def.type === 'occupancysensor') {
642
- // The OccupancySensing cluster is not added by default: the sensor type must be chosen (we expose it as PIR)
643
- endpoint = new Endpoint(OccupancySensorDevice.with(OccupancySensingServer.with('PassiveInfrared'), BridgedDeviceBasicInformationServer), initialState)
644
- } else if (def.type === 'rgblight') {
645
- // colorMode/enhancedColorMode and the color attributes are mandatory initial values
646
- initialState.colorControl = {
647
- colorMode: 0, // CurrentHueAndCurrentSaturation
648
- enhancedColorMode: 0,
649
- currentHue: 0,
650
- currentSaturation: 0,
651
- currentX: Math.round(0.31 * 65536),
652
- currentY: Math.round(0.33 * 65536)
653
- }
654
- const { RawColorControlServer, attachLevelTracker } = createRawColorControlServer(def, onCommand)
655
- endpoint = new Endpoint(ExtendedColorLightDevice.with(RawOnOffServer, RawLevelControlServer, RawColorControlServer, BridgedDeviceBasicInformationServer), initialState)
656
- attachLevelTracker(endpoint)
657
- } else if (def.type === 'colortemperaturelight') {
658
- initialState.colorControl = {
659
- colorMode: 2, // ColorTemperatureMireds
660
- enhancedColorMode: 2,
661
- colorTempPhysicalMinMireds: 153, // 6500 K
662
- colorTempPhysicalMaxMireds: 500, // 2000 K
663
- colorTemperatureMireds: 250,
664
- startUpColorTemperatureMireds: 250,
665
- coupleColorTempToLevelMinMireds: 153
666
- }
667
- class RawColorTemperatureServer extends ColorControlServer.with('ColorTemperature') {
668
- async moveToColorTemperature (request) {
669
- await super.moveToColorTemperature(request)
670
- const mireds = Number(request.colorTemperatureMireds)
671
- if (Number.isNaN(mireds) || mireds <= 0) return
672
- onCommand({ deviceId: def.id, fn: 'colortemp', value: Math.round(1000000 / mireds) }) // mireds -> Kelvin
673
- }
674
- }
675
- endpoint = new Endpoint(ColorTemperatureLightDevice.with(RawOnOffServer, RawLevelControlServer, RawColorTemperatureServer, BridgedDeviceBasicInformationServer), initialState)
676
- } else if (def.type === 'smokecoalarm') {
677
- initialState.smokeCoAlarm = {
678
- expressedState: 0, // Normal
679
- smokeState: 0,
680
- coState: 0,
681
- batteryAlert: 0,
682
- testInProgress: false,
683
- hardwareFaultAlert: false,
684
- endOfServiceAlert: 0
685
- }
686
- endpoint = new Endpoint(SmokeCoAlarmDevice.with(SmokeCoAlarmServer.with('SmokeAlarm', 'CoAlarm'), BridgedDeviceBasicInformationServer), initialState)
687
- } else if (def.type === 'waterleakdetector') {
688
- initialState.booleanState = { stateValue: false }
689
- endpoint = new Endpoint(WaterLeakDetectorDevice.with(BridgedDeviceBasicInformationServer), initialState)
690
- } else if (def.type === 'airqualitysensor') {
691
- initialState.airQuality = { airQuality: 0 } // Unknown
692
- initialState.carbonDioxideConcentrationMeasurement = {
693
- measuredValue: null,
694
- minMeasuredValue: null,
695
- maxMeasuredValue: null,
696
- measurementUnit: 0, // PPM
697
- measurementMedium: 0 // Air
698
- }
699
- endpoint = new Endpoint(AirQualitySensorDevice.with(
700
- AirQualityServer.with('Fair', 'Moderate', 'VeryPoor', 'ExtremelyPoor'),
701
- CarbonDioxideConcentrationMeasurementServer.with('NumericMeasurement'),
702
- BridgedDeviceBasicInformationServer
703
- ), initialState)
704
- } else if (def.type === 'fan') {
705
- configureFanState(initialState)
706
- endpoint = new Endpoint(FanDevice.with(BridgedDeviceBasicInformationServer), initialState)
707
- // Speed changes from the controller (percent write or fan mode change). Like the
708
- // Thermostat setpoints above, FanControlServer exposes no command to intercept for
709
- // percentSetting (@matter/node's FanControlServer overrides nothing beyond
710
- // initialize()) - it is attribute-write only, so this cannot be made "raw" either.
711
- attachFanCommandHandlers(endpoint, def, onCommand)
712
- } else if (def.type === 'robotvacuum') {
713
- // Flow-only device: run mode changes and operational commands are forwarded to the flow
714
- // (node PINs); the flow reports the state back through the input PIN.
715
- class KnxRvcRunModeServer extends RvcRunModeServer {
716
- changeToMode ({ newMode }) {
717
- try {
718
- const result = ModeUtils.assertModeChange(this.state.supportedModes, this.state.currentMode, newMode)
719
- if (result.status !== 0) return result
720
- this.state.currentMode = newMode
721
- return result
722
- } catch (error) {
723
- return { status: 2, statusText: error.message } // GenericFailure
724
- }
725
- }
726
- }
727
- class KnxRvcOperationalStateServer extends RvcOperationalStateServer {
728
- async goHome () {
729
- try { onCommand({ deviceId: def.id, fn: 'rvccommand', value: 'gohome' }) } catch (error) { /* empty */ }
730
- return { commandResponseState: { errorStateId: 0 } }
731
- }
732
-
733
- async pause () {
734
- try { onCommand({ deviceId: def.id, fn: 'rvccommand', value: 'pause' }) } catch (error) { /* empty */ }
735
- return { commandResponseState: { errorStateId: 0 } }
736
- }
737
-
738
- async resume () {
739
- try { onCommand({ deviceId: def.id, fn: 'rvccommand', value: 'resume' }) } catch (error) { /* empty */ }
740
- return { commandResponseState: { errorStateId: 0 } }
741
- }
742
- }
743
- initialState.rvcRunMode = {
744
- supportedModes: [
745
- { label: 'Idle', mode: 0, modeTags: [{ value: 0x4000 }] }, // RvcRunMode.ModeTag.Idle
746
- { label: 'Cleaning', mode: 1, modeTags: [{ value: 0x4001 }] } // RvcRunMode.ModeTag.Cleaning
747
- ],
748
- currentMode: 0
749
- }
750
- initialState.rvcOperationalState = {
751
- operationalStateList: [
752
- { operationalStateId: RVC_OP_STATES.stopped },
753
- { operationalStateId: RVC_OP_STATES.running },
754
- { operationalStateId: RVC_OP_STATES.paused },
755
- { operationalStateId: RVC_OP_STATES.error },
756
- { operationalStateId: RVC_OP_STATES.seekingcharger },
757
- { operationalStateId: RVC_OP_STATES.charging },
758
- { operationalStateId: RVC_OP_STATES.docked }
759
- ],
760
- operationalState: RVC_OP_STATES.docked
761
- }
762
- endpoint = new Endpoint(RoboticVacuumCleanerDevice.with(KnxRvcRunModeServer, KnxRvcOperationalStateServer, BridgedDeviceBasicInformationServer), initialState)
763
- // Run mode changed by a controller ("Alexa, start cleaning")
764
- endpoint.events.rvcRunMode.currentMode$Changed.on((value, oldValue, context) => {
765
- try {
766
- if (context?.offline === true) return
767
- onCommand({ deviceId: def.id, fn: 'rvcmode', value: Number(value) === 1 ? 'cleaning' : 'idle' })
768
- } catch (error) { /* empty */ }
769
- })
770
- } else {
771
- let device = typeInfo.device
772
- if (typeInfo.commandFunctions.includes('onoff')) device = device.with(RawOnOffServer)
773
- if (typeInfo.commandFunctions.includes('level')) device = device.with(RawLevelControlServer)
774
- endpoint = new Endpoint(device.with(BridgedDeviceBasicInformationServer), initialState)
775
- }
776
-
777
- return endpoint
778
- }
779
-
780
- export { BRIDGE_TYPES, createBridgedEndpoint, knxValueToMatterPatch }