node-red-contrib-knx-ultimate 5.2.4 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -8
- package/README.md +10 -3
- package/img/readmemain.png +0 -0
- package/nodes/commonFunctions.js +40 -3
- package/nodes/knxUltimate-config.js +379 -335
- package/nodes/knxUltimate.html +8 -9
- package/nodes/knxUltimate.js +5 -5
- package/nodes/knxUltimateAI.js +1 -1
- package/nodes/knxUltimateHueLight.html +3 -3
- package/nodes/knxUltimateHueLight.js +1 -1
- package/nodes/knxUltimateMatterBridge.html +321 -247
- package/nodes/knxUltimateMatterBridge.js +48 -1
- package/nodes/knxUltimateMatterControllerDevice.html +2119 -0
- package/nodes/knxUltimateMatterControllerDevice.js +1701 -0
- package/nodes/locales/de/knxUltimateMatterBridge.html +6 -2
- package/nodes/locales/de/knxUltimateMatterBridge.json +14 -1
- package/nodes/locales/de/knxUltimateMatterControllerDevice.html +27 -0
- package/nodes/locales/de/knxUltimateMatterControllerDevice.json +97 -0
- package/nodes/locales/de/matter-config.json +5 -1
- package/nodes/locales/de/matterbridge-config.json +1 -0
- package/nodes/locales/en/knxUltimateMatterBridge.html +6 -2
- package/nodes/locales/en/knxUltimateMatterBridge.json +14 -1
- package/nodes/locales/en/knxUltimateMatterControllerDevice.html +27 -0
- package/nodes/locales/en/knxUltimateMatterControllerDevice.json +97 -0
- package/nodes/locales/en/matter-config.json +6 -1
- package/nodes/locales/en/matterbridge-config.json +1 -0
- package/nodes/locales/es/knxUltimateMatterBridge.html +6 -2
- package/nodes/locales/es/knxUltimateMatterBridge.json +14 -1
- package/nodes/locales/es/knxUltimateMatterControllerDevice.html +27 -0
- package/nodes/locales/es/knxUltimateMatterControllerDevice.json +97 -0
- package/nodes/locales/es/matter-config.json +5 -1
- package/nodes/locales/es/matterbridge-config.json +1 -0
- package/nodes/locales/fr/knxUltimateMatterBridge.html +6 -2
- package/nodes/locales/fr/knxUltimateMatterBridge.json +14 -1
- package/nodes/locales/fr/knxUltimateMatterControllerDevice.html +27 -0
- package/nodes/locales/fr/knxUltimateMatterControllerDevice.json +89 -0
- package/nodes/locales/fr/matter-config.json +5 -1
- package/nodes/locales/fr/matterbridge-config.json +1 -0
- package/nodes/locales/it/knxUltimateMatterBridge.html +6 -2
- package/nodes/locales/it/knxUltimateMatterBridge.json +14 -1
- package/nodes/locales/it/knxUltimateMatterControllerDevice.html +27 -0
- package/nodes/locales/it/knxUltimateMatterControllerDevice.json +97 -0
- package/nodes/locales/it/matter-config.json +6 -1
- package/nodes/locales/it/matterbridge-config.json +1 -0
- package/nodes/locales/zh-CN/knxUltimateMatterBridge.html +6 -2
- package/nodes/locales/zh-CN/knxUltimateMatterBridge.json +14 -1
- package/nodes/locales/zh-CN/knxUltimateMatterControllerDevice.html +27 -0
- package/nodes/locales/zh-CN/knxUltimateMatterControllerDevice.json +89 -0
- package/nodes/locales/zh-CN/matter-config.json +5 -1
- package/nodes/locales/zh-CN/matterbridge-config.json +1 -0
- package/nodes/matter-config.html +58 -6
- package/nodes/matter-config.js +7 -2
- package/nodes/matterbridge-config.html +1 -0
- package/nodes/utils/lightEngines/canonicalLight.js +75 -0
- package/nodes/utils/lightEngines/hueLightEngine.js +51 -0
- package/nodes/utils/lightEngines/index.js +25 -0
- package/nodes/utils/lightEngines/knxLightCommand.js +79 -0
- package/nodes/utils/lightEngines/lightEngine.js +46 -0
- package/nodes/utils/lightEngines/matterHueShim.js +59 -0
- package/nodes/utils/lightEngines/matterLightEngine.js +117 -0
- package/nodes/utils/matterEngine.mjs +185 -14
- package/nodes/utils/matterKnxConverter.js +1 -1
- package/package.json +21 -3
- package/resources/KNXSendSnippets.js +53 -53
- package/resources/htmlUtils.js +6 -4
- package/nodes/knxUltimateMatterDevice.html +0 -632
- package/nodes/knxUltimateMatterDevice.js +0 -308
- package/nodes/locales/de/knxUltimateMatterDevice.html +0 -56
- package/nodes/locales/de/knxUltimateMatterDevice.json +0 -109
- package/nodes/locales/en/knxUltimateMatterDevice.html +0 -56
- package/nodes/locales/en/knxUltimateMatterDevice.json +0 -109
- package/nodes/locales/es/knxUltimateMatterDevice.html +0 -56
- package/nodes/locales/es/knxUltimateMatterDevice.json +0 -109
- package/nodes/locales/fr/knxUltimateMatterDevice.html +0 -56
- package/nodes/locales/fr/knxUltimateMatterDevice.json +0 -109
- package/nodes/locales/it/knxUltimateMatterDevice.html +0 -56
- package/nodes/locales/it/knxUltimateMatterDevice.json +0 -109
- package/nodes/locales/zh-CN/knxUltimateMatterDevice.html +0 -56
- package/nodes/locales/zh-CN/knxUltimateMatterDevice.json +0 -109
|
@@ -879,6 +879,19 @@ module.exports = (RED) => {
|
|
|
879
879
|
}
|
|
880
880
|
}
|
|
881
881
|
|
|
882
|
+
function getUniversalNodeAcceptedGAs (_oNode) {
|
|
883
|
+
const raw = _oNode?.knxUltimateAcceptedGAs
|
|
884
|
+
if (raw === undefined || raw === null) return null
|
|
885
|
+
const values = raw instanceof Set ? Array.from(raw) : Array.isArray(raw) ? raw : typeof raw === 'string' ? raw.split(/[,\s;]+/) : []
|
|
886
|
+
return values.map((ga) => String(ga || '').trim()).filter((ga) => ga !== '')
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
function universalNodeAcceptsGA (_oNode, _dest) {
|
|
890
|
+
const acceptedGAs = getUniversalNodeAcceptedGAs(_oNode)
|
|
891
|
+
if (acceptedGAs === null || acceptedGAs.length === 0) return true
|
|
892
|
+
return acceptedGAs.includes(String(_dest || '').trim())
|
|
893
|
+
}
|
|
894
|
+
|
|
882
895
|
// 17/02/2020 Do initial read (called by node.timerDoInitialRead timer)
|
|
883
896
|
function DoInitialReadFromKNXBusOrFile () {
|
|
884
897
|
if (node.linkStatus !== 'connected') return // 29/08/2019 If not connected, exit
|
|
@@ -1000,18 +1013,36 @@ module.exports = (RED) => {
|
|
|
1000
1013
|
} else if (_oClient.hasOwnProperty('isLoadControlNode') && _oClient.isLoadControlNode) {
|
|
1001
1014
|
_oClient.initialReadAllDevicesInRules()
|
|
1002
1015
|
} else if (_oClient.listenallga === true) {
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
node.
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1016
|
+
const acceptedGAs = getUniversalNodeAcceptedGAs(_oClient)
|
|
1017
|
+
if (acceptedGAs === null) {
|
|
1018
|
+
for (let index = 0; index < node.csv.length; index++) {
|
|
1019
|
+
const element = node.csv[index]
|
|
1020
|
+
if (!readHistory.includes(element.ga)) {
|
|
1021
|
+
node.sendKNXTelegramToKNXEngine({
|
|
1022
|
+
grpaddr: element.ga,
|
|
1023
|
+
payload: '',
|
|
1024
|
+
dpt: '',
|
|
1025
|
+
outputtype: 'read',
|
|
1026
|
+
nodecallerid: element.id
|
|
1027
|
+
})
|
|
1028
|
+
readHistory.push(element.ga)
|
|
1029
|
+
node.sysLogger?.debug('DoInitialReadFromKNXBusOrFile from Universal Node: sent read request to GA ' + element.ga)
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
} else {
|
|
1033
|
+
for (let index = 0; index < acceptedGAs.length; index++) {
|
|
1034
|
+
const ga = acceptedGAs[index]
|
|
1035
|
+
if (!readHistory.includes(ga)) {
|
|
1036
|
+
node.sendKNXTelegramToKNXEngine({
|
|
1037
|
+
grpaddr: ga,
|
|
1038
|
+
payload: '',
|
|
1039
|
+
dpt: '',
|
|
1040
|
+
outputtype: 'read',
|
|
1041
|
+
nodecallerid: _oClient.id
|
|
1042
|
+
})
|
|
1043
|
+
readHistory.push(ga)
|
|
1044
|
+
node.sysLogger?.debug('DoInitialReadFromKNXBusOrFile from filtered Universal Node: sent read request to GA ' + ga)
|
|
1045
|
+
}
|
|
1015
1046
|
}
|
|
1016
1047
|
}
|
|
1017
1048
|
} else {
|
|
@@ -1261,6 +1292,10 @@ module.exports = (RED) => {
|
|
|
1261
1292
|
await node.knxConnection.Disconnect()
|
|
1262
1293
|
node.sysLogger?.debug('removing old handlers. Node ' + node.name)
|
|
1263
1294
|
node.knxConnection.removeAllListeners()
|
|
1295
|
+
// The orphaned client may still emit a late async 'error' (e.g. the KNX Secure
|
|
1296
|
+
// IA discovery timing out): with no listener, emit('error') would CRASH the
|
|
1297
|
+
// whole process. Keep a swallow-all handler on it.
|
|
1298
|
+
node.knxConnection.on(knx.KNXClientEvents.error, () => { })
|
|
1264
1299
|
}
|
|
1265
1300
|
} catch (error) {
|
|
1266
1301
|
node.sysLogger?.info('BANANA ERRORINO', error)
|
|
@@ -1453,200 +1488,202 @@ module.exports = (RED) => {
|
|
|
1453
1488
|
node.nodeClients
|
|
1454
1489
|
.filter((_input) => _input.notifywrite === true)
|
|
1455
1490
|
.forEach((_input) => {
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1491
|
+
try {
|
|
1492
|
+
if (_input.hasOwnProperty('isMultiRouting')) {
|
|
1493
|
+
const msg = {
|
|
1494
|
+
topic: _input.outputtopic || _dest,
|
|
1495
|
+
payload: {
|
|
1496
|
+
knx: {
|
|
1497
|
+
event: _evt,
|
|
1498
|
+
source: _src,
|
|
1499
|
+
destination: _dest,
|
|
1500
|
+
apdu: { data: _apduData, bitlength: _apduBitLength, hex: _apduHex },
|
|
1501
|
+
cemi: { hex: _cemiETS },
|
|
1502
|
+
echoed: _echoed,
|
|
1503
|
+
repeated: isRepeated,
|
|
1504
|
+
repeat: isRepeated
|
|
1505
|
+
},
|
|
1506
|
+
knxMultiRouting: {
|
|
1507
|
+
gateway: { id: node.id, name: node.name || '', physAddr: node.physAddr || '' },
|
|
1508
|
+
receivedAt: Date.now()
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1512
|
+
_input.setNodeStatus({ fill: 'green', shape: 'dot', text: 'RAW', payload: _evt, GA: _dest, dpt: '', devicename: _src })
|
|
1513
|
+
_input.handleSend(msg)
|
|
1514
|
+
} else
|
|
1515
|
+
// 21/10/2024 check wether is a HUE device
|
|
1516
|
+
if (_input.type.includes('knxUltimateHue')) {
|
|
1517
|
+
const msg = {
|
|
1460
1518
|
knx: {
|
|
1461
1519
|
event: _evt,
|
|
1462
|
-
source: _src,
|
|
1463
1520
|
destination: _dest,
|
|
1464
|
-
|
|
1465
|
-
cemi: { hex: _cemiETS },
|
|
1466
|
-
echoed: _echoed,
|
|
1521
|
+
rawValue: _rawValue,
|
|
1467
1522
|
repeated: isRepeated,
|
|
1468
1523
|
repeat: isRepeated
|
|
1469
|
-
},
|
|
1470
|
-
knxMultiRouting: {
|
|
1471
|
-
gateway: { id: node.id, name: node.name || '', physAddr: node.physAddr || '' },
|
|
1472
|
-
receivedAt: Date.now()
|
|
1473
1524
|
}
|
|
1474
1525
|
}
|
|
1475
|
-
|
|
1476
|
-
_input.
|
|
1477
|
-
_input.handleSend(msg)
|
|
1478
|
-
} else
|
|
1479
|
-
// 21/10/2024 check wether is a HUE device
|
|
1480
|
-
if (_input.type.includes('knxUltimateHue')) {
|
|
1481
|
-
const msg = {
|
|
1482
|
-
knx: {
|
|
1483
|
-
event: _evt,
|
|
1484
|
-
destination: _dest,
|
|
1485
|
-
rawValue: _rawValue,
|
|
1486
|
-
repeated: isRepeated,
|
|
1487
|
-
repeat: isRepeated
|
|
1488
|
-
}
|
|
1489
|
-
}
|
|
1490
|
-
_input.handleSend(msg)
|
|
1491
|
-
} else if (_input.hasOwnProperty('isSceneController')) { // 19/03/2020 in the middle of coronavirus. Whole italy is red zone, closed down. Scene Controller implementation
|
|
1526
|
+
_input.handleSend(msg)
|
|
1527
|
+
} else if (_input.hasOwnProperty('isSceneController')) { // 19/03/2020 in the middle of coronavirus. Whole italy is red zone, closed down. Scene Controller implementation
|
|
1492
1528
|
// 12/08/2020 Check wether is a learn (save) command or a activate (play) command.
|
|
1493
|
-
|
|
1529
|
+
if (_dest === _input.topic || _dest === _input.topicSave) {
|
|
1494
1530
|
// Prepare the two messages to be evaluated directly into the Scene Controller node.
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
+
new Promise((resolve) => {
|
|
1532
|
+
if (_dest === _input.topic) {
|
|
1533
|
+
try {
|
|
1534
|
+
const msgRecall = buildInputMessage({
|
|
1535
|
+
_srcGA: _src,
|
|
1536
|
+
_destGA: _dest,
|
|
1537
|
+
_event: _evt,
|
|
1538
|
+
_Rawvalue: _rawValue,
|
|
1539
|
+
_inputDpt: _input.dpt,
|
|
1540
|
+
_devicename: _input.name ? _input.name : '',
|
|
1541
|
+
_outputtopic: _input.outputtopic,
|
|
1542
|
+
_oNode: null,
|
|
1543
|
+
_echoed,
|
|
1544
|
+
_repeated: isRepeated
|
|
1545
|
+
})
|
|
1546
|
+
_input.RecallScene(msgRecall.payload, false)
|
|
1547
|
+
} catch (error) { }
|
|
1548
|
+
} // 12/08/2020 Do NOT use "else", because both topics must be evaluated in case both recall and save have same group address.
|
|
1549
|
+
if (_dest === _input.topicSave) {
|
|
1550
|
+
try {
|
|
1551
|
+
const msgSave = buildInputMessage({
|
|
1552
|
+
_srcGA: _src,
|
|
1553
|
+
_destGA: _dest,
|
|
1554
|
+
_event: _evt,
|
|
1555
|
+
_Rawvalue: _rawValue,
|
|
1556
|
+
_inputDpt: _input.dptSave,
|
|
1557
|
+
_devicename: _input.name || '',
|
|
1558
|
+
_outputtopic: _dest,
|
|
1559
|
+
_oNode: null,
|
|
1560
|
+
_echoed,
|
|
1561
|
+
_repeated: isRepeated
|
|
1562
|
+
})
|
|
1563
|
+
_input.SaveScene(msgSave.payload, false)
|
|
1564
|
+
} catch (error) { }
|
|
1565
|
+
}
|
|
1566
|
+
resolve(true) // fulfilled
|
|
1531
1567
|
// reject("error"); // rejected
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1568
|
+
})
|
|
1569
|
+
.then(function () { })
|
|
1570
|
+
.catch(function () { })
|
|
1571
|
+
} else {
|
|
1536
1572
|
// 19/03/2020 Check and Update value if the input is part of a scene controller
|
|
1537
|
-
|
|
1573
|
+
new Promise((resolve) => {
|
|
1538
1574
|
// Check and update the values of each device in the scene and update the rule array accordingly.
|
|
1539
|
-
|
|
1575
|
+
for (let i = 0; i < _input.rules.length; i++) {
|
|
1540
1576
|
// rule is { topic: rowRuleTopic, devicename: rowRuleDeviceName, dpt:rowRuleDPT, send: rowRuleSend}
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1577
|
+
const oDevice = _input.rules[i]
|
|
1578
|
+
if (typeof oDevice !== 'undefined' && oDevice.topic == _dest) {
|
|
1579
|
+
const msg = buildInputMessage({
|
|
1580
|
+
_srcGA: _src,
|
|
1581
|
+
_destGA: _dest,
|
|
1582
|
+
_event: _evt,
|
|
1583
|
+
_Rawvalue: _rawValue,
|
|
1584
|
+
_inputDpt: oDevice.dpt,
|
|
1585
|
+
_devicename: oDevice.name || '',
|
|
1586
|
+
_outputtopic: oDevice.outputtopic,
|
|
1587
|
+
_oNode: null,
|
|
1588
|
+
_echoed,
|
|
1589
|
+
_repeated: isRepeated
|
|
1590
|
+
})
|
|
1591
|
+
oDevice.currentPayload = msg.payload
|
|
1592
|
+
_input.setNodeStatus({
|
|
1593
|
+
fill: 'grey',
|
|
1594
|
+
shape: 'dot',
|
|
1595
|
+
text: 'Update dev in scene',
|
|
1596
|
+
payload: oDevice.currentPayload,
|
|
1597
|
+
GA: oDevice.topic,
|
|
1598
|
+
dpt: oDevice.dpt,
|
|
1599
|
+
devicename: oDevice.devicename || ''
|
|
1600
|
+
})
|
|
1601
|
+
break
|
|
1602
|
+
}
|
|
1566
1603
|
}
|
|
1567
|
-
|
|
1568
|
-
resolve(true) // fulfilled
|
|
1604
|
+
resolve(true) // fulfilled
|
|
1569
1605
|
// reject("error"); // rejected
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1606
|
+
})
|
|
1607
|
+
.then(function () { })
|
|
1608
|
+
.catch(function () { })
|
|
1609
|
+
}
|
|
1610
|
+
} else if (_input.hasOwnProperty('isLogger')) {
|
|
1575
1611
|
// 26/03/2020 Coronavirus is slightly decreasing the affected numer of people. Logger Node
|
|
1576
1612
|
// 24/03/2021 Logger Node, i'll pass cemiETS
|
|
1577
|
-
|
|
1613
|
+
if (_cemiETS !== undefined) {
|
|
1578
1614
|
// new Promise((resolve, reject) => {
|
|
1579
|
-
|
|
1615
|
+
_input.handleSend(_cemiETS)
|
|
1580
1616
|
// resolve(true); // fulfilled
|
|
1581
1617
|
// reject("error"); // rejected
|
|
1582
1618
|
// }).then(function () { }).catch(function () { });
|
|
1583
|
-
|
|
1584
|
-
|
|
1619
|
+
}
|
|
1620
|
+
} else if (_input.listenallga === true && universalNodeAcceptsGA(_input, _dest)) {
|
|
1585
1621
|
// 25/10/2019 TRY TO AUTO DECODE IF Group address not found in the CSV
|
|
1586
|
-
const msg = buildInputMessage({
|
|
1587
|
-
_srcGA: _src,
|
|
1588
|
-
_destGA: _dest,
|
|
1589
|
-
_event: _evt,
|
|
1590
|
-
_Rawvalue: _rawValue,
|
|
1591
|
-
_outputtopic: _dest,
|
|
1592
|
-
_oNode: _input,
|
|
1593
|
-
_echoed,
|
|
1594
|
-
_repeated: isRepeated
|
|
1595
|
-
})
|
|
1596
|
-
_input.setNodeStatus({
|
|
1597
|
-
fill: 'green',
|
|
1598
|
-
shape: 'dot',
|
|
1599
|
-
text: '',
|
|
1600
|
-
payload: msg.payload,
|
|
1601
|
-
GA: msg.knx.destination,
|
|
1602
|
-
dpt: msg.knx.dpt,
|
|
1603
|
-
devicename: msg.devicename
|
|
1604
|
-
})
|
|
1605
|
-
_input.handleSend(msg)
|
|
1606
|
-
} else if (_input.topic == _dest) {
|
|
1607
|
-
if (_input.hasOwnProperty('isWatchDog')) {
|
|
1608
|
-
// 04/02/2020 Watchdog implementation
|
|
1609
|
-
// Is a watchdog node
|
|
1610
|
-
} else {
|
|
1611
1622
|
const msg = buildInputMessage({
|
|
1612
1623
|
_srcGA: _src,
|
|
1613
1624
|
_destGA: _dest,
|
|
1614
1625
|
_event: _evt,
|
|
1615
1626
|
_Rawvalue: _rawValue,
|
|
1616
|
-
|
|
1617
|
-
_devicename: _input.name ? _input.name : '',
|
|
1618
|
-
_outputtopic: _input.outputtopic,
|
|
1627
|
+
_outputtopic: _dest,
|
|
1619
1628
|
_oNode: _input,
|
|
1620
1629
|
_echoed,
|
|
1621
1630
|
_repeated: isRepeated
|
|
1622
1631
|
})
|
|
1623
|
-
// Check RBE INPUT from KNX Bus, to avoid send the payload to the flow, if it's equal to the current payload
|
|
1624
|
-
if (!checkRBEInputFromKNXBusAllowSend(_input, msg.payload)) {
|
|
1625
|
-
_input.setNodeStatus({
|
|
1626
|
-
fill: 'grey',
|
|
1627
|
-
shape: 'ring',
|
|
1628
|
-
text: 'rbe block (' + msg.payload + ') from KNX',
|
|
1629
|
-
payload: '',
|
|
1630
|
-
GA: '',
|
|
1631
|
-
dpt: '',
|
|
1632
|
-
devicename: ''
|
|
1633
|
-
})
|
|
1634
|
-
return
|
|
1635
|
-
}
|
|
1636
|
-
msg.previouspayload = typeof _input.currentPayload !== 'undefined' ? _input.currentPayload : '' // 24/01/2020 Added previous payload
|
|
1637
|
-
_input.currentPayload = msg.payload // Set the current value for the RBE input
|
|
1638
1632
|
_input.setNodeStatus({
|
|
1639
1633
|
fill: 'green',
|
|
1640
1634
|
shape: 'dot',
|
|
1641
1635
|
text: '',
|
|
1642
1636
|
payload: msg.payload,
|
|
1643
|
-
GA:
|
|
1644
|
-
dpt:
|
|
1645
|
-
devicename:
|
|
1637
|
+
GA: msg.knx.destination,
|
|
1638
|
+
dpt: msg.knx.dpt,
|
|
1639
|
+
devicename: msg.devicename
|
|
1646
1640
|
})
|
|
1647
1641
|
_input.handleSend(msg)
|
|
1642
|
+
} else if (_input.topic == _dest) {
|
|
1643
|
+
if (_input.hasOwnProperty('isWatchDog')) {
|
|
1644
|
+
// 04/02/2020 Watchdog implementation
|
|
1645
|
+
// Is a watchdog node
|
|
1646
|
+
} else {
|
|
1647
|
+
const msg = buildInputMessage({
|
|
1648
|
+
_srcGA: _src,
|
|
1649
|
+
_destGA: _dest,
|
|
1650
|
+
_event: _evt,
|
|
1651
|
+
_Rawvalue: _rawValue,
|
|
1652
|
+
_inputDpt: _input.dpt,
|
|
1653
|
+
_devicename: _input.name ? _input.name : '',
|
|
1654
|
+
_outputtopic: _input.outputtopic,
|
|
1655
|
+
_oNode: _input,
|
|
1656
|
+
_echoed,
|
|
1657
|
+
_repeated: isRepeated
|
|
1658
|
+
})
|
|
1659
|
+
// Check RBE INPUT from KNX Bus, to avoid send the payload to the flow, if it's equal to the current payload
|
|
1660
|
+
if (!checkRBEInputFromKNXBusAllowSend(_input, msg.payload)) {
|
|
1661
|
+
_input.setNodeStatus({
|
|
1662
|
+
fill: 'grey',
|
|
1663
|
+
shape: 'ring',
|
|
1664
|
+
text: 'rbe block (' + msg.payload + ') from KNX',
|
|
1665
|
+
payload: '',
|
|
1666
|
+
GA: '',
|
|
1667
|
+
dpt: '',
|
|
1668
|
+
devicename: ''
|
|
1669
|
+
})
|
|
1670
|
+
return
|
|
1671
|
+
}
|
|
1672
|
+
msg.previouspayload = typeof _input.currentPayload !== 'undefined' ? _input.currentPayload : '' // 24/01/2020 Added previous payload
|
|
1673
|
+
_input.currentPayload = msg.payload // Set the current value for the RBE input
|
|
1674
|
+
_input.setNodeStatus({
|
|
1675
|
+
fill: 'green',
|
|
1676
|
+
shape: 'dot',
|
|
1677
|
+
text: '',
|
|
1678
|
+
payload: msg.payload,
|
|
1679
|
+
GA: _input.topic,
|
|
1680
|
+
dpt: _input.dpt,
|
|
1681
|
+
devicename: ''
|
|
1682
|
+
})
|
|
1683
|
+
_input.handleSend(msg)
|
|
1684
|
+
}
|
|
1648
1685
|
}
|
|
1649
|
-
}
|
|
1686
|
+
} catch (errDispatch) { node.sysLogger?.error('KNX dispatch client error: ' + (errDispatch && errDispatch.message)) }
|
|
1650
1687
|
})
|
|
1651
1688
|
// console.timeEnd('GroupValue_Write');
|
|
1652
1689
|
break
|
|
@@ -1655,103 +1692,105 @@ module.exports = (RED) => {
|
|
|
1655
1692
|
node.nodeClients
|
|
1656
1693
|
.filter((_input) => _input.notifyresponse === true)
|
|
1657
1694
|
.forEach((_input) => {
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1695
|
+
try {
|
|
1696
|
+
if (_input.hasOwnProperty('isMultiRouting')) {
|
|
1697
|
+
const msg = {
|
|
1698
|
+
topic: _input.outputtopic || _dest,
|
|
1699
|
+
payload: {
|
|
1700
|
+
knx: {
|
|
1701
|
+
event: _evt,
|
|
1702
|
+
source: _src,
|
|
1703
|
+
destination: _dest,
|
|
1704
|
+
apdu: { data: _apduData, bitlength: _apduBitLength, hex: _apduHex },
|
|
1705
|
+
cemi: { hex: _cemiETS },
|
|
1706
|
+
echoed: _echoed,
|
|
1707
|
+
repeated: isRepeated,
|
|
1708
|
+
repeat: isRepeated
|
|
1709
|
+
},
|
|
1710
|
+
knxMultiRouting: {
|
|
1711
|
+
gateway: { id: node.id, name: node.name || '', physAddr: node.physAddr || '' },
|
|
1712
|
+
receivedAt: Date.now()
|
|
1713
|
+
}
|
|
1675
1714
|
}
|
|
1676
1715
|
}
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
if (_input.hasOwnProperty('isLogger')) {
|
|
1716
|
+
_input.setNodeStatus({ fill: 'blue', shape: 'dot', text: 'RAW', payload: _evt, GA: _dest, dpt: '', devicename: _src })
|
|
1717
|
+
_input.handleSend(msg)
|
|
1718
|
+
} else
|
|
1719
|
+
if (_input.hasOwnProperty('isLogger')) {
|
|
1682
1720
|
// 26/03/2020 Coronavirus is slightly decreasing the affected numer of people. Logger Node
|
|
1683
1721
|
// 24/03/2021 Logger Node, i'll pass cemiETS
|
|
1684
|
-
|
|
1722
|
+
if (_cemiETS !== undefined) {
|
|
1685
1723
|
// new Promise((resolve, reject) => {
|
|
1686
|
-
|
|
1724
|
+
_input.handleSend(_cemiETS)
|
|
1687
1725
|
// resolve(true); // fulfilled
|
|
1688
1726
|
// reject("error"); // rejected
|
|
1689
1727
|
// }).then(function () { }).catch(function () { });
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
const msg = buildInputMessage({
|
|
1693
|
-
_srcGA: _src,
|
|
1694
|
-
_destGA: _dest,
|
|
1695
|
-
_event: _evt,
|
|
1696
|
-
_Rawvalue: _rawValue,
|
|
1697
|
-
_outputtopic: _dest,
|
|
1698
|
-
_oNode: _input,
|
|
1699
|
-
_echoed,
|
|
1700
|
-
_repeated: isRepeated
|
|
1701
|
-
})
|
|
1702
|
-
_input.setNodeStatus({
|
|
1703
|
-
fill: 'blue',
|
|
1704
|
-
shape: 'dot',
|
|
1705
|
-
text: '',
|
|
1706
|
-
payload: msg.payload,
|
|
1707
|
-
GA: msg.knx.destination,
|
|
1708
|
-
dpt: msg.knx.dpt,
|
|
1709
|
-
devicename: msg.devicename
|
|
1710
|
-
})
|
|
1711
|
-
_input.handleSend(msg)
|
|
1712
|
-
} else if (_input.topic === _dest) {
|
|
1713
|
-
// 04/02/2020 Watchdog implementation
|
|
1714
|
-
if (_input.hasOwnProperty('isWatchDog')) {
|
|
1715
|
-
// Is a watchdog node
|
|
1716
|
-
_input.watchDogTimerReset()
|
|
1717
|
-
} else {
|
|
1728
|
+
}
|
|
1729
|
+
} else if (_input.listenallga === true && universalNodeAcceptsGA(_input, _dest)) {
|
|
1718
1730
|
const msg = buildInputMessage({
|
|
1719
1731
|
_srcGA: _src,
|
|
1720
1732
|
_destGA: _dest,
|
|
1721
1733
|
_event: _evt,
|
|
1722
1734
|
_Rawvalue: _rawValue,
|
|
1723
|
-
|
|
1724
|
-
_devicename: _input.name ? _input.name : '',
|
|
1725
|
-
_outputtopic: _input.outputtopic,
|
|
1735
|
+
_outputtopic: _dest,
|
|
1726
1736
|
_oNode: _input,
|
|
1727
1737
|
_echoed,
|
|
1728
1738
|
_repeated: isRepeated
|
|
1729
1739
|
})
|
|
1730
|
-
// Check RBE INPUT from KNX Bus, to avoid send the payload to the flow, if it's equal to the current payload
|
|
1731
|
-
if (!checkRBEInputFromKNXBusAllowSend(_input, msg.payload)) {
|
|
1732
|
-
_input.setNodeStatus({
|
|
1733
|
-
fill: 'grey',
|
|
1734
|
-
shape: 'ring',
|
|
1735
|
-
text: 'rbe INPUT filter applied on ' + msg.payload,
|
|
1736
|
-
payload: msg.payload,
|
|
1737
|
-
GA: _dest
|
|
1738
|
-
})
|
|
1739
|
-
return
|
|
1740
|
-
}
|
|
1741
|
-
msg.previouspayload = typeof _input.currentPayload !== 'undefined' ? _input.currentPayload : '' // 24/01/2020 Added previous payload
|
|
1742
|
-
_input.currentPayload = msg.payload // Set the current value for the RBE input
|
|
1743
1740
|
_input.setNodeStatus({
|
|
1744
1741
|
fill: 'blue',
|
|
1745
1742
|
shape: 'dot',
|
|
1746
1743
|
text: '',
|
|
1747
1744
|
payload: msg.payload,
|
|
1748
|
-
GA:
|
|
1745
|
+
GA: msg.knx.destination,
|
|
1749
1746
|
dpt: msg.knx.dpt,
|
|
1750
1747
|
devicename: msg.devicename
|
|
1751
1748
|
})
|
|
1752
1749
|
_input.handleSend(msg)
|
|
1750
|
+
} else if (_input.topic === _dest) {
|
|
1751
|
+
// 04/02/2020 Watchdog implementation
|
|
1752
|
+
if (_input.hasOwnProperty('isWatchDog')) {
|
|
1753
|
+
// Is a watchdog node
|
|
1754
|
+
_input.watchDogTimerReset()
|
|
1755
|
+
} else {
|
|
1756
|
+
const msg = buildInputMessage({
|
|
1757
|
+
_srcGA: _src,
|
|
1758
|
+
_destGA: _dest,
|
|
1759
|
+
_event: _evt,
|
|
1760
|
+
_Rawvalue: _rawValue,
|
|
1761
|
+
_inputDpt: _input.dpt,
|
|
1762
|
+
_devicename: _input.name ? _input.name : '',
|
|
1763
|
+
_outputtopic: _input.outputtopic,
|
|
1764
|
+
_oNode: _input,
|
|
1765
|
+
_echoed,
|
|
1766
|
+
_repeated: isRepeated
|
|
1767
|
+
})
|
|
1768
|
+
// Check RBE INPUT from KNX Bus, to avoid send the payload to the flow, if it's equal to the current payload
|
|
1769
|
+
if (!checkRBEInputFromKNXBusAllowSend(_input, msg.payload)) {
|
|
1770
|
+
_input.setNodeStatus({
|
|
1771
|
+
fill: 'grey',
|
|
1772
|
+
shape: 'ring',
|
|
1773
|
+
text: 'rbe INPUT filter applied on ' + msg.payload,
|
|
1774
|
+
payload: msg.payload,
|
|
1775
|
+
GA: _dest
|
|
1776
|
+
})
|
|
1777
|
+
return
|
|
1778
|
+
}
|
|
1779
|
+
msg.previouspayload = typeof _input.currentPayload !== 'undefined' ? _input.currentPayload : '' // 24/01/2020 Added previous payload
|
|
1780
|
+
_input.currentPayload = msg.payload // Set the current value for the RBE input
|
|
1781
|
+
_input.setNodeStatus({
|
|
1782
|
+
fill: 'blue',
|
|
1783
|
+
shape: 'dot',
|
|
1784
|
+
text: '',
|
|
1785
|
+
payload: msg.payload,
|
|
1786
|
+
GA: _input.topic,
|
|
1787
|
+
dpt: msg.knx.dpt,
|
|
1788
|
+
devicename: msg.devicename
|
|
1789
|
+
})
|
|
1790
|
+
_input.handleSend(msg)
|
|
1791
|
+
}
|
|
1753
1792
|
}
|
|
1754
|
-
}
|
|
1793
|
+
} catch (errDispatch) { node.sysLogger?.error('KNX dispatch client error: ' + (errDispatch && errDispatch.message)) }
|
|
1755
1794
|
})
|
|
1756
1795
|
break
|
|
1757
1796
|
|
|
@@ -1759,133 +1798,135 @@ module.exports = (RED) => {
|
|
|
1759
1798
|
node.nodeClients
|
|
1760
1799
|
.filter((_input) => _input.notifyreadrequest === true)
|
|
1761
1800
|
.forEach((_input) => {
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1801
|
+
try {
|
|
1802
|
+
if (_input.hasOwnProperty('isMultiRouting')) {
|
|
1803
|
+
const msg = {
|
|
1804
|
+
topic: _input.outputtopic || _dest,
|
|
1805
|
+
payload: {
|
|
1806
|
+
knx: {
|
|
1807
|
+
event: _evt,
|
|
1808
|
+
source: _src,
|
|
1809
|
+
destination: _dest,
|
|
1810
|
+
apdu: { data: null, bitlength: 0, hex: '' },
|
|
1811
|
+
cemi: { hex: _cemiETS },
|
|
1812
|
+
echoed: _echoed,
|
|
1813
|
+
repeated: isRepeated,
|
|
1814
|
+
repeat: isRepeated
|
|
1815
|
+
},
|
|
1816
|
+
knxMultiRouting: {
|
|
1817
|
+
gateway: { id: node.id, name: node.name || '', physAddr: node.physAddr || '' },
|
|
1818
|
+
receivedAt: Date.now()
|
|
1819
|
+
}
|
|
1779
1820
|
}
|
|
1780
1821
|
}
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
if (_input.hasOwnProperty('isLogger')) {
|
|
1822
|
+
_input.setNodeStatus({ fill: 'grey', shape: 'dot', text: 'RAW Read', payload: '', GA: _dest, dpt: '', devicename: _src })
|
|
1823
|
+
_input.handleSend(msg)
|
|
1824
|
+
} else
|
|
1825
|
+
if (_input.hasOwnProperty('isLogger')) {
|
|
1786
1826
|
// 26/03/2020 Coronavirus is slightly decreasing the affected numer of people. Logger Node
|
|
1787
1827
|
// node.sysLogger?.info("BANANA isLogger", _evt, _src, _dest, _rawValue, _cemiETS);
|
|
1788
1828
|
// 24/03/2021 Logger Node, i'll pass cemiETS
|
|
1789
|
-
|
|
1829
|
+
if (_cemiETS !== undefined) {
|
|
1790
1830
|
// new Promise((resolve, reject) => {
|
|
1791
|
-
|
|
1831
|
+
_input.handleSend(_cemiETS)
|
|
1792
1832
|
// resolve(true); // fulfilled
|
|
1793
1833
|
// reject("error"); // rejected
|
|
1794
1834
|
// }).then(function () { }).catch(function () { });
|
|
1795
|
-
|
|
1796
|
-
|
|
1835
|
+
}
|
|
1836
|
+
} else if (_input.listenallga === true && universalNodeAcceptsGA(_input, _dest)) {
|
|
1797
1837
|
// Read Request
|
|
1798
|
-
const msg = buildInputMessage({
|
|
1799
|
-
_srcGA: _src,
|
|
1800
|
-
_destGA: _dest,
|
|
1801
|
-
_event: _evt,
|
|
1802
|
-
_Rawvalue: null,
|
|
1803
|
-
_outputtopic: _dest,
|
|
1804
|
-
_oNode: _input,
|
|
1805
|
-
_echoed,
|
|
1806
|
-
_repeated: isRepeated
|
|
1807
|
-
})
|
|
1808
|
-
_input.setNodeStatus({
|
|
1809
|
-
fill: 'grey',
|
|
1810
|
-
shape: 'dot',
|
|
1811
|
-
text: 'Read',
|
|
1812
|
-
payload: '',
|
|
1813
|
-
GA: msg.knx.destination,
|
|
1814
|
-
dpt: msg.knx.dpt,
|
|
1815
|
-
devicename: msg.devicename
|
|
1816
|
-
})
|
|
1817
|
-
_input.handleSend(msg)
|
|
1818
|
-
} else if (_input.topic === _dest) {
|
|
1819
|
-
// 04/02/2020 Watchdog implementation
|
|
1820
|
-
if (_input.hasOwnProperty('isWatchDog')) {
|
|
1821
|
-
// Is a watchdog node
|
|
1822
|
-
} else {
|
|
1823
|
-
// Read Request
|
|
1824
1838
|
const msg = buildInputMessage({
|
|
1825
1839
|
_srcGA: _src,
|
|
1826
1840
|
_destGA: _dest,
|
|
1827
1841
|
_event: _evt,
|
|
1828
1842
|
_Rawvalue: null,
|
|
1829
|
-
|
|
1830
|
-
_devicename: _input.name || '',
|
|
1831
|
-
_outputtopic: _input.outputtopic,
|
|
1843
|
+
_outputtopic: _dest,
|
|
1832
1844
|
_oNode: _input,
|
|
1833
1845
|
_echoed,
|
|
1834
1846
|
_repeated: isRepeated
|
|
1835
1847
|
})
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1848
|
+
_input.setNodeStatus({
|
|
1849
|
+
fill: 'grey',
|
|
1850
|
+
shape: 'dot',
|
|
1851
|
+
text: 'Read',
|
|
1852
|
+
payload: '',
|
|
1853
|
+
GA: msg.knx.destination,
|
|
1854
|
+
dpt: msg.knx.dpt,
|
|
1855
|
+
devicename: msg.devicename
|
|
1856
|
+
})
|
|
1857
|
+
_input.handleSend(msg)
|
|
1858
|
+
} else if (_input.topic === _dest) {
|
|
1859
|
+
// 04/02/2020 Watchdog implementation
|
|
1860
|
+
if (_input.hasOwnProperty('isWatchDog')) {
|
|
1861
|
+
// Is a watchdog node
|
|
1862
|
+
} else {
|
|
1863
|
+
// Read Request
|
|
1864
|
+
const msg = buildInputMessage({
|
|
1865
|
+
_srcGA: _src,
|
|
1866
|
+
_destGA: _dest,
|
|
1867
|
+
_event: _evt,
|
|
1868
|
+
_Rawvalue: null,
|
|
1869
|
+
_inputDpt: _input.dpt,
|
|
1870
|
+
_devicename: _input.name || '',
|
|
1871
|
+
_outputtopic: _input.outputtopic,
|
|
1872
|
+
_oNode: _input,
|
|
1873
|
+
_echoed,
|
|
1874
|
+
_repeated: isRepeated
|
|
1875
|
+
})
|
|
1876
|
+
msg.previouspayload = typeof _input.currentPayload !== 'undefined' ? _input.currentPayload : '' // 24/01/2020 Reset previous payload
|
|
1877
|
+
// 24/09/2019 Autorespond to BUS
|
|
1878
|
+
if (_input.hasOwnProperty('notifyreadrequestalsorespondtobus') && _input.notifyreadrequestalsorespondtobus === true) {
|
|
1879
|
+
if (typeof _input.currentPayload === 'undefined' || _input.currentPayload === '' || _input.currentPayload === null) {
|
|
1840
1880
|
// 14/08/2021 Added || input.currentPayload === null
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1881
|
+
node.sendKNXTelegramToKNXEngine({
|
|
1882
|
+
grpaddr: _dest,
|
|
1883
|
+
payload: _input.notifyreadrequestalsorespondtobusdefaultvalueifnotinitialized,
|
|
1884
|
+
dpt: _input.dpt,
|
|
1885
|
+
outputtype: 'response',
|
|
1886
|
+
nodecallerid: _input.id
|
|
1887
|
+
})
|
|
1888
|
+
_input.setNodeStatus({
|
|
1889
|
+
fill: 'blue',
|
|
1890
|
+
shape: 'ring',
|
|
1891
|
+
text: 'Read & Autorespond with default',
|
|
1892
|
+
payload: _input.notifyreadrequestalsorespondtobusdefaultvalueifnotinitialized,
|
|
1893
|
+
GA: _input.topic,
|
|
1894
|
+
dpt: msg.knx.dpt,
|
|
1895
|
+
devicename: ''
|
|
1896
|
+
})
|
|
1897
|
+
} else {
|
|
1898
|
+
node.sendKNXTelegramToKNXEngine({
|
|
1899
|
+
grpaddr: _dest,
|
|
1900
|
+
payload: _input.currentPayload,
|
|
1901
|
+
dpt: _input.dpt,
|
|
1902
|
+
outputtype: 'response',
|
|
1903
|
+
nodecallerid: _input.id
|
|
1904
|
+
})
|
|
1905
|
+
_input.setNodeStatus({
|
|
1906
|
+
fill: 'blue',
|
|
1907
|
+
shape: 'ring',
|
|
1908
|
+
text: 'Read & Autorespond with default',
|
|
1909
|
+
payload: _input.notifyreadrequestalsorespondtobusdefaultvalueifnotinitialized,
|
|
1910
|
+
GA: _input.topic,
|
|
1911
|
+
dpt: msg.knx.dpt,
|
|
1912
|
+
devicename: ''
|
|
1913
|
+
})
|
|
1914
|
+
}
|
|
1857
1915
|
} else {
|
|
1858
|
-
node.sendKNXTelegramToKNXEngine({
|
|
1859
|
-
grpaddr: _dest,
|
|
1860
|
-
payload: _input.currentPayload,
|
|
1861
|
-
dpt: _input.dpt,
|
|
1862
|
-
outputtype: 'response',
|
|
1863
|
-
nodecallerid: _input.id
|
|
1864
|
-
})
|
|
1865
1916
|
_input.setNodeStatus({
|
|
1866
|
-
fill: '
|
|
1867
|
-
shape: '
|
|
1868
|
-
text: 'Read
|
|
1869
|
-
payload:
|
|
1917
|
+
fill: 'grey',
|
|
1918
|
+
shape: 'dot',
|
|
1919
|
+
text: 'Read',
|
|
1920
|
+
payload: msg.payload,
|
|
1870
1921
|
GA: _input.topic,
|
|
1871
1922
|
dpt: msg.knx.dpt,
|
|
1872
1923
|
devicename: ''
|
|
1873
1924
|
})
|
|
1874
1925
|
}
|
|
1875
|
-
|
|
1876
|
-
_input.setNodeStatus({
|
|
1877
|
-
fill: 'grey',
|
|
1878
|
-
shape: 'dot',
|
|
1879
|
-
text: 'Read',
|
|
1880
|
-
payload: msg.payload,
|
|
1881
|
-
GA: _input.topic,
|
|
1882
|
-
dpt: msg.knx.dpt,
|
|
1883
|
-
devicename: ''
|
|
1884
|
-
})
|
|
1926
|
+
_input.handleSend(msg)
|
|
1885
1927
|
}
|
|
1886
|
-
_input.handleSend(msg)
|
|
1887
1928
|
}
|
|
1888
|
-
}
|
|
1929
|
+
} catch (errDispatch) { node.sysLogger?.error('KNX dispatch client error: ' + (errDispatch && errDispatch.message)) }
|
|
1889
1930
|
})
|
|
1890
1931
|
break
|
|
1891
1932
|
|
|
@@ -2666,6 +2707,9 @@ module.exports = (RED) => {
|
|
|
2666
2707
|
} finally {
|
|
2667
2708
|
try {
|
|
2668
2709
|
connection.removeAllListeners()
|
|
2710
|
+
// Never leave a (possibly still async-active) client without an 'error'
|
|
2711
|
+
// listener: a late rejection would crash the whole process.
|
|
2712
|
+
connection.on(knx.KNXClientEvents.error, () => { })
|
|
2669
2713
|
} catch (error) { /* empty */ }
|
|
2670
2714
|
if (isSerial && serialDriver && typeof serialDriver.close === 'function') {
|
|
2671
2715
|
try {
|