node-red-contrib-knx-ultimate 1.3.13 → 1.3.14
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
CHANGED
|
@@ -4,6 +4,12 @@
|
|
|
4
4
|
|
|
5
5
|
<br/>
|
|
6
6
|
<p>
|
|
7
|
+
<b>Version 1.3.14</b> - 26 December 2021<br/>
|
|
8
|
+
- KNXEngine: ACK management: the not acknowledged message will be re-transmitted once, then the connection will be dropped, as per KNX specs.<br/>
|
|
9
|
+
- KNXEngine: ACK management: the telegram's queue to be sent to the KNX BUS will be paused during the ACK waiting.<br/>
|
|
10
|
+
- KNXEngine: Routing: now the routing_busy and routing_lost_messages telegrams sent by the KNX/IP Router are handled.<br/>
|
|
11
|
+
</p>
|
|
12
|
+
<p>
|
|
7
13
|
<b>Version 1.3.13</b> - 25 December 2021<br/>
|
|
8
14
|
- KNXEngine: when in tunneling and suppress ACK request is disabled, the error is raised only after 3° failed ACK reception instead of 1°.<br/>
|
|
9
15
|
- KNXEngine: at disconnection, delete all pending ACK requests timer.<br/>
|
package/KNXEngine/KNXClient.js
CHANGED
|
@@ -86,7 +86,7 @@ class KNXClient extends EventEmitter {
|
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
super();
|
|
89
|
-
this._clientTunnelSeqNumber =
|
|
89
|
+
this._clientTunnelSeqNumber = -1;
|
|
90
90
|
this._options = options;//Object.assign(optionsDefaults, options);
|
|
91
91
|
this._options.connectionKeepAliveTimeout = KNXConstants.KNX_CONSTANTS.CONNECTION_ALIVE_TIME,
|
|
92
92
|
this._localPort = null;
|
|
@@ -169,10 +169,10 @@ class KNXClient extends EventEmitter {
|
|
|
169
169
|
});
|
|
170
170
|
}
|
|
171
171
|
|
|
172
|
-
this._clientTunnelSeqNumber =
|
|
172
|
+
this._clientTunnelSeqNumber = -1;
|
|
173
173
|
this._channelID = null;
|
|
174
174
|
this._connectionState = STATE.DISCONNECTED;
|
|
175
|
-
this._tunnelReqTimer =
|
|
175
|
+
this._tunnelReqTimer = null;
|
|
176
176
|
this._numFailedTelegramACK = 0; // 25/12/2021 Keep count of the failed tunnelig ACK telegrams
|
|
177
177
|
|
|
178
178
|
}
|
|
@@ -240,6 +240,7 @@ class KNXClient extends EventEmitter {
|
|
|
240
240
|
});
|
|
241
241
|
}
|
|
242
242
|
send(knxPacket) {
|
|
243
|
+
|
|
243
244
|
// Logging
|
|
244
245
|
if (this.sysLogger !== undefined && this.sysLogger !== null) {
|
|
245
246
|
try {
|
|
@@ -342,9 +343,11 @@ class KNXClient extends EventEmitter {
|
|
|
342
343
|
cEMIMessage.control.priority = 3;
|
|
343
344
|
cEMIMessage.control.addressType = 1;
|
|
344
345
|
cEMIMessage.control.hopCount = 6;
|
|
346
|
+
this._incSeqNumber(); // 26/12/2021
|
|
345
347
|
const seqNum = this._getSeqNumber();
|
|
346
348
|
const knxPacketRequest = KNXProtocol.KNXProtocol.newKNXTunnelingRequest(this._channelID, seqNum, cEMIMessage);
|
|
347
|
-
if (!this._options.suppress_ack_ldatareq) this.
|
|
349
|
+
if (!this._options.suppress_ack_ldatareq) this._setTimerWaitingForACK(knxPacketRequest);
|
|
350
|
+
//if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.error("this._tunnelReqTimer "+ this._tunnelReqTimer.size);
|
|
348
351
|
this.send(knxPacketRequest);
|
|
349
352
|
// 06/12/2021 Echo the sent telegram. Last parameter is the echo true/false
|
|
350
353
|
try {
|
|
@@ -386,9 +389,10 @@ class KNXClient extends EventEmitter {
|
|
|
386
389
|
cEMIMessage.control.priority = 3;
|
|
387
390
|
cEMIMessage.control.addressType = 1;
|
|
388
391
|
cEMIMessage.control.hopCount = 6;
|
|
392
|
+
this._incSeqNumber(); // 26/12/2021
|
|
389
393
|
const seqNum = this._getSeqNumber();
|
|
390
394
|
const knxPacketRequest = KNXProtocol.KNXProtocol.newKNXTunnelingRequest(this._channelID, seqNum, cEMIMessage);
|
|
391
|
-
if (!this._options.suppress_ack_ldatareq) this.
|
|
395
|
+
if (!this._options.suppress_ack_ldatareq) this._setTimerWaitingForACK(knxPacketRequest);
|
|
392
396
|
this.send(knxPacketRequest);
|
|
393
397
|
// 06/12/2021 Echo the sent telegram. Last parameter is the echo true/false
|
|
394
398
|
try {
|
|
@@ -427,9 +431,10 @@ class KNXClient extends EventEmitter {
|
|
|
427
431
|
cEMIMessage.control.priority = 3;
|
|
428
432
|
cEMIMessage.control.addressType = 1;
|
|
429
433
|
cEMIMessage.control.hopCount = 6;
|
|
434
|
+
this._incSeqNumber(); // 26/12/2021
|
|
430
435
|
const seqNum = this._getSeqNumber();
|
|
431
436
|
const knxPacketRequest = KNXProtocol.KNXProtocol.newKNXTunnelingRequest(this._channelID, seqNum, cEMIMessage);
|
|
432
|
-
if (!this._options.suppress_ack_ldatareq) this.
|
|
437
|
+
if (!this._options.suppress_ack_ldatareq) this._setTimerWaitingForACK(knxPacketRequest);
|
|
433
438
|
this.send(knxPacketRequest);
|
|
434
439
|
// 06/12/2021 Echo the sent telegram. Last parameter is the echo true/false
|
|
435
440
|
try {
|
|
@@ -475,9 +480,10 @@ class KNXClient extends EventEmitter {
|
|
|
475
480
|
cEMIMessage.control.priority = 3;
|
|
476
481
|
cEMIMessage.control.addressType = 1;
|
|
477
482
|
cEMIMessage.control.hopCount = 6;
|
|
483
|
+
this._incSeqNumber(); // 26/12/2021
|
|
478
484
|
const seqNum = this._getSeqNumber();
|
|
479
485
|
const knxPacketRequest = KNXProtocol.KNXProtocol.newKNXTunnelingRequest(this._channelID, seqNum, cEMIMessage);
|
|
480
|
-
if (!this._options.suppress_ack_ldatareq) this.
|
|
486
|
+
if (!this._options.suppress_ack_ldatareq) this._setTimerWaitingForACK(knxPacketRequest);
|
|
481
487
|
this.send(knxPacketRequest);
|
|
482
488
|
// 06/12/2021 Echo the sent telegram. Last parameter is the echo true/false
|
|
483
489
|
try {
|
|
@@ -546,6 +552,7 @@ class KNXClient extends EventEmitter {
|
|
|
546
552
|
|
|
547
553
|
this._connectionState = STATE.CONNECTING;
|
|
548
554
|
this._numFailedTelegramACK = 0; // 25/12/2021 Reset the failed ACK counter
|
|
555
|
+
this._clearToSend = true; // 26/12/2021 allow to send
|
|
549
556
|
|
|
550
557
|
if (this._timer !== null) clearTimeout(this._timer);
|
|
551
558
|
|
|
@@ -566,7 +573,7 @@ class KNXClient extends EventEmitter {
|
|
|
566
573
|
|
|
567
574
|
}, 1000 * KNXConstants.KNX_CONSTANTS.CONNECT_REQUEST_TIMEOUT);
|
|
568
575
|
this._awaitingResponseType = KNXConstants.KNX_CONSTANTS.CONNECT_RESPONSE;
|
|
569
|
-
this._clientTunnelSeqNumber =
|
|
576
|
+
this._clientTunnelSeqNumber = -1;
|
|
570
577
|
this._sendConnectRequestMessage(new TunnelCRI.TunnelCRI(knxLayer));
|
|
571
578
|
|
|
572
579
|
} else if (this._options.hostProtocol === "TunnelTCP") {
|
|
@@ -584,12 +591,11 @@ class KNXClient extends EventEmitter {
|
|
|
584
591
|
if (conn._options.isSecureKNXEnabled) conn._sendSecureSessionRequestMessage(new TunnelCRI.TunnelCRI(knxLayer));
|
|
585
592
|
});
|
|
586
593
|
|
|
587
|
-
|
|
588
594
|
} else {
|
|
589
595
|
|
|
590
596
|
// Multicast
|
|
591
597
|
this._connectionState = STATE.CONNECTED;
|
|
592
|
-
this._clientTunnelSeqNumber =
|
|
598
|
+
this._clientTunnelSeqNumber = -1;
|
|
593
599
|
try {
|
|
594
600
|
this.emit(KNXClientEvents.connected, this._options);
|
|
595
601
|
} catch (error) {
|
|
@@ -647,6 +653,7 @@ class KNXClient extends EventEmitter {
|
|
|
647
653
|
if (this._timerTimeoutSendDisconnectRequestMessagetimer !== null) clearTimeout(this._timerTimeoutSendDisconnectRequestMessagetimer);
|
|
648
654
|
this._timerTimeoutSendDisconnectRequestMessage = null;
|
|
649
655
|
if (this._timer !== null) clearTimeout(this._timer);
|
|
656
|
+
if (this._tunnelReqTimer !== null) clearTimeout(this._tunnelReqTimer);
|
|
650
657
|
this.stopHeartBeat();
|
|
651
658
|
this._connectionState = STATE.DISCONNECTED;
|
|
652
659
|
try {
|
|
@@ -654,16 +661,9 @@ class KNXClient extends EventEmitter {
|
|
|
654
661
|
} catch (error) {
|
|
655
662
|
}
|
|
656
663
|
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
try {
|
|
660
|
-
clearTimeout(oTimer);
|
|
661
|
-
} catch (error) { }
|
|
662
|
-
}
|
|
663
|
-
this._tunnelReqTimer.clear();
|
|
664
|
-
this._clientTunnelSeqNumber = 0;
|
|
664
|
+
this._clientTunnelSeqNumber = -1;
|
|
665
|
+
this._clearToSend = true; // 26/12/2021 allow to send
|
|
665
666
|
this._channelID = null;
|
|
666
|
-
this._tunnelReqTimer = new Map();
|
|
667
667
|
|
|
668
668
|
// 08/12/2021
|
|
669
669
|
try {
|
|
@@ -682,50 +682,77 @@ class KNXClient extends EventEmitter {
|
|
|
682
682
|
_getSeqNumber() {
|
|
683
683
|
return this._clientTunnelSeqNumber;
|
|
684
684
|
}
|
|
685
|
+
// 26/12/2021 Handle the busy state, for example while waiting for ACK
|
|
686
|
+
_getClearToSend() {
|
|
687
|
+
return (this._clearToSend !== undefined ? this._clearToSend : true);
|
|
688
|
+
}
|
|
689
|
+
|
|
685
690
|
_incSeqNumber(seq) {
|
|
686
|
-
this._clientTunnelSeqNumber
|
|
691
|
+
this._clientTunnelSeqNumber++;
|
|
687
692
|
if (this._clientTunnelSeqNumber > 255) {
|
|
688
693
|
this._clientTunnelSeqNumber = 0;
|
|
689
694
|
}
|
|
690
695
|
return this._clientTunnelSeqNumber;
|
|
691
696
|
}
|
|
692
|
-
|
|
693
697
|
_keyFromCEMIMessage(cEMIMessage) {
|
|
694
698
|
return cEMIMessage.dstAddress.toString();
|
|
695
699
|
}
|
|
696
|
-
|
|
700
|
+
_setTimerWaitingForACK(knxTunnelingRequest) {
|
|
697
701
|
const timeoutErr = new errors.RequestTimeoutError(`RequestTimeoutError seqCounter:${knxTunnelingRequest.seqCounter}, DestAddr:${knxTunnelingRequest.cEMIMessage.dstAddress.toString() || "Non definito"}, AckRequested:${knxTunnelingRequest.cEMIMessage.control.ack}, timed out waiting telegram acknowledge by ${this._options.ipAddr || "No Peer host detected"}`);
|
|
698
|
-
this._tunnelReqTimer
|
|
699
|
-
|
|
702
|
+
if (this._tunnelReqTimer !== null) clearTimeout(this._tunnelReqTimer);
|
|
703
|
+
this._clearToSend = false; // 26/12/2021 stop sending until ACK received
|
|
704
|
+
this._tunnelReqTimer = setTimeout(() => {
|
|
700
705
|
try {
|
|
701
706
|
this._numFailedTelegramACK += 1;
|
|
702
|
-
if (this._numFailedTelegramACK >
|
|
707
|
+
if (this._numFailedTelegramACK > 2) {
|
|
703
708
|
this._numFailedTelegramACK = 0;
|
|
709
|
+
this._clearToSend = true;
|
|
704
710
|
this.emit(KNXClientEvents.error, timeoutErr);
|
|
705
711
|
} else {
|
|
706
|
-
|
|
712
|
+
// 26/12/2021 // If no ACK received, resend the datagram once with the same sequence number
|
|
713
|
+
this._setTimerWaitingForACK(knxTunnelingRequest);
|
|
714
|
+
this.send(knxTunnelingRequest);
|
|
715
|
+
if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.error("KNXClient: _setTimerWaitingForACK: " + (timeoutErr.message || "Undef error") + " no ACK received. Retransmit datagram with seqNumber " + this._getSeqNumber());
|
|
707
716
|
}
|
|
708
|
-
} catch (error) {
|
|
709
|
-
|
|
710
|
-
|
|
717
|
+
} catch (error) { }
|
|
718
|
+
}, KNXConstants.KNX_CONSTANTS.TUNNELING_REQUEST_TIMEOUT * 1000);
|
|
719
|
+
|
|
711
720
|
}
|
|
712
721
|
_processInboundMessage(msg, rinfo) {
|
|
713
722
|
|
|
714
723
|
try {
|
|
715
724
|
|
|
716
725
|
// Composing debug string
|
|
717
|
-
var sProcessInboundLog = "???";
|
|
718
|
-
try {
|
|
719
|
-
sProcessInboundLog = "Data received: " + msg.toString("hex");
|
|
720
|
-
sProcessInboundLog += " srcAddress: " + JSON.stringify(rinfo);
|
|
721
|
-
} catch (error) { }
|
|
722
726
|
try {
|
|
723
|
-
if (this.sysLogger !== undefined && this.sysLogger !== null)
|
|
727
|
+
if (this.sysLogger !== undefined && this.sysLogger !== null) {
|
|
728
|
+
var sProcessInboundLog = "???";
|
|
729
|
+
try {
|
|
730
|
+
sProcessInboundLog = "Data received: " + msg.toString("hex");
|
|
731
|
+
sProcessInboundLog += " srcAddress: " + JSON.stringify(rinfo);
|
|
732
|
+
} catch (error) { }
|
|
733
|
+
this.sysLogger.trace("Received KNX packet: _processInboundMessage, " + sProcessInboundLog + " ChannelID:" + this._channelID || "??" + " Host:" + this._options.ipAddr + ":" + this._options.ipPort);
|
|
734
|
+
}
|
|
724
735
|
} catch (error) { }
|
|
725
736
|
|
|
726
737
|
const { knxHeader, knxMessage } = KNXProtocol.KNXProtocol.parseMessage(msg);
|
|
727
738
|
|
|
739
|
+
// 26/12/2021 ROUTING LOST MESSAGE OR BUSY
|
|
740
|
+
if (knxHeader.service_type === KNXConstants.KNX_CONSTANTS.ROUTING_LOST_MESSAGE) {
|
|
741
|
+
try {
|
|
742
|
+
this.emit(KNXClientEvents.error, new Error('ROUTING_LOST_MESSAGE'));
|
|
743
|
+
this._setDisconnected();
|
|
744
|
+
return;
|
|
745
|
+
} catch (error) { }
|
|
746
|
+
} else if (knxHeader.service_type === KNXConstants.KNX_CONSTANTS.ROUTING_BUSY) {
|
|
747
|
+
try {
|
|
748
|
+
this.emit(KNXClientEvents.error, new Error('ROUTING_BUSY'));
|
|
749
|
+
this._setDisconnected();
|
|
750
|
+
return;
|
|
751
|
+
} catch (error) { }
|
|
752
|
+
}
|
|
753
|
+
|
|
728
754
|
if (knxHeader.service_type === KNXConstants.KNX_CONSTANTS.SEARCH_RESPONSE) {
|
|
755
|
+
|
|
729
756
|
if (this._discovery_timer == null) {
|
|
730
757
|
return;
|
|
731
758
|
}
|
|
@@ -743,8 +770,7 @@ class KNXClient extends EventEmitter {
|
|
|
743
770
|
if (knxConnectResponse.status !== KNXConstants.ConnectionStatus.E_NO_ERROR) {
|
|
744
771
|
try {
|
|
745
772
|
this.emit(KNXClientEvents.error, KNXConnectResponse.KNXConnectResponse.statusToString(knxConnectResponse.status));
|
|
746
|
-
} catch (error) {
|
|
747
|
-
}
|
|
773
|
+
} catch (error) { }
|
|
748
774
|
this._setDisconnected();
|
|
749
775
|
return;
|
|
750
776
|
}
|
|
@@ -799,34 +825,38 @@ class KNXClient extends EventEmitter {
|
|
|
799
825
|
if (knxTunnelingRequest.cEMIMessage.msgCode === CEMIConstants.CEMIConstants.L_DATA_IND) {
|
|
800
826
|
|
|
801
827
|
// Composing debug string
|
|
802
|
-
let sDebugString = "???";
|
|
803
|
-
try {
|
|
804
|
-
sDebugString = "Data: " + JSON.stringify(knxTunnelingRequest.cEMIMessage.npdu);
|
|
805
|
-
sDebugString += " srcAddress: " + knxTunnelingRequest.cEMIMessage.srcAddress.toString();
|
|
806
|
-
sDebugString += " dstAddress: " + knxTunnelingRequest.cEMIMessage.dstAddress.toString();
|
|
807
|
-
} catch (error) { }
|
|
808
|
-
|
|
809
828
|
try {
|
|
810
|
-
if (this.sysLogger !== undefined && this.sysLogger !== null)
|
|
829
|
+
if (this.sysLogger !== undefined && this.sysLogger !== null) {
|
|
830
|
+
let sDebugString = "???";
|
|
831
|
+
try {
|
|
832
|
+
sDebugString = "Data: " + JSON.stringify(knxTunnelingRequest.cEMIMessage.npdu);
|
|
833
|
+
sDebugString += " srcAddress: " + knxTunnelingRequest.cEMIMessage.srcAddress.toString();
|
|
834
|
+
sDebugString += " dstAddress: " + knxTunnelingRequest.cEMIMessage.dstAddress.toString();
|
|
835
|
+
} catch (error) { }
|
|
836
|
+
this.sysLogger.debug("Received KNX packet: TUNNELING: L_DATA_IND, " + sDebugString + " ChannelID:" + this._channelID + " seqCounter:" + knxTunnelingRequest.seqCounter + " Host:" + this._options.ipAddr + ":" + this._options.ipPort);
|
|
837
|
+
}
|
|
811
838
|
} catch (error) { }
|
|
812
839
|
|
|
813
840
|
try {
|
|
814
841
|
this.emit(KNXClientEvents.indication, knxTunnelingRequest, false, msg.toString("hex"));
|
|
815
|
-
} catch (error) {
|
|
816
|
-
}
|
|
842
|
+
} catch (error) { }
|
|
817
843
|
|
|
818
|
-
}
|
|
819
|
-
else if (knxTunnelingRequest.cEMIMessage.msgCode === CEMIConstants.CEMIConstants.L_DATA_CON) {
|
|
844
|
+
} else if (knxTunnelingRequest.cEMIMessage.msgCode === CEMIConstants.CEMIConstants.L_DATA_CON) {
|
|
820
845
|
|
|
821
846
|
try {
|
|
822
847
|
if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.debug("Received KNX packet: TUNNELING: L_DATA_CON, ChannelID:" + this._channelID + " seqCounter:" + knxTunnelingRequest.seqCounter + " Host:" + this._options.ipAddr + ":" + this._options.ipPort);
|
|
823
848
|
} catch (error) { }
|
|
824
849
|
|
|
825
850
|
}
|
|
851
|
+
|
|
852
|
+
// 26/12/2021 send the ACK if the server requestet that
|
|
853
|
+
// Then REMOVED, because some interfaces sets the "ack request" always to 0 even if it needs ack.
|
|
854
|
+
//if (knxMessage.cEMIMessage.control.ack){
|
|
826
855
|
const knxTunnelAck = KNXProtocol.KNXProtocol.newKNXTunnelingACK(knxTunnelingRequest.channelID, knxTunnelingRequest.seqCounter, KNXConstants.KNX_CONSTANTS.E_NO_ERROR);
|
|
827
856
|
this.send(knxTunnelAck);
|
|
828
|
-
|
|
829
|
-
|
|
857
|
+
//}
|
|
858
|
+
|
|
859
|
+
} else if (knxHeader.service_type === KNXConstants.KNX_CONSTANTS.TUNNELING_ACK) {
|
|
830
860
|
//const knxTunnelingAck = lodash.cloneDeep(knxMessage);
|
|
831
861
|
const knxTunnelingAck = knxMessage;
|
|
832
862
|
if (knxTunnelingAck.channelID !== this._channelID) {
|
|
@@ -837,22 +867,17 @@ class KNXClient extends EventEmitter {
|
|
|
837
867
|
if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.debug("Received KNX packet: TUNNELING: TUNNELING_ACK, ChannelID:" + this._channelID + " seqCounter:" + knxTunnelingAck.seqCounter + " Host:" + this._options.ipAddr + ":" + this._options.ipPort);
|
|
838
868
|
} catch (error) { }
|
|
839
869
|
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
this.
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
}
|
|
852
|
-
else {
|
|
853
|
-
|
|
854
|
-
// Avoid warning if the KNXEngine is set to ignore ACK's telegrams
|
|
855
|
-
if (!this._options.suppress_ack_ldatareq) {
|
|
870
|
+
// Check the received ACK sequence number
|
|
871
|
+
if (!this._options.suppress_ack_ldatareq) {
|
|
872
|
+
if (knxTunnelingAck.seqCounter === this._getSeqNumber()) {
|
|
873
|
+
if (this._tunnelReqTimer !== null) clearTimeout(this._tunnelReqTimer);
|
|
874
|
+
this._numFailedTelegramACK = 0; // 25/12/2021 clear the current ACK failed telegram number
|
|
875
|
+
this._clearToSend = true; // I'm ready to send a new datagram now
|
|
876
|
+
try {
|
|
877
|
+
if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.debug("Received KNX packet: TUNNELING: DELETED_TUNNELING_ACK FROM PENDING ACK's, ChannelID:" + this._channelID + " seqCounter:" + knxTunnelingAck.seqCounter + " Host:" + this._options.ipAddr + ":" + this._options.ipPort);
|
|
878
|
+
} catch (error) { }
|
|
879
|
+
} else {
|
|
880
|
+
// Inform that i received an ACK with an unexpected sequence number
|
|
856
881
|
try {
|
|
857
882
|
if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.error("Received KNX packet: TUNNELING: Unexpected Tunnel Ack with seqCounter = " + knxTunnelingAck.seqCounter);
|
|
858
883
|
} catch (error) { }
|
|
@@ -867,15 +892,16 @@ class KNXClient extends EventEmitter {
|
|
|
867
892
|
if (knxRoutingInd.cEMIMessage.msgCode === CEMIConstants.CEMIConstants.L_DATA_IND) {
|
|
868
893
|
|
|
869
894
|
// Composing debug string
|
|
870
|
-
let sDebugString = "???";
|
|
871
|
-
try {
|
|
872
|
-
sDebugString = "Data: " + JSON.stringify(knxRoutingInd.cEMIMessage.npdu);
|
|
873
|
-
sDebugString += " srcAddress: " + knxRoutingInd.cEMIMessage.srcAddress.toString();
|
|
874
|
-
sDebugString += " dstAddress: " + knxRoutingInd.cEMIMessage.dstAddress.toString();
|
|
875
|
-
} catch (error) { }
|
|
876
|
-
|
|
877
895
|
try {
|
|
878
|
-
if (this.sysLogger !== undefined && this.sysLogger !== null)
|
|
896
|
+
if (this.sysLogger !== undefined && this.sysLogger !== null) {
|
|
897
|
+
let sDebugString = "???";
|
|
898
|
+
try {
|
|
899
|
+
sDebugString = "Data: " + JSON.stringify(knxRoutingInd.cEMIMessage.npdu);
|
|
900
|
+
sDebugString += " srcAddress: " + knxRoutingInd.cEMIMessage.srcAddress.toString();
|
|
901
|
+
sDebugString += " dstAddress: " + knxRoutingInd.cEMIMessage.dstAddress.toString();
|
|
902
|
+
} catch (error) { }
|
|
903
|
+
this.sysLogger.debug("Received KNX packet: ROUTING: L_DATA_IND, " + sDebugString + " Host:" + this._options.ipAddr + ":" + this._options.ipPort);
|
|
904
|
+
}
|
|
879
905
|
} catch (error) { }
|
|
880
906
|
|
|
881
907
|
try {
|
|
@@ -932,6 +958,7 @@ class KNXClient extends EventEmitter {
|
|
|
932
958
|
} catch (error) { }
|
|
933
959
|
try {
|
|
934
960
|
this.emit(KNXClientEvents.error, e);
|
|
961
|
+
this._setDisconnected();
|
|
935
962
|
} catch (error) { }
|
|
936
963
|
|
|
937
964
|
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.KNXConnectResponse = void 0;
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
class KNXConnectResponse extends
|
|
4
|
+
const KNXConstants = require("./KNXConstants");
|
|
5
|
+
const KNXPacket = require("./KNXPacket");
|
|
6
|
+
const HPAI = require("./HPAI");
|
|
7
|
+
const CRD = require("./CRD");
|
|
8
|
+
class KNXConnectResponse extends KNXPacket.KNXPacket {
|
|
9
9
|
constructor(channelID, status, hpai, crd) {
|
|
10
|
-
super(
|
|
10
|
+
super(KNXConstants.KNX_CONSTANTS.CONNECT_RESPONSE, hpai == null ? 2 : 2 + hpai.length + crd.length);
|
|
11
11
|
this.channelID = channelID;
|
|
12
12
|
this.status = status;
|
|
13
13
|
this.hpai = hpai;
|
|
@@ -21,27 +21,27 @@ class KNXConnectResponse extends KNXPacket_1.KNXPacket {
|
|
|
21
21
|
const status = buffer.readUInt8(offset++);
|
|
22
22
|
let hpai, crd;
|
|
23
23
|
if (offset < buffer.length) {
|
|
24
|
-
hpai =
|
|
24
|
+
hpai = HPAI.HPAI.createFromBuffer(buffer, offset);
|
|
25
25
|
offset += hpai.length;
|
|
26
|
-
crd =
|
|
26
|
+
crd = CRD.CRD.createFromBuffer(buffer, offset);
|
|
27
27
|
}
|
|
28
28
|
return new KNXConnectResponse(channelID, status, hpai, crd);
|
|
29
29
|
}
|
|
30
30
|
static statusToString(status) {
|
|
31
31
|
switch (status) {
|
|
32
|
-
case
|
|
32
|
+
case KNXConstants.KNX_CONSTANTS.E_SEQUENCE_NUMBER:
|
|
33
33
|
return 'Invalid Sequence Number';
|
|
34
|
-
case
|
|
34
|
+
case KNXConstants.KNX_CONSTANTS.E_CONNECTION_TYPE:
|
|
35
35
|
return 'Invalid Connection Type';
|
|
36
|
-
case
|
|
36
|
+
case KNXConstants.KNX_CONSTANTS.E_CONNECTION_OPTION:
|
|
37
37
|
return 'Invalid Connection Option';
|
|
38
|
-
case
|
|
38
|
+
case KNXConstants.KNX_CONSTANTS.E_NO_MORE_CONNECTIONS:
|
|
39
39
|
return 'No More Connections';
|
|
40
|
-
case
|
|
40
|
+
case KNXConstants.KNX_CONSTANTS.E_DATA_CONNECTION:
|
|
41
41
|
return 'Invalid Data Connection';
|
|
42
|
-
case
|
|
42
|
+
case KNXConstants.KNX_CONSTANTS.E_KNX_CONNECTION:
|
|
43
43
|
return 'Invalid KNX Connection';
|
|
44
|
-
case
|
|
44
|
+
case KNXConstants.KNX_CONSTANTS.E_TUNNELING_LAYER:
|
|
45
45
|
return 'Invalid Tunneling Layer';
|
|
46
46
|
default:
|
|
47
47
|
return `Unknown error ${status}`;
|
|
@@ -18,6 +18,7 @@ exports.KNX_CONSTANTS = {
|
|
|
18
18
|
DEVICE_CONFIGURATION_ACK: 0x0311,
|
|
19
19
|
TUNNELING_REQUEST: 0x0420,
|
|
20
20
|
TUNNELING_ACK: 0x0421,
|
|
21
|
+
ROUTING_BUSY: 0x0532,
|
|
21
22
|
ROUTING_INDICATION: 0x0530,
|
|
22
23
|
ROUTING_LOST_MESSAGE: 0x0531,
|
|
23
24
|
DEVICE_MGMT_CONNECTION: 0x03,
|
|
@@ -61,15 +62,15 @@ exports.KNX_CONSTANTS = {
|
|
|
61
62
|
KNX_IP: '224.0.23.12',
|
|
62
63
|
IPV4_ADDRESS_LENGTH: 4,
|
|
63
64
|
// Search for KNX IP Secure Unicasts Setups
|
|
64
|
-
SECURE_SEARCH_REQUEST
|
|
65
|
-
SECURE_SEARCH_RESPONSE
|
|
65
|
+
SECURE_SEARCH_REQUEST: 0x20b,
|
|
66
|
+
SECURE_SEARCH_RESPONSE: 0x20c,
|
|
66
67
|
// KNX IP Secure
|
|
67
|
-
SECURE_WRAPPER
|
|
68
|
-
SECURE_SESSION_REQUEST
|
|
69
|
-
SECURE_SESSION_RESPONSE
|
|
70
|
-
SECURE_SESSION_AUTH
|
|
71
|
-
SECURE_SESSION_STATUS
|
|
72
|
-
SECURE_GROUP_SYNC
|
|
68
|
+
SECURE_WRAPPER: 0x0950,
|
|
69
|
+
SECURE_SESSION_REQUEST: 0x0951,
|
|
70
|
+
SECURE_SESSION_RESPONSE: 0x0952,
|
|
71
|
+
SECURE_SESSION_AUTH: 0x0953,
|
|
72
|
+
SECURE_SESSION_STATUS: 0x0954,
|
|
73
|
+
SECURE_GROUP_SYNC: 0x0955
|
|
73
74
|
};
|
|
74
75
|
|
|
75
76
|
var ConnectionStatus;
|
|
@@ -801,7 +801,7 @@ return msg;`, "helplink": "https://github.com/Supergiovane/node-red-contrib-knx-
|
|
|
801
801
|
//function handleBusEvents(_evt, _src, _dest, _rawValue, _datagram, _isRepeated) {
|
|
802
802
|
function handleBusEvents(_datagram, _echoed, _CEMI) {
|
|
803
803
|
|
|
804
|
-
|
|
804
|
+
|
|
805
805
|
// _rawValue
|
|
806
806
|
try {
|
|
807
807
|
_rawValue = _datagram.cEMIMessage.npdu.dataValue;
|
|
@@ -835,7 +835,7 @@ return msg;`, "helplink": "https://github.com/Supergiovane/node-red-contrib-knx-
|
|
|
835
835
|
// I'm receiving a telegram from the BUS
|
|
836
836
|
try {
|
|
837
837
|
var iStart = _datagram._header._headerLength; //+ 4;
|
|
838
|
-
_cemiETS = _CEMI.substring(iStart*2
|
|
838
|
+
_cemiETS = _CEMI.substring(iStart * 2);
|
|
839
839
|
//_cemiETS = datagram.cEMIMessage.srcAddress.toBuffer().toString("hex") + _datagram.cEMIMessage.dstAddress.toBuffer().toString("hex") + "01" + _datagram.cEMIMessage.npdu._tpci.toString(16)
|
|
840
840
|
} catch (error) { }
|
|
841
841
|
|
|
@@ -1087,7 +1087,6 @@ return msg;`, "helplink": "https://github.com/Supergiovane/node-red-contrib-knx-
|
|
|
1087
1087
|
|
|
1088
1088
|
function handleTelegramQueue() {
|
|
1089
1089
|
if (node.knxConnection !== null || node.host.toUpperCase() === "EMULATE") {
|
|
1090
|
-
//console.log("BANANA handleTelegramQueueSONO BLOCCATO ? ",node.lockHandleTelegramQueue, "CONNECTED ? ", node.linkStatus )
|
|
1091
1090
|
if (node.lockHandleTelegramQueue === true) return; // Exits if the funtion is busy
|
|
1092
1091
|
node.lockHandleTelegramQueue = true; // Lock the function. It cannot be called again until finished.
|
|
1093
1092
|
|
|
@@ -1098,6 +1097,15 @@ return msg;`, "helplink": "https://github.com/Supergiovane/node-red-contrib-knx-
|
|
|
1098
1097
|
return;
|
|
1099
1098
|
}
|
|
1100
1099
|
|
|
1100
|
+
// 26/12/2021 If the KNXEngine is busy waiting for telegram's ACK, exit
|
|
1101
|
+
if (!node.knxConnection._getClearToSend()) {
|
|
1102
|
+
node.lockHandleTelegramQueue = false; // Unlock the function
|
|
1103
|
+
if (node.telegramsQueue.length > 0) {
|
|
1104
|
+
if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.warn("knxUltimate-config: handleTelegramQueue: the KNXEngine is busy or is waiting for a telegram ACK with seqNumner " + node.knxConnection._getSeqNumber() + ". Delay handling queue.");
|
|
1105
|
+
}
|
|
1106
|
+
return;
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1101
1109
|
// Retrieving oKNXMessage { grpaddr, payload,dpt,outputtype (write or response),nodecallerid (node caller)}. 06/03/2020 "Read" request does have the lower priority in the queue, so firstly, i search for "read" telegrams and i move it on the top of the queue pile.
|
|
1102
1110
|
var aTelegramsFiltered = [];
|
|
1103
1111
|
aTelegramsFiltered = node.telegramsQueue.filter(a => a.outputtype !== "read");
|
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.14",
|
|
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
|
"fs": "0.0.1-security",
|