node-red-contrib-knx-ultimate 6.4.1 → 7.0.1

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 (41) hide show
  1. package/CHANGELOG.md +129 -121
  2. package/README.md +4 -0
  3. package/nodes/knxUltimate-config.js +38 -38
  4. package/nodes/knxUltimate.js +1 -1
  5. package/nodes/knxUltimateAI.html +9 -5
  6. package/nodes/knxUltimateAI.js +143 -143
  7. package/nodes/knxUltimateAIHomeAssistant.html +7 -5
  8. package/nodes/knxUltimateAIHomeAssistant.js +1 -1
  9. package/nodes/knxUltimateHueController.html +1 -1
  10. package/nodes/knxUltimateMatterBridge.html +2 -2
  11. package/nodes/knxUltimateMatterControllerDevice.html +12 -12
  12. package/nodes/locales/de/knxUltimateAI.html +4 -199
  13. package/nodes/locales/de/knxUltimateAI.json +6 -6
  14. package/nodes/locales/de/knxUltimateViewer.html +1 -1
  15. package/nodes/locales/en/knxUltimateAI.html +4 -211
  16. package/nodes/locales/en/knxUltimateAI.json +6 -6
  17. package/nodes/locales/en/knxUltimateViewer.html +1 -1
  18. package/nodes/locales/es/knxUltimateAI.html +4 -199
  19. package/nodes/locales/es/knxUltimateAI.json +6 -6
  20. package/nodes/locales/es/knxUltimateViewer.html +1 -1
  21. package/nodes/locales/fr/knxUltimateAI.html +4 -199
  22. package/nodes/locales/fr/knxUltimateAI.json +6 -6
  23. package/nodes/locales/fr/knxUltimateViewer.html +1 -1
  24. package/nodes/locales/it/knxUltimateAI.html +4 -211
  25. package/nodes/locales/it/knxUltimateAI.json +6 -6
  26. package/nodes/locales/it/knxUltimateViewer.html +1 -1
  27. package/nodes/locales/zh-CN/knxUltimateAI.html +4 -199
  28. package/nodes/locales/zh-CN/knxUltimateAI.json +6 -6
  29. package/nodes/locales/zh-CN/knxUltimateViewer.html +1 -1
  30. package/nodes/plugins/knxUltimateAI-vue/assets/app.css +1 -1
  31. package/nodes/plugins/knxUltimateAI-vue/assets/app.js +10 -10
  32. package/nodes/plugins/knxUltimateAI-vue/index.html +1 -1
  33. package/nodes/plugins/knxUltimateViewer-vue/assets/app.js +2 -2
  34. package/nodes/utils/knxAiChatContext.js +4 -4
  35. package/nodes/utils/knxAiHomeMemory.js +2 -2
  36. package/nodes/utils/knxAiScheduler.js +2 -2
  37. package/package.json +1 -1
  38. package/resources/KNXAIChatAdapterMappings.js +4 -4
  39. package/examples/KNX AI - Conversational Control with Confirmation.json +0 -395
  40. package/examples/KNX AI - Summary Anomalies and Ask.json +0 -226
  41. package/examples/KNX AI - Telegrambot Direct Chat.json +0 -198
package/README.md CHANGED
@@ -8,6 +8,10 @@
8
8
 
9
9
  KNX Ultimate is the most advanced KNX integration for Node-RED, providing secure KNX/IP communication, routing, ETS project import, Philips Hue, Matter Controller and Matter Bridge (control matter device via KNX and expose KNX GA via Matter), MQTT, diagnostics, virtual devices, and powerful automation nodes. Build professional, reliable, and scalable smart home and building automation projects with minimal effort.
10
10
 
