node-red-contrib-knx-ultimate 1.3.40 → 1.3.41
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 +7 -1
- package/KNXEngine/KNXClient.js +23 -6
- package/KNXEngine/util/ipAddressHelper.js +9 -4
- package/nodes/knxUltimate-config.html +5 -4
- package/nodes/knxUltimate-config.js +1 -0
- package/nodes/knxUltimate.js +1 -1
- package/nodes/knxUltimateSceneController.js +1 -1
- package/nodes/knxUltimateWatchDog.js +2 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,7 +7,13 @@
|
|
|
7
7
|
# CHANGELOG
|
|
8
8
|
|
|
9
9
|
<p>
|
|
10
|
-
<b>Version 1.3.
|
|
10
|
+
<b>Version 1.3.41</b> - Mai 2022<br/>
|
|
11
|
+
- Fixed an issue in the gateway config node UI, where you manually set the IP interface name.<br />
|
|
12
|
+
- Fixed an issue introduced by a breaking change in Node 18.<br />
|
|
13
|
+
- Added more "trace" log in the ipAddressHelper function, to better track the ethernet interface details.<br />
|
|
14
|
+
</p>
|
|
15
|
+
<p>
|
|
16
|
+
<b>Version 1.3.40</b> - Mai 2022<br/>
|
|
11
17
|
- Fixed an issue in the GlobalContext node, preventing the node from searching for the DPT, if the CSV ETS file has been imported and you don't specify the DPT in the msg input. Thanks to @Sebastien-Posca for pointing me out that.<br />
|
|
12
18
|
</p>
|
|
13
19
|
<p>
|
package/KNXEngine/KNXClient.js
CHANGED
|
@@ -350,7 +350,8 @@ class KNXClient extends EventEmitter {
|
|
|
350
350
|
} else {
|
|
351
351
|
// Tunneling
|
|
352
352
|
const cEMIMessage = CEMIFactory.CEMIFactory.newLDataRequestMessage("write", srcAddress, dstAddress, data);
|
|
353
|
-
cEMIMessage.control.ack = this._options.suppress_ack_ldatareq ? 0 : 1;
|
|
353
|
+
//cEMIMessage.control.ack = this._options.suppress_ack_ldatareq ? 0 : 1; // No ack like telegram sent from ETS (0 means don't care)
|
|
354
|
+
cEMIMessage.control.ack = 0;// No ack like telegram sent from ETS (0 means don't care)
|
|
354
355
|
cEMIMessage.control.broadcast = 1;
|
|
355
356
|
cEMIMessage.control.priority = 3;
|
|
356
357
|
cEMIMessage.control.addressType = 1;
|
|
@@ -383,7 +384,7 @@ class KNXClient extends EventEmitter {
|
|
|
383
384
|
if (this._options.hostProtocol === "Multicast") {
|
|
384
385
|
// Multicast
|
|
385
386
|
const cEMIMessage = CEMIFactory.CEMIFactory.newLDataIndicationMessage("response", srcAddress, dstAddress, data);
|
|
386
|
-
cEMIMessage.control.ack = 0;
|
|
387
|
+
cEMIMessage.control.ack = 0; // No ack like telegram sent from ETS (0 means don't care)
|
|
387
388
|
cEMIMessage.control.broadcast = 1;
|
|
388
389
|
cEMIMessage.control.priority = 3;
|
|
389
390
|
cEMIMessage.control.addressType = 1;
|
|
@@ -395,7 +396,8 @@ class KNXClient extends EventEmitter {
|
|
|
395
396
|
} else {
|
|
396
397
|
// Tunneling
|
|
397
398
|
const cEMIMessage = CEMIFactory.CEMIFactory.newLDataRequestMessage("response", srcAddress, dstAddress, data);
|
|
398
|
-
cEMIMessage.control.ack = this._options.suppress_ack_ldatareq ? 0 : 1;
|
|
399
|
+
//cEMIMessage.control.ack = this._options.suppress_ack_ldatareq ? 0 : 1;
|
|
400
|
+
cEMIMessage.control.ack = 0;// No ack like telegram sent from ETS (0 means don't care)
|
|
399
401
|
cEMIMessage.control.broadcast = 1;
|
|
400
402
|
cEMIMessage.control.priority = 3;
|
|
401
403
|
cEMIMessage.control.addressType = 1;
|
|
@@ -436,7 +438,8 @@ class KNXClient extends EventEmitter {
|
|
|
436
438
|
} else {
|
|
437
439
|
// Tunneling
|
|
438
440
|
const cEMIMessage = CEMIFactory.CEMIFactory.newLDataRequestMessage("read", srcAddress, dstAddress, null);
|
|
439
|
-
|
|
441
|
+
//cEMIMessage.control.ack = this._options.suppress_ack_ldatareq ? 0 : 1;
|
|
442
|
+
cEMIMessage.control.ack = 0;// No ack like telegram sent from ETS (0 means don't care)
|
|
440
443
|
cEMIMessage.control.broadcast = 1;
|
|
441
444
|
cEMIMessage.control.priority = 3;
|
|
442
445
|
cEMIMessage.control.addressType = 1;
|
|
@@ -764,6 +767,7 @@ class KNXClient extends EventEmitter {
|
|
|
764
767
|
}, KNXConstants.KNX_CONSTANTS.TUNNELING_REQUEST_TIMEOUT * 1000);
|
|
765
768
|
|
|
766
769
|
}
|
|
770
|
+
|
|
767
771
|
_processInboundMessage(msg, rinfo) {
|
|
768
772
|
|
|
769
773
|
try {
|
|
@@ -879,13 +883,24 @@ class KNXClient extends EventEmitter {
|
|
|
879
883
|
|
|
880
884
|
const knxTunnelingRequest = knxMessage;
|
|
881
885
|
if (knxTunnelingRequest.channelID !== this._channelID) {
|
|
886
|
+
try {
|
|
887
|
+
this.sysLogger.debug("Received KNX packet: TUNNELING: L_DATA_IND, NOT FOR ME: MyChannelID:" + this._channelID + " ReceivedPacketChannelID: " + knxTunnelingRequest.channelID + " ReceivedPacketseqCounter:" + knxTunnelingRequest.seqCounter + " Host:" + this._options.ipAddr + ":" + this._options.ipPort);
|
|
888
|
+
} catch (error) { }
|
|
882
889
|
return;
|
|
883
890
|
}
|
|
884
891
|
// 26/12/2021 send the ACK if the server requestet that
|
|
885
892
|
// Then REMOVED, because some interfaces sets the "ack request" always to 0 even if it needs ack.
|
|
886
893
|
//if (knxMessage.cEMIMessage.control.ack){
|
|
887
|
-
|
|
888
|
-
|
|
894
|
+
//setTimeout(() => {
|
|
895
|
+
try {
|
|
896
|
+
let knxTunnelAck = KNXProtocol.KNXProtocol.newKNXTunnelingACK(knxTunnelingRequest.channelID, knxTunnelingRequest.seqCounter, KNXConstants.KNX_CONSTANTS.E_NO_ERROR);
|
|
897
|
+
this.send(knxTunnelAck);
|
|
898
|
+
} catch (error) {
|
|
899
|
+
this.sysLogger.error("Received KNX packet: TUNNELING: L_DATA_IND, ERROR BUOLDING THE TUNNELINK ACK: " + error.message + " MyChannelID:" + this._channelID + " ReceivedPacketChannelID: " + knxTunnelingRequest.channelID + " ReceivedPacketseqCounter:" + knxTunnelingRequest.seqCounter + " Host:" + this._options.ipAddr + ":" + this._options.ipPort);
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
//}, 20);
|
|
903
|
+
|
|
889
904
|
//}
|
|
890
905
|
|
|
891
906
|
if (knxTunnelingRequest.cEMIMessage.msgCode === CEMIConstants.CEMIConstants.L_DATA_IND) {
|
|
@@ -973,6 +988,8 @@ class KNXClient extends EventEmitter {
|
|
|
973
988
|
this.emit(KNXClientEvents.indication, knxRoutingInd, false);
|
|
974
989
|
} catch (error) {
|
|
975
990
|
}
|
|
991
|
+
|
|
992
|
+
|
|
976
993
|
}
|
|
977
994
|
else if (knxRoutingInd.cEMIMessage.msgCode === CEMIConstants.CEMIConstants.L_DATA_CON) {
|
|
978
995
|
|
|
@@ -3,16 +3,20 @@ const knxLog = require('../KnxLog');
|
|
|
3
3
|
const os = require('os');
|
|
4
4
|
|
|
5
5
|
//#region "GET LOCAL INTERFACE PROPERTIES"
|
|
6
|
-
|
|
6
|
+
function getIPv4Interfaces () {
|
|
7
7
|
// get the local address of the IPv4 interface we're going to use
|
|
8
8
|
let candidateInterfaces = {}
|
|
9
9
|
let interfaces = os.networkInterfaces()
|
|
10
10
|
for (let iface in interfaces) {
|
|
11
11
|
for (let key in interfaces[iface]) {
|
|
12
12
|
let intf = interfaces[iface][key]
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
// 11/05/2022 Fixed a breaking change introduced by node 18 (https://nodejs.org/api/os.html#osnetworkinterfaces)
|
|
14
|
+
// In Node < 18, intf.family is a string "IPv4" or "IPv6", from node 18, is an integer, for example 4.
|
|
15
|
+
if (intf.family.toString().includes("4") && !intf.internal) {
|
|
16
|
+
knxLog.get().trace('ipAddressHelper.js: Found suitable interface: %s (%j)', iface, intf);
|
|
15
17
|
candidateInterfaces[iface] = intf
|
|
18
|
+
} else {
|
|
19
|
+
knxLog.get().trace('ipAddressHelper.js: Found NOT suitable interface: %s (%j)', iface, intf);
|
|
16
20
|
}
|
|
17
21
|
}
|
|
18
22
|
}
|
|
@@ -21,7 +25,8 @@ const getIPv4Interfaces = function () {
|
|
|
21
25
|
}
|
|
22
26
|
|
|
23
27
|
exports.getLocalAddress = function (_interface = "") {
|
|
24
|
-
|
|
28
|
+
knxLog.get().trace("ipAddressHelper.js: getLocalAddress: getting interfaces");
|
|
29
|
+
let candidateInterfaces = getIPv4Interfaces();
|
|
25
30
|
// if user has declared a desired interface then use it
|
|
26
31
|
if (_interface !== "") {
|
|
27
32
|
if (!candidateInterfaces.hasOwnProperty(_interface)) {
|
|
@@ -278,6 +278,10 @@
|
|
|
278
278
|
</label>
|
|
279
279
|
<select id="node-config-input-KNXEthInterface"></select>
|
|
280
280
|
</div>
|
|
281
|
+
<div class="form-row" id="divKNXEthInterfaceManuallyInput" style="display: none;">
|
|
282
|
+
<label for="node-config-input-KNXEthInterfaceManuallyInput">Interface name:</label>
|
|
283
|
+
<input type="text" id="node-config-input-KNXEthInterfaceManuallyInput" placeholder="Interface name, ex: eth0 or ens1 or Ethernet 1 and so on..."></input>
|
|
284
|
+
</div>
|
|
281
285
|
<div class="form-row">
|
|
282
286
|
<label for="node-config-input-autoReconnect" style="width: 200px">
|
|
283
287
|
<i class="fa fa-plug"></i>
|
|
@@ -288,10 +292,7 @@
|
|
|
288
292
|
<option value="no" data-i18n="knxUltimate-config.properties.autoReconnect_no"></option>
|
|
289
293
|
</select>
|
|
290
294
|
</div>
|
|
291
|
-
|
|
292
|
-
<label for="node-config-input-KNXEthInterfaceManuallyInput"></label>
|
|
293
|
-
<input type="text" id="node-config-input-KNXEthInterfaceManuallyInput" placeholder="Interface name, ex: eth0 or ens1 or Ethernet 1 and so on..."></input>
|
|
294
|
-
</div>
|
|
295
|
+
|
|
295
296
|
<div id="advancedOptionsAccordion">
|
|
296
297
|
<h3><span data-i18n="knxUltimate-config.properties.adv_options"></span></h3>
|
|
297
298
|
<div>
|
|
@@ -431,6 +431,7 @@ return msg;`, "helplink": "https://github.com/Supergiovane/node-red-contrib-knx-
|
|
|
431
431
|
|
|
432
432
|
// 16/02/2020 KNX-Ultimate nodes calls this function, then this funcion calls the same function on the Watchdog
|
|
433
433
|
node.reportToWatchdogCalledByKNXUltimateNode = (_oError) => {
|
|
434
|
+
// _oError is = { nodeid: node.id, topic: node.outputtopic, devicename: devicename, GA: GA, text: text };
|
|
434
435
|
var readHistory = [];
|
|
435
436
|
let delay = 0;
|
|
436
437
|
node.nodeClients
|
package/nodes/knxUltimate.js
CHANGED
|
@@ -51,7 +51,7 @@ module.exports = function (RED) {
|
|
|
51
51
|
// 16/02/2020 signal errors to the server
|
|
52
52
|
if (fill.toUpperCase() === "RED") {
|
|
53
53
|
if (node.server) {
|
|
54
|
-
|
|
54
|
+
let oError = { nodeid: node.id, topic: node.outputtopic, devicename: devicename, GA: GA, text: text };
|
|
55
55
|
node.server.reportToWatchdogCalledByKNXUltimateNode(oError);
|
|
56
56
|
};
|
|
57
57
|
};
|
|
@@ -106,7 +106,7 @@ module.exports = function (RED) {
|
|
|
106
106
|
// 16/02/2020 signal errors to the server
|
|
107
107
|
if (fill.toUpperCase() == "RED") {
|
|
108
108
|
if (node.server) {
|
|
109
|
-
|
|
109
|
+
let oError = { nodeid: node.id, topic: node.outputtopic, devicename: devicename, GA: GA, text: text };
|
|
110
110
|
node.server.reportToWatchdogCalledByKNXUltimateNode(oError);
|
|
111
111
|
};
|
|
112
112
|
};
|
|
@@ -48,7 +48,7 @@ module.exports = function (RED) {
|
|
|
48
48
|
if (node.beatNumber > node.maxRetry) {
|
|
49
49
|
// Confirmed connection error
|
|
50
50
|
node.beatNumber = 0; // Reset Counter
|
|
51
|
-
|
|
51
|
+
let msg = {
|
|
52
52
|
type: "BUSError",
|
|
53
53
|
checkPerformed: node.checkLevel,
|
|
54
54
|
nodeid: node.id,
|
|
@@ -102,7 +102,7 @@ module.exports = function (RED) {
|
|
|
102
102
|
// 16/02/2020 This function is called by the knx-ultimate config node.
|
|
103
103
|
node.signalNodeErrorCalledByConfigNode = _oError => {
|
|
104
104
|
// Report an error from knx-ultimate node.
|
|
105
|
-
//
|
|
105
|
+
// let oError = {nodeid:node.id,topic:node.outputtopic,devicename:devicename,GA:GA,text:text};
|
|
106
106
|
let msg = {
|
|
107
107
|
type: "NodeError",
|
|
108
108
|
checkPerformed: "Self KNX-Ultimate node reporting a red color status",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-red-contrib-knx-ultimate",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.41",
|
|
4
4
|
"description": "Control your KNX intallation via Node-Red! Single Node KNX IN/OUT with optional ETS group address importer. Easy to use and highly configurable.",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"mkdirp": "1.0.4",
|