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,631 +0,0 @@
1
- const dns = require('dns')
2
- const https = require('https')
3
- const net = require('net')
4
-
5
- const DEFAULT_TIMEOUT_MS = 10000
6
- const DEFAULT_MAX_REDIRECTS = 3
7
- const DEFAULT_MAX_ACTIONS = 2
8
- const DEFAULT_MAX_RESULTS = 3
9
- const DEFAULT_SEARCH_MAX_BYTES = 512 * 1024
10
- const DEFAULT_OPEN_MAX_BYTES = 1024 * 1024
11
- const DEFAULT_TEXT_MAX_CHARS = 16000
12
- const HARD_MAX_BYTES = 2 * 1024 * 1024
13
- const HARD_MAX_ACTIONS = 5
14
- const HARD_MAX_REDIRECTS = 5
15
- const HARD_MAX_RESULTS = 5
16
- const MAX_QUERY_CHARS = 500
17
- const MAX_URL_CHARS = 4096
18
- const DEFAULT_SEARCH_ENDPOINTS = [
19
- 'https://html.duckduckgo.com/html/',
20
- 'https://lite.duckduckgo.com/lite/'
21
- ]
22
- const DEFAULT_USER_AGENT = 'Mozilla/5.0 (compatible; KNX-Ultimate-AI/1.0; +https://github.com/Supergiovane/node-red-contrib-knx-ultimate)'
23
-
24
- class KnxAiWebAccessError extends Error {
25
- constructor (code, message) {
26
- super(message)
27
- this.name = 'KnxAiWebAccessError'
28
- this.code = code
29
- }
30
- }
31
-
32
- const boundedInteger = (value, fallback, minimum, maximum) => {
33
- const numeric = Number(value)
34
- if (!Number.isFinite(numeric)) return fallback
35
- return Math.min(maximum, Math.max(minimum, Math.floor(numeric)))
36
- }
37
-
38
- const compactWhitespace = (value, maxChars = DEFAULT_TEXT_MAX_CHARS) => {
39
- const limit = boundedInteger(maxChars, DEFAULT_TEXT_MAX_CHARS, 1, 100000)
40
- const normalized = String(value || '')
41
- .replace(/[\s\S]/g, character => {
42
- const code = character.charCodeAt(0)
43
- if (code === 0) return ''
44
- if ((code >= 1 && code <= 8) || code === 11 || code === 12 || (code >= 14 && code <= 31) || (code >= 127 && code <= 159)) return ' '
45
- if ((code >= 0x200b && code <= 0x200f) || (code >= 0x202a && code <= 0x202e) || (code >= 0x2066 && code <= 0x2069) || code === 0xfeff) return ''
46
- return character
47
- })
48
- .replace(/\r\n?/g, '\n')
49
- .replace(/[\t\f\v ]+/g, ' ')
50
- .replace(/ +([,.;:!?])/g, '$1')
51
- .replace(/ *\n */g, '\n')
52
- .replace(/\n{3,}/g, '\n\n')
53
- .trim()
54
- if (normalized.length <= limit) return normalized
55
- return `${normalized.slice(0, Math.max(1, limit - 1)).trimEnd()}…`
56
- }
57
-
58
- const decodeHtmlEntities = (value) => {
59
- const named = {
60
- amp: '&',
61
- apos: "'",
62
- gt: '>',
63
- hellip: '…',
64
- ldquo: '“',
65
- lsquo: '‘',
66
- lt: '<',
67
- nbsp: ' ',
68
- ndash: '–',
69
- quot: '"',
70
- rdquo: '”',
71
- rsquo: '’',
72
- trade: '™'
73
- }
74
- return String(value || '').replace(/&(#(?:x[0-9a-f]{1,6}|[0-9]{1,7})|[a-z][a-z0-9]{1,15});/gi, (match, entity) => {
75
- if (entity[0] !== '#') return Object.prototype.hasOwnProperty.call(named, entity.toLowerCase()) ? named[entity.toLowerCase()] : ' '
76
- const hexadecimal = entity[1].toLowerCase() === 'x'
77
- const numeric = Number.parseInt(entity.slice(hexadecimal ? 2 : 1), hexadecimal ? 16 : 10)
78
- if (!Number.isInteger(numeric) || numeric <= 0 || numeric > 0x10ffff || (numeric >= 0xd800 && numeric <= 0xdfff)) return ' '
79
- try { return String.fromCodePoint(numeric) } catch (error) { return ' ' }
80
- })
81
- }
82
-
83
- const stripHtmlTags = (value, maxChars = DEFAULT_TEXT_MAX_CHARS) => {
84
- let html = String(value || '')
85
- html = html
86
- .replace(/<!--[\s\S]*?-->/g, ' ')
87
- .replace(/<!--[\s\S]*$/g, ' ')
88
- .replace(/<(script|style|noscript|template|svg|canvas|iframe|object|embed)\b[^>]*>[\s\S]*?<\/\1\s*>/gi, ' ')
89
- .replace(/<(script|style|noscript|template|svg|canvas|iframe|object|embed)\b[^>]*>[\s\S]*$/gi, ' ')
90
- .replace(/<(br|hr)\b[^>]*>/gi, '\n')
91
- .replace(/<\/(address|article|aside|blockquote|div|dl|fieldset|figcaption|figure|footer|form|h[1-6]|header|li|main|nav|ol|p|pre|section|table|tr|ul)\s*>/gi, '\n')
92
- .replace(/<[^>]+>/g, ' ')
93
- return compactWhitespace(decodeHtmlEntities(html), maxChars)
94
- }
95
-
96
- const extractHtmlDocument = (html, maxChars = DEFAULT_TEXT_MAX_CHARS) => {
97
- const source = String(html || '')
98
- const titleMatch = source.match(/<title\b[^>]*>([\s\S]*?)<\/title\s*>/i)
99
- const bodyMatch = source.match(/<body\b[^>]*>([\s\S]*?)<\/body\s*>/i)
100
- return {
101
- title: compactWhitespace(stripHtmlTags(titleMatch ? titleMatch[1] : '', 300), 300),
102
- text: stripHtmlTags(bodyMatch ? bodyMatch[1] : source, maxChars)
103
- }
104
- }
105
-
106
- const getHtmlAttribute = (tag, attributeName) => {
107
- const escaped = String(attributeName || '').replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
108
- const expression = new RegExp(`(?:^|\\s)${escaped}\\s*=\\s*(?:"([^"]*)"|'([^']*)'|([^\\s>]+))`, 'i')
109
- const match = String(tag || '').match(expression)
110
- return match ? decodeHtmlEntities(match[1] ?? match[2] ?? match[3] ?? '') : ''
111
- }
112
-
113
- const resolveDuckDuckGoResultUrl = (href) => {
114
- const raw = decodeHtmlEntities(href).trim()
115
- if (!raw || raw.length > MAX_URL_CHARS) return ''
116
- let parsed
117
- try { parsed = new URL(raw, 'https://duckduckgo.com/') } catch (error) { return '' }
118
- const hostname = parsed.hostname.toLowerCase().replace(/\.$/, '')
119
- if ((hostname === 'duckduckgo.com' || hostname.endsWith('.duckduckgo.com')) && parsed.pathname.startsWith('/l/')) {
120
- const target = parsed.searchParams.get('uddg')
121
- if (!target) return ''
122
- try { parsed = new URL(target) } catch (error) { return '' }
123
- }
124
- if (parsed.protocol !== 'https:' || parsed.username || parsed.password || parsed.port) return ''
125
- parsed.hash = ''
126
- try { return assertSafeHttpsUrl(parsed.toString()).toString() } catch (error) { return '' }
127
- }
128
-
129
- const parseDuckDuckGoResults = (html, { maxResults = DEFAULT_MAX_RESULTS, retrievedAt = new Date().toISOString() } = {}) => {
130
- const source = String(html || '')
131
- const limit = boundedInteger(maxResults, DEFAULT_MAX_RESULTS, 1, HARD_MAX_RESULTS)
132
- const anchors = []
133
- const anchorPattern = /<a\b[^>]*\bclass\s*=\s*(?:"[^"]*(?:result__a|result-link)[^"]*"|'[^']*(?:result__a|result-link)[^']*'|[^\s>]*(?:result__a|result-link)[^\s>]*)[^>]*>[\s\S]*?<\/a\s*>/gi
134
- let match
135
- while ((match = anchorPattern.exec(source)) && anchors.length < limit * 4) {
136
- anchors.push({ index: match.index, end: anchorPattern.lastIndex, tag: match[0] })
137
- }
138
-
139
- const results = []
140
- const seen = new Set()
141
- for (let index = 0; index < anchors.length && results.length < limit; index++) {
142
- const anchor = anchors[index]
143
- const url = resolveDuckDuckGoResultUrl(getHtmlAttribute(anchor.tag, 'href'))
144
- if (!url || seen.has(url)) continue
145
- const title = stripHtmlTags(anchor.tag.replace(/^<a\b[^>]*>/i, '').replace(/<\/a\s*>$/i, ''), 300)
146
- if (!title) continue
147
- const nextIndex = anchors[index + 1] ? anchors[index + 1].index : Math.min(source.length, anchor.end + 6000)
148
- const vicinity = source.slice(anchor.end, nextIndex)
149
- const snippetMatch = vicinity.match(/<(?:a|div|span|td)\b[^>]*\bclass\s*=\s*(?:"[^"]*(?:result__snippet|result-snippet)[^"]*"|'[^']*(?:result__snippet|result-snippet)[^']*'|[^\s>]*(?:result__snippet|result-snippet)[^\s>]*)[^>]*>([\s\S]*?)<\/(?:a|div|span|td)\s*>/i)
150
- const text = stripHtmlTags(snippetMatch ? snippetMatch[1] : title, 1200) || title
151
- seen.add(url)
152
- results.push({ title, url, text, retrievedAt })
153
- }
154
- return results
155
- }
156
-
157
- const ipv4ToInteger = (value) => {
158
- if (net.isIP(value) !== 4) return null
159
- return value.split('.').reduce((total, part) => ((total << 8) + Number(part)) >>> 0, 0) >>> 0
160
- }
161
-
162
- const ipv4InRange = (value, base, prefix) => {
163
- const candidate = ipv4ToInteger(value)
164
- const network = ipv4ToInteger(base)
165
- if (candidate === null || network === null) return false
166
- if (prefix === 0) return true
167
- const mask = (0xffffffff << (32 - prefix)) >>> 0
168
- return (candidate & mask) === (network & mask)
169
- }
170
-
171
- const ipv6ToBigInt = (value) => {
172
- let source = String(value || '').toLowerCase().replace(/^\[|\]$/g, '')
173
- if (source.includes('%') || net.isIP(source) !== 6) return null
174
- if (source.includes('.')) {
175
- const separator = source.lastIndexOf(':')
176
- const ipv4 = source.slice(separator + 1)
177
- const numeric = ipv4ToInteger(ipv4)
178
- if (numeric === null) return null
179
- source = `${source.slice(0, separator)}:${(numeric >>> 16).toString(16)}:${(numeric & 0xffff).toString(16)}`
180
- }
181
- const halves = source.split('::')
182
- if (halves.length > 2) return null
183
- const left = halves[0] ? halves[0].split(':') : []
184
- const right = halves.length === 2 && halves[1] ? halves[1].split(':') : []
185
- if (halves.length === 1 && left.length !== 8) return null
186
- const missing = 8 - left.length - right.length
187
- if (missing < 0 || (halves.length === 2 && missing < 1)) return null
188
- const parts = [...left, ...Array(missing).fill('0'), ...right]
189
- if (parts.length !== 8 || parts.some(part => !/^[0-9a-f]{1,4}$/.test(part))) return null
190
- return parts.reduce((total, part) => (total << 16n) + BigInt(Number.parseInt(part, 16)), 0n)
191
- }
192
-
193
- const ipv6InRange = (value, base, prefix) => {
194
- const candidate = ipv6ToBigInt(value)
195
- const network = ipv6ToBigInt(base)
196
- if (candidate === null || network === null) return false
197
- if (prefix === 0) return true
198
- const shift = BigInt(128 - prefix)
199
- return (candidate >> shift) === (network >> shift)
200
- }
201
-
202
- const BLOCKED_IPV4_RANGES = [
203
- ['0.0.0.0', 8], ['10.0.0.0', 8], ['100.64.0.0', 10], ['127.0.0.0', 8],
204
- ['169.254.0.0', 16], ['172.16.0.0', 12], ['192.0.0.0', 24], ['192.0.2.0', 24],
205
- ['192.88.99.0', 24], ['192.168.0.0', 16], ['198.18.0.0', 15], ['198.51.100.0', 24],
206
- ['203.0.113.0', 24], ['224.0.0.0', 4], ['240.0.0.0', 4]
207
- ]
208
-
209
- const BLOCKED_IPV6_RANGES = [
210
- ['2001::', 23], ['2001:2::', 48], ['2001:db8::', 32], ['2002::', 16], ['3ffe::', 16], ['3fff::', 20]
211
- ]
212
-
213
- const isPublicIpAddress = (value) => {
214
- const address = String(value || '').trim().replace(/^\[|\]$/g, '')
215
- const family = net.isIP(address)
216
- if (family === 4) return !BLOCKED_IPV4_RANGES.some(([base, prefix]) => ipv4InRange(address, base, prefix))
217
- if (family !== 6) return false
218
- // Current globally routable unicast space is 2000::/3. Explicitly reject its special-use subnets.
219
- if (!ipv6InRange(address, '2000::', 3)) return false
220
- return !BLOCKED_IPV6_RANGES.some(([base, prefix]) => ipv6InRange(address, base, prefix))
221
- }
222
-
223
- const normalizeHostname = (value) => String(value || '').trim().toLowerCase().replace(/^\[|\]$/g, '').replace(/\.$/, '')
224
-
225
- const assertSafeHttpsUrl = (value) => {
226
- const raw = String(value || '').trim()
227
- if (!raw || raw.length > MAX_URL_CHARS) throw new KnxAiWebAccessError('INVALID_URL', 'A valid HTTPS URL is required')
228
- let parsed
229
- try { parsed = new URL(raw) } catch (error) { throw new KnxAiWebAccessError('INVALID_URL', 'A valid HTTPS URL is required') }
230
- if (parsed.protocol !== 'https:') throw new KnxAiWebAccessError('UNSAFE_PROTOCOL', 'Only HTTPS web addresses are allowed')
231
- if (parsed.username || parsed.password) throw new KnxAiWebAccessError('URL_CREDENTIALS', 'Web addresses containing credentials are not allowed')
232
- if (parsed.port && parsed.port !== '443') throw new KnxAiWebAccessError('UNSAFE_PORT', 'Only the standard HTTPS port is allowed')
233
- const hostname = normalizeHostname(parsed.hostname)
234
- if (!hostname || hostname.length > 253 || hostname.includes('%')) throw new KnxAiWebAccessError('INVALID_HOST', 'The web address has an invalid host')
235
- if (net.isIP(hostname)) {
236
- if (!isPublicIpAddress(hostname)) throw new KnxAiWebAccessError('NON_PUBLIC_TARGET', 'Private, local, and reserved web addresses are not allowed')
237
- } else {
238
- const localSuffixes = ['localhost', 'local', 'lan', 'internal', 'home', 'home.arpa', 'test', 'invalid', 'example']
239
- if (!hostname.includes('.') || localSuffixes.some(suffix => hostname === suffix || hostname.endsWith(`.${suffix}`))) {
240
- throw new KnxAiWebAccessError('NON_PUBLIC_TARGET', 'Private, local, and reserved web addresses are not allowed')
241
- }
242
- }
243
- parsed.hash = ''
244
- return parsed
245
- }
246
-
247
- const normalizeDnsRecords = (value) => {
248
- const source = Array.isArray(value) ? value : [value]
249
- const records = []
250
- const seen = new Set()
251
- for (const item of source) {
252
- const address = typeof item === 'string' ? item : item && item.address
253
- const normalized = String(address || '').trim().replace(/^\[|\]$/g, '')
254
- const family = net.isIP(normalized)
255
- if (!family) throw new KnxAiWebAccessError('DNS_INVALID', 'The web address returned an invalid DNS response')
256
- const key = `${family}:${normalized}`
257
- if (!seen.has(key)) records.push({ address: normalized, family })
258
- seen.add(key)
259
- }
260
- if (!records.length || records.length > 32) throw new KnxAiWebAccessError('DNS_INVALID', 'The web address returned an invalid DNS response')
261
- return records
262
- }
263
-
264
- const defaultDnsLookup = async (hostname) => dns.promises.lookup(hostname, { all: true, verbatim: true })
265
-
266
- const runWithTimeout = async (factory, timeoutMs, message) => {
267
- const controller = new AbortController()
268
- let timer
269
- try {
270
- return await new Promise((resolve, reject) => {
271
- let settled = false
272
- timer = setTimeout(() => {
273
- if (settled) return
274
- settled = true
275
- controller.abort()
276
- reject(new KnxAiWebAccessError('TIMEOUT', message))
277
- }, timeoutMs)
278
- Promise.resolve()
279
- .then(() => factory(controller.signal))
280
- .then(value => {
281
- if (settled) return
282
- settled = true
283
- resolve(value)
284
- }, error => {
285
- if (settled) return
286
- settled = true
287
- reject(error)
288
- })
289
- })
290
- } finally {
291
- clearTimeout(timer)
292
- }
293
- }
294
-
295
- const resolvePublicTarget = async (parsedUrl, { dnsLookup, timeoutMs }) => {
296
- const hostname = normalizeHostname(parsedUrl.hostname)
297
- if (net.isIP(hostname)) return [{ address: hostname, family: net.isIP(hostname) }]
298
- let rawRecords
299
- try {
300
- rawRecords = await runWithTimeout(
301
- () => dnsLookup(hostname, { all: true, verbatim: true }),
302
- timeoutMs,
303
- 'DNS lookup timed out'
304
- )
305
- } catch (error) {
306
- if (error instanceof KnxAiWebAccessError) throw error
307
- throw new KnxAiWebAccessError('DNS_FAILED', 'The web address could not be resolved')
308
- }
309
- const records = normalizeDnsRecords(rawRecords)
310
- if (records.some(record => !isPublicIpAddress(record.address))) {
311
- throw new KnxAiWebAccessError('NON_PUBLIC_TARGET', 'The web address resolves to a private, local, or reserved network')
312
- }
313
- return records.sort((left, right) => left.family - right.family)
314
- }
315
-
316
- const getHeader = (headers, name) => {
317
- if (!headers) return ''
318
- if (typeof headers.get === 'function') return String(headers.get(name) || '')
319
- const normalized = String(name || '').toLowerCase()
320
- const entry = Object.entries(headers).find(([key]) => String(key).toLowerCase() === normalized)
321
- if (!entry) return ''
322
- return Array.isArray(entry[1]) ? String(entry[1][0] || '') : String(entry[1] || '')
323
- }
324
-
325
- const defaultPinnedHttpsTransport = ({ url, resolvedAddress, headers, timeoutMs, maxBytes, signal }) => new Promise((resolve, reject) => {
326
- let settled = false
327
- const finish = (error, response) => {
328
- if (settled) return
329
- settled = true
330
- if (signal) signal.removeEventListener('abort', abort)
331
- if (error) reject(error)
332
- else resolve(response)
333
- }
334
- const abort = () => {
335
- request.destroy(new KnxAiWebAccessError('TIMEOUT', 'Web request timed out'))
336
- }
337
- const lookup = (_hostname, options, callback) => {
338
- if (typeof options === 'function') callback = options
339
- const wantsAll = options && typeof options === 'object' && options.all
340
- if (wantsAll) callback(null, [resolvedAddress])
341
- else callback(null, resolvedAddress.address, resolvedAddress.family)
342
- }
343
- const request = https.request(url, {
344
- method: 'GET',
345
- agent: false,
346
- headers,
347
- lookup,
348
- rejectUnauthorized: true
349
- }, response => {
350
- const statusCode = Number(response.statusCode) || 0
351
- if (statusCode >= 300 && statusCode < 400) {
352
- response.destroy()
353
- return finish(null, { statusCode, headers: response.headers, body: Buffer.alloc(0) })
354
- }
355
- if (statusCode < 200 || statusCode >= 300) {
356
- response.destroy()
357
- return finish(null, { statusCode, headers: response.headers, body: Buffer.alloc(0) })
358
- }
359
- const declaredLength = Number(getHeader(response.headers, 'content-length'))
360
- if (Number.isFinite(declaredLength) && declaredLength > maxBytes) {
361
- response.destroy()
362
- return finish(new KnxAiWebAccessError('RESPONSE_TOO_LARGE', 'The web response exceeds the size limit'))
363
- }
364
- const chunks = []
365
- let total = 0
366
- response.on('data', chunk => {
367
- if (settled) return
368
- const buffer = Buffer.from(chunk)
369
- total += buffer.length
370
- if (total > maxBytes) {
371
- response.destroy()
372
- finish(new KnxAiWebAccessError('RESPONSE_TOO_LARGE', 'The web response exceeds the size limit'))
373
- return
374
- }
375
- chunks.push(buffer)
376
- })
377
- response.on('end', () => finish(null, { statusCode, headers: response.headers, body: Buffer.concat(chunks) }))
378
- response.on('error', error => finish(error))
379
- })
380
- request.setTimeout(timeoutMs, abort)
381
- request.on('error', error => finish(error))
382
- if (signal) {
383
- if (signal.aborted) abort()
384
- else signal.addEventListener('abort', abort, { once: true })
385
- }
386
- request.end()
387
- })
388
-
389
- const isTextualMimeType = (value) => {
390
- const mimeType = String(value || '').split(';')[0].trim().toLowerCase()
391
- if (mimeType.startsWith('text/')) return true
392
- if (!mimeType.startsWith('application/')) return false
393
- return mimeType === 'application/json' || mimeType.endsWith('+json') ||
394
- mimeType === 'application/xml' || mimeType.endsWith('+xml')
395
- }
396
-
397
- const responseBodyToBuffer = (body) => {
398
- if (Buffer.isBuffer(body)) return body
399
- if (body instanceof Uint8Array) return Buffer.from(body)
400
- if (typeof body === 'string') return Buffer.from(body, 'utf8')
401
- if (body === undefined || body === null) return Buffer.alloc(0)
402
- throw new KnxAiWebAccessError('INVALID_RESPONSE', 'The web server returned an invalid response')
403
- }
404
-
405
- const requestTextWithRedirects = async (initialUrl, options) => {
406
- let current = assertSafeHttpsUrl(initialUrl)
407
- const deadline = Date.now() + options.timeoutMs
408
- const remainingTimeout = () => {
409
- const remaining = deadline - Date.now()
410
- if (remaining <= 0) throw new KnxAiWebAccessError('TIMEOUT', 'Web request timed out')
411
- return remaining
412
- }
413
- for (let redirects = 0; redirects <= options.maxRedirects; redirects++) {
414
- const resolvedAddresses = await resolvePublicTarget(current, {
415
- ...options,
416
- timeoutMs: remainingTimeout()
417
- })
418
- let response
419
- try {
420
- const timeoutMs = remainingTimeout()
421
- response = await runWithTimeout(
422
- signal => options.transport({
423
- url: current.toString(),
424
- resolvedAddress: resolvedAddresses[0],
425
- resolvedAddresses,
426
- headers: options.headers,
427
- timeoutMs,
428
- maxBytes: options.maxBytes,
429
- signal
430
- }),
431
- timeoutMs,
432
- 'Web request timed out'
433
- )
434
- } catch (error) {
435
- if (error instanceof KnxAiWebAccessError) throw error
436
- throw new KnxAiWebAccessError('REQUEST_FAILED', 'The web request failed')
437
- }
438
-
439
- const statusCode = Number(response && (response.statusCode ?? response.status)) || 0
440
- if (statusCode >= 300 && statusCode < 400) {
441
- const location = getHeader(response.headers, 'location')
442
- if (!location) throw new KnxAiWebAccessError('INVALID_REDIRECT', 'The web server returned an invalid redirect')
443
- if (redirects >= options.maxRedirects) throw new KnxAiWebAccessError('TOO_MANY_REDIRECTS', 'The web request exceeded the redirect limit')
444
- let redirected
445
- try { redirected = new URL(location, current) } catch (error) { throw new KnxAiWebAccessError('INVALID_REDIRECT', 'The web server returned an invalid redirect') }
446
- current = assertSafeHttpsUrl(redirected.toString())
447
- continue
448
- }
449
- if (statusCode < 200 || statusCode >= 300) throw new KnxAiWebAccessError('HTTP_ERROR', `The web server returned HTTP ${statusCode || 'error'}`)
450
- const contentEncoding = getHeader(response.headers, 'content-encoding').trim().toLowerCase()
451
- if (contentEncoding && contentEncoding !== 'identity') throw new KnxAiWebAccessError('UNSUPPORTED_ENCODING', 'The web server returned an unsupported content encoding')
452
- const contentType = getHeader(response.headers, 'content-type')
453
- if (!isTextualMimeType(contentType)) throw new KnxAiWebAccessError('UNSUPPORTED_MIME', 'Only textual web content can be opened')
454
- const body = responseBodyToBuffer(response.body)
455
- const declaredLength = Number(getHeader(response.headers, 'content-length'))
456
- if (body.length > options.maxBytes || (Number.isFinite(declaredLength) && declaredLength > options.maxBytes)) {
457
- throw new KnxAiWebAccessError('RESPONSE_TOO_LARGE', 'The web response exceeds the size limit')
458
- }
459
- return {
460
- body: body.toString('utf8'),
461
- contentType: contentType.split(';')[0].trim().toLowerCase(),
462
- statusCode,
463
- url: current.toString()
464
- }
465
- }
466
- throw new KnxAiWebAccessError('TOO_MANY_REDIRECTS', 'The web request exceeded the redirect limit')
467
- }
468
-
469
- /**
470
- * Normalize the explicit, provider-independent web action contract used by the AI runtime.
471
- * No query classification or intent/keyword routing happens here.
472
- */
473
- const normalizeKnxAiWebActions = (value, { maxActions = DEFAULT_MAX_ACTIONS } = {}) => {
474
- let source = value
475
- if (typeof source === 'string') {
476
- try { source = JSON.parse(source) } catch (error) { return [] }
477
- }
478
- if (source && !Array.isArray(source) && Array.isArray(source.webActions)) source = source.webActions
479
- if (!Array.isArray(source)) source = source && typeof source === 'object' ? [source] : []
480
- const limit = boundedInteger(maxActions, DEFAULT_MAX_ACTIONS, 0, HARD_MAX_ACTIONS)
481
- const normalized = []
482
- for (const candidate of source) {
483
- if (normalized.length >= limit) break
484
- if (!candidate || typeof candidate !== 'object') continue
485
- const rawOperation = String(candidate.operation || candidate.type || candidate.action || '').trim().toLowerCase().replace(/[ -]+/g, '_')
486
- const operation = rawOperation === 'open_url' ? 'open' : rawOperation
487
- if (operation === 'search') {
488
- const query = compactWhitespace(candidate.query, MAX_QUERY_CHARS)
489
- if (query) normalized.push({ operation, query, maxResults: boundedInteger(candidate.maxResults, DEFAULT_MAX_RESULTS, 1, HARD_MAX_RESULTS) })
490
- } else if (operation === 'open') {
491
- const url = String(candidate.url || '').trim().slice(0, MAX_URL_CHARS + 1)
492
- if (url) normalized.push({ operation, url })
493
- }
494
- }
495
- return normalized
496
- }
497
-
498
- const normalizeSearchEndpoints = (value) => {
499
- const source = Array.isArray(value) && value.length ? value : DEFAULT_SEARCH_ENDPOINTS
500
- return source.slice(0, 3).map(endpoint => assertSafeHttpsUrl(endpoint).toString())
501
- }
502
-
503
- /**
504
- * Build an isolated web client. dnsLookup, transport and now are injectable for deterministic tests.
505
- * A custom transport must connect to resolvedAddress while retaining url's host for TLS verification.
506
- */
507
- const createKnxAiWebAccess = (options = {}) => {
508
- const timeoutMs = boundedInteger(options.timeoutMs, DEFAULT_TIMEOUT_MS, 10, 60000)
509
- const maxRedirects = boundedInteger(options.maxRedirects, DEFAULT_MAX_REDIRECTS, 0, HARD_MAX_REDIRECTS)
510
- const dnsLookup = typeof options.dnsLookup === 'function' ? options.dnsLookup : defaultDnsLookup
511
- const transport = typeof options.transport === 'function' ? options.transport : defaultPinnedHttpsTransport
512
- const now = typeof options.now === 'function' ? options.now : () => new Date()
513
- const maxTextChars = boundedInteger(options.maxTextChars, DEFAULT_TEXT_MAX_CHARS, 100, 100000)
514
- const searchMaxBytes = boundedInteger(options.searchMaxBytes ?? options.maxBytes, DEFAULT_SEARCH_MAX_BYTES, 1, HARD_MAX_BYTES)
515
- const openMaxBytes = boundedInteger(options.openMaxBytes ?? options.maxBytes, DEFAULT_OPEN_MAX_BYTES, 1, HARD_MAX_BYTES)
516
- const searchEndpoints = normalizeSearchEndpoints(options.searchEndpoints)
517
- const baseHeaders = {
518
- accept: 'text/html,application/xhtml+xml,text/plain,application/json;q=0.8,application/xml;q=0.7',
519
- 'accept-encoding': 'identity',
520
- 'user-agent': compactWhitespace(options.userAgent || DEFAULT_USER_AGENT, 300)
521
- }
522
-
523
- const open = async (url) => {
524
- const response = await requestTextWithRedirects(url, {
525
- dnsLookup,
526
- headers: baseHeaders,
527
- maxBytes: openMaxBytes,
528
- maxRedirects,
529
- timeoutMs,
530
- transport
531
- })
532
- const retrievedAt = now().toISOString()
533
- const html = response.contentType === 'text/html' || response.contentType === 'application/xhtml+xml'
534
- const extracted = html
535
- ? extractHtmlDocument(response.body, maxTextChars)
536
- : { title: '', text: compactWhitespace(response.body, maxTextChars) }
537
- const finalUrl = assertSafeHttpsUrl(response.url)
538
- return {
539
- operation: 'open',
540
- ok: true,
541
- url: finalUrl.toString(),
542
- title: extracted.title || normalizeHostname(finalUrl.hostname),
543
- text: extracted.text,
544
- retrievedAt
545
- }
546
- }
547
-
548
- const search = async (query, maxResults = DEFAULT_MAX_RESULTS) => {
549
- const normalizedQuery = compactWhitespace(query, MAX_QUERY_CHARS)
550
- if (!normalizedQuery) throw new KnxAiWebAccessError('INVALID_QUERY', 'A search query is required')
551
- let lastError = null
552
- for (const endpoint of searchEndpoints) {
553
- const searchUrl = new URL(endpoint)
554
- searchUrl.searchParams.set('q', normalizedQuery)
555
- try {
556
- const response = await requestTextWithRedirects(searchUrl.toString(), {
557
- dnsLookup,
558
- headers: baseHeaders,
559
- maxBytes: searchMaxBytes,
560
- maxRedirects,
561
- timeoutMs,
562
- transport
563
- })
564
- const retrievedAt = now().toISOString()
565
- const results = parseDuckDuckGoResults(response.body, { maxResults, retrievedAt })
566
- if (results.length) {
567
- return { operation: 'search', ok: true, query: normalizedQuery, results, retrievedAt }
568
- }
569
- lastError = new KnxAiWebAccessError('NO_RESULTS', 'The web search returned no usable results')
570
- } catch (error) {
571
- lastError = error
572
- }
573
- }
574
- throw lastError || new KnxAiWebAccessError('SEARCH_FAILED', 'The web search failed')
575
- }
576
-
577
- const executeAction = async (action) => {
578
- const retrievedAt = now().toISOString()
579
- try {
580
- if (action.operation === 'search') return await search(action.query, action.maxResults)
581
- if (action.operation === 'open') return await open(action.url)
582
- throw new KnxAiWebAccessError('UNSUPPORTED_OPERATION', 'Unsupported web operation')
583
- } catch (error) {
584
- const message = error instanceof KnxAiWebAccessError ? error.message : 'The web operation failed'
585
- return {
586
- operation: action.operation,
587
- ok: false,
588
- ...(action.query ? { query: action.query } : {}),
589
- ...(action.url ? { url: action.url } : {}),
590
- retrievedAt,
591
- error: message
592
- }
593
- }
594
- }
595
-
596
- return { executeAction, open, search }
597
- }
598
-
599
- /**
600
- * Execute normalized actions sequentially and return one bounded result envelope per valid action.
601
- */
602
- const executeKnxAiWebActions = async (actions, options = {}) => {
603
- const normalized = normalizeKnxAiWebActions(actions, { maxActions: options.maxActions })
604
- const access = createKnxAiWebAccess(options)
605
- const results = []
606
- for (const action of normalized) results.push(await access.executeAction(action))
607
- return results
608
- }
609
-
610
- module.exports = {
611
- createKnxAiWebAccess,
612
- executeKnxAiWebActions,
613
- normalizeKnxAiWebActions,
614
- __test: {
615
- KnxAiWebAccessError,
616
- assertSafeHttpsUrl,
617
- compactWhitespace,
618
- decodeHtmlEntities,
619
- extractHtmlDocument,
620
- getHeader,
621
- ipv4InRange,
622
- ipv6InRange,
623
- isPublicIpAddress,
624
- isTextualMimeType,
625
- normalizeDnsRecords,
626
- parseDuckDuckGoResults,
627
- requestTextWithRedirects,
628
- resolveDuckDuckGoResultUrl,
629
- stripHtmlTags
630
- }
631
- }