11
+
12
+
13
+ The former bundled AI assistant has moved to the standalone [Cerebrum Ultimate](https://github.com/Supergiovane/node-red-contrib-cerebrum-ultimate) package. Cerebrum Ultimate now provides the conversational, learning and supervised home-intelligence features, while using KNX Ultimate as an optional compatible integration. Hidden legacy runtime types remain in this package only so existing Node-RED flows continue to load; new installations should add the Cerebrum node from the standalone package.
14
+
11
15
  <br/>
12
16
  <br/>
13
17
  <br/>
@@ -1529,9 +1529,9 @@ module.exports = (RED) => {
1529
1529
  }
1530
1530
  _input.handleSend(msg)
1531
1531
  } else if (_input.hasOwnProperty('isSceneController')) { // 19/03/2020 in the middle of coronavirus. Whole italy is red zone, closed down. Scene Controller implementation
1532
- // 12/08/2020 Check wether is a learn (save) command or a activate (play) command.
1532
+ // 12/08/2020 Check wether is a learn (save) command or a activate (play) command.
1533
1533
  if (_dest === _input.topic || _dest === _input.topicSave) {
1534
- // Prepare the two messages to be evaluated directly into the Scene Controller node.
1534
+ // Prepare the two messages to be evaluated directly into the Scene Controller node.
1535
1535
  new Promise((resolve) => {
1536
1536
  if (_dest === _input.topic) {
1537
1537
  try {
@@ -1568,16 +1568,16 @@ module.exports = (RED) => {
1568
1568
  } catch (error) { }
1569
1569
  }
1570
1570
  resolve(true) // fulfilled
1571
- // reject("error"); // rejected
1571
+ // reject("error"); // rejected
1572
1572
  })
1573
1573
  .then(function () { })
1574
1574
  .catch(function () { })
1575
1575
  } else {
1576
- // 19/03/2020 Check and Update value if the input is part of a scene controller
1576
+ // 19/03/2020 Check and Update value if the input is part of a scene controller
1577
1577
  new Promise((resolve) => {
1578
- // Check and update the values of each device in the scene and update the rule array accordingly.
1578
+ // Check and update the values of each device in the scene and update the rule array accordingly.
1579
1579
  for (let i = 0; i < _input.rules.length; i++) {
1580
- // rule is { topic: rowRuleTopic, devicename: rowRuleDeviceName, dpt:rowRuleDPT, send: rowRuleSend}
1580
+ // rule is { topic: rowRuleTopic, devicename: rowRuleDeviceName, dpt:rowRuleDPT, send: rowRuleSend}
1581
1581
  const oDevice = _input.rules[i]
1582
1582
  if (typeof oDevice !== 'undefined' && oDevice.topic == _dest) {
1583
1583
  const msg = buildInputMessage({
@@ -1606,23 +1606,23 @@ module.exports = (RED) => {
1606
1606
  }
1607
1607
  }
1608
1608
  resolve(true) // fulfilled
1609
- // reject("error"); // rejected
1609
+ // reject("error"); // rejected
1610
1610
  })
1611
1611
  .then(function () { })
1612
1612
  .catch(function () { })
1613
1613
  }
1614
1614
  } else if (_input.hasOwnProperty('isLogger')) {
1615
- // 26/03/2020 Coronavirus is slightly decreasing the affected numer of people. Logger Node
1616
- // 24/03/2021 Logger Node, i'll pass cemiETS
1615
+ // 26/03/2020 Coronavirus is slightly decreasing the affected numer of people. Logger Node
1616
+ // 24/03/2021 Logger Node, i'll pass cemiETS
1617
1617
  if (_cemiETS !== undefined) {
1618
- // new Promise((resolve, reject) => {
1618
+ // new Promise((resolve, reject) => {
1619
1619
  _input.handleSend(_cemiETS)
1620
- // resolve(true); // fulfilled
1621
- // reject("error"); // rejected
1622
- // }).then(function () { }).catch(function () { });
1620
+ // resolve(true); // fulfilled
1621
+ // reject("error"); // rejected
1622
+ // }).then(function () { }).catch(function () { });
1623
1623
  }
1624
1624
  } else if (_input.listenallga === true && universalNodeAcceptsGA(_input, _dest)) {
1625
- // 25/10/2019 TRY TO AUTO DECODE IF Group address not found in the CSV
1625
+ // 25/10/2019 TRY TO AUTO DECODE IF Group address not found in the CSV
1626
1626
  const msg = buildInputMessage({
1627
1627
  _srcGA: _src,
1628
1628
  _destGA: _dest,
@@ -1645,8 +1645,8 @@ module.exports = (RED) => {
1645
1645
  _input.handleSend(msg)
1646
1646
  } else if (_input.topic == _dest) {
1647
1647
  if (_input.hasOwnProperty('isWatchDog')) {
1648
- // 04/02/2020 Watchdog implementation
1649
- // Is a watchdog node
1648
+ // 04/02/2020 Watchdog implementation
1649
+ // Is a watchdog node
1650
1650
  } else {
1651
1651
  const msg = buildInputMessage({
1652
1652
  _srcGA: _src,
@@ -1721,14 +1721,14 @@ module.exports = (RED) => {
1721
1721
  _input.handleSend(msg)
1722
1722
  } else
1723
1723
  if (_input.hasOwnProperty('isLogger')) {
1724
- // 26/03/2020 Coronavirus is slightly decreasing the affected numer of people. Logger Node
1725
- // 24/03/2021 Logger Node, i'll pass cemiETS
1724
+ // 26/03/2020 Coronavirus is slightly decreasing the affected numer of people. Logger Node
1725
+ // 24/03/2021 Logger Node, i'll pass cemiETS
1726
1726
  if (_cemiETS !== undefined) {
1727
- // new Promise((resolve, reject) => {
1727
+ // new Promise((resolve, reject) => {
1728
1728
  _input.handleSend(_cemiETS)
1729
- // resolve(true); // fulfilled
1730
- // reject("error"); // rejected
1731
- // }).then(function () { }).catch(function () { });
1729
+ // resolve(true); // fulfilled
1730
+ // reject("error"); // rejected
1731
+ // }).then(function () { }).catch(function () { });
1732
1732
  }
1733
1733
  } else if (_input.listenallga === true && universalNodeAcceptsGA(_input, _dest)) {
1734
1734
  const msg = buildInputMessage({
@@ -1752,9 +1752,9 @@ module.exports = (RED) => {
1752
1752
  })
1753
1753
  _input.handleSend(msg)
1754
1754
  } else if (_input.topic === _dest) {
1755
- // 04/02/2020 Watchdog implementation
1755
+ // 04/02/2020 Watchdog implementation
1756
1756
  if (_input.hasOwnProperty('isWatchDog')) {
1757
- // Is a watchdog node
1757
+ // Is a watchdog node
1758
1758
  _input.watchDogTimerReset()
1759
1759
  } else {
1760
1760
  const msg = buildInputMessage({
@@ -1827,18 +1827,18 @@ module.exports = (RED) => {
1827
1827
  _input.handleSend(msg)
1828
1828
  } else
1829
1829
  if (_input.hasOwnProperty('isLogger')) {
1830
- // 26/03/2020 Coronavirus is slightly decreasing the affected numer of people. Logger Node
1831
- // node.sysLogger?.info("BANANA isLogger", _evt, _src, _dest, _rawValue, _cemiETS);
1832
- // 24/03/2021 Logger Node, i'll pass cemiETS
1830
+ // 26/03/2020 Coronavirus is slightly decreasing the affected numer of people. Logger Node
1831
+ // node.sysLogger?.info("BANANA isLogger", _evt, _src, _dest, _rawValue, _cemiETS);
1832
+ // 24/03/2021 Logger Node, i'll pass cemiETS
1833
1833
  if (_cemiETS !== undefined) {
1834
- // new Promise((resolve, reject) => {
1834
+ // new Promise((resolve, reject) => {
1835
1835
  _input.handleSend(_cemiETS)
1836
- // resolve(true); // fulfilled
1837
- // reject("error"); // rejected
1838
- // }).then(function () { }).catch(function () { });
1836
+ // resolve(true); // fulfilled
1837
+ // reject("error"); // rejected
1838
+ // }).then(function () { }).catch(function () { });
1839
1839
  }
1840
1840
  } else if (_input.listenallga === true && universalNodeAcceptsGA(_input, _dest)) {
1841
- // Read Request
1841
+ // Read Request
1842
1842
  const msg = buildInputMessage({
1843
1843
  _srcGA: _src,
1844
1844
  _destGA: _dest,
@@ -1860,11 +1860,11 @@ module.exports = (RED) => {
1860
1860
  })
1861
1861
  _input.handleSend(msg)
1862
1862
  } else if (_input.topic === _dest) {
1863
- // 04/02/2020 Watchdog implementation
1863
+ // 04/02/2020 Watchdog implementation
1864
1864
  if (_input.hasOwnProperty('isWatchDog')) {
1865
- // Is a watchdog node
1865
+ // Is a watchdog node
1866
1866
  } else {
1867
- // Read Request
1867
+ // Read Request
1868
1868
  const msg = buildInputMessage({
1869
1869
  _srcGA: _src,
1870
1870
  _destGA: _dest,
@@ -1881,7 +1881,7 @@ module.exports = (RED) => {
1881
1881
  // 24/09/2019 Autorespond to BUS
1882
1882
  if (_input.hasOwnProperty('notifyreadrequestalsorespondtobus') && _input.notifyreadrequestalsorespondtobus === true) {
1883
1883
  if (typeof _input.currentPayload === 'undefined' || _input.currentPayload === '' || _input.currentPayload === null) {
1884
- // 14/08/2021 Added || input.currentPayload === null
1884
+ // 14/08/2021 Added || input.currentPayload === null
1885
1885
  node.sendKNXTelegramToKNXEngine({
1886
1886
  grpaddr: _dest,
1887
1887
  payload: _input.notifyreadrequestalsorespondtobusdefaultvalueifnotinitialized,
@@ -1909,8 +1909,8 @@ module.exports = (RED) => {
1909
1909
  _input.setNodeStatus({
1910
1910
  fill: 'blue',
1911
1911
  shape: 'ring',
1912
- text: 'Read & Autorespond with default',
1913
- payload: _input.notifyreadrequestalsorespondtobusdefaultvalueifnotinitialized,
1912
+ text: 'Read & Autorespond',
1913
+ payload: _input.currentPayload,
1914
1914
  GA: _input.topic,
1915
1915
  dpt: msg.knx.dpt,
1916
1916
  devicename: ''
@@ -756,7 +756,7 @@ module.exports = function (RED) {
756
756
  // #endregion
757
757
 
758
758
  // 25/07/2019 if payload is read or the Telegram type is set to "read", do a read, otherwise, write to the bus
759
- if ((msg.hasOwnProperty('readstatus') && msg.readstatus === true) || node.outputtype === 'read') {
759
+ if ((msg.hasOwnProperty('readstatus') && msg.readstatus === true) || node.outputtype === 'read' || (msg.hasOwnProperty('event') && msg.event === 'GroupValue_Read')) {
760
760
  // READ: Send a Read request to the bus
761
761
  let grpaddr = ''
762
762
  if (node.listenallga == false) {
@@ -467,11 +467,11 @@
467
467
 
468
468
  <script type="text/javascript">
469
469
  RED.nodes.registerType('knxUltimateAI', {
470
- category: "KNX Ultimate AI",
470
+ category: "KNX Ultimate (legacy)",
471
471
  color: '#FF9800',
472
472
  defaults: {
473
473
  server: { type: "knxUltimate-config", required: true },
474
- name: { value: "KNX AI", required: false },
474
+ name: { value: "Legacy AI node", required: false },
475
475
  topic: { value: "", required: false },
476
476
 
477
477
  llmEnabled: { value: false },
@@ -509,9 +509,9 @@
509
509
  },
510
510
  icon: "node-eye-icon.svg",
511
511
  label: function () {
512
- return (this.name || "KNX AI");
512
+ return (this.name || "Legacy AI node");
513
513
  },
514
- paletteLabel: "KNX AI",
514
+ paletteLabel: "Legacy AI node",
515
515
  oneditprepare: function () {
516
516
  try { RED.sidebar.show("help"); } catch (error) { }
517
517
  const node = this;
@@ -1531,9 +1531,13 @@
1531
1531
  } catch (error) { }
1532
1532
  }
1533
1533
  })
1534
+ // The historical type remains registered so deployed flows keep loading,
1535
+ // but new Cerebrum nodes belong to node-red-contrib-cerebrum-ultimate.
1536
+ try { RED.palette.remove('knxUltimateAI'); } catch (error) { }
1534
1537
  </script>
1535
1538
 
1536
1539
  <script type="text/html" data-template-name="knxUltimateAI">
1540
+ <div class="form-tips" style="margin-bottom:10px;"><b>Legacy node:</b> existing flow instances remain supported. For new installations use <a href="https://github.com/Supergiovane/node-red-contrib-cerebrum-ultimate#readme" target="_blank"><b>Cerebrum Ultimate</b></a>.</div>
1537
1541
  <div class="form-row" style="margin-bottom:10px;">
1538
1542
  <span style="color:#ff0000"><i class="fa fa-youtube"></i></span>&nbsp;<a target="_blank" href="https://www.youtube.com/playlist?list=PL9Yh1bjbLAYrU8PsVhW4xzEug2WtVFv3E"><b>KNX-Ultimate video tutorials (YouTube playlist)</b></a>
1539
1543
  </div>
@@ -1559,7 +1563,7 @@
1559
1563
  <label><i class="fa fa-external-link"></i> Web UI</label>
1560
1564
  <div style="display:flex; gap:8px; flex-wrap:wrap;">
1561
1565
  <button type="button" class="red-ui-button" id="knx-ai-open-web-page-vue" style="background-color:#ff9800; border-color:#ff9800; color:#ffffff !important; -webkit-text-fill-color:#ffffff;">
1562
- <i class="fa fa-external-link" style="color:#ffffff !important;"></i> <span style="color:#ffffff !important;">Open KNX AI Web Page</span>
1566
+ <i class="fa fa-external-link" style="color:#ffffff !important;"></i> <span style="color:#ffffff !important;">Open Cerebrum Ultimate Web Page</span>
1563
1567
  </button>
1564
1568
  </div>
1565
1569
  </div>