node-red-contrib-knx-ultimate 1.3.13 → 1.3.18

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,28 @@
4
4
 
5
5
  <br/>
6
6
  <p>
7
+ <b>Version 1.3.18</b> - Januar 2022<br/>
8
+ - FIX: Scene Controller: fixed an issue preventing the node to work if you haven't set the RECALL and SAVE group addresses.<br/>
9
+ - WIKI: updated the samples in the scene controller node.<br/>
10
+ </p>
11
+ <p>
12
+ <b>Version 1.3.16</b> - Januar 2022<br/>
13
+ - KNXEngine: there are some weird KNX gateways out there, either sending malformed header or CEMI messages. Now KNX-Ultimate will simply ignore these bad messages. Prior, it was disconnecting.<br/>
14
+ - KNXEngine: KNX-Secure packets are silently discarded for now, until KNX Secure will be ready.<br/>
15
+ - KNXEngine: added more logs to for troubleshooting pourposes.<br/>
16
+ </p>
17
+ <p>
18
+ <b>Version 1.3.15</b> - Januar 2022<br/>
19
+ - KNXEngine: better handling of disconnection in UDP mode, allowing very old grandpa KNX/IP interfaces enough time to understand what's happening, avoiding it to go crazy.<br/>
20
+ - KNXEngine: corrected Curve Crypto in KNX-Secure (KNX Secure is not enabled yet!).<br/>
21
+ </p>
22
+ <p>
23
+ <b>Version 1.3.14</b> - 26 December 2021<br/>
24
+ - KNXEngine: ACK management: the not acknowledged message will be re-transmitted once, then the connection will be dropped, as per KNX specs.<br/>
25
+ - KNXEngine: ACK management: the telegram's queue to be sent to the KNX BUS will be paused during the ACK waiting.<br/>
26
+ - KNXEngine: Routing: now the routing_busy and routing_lost_messages telegrams sent by the KNX/IP Router are handled.<br/>
27
+ </p>
28
+ <p>
7
29
  <b>Version 1.3.13</b> - 25 December 2021<br/>
8
30
  - 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
31
  - KNXEngine: at disconnection, delete all pending ACK requests timer.<br/>
@@ -1,3 +1,5 @@
1
+ // Made with love by Supergiovane
2
+
1
3
  "use strict";
2
4
 
3
5
 
@@ -17,7 +19,7 @@ const ipAddressHelper = require("./util/ipAddressHelper");
17
19
  const KNXAddress = require("./protocol/KNXAddress").KNXAddress;
18
20
  const KNXDataBuffer = require("./protocol/KNXDataBuffer").KNXDataBuffer;
19
21
  const DPTLib = require('./dptlib');
20
- const secureKeyring = require("./KNXsecureKeyring.js");
22
+ const KNXsecureKeyring = require("./KNXsecureKeyring.js");
21
23
  //const lodash = require("lodash");
22
24
 
23
25
  var STATE;
@@ -74,7 +76,8 @@ const optionsDefaults = {
74
76
  loglevel: "info",
75
77
  localEchoInTunneling: true,
76
78
  localIPAddress: "",
77
- interface: ""
79
+ interface: "",
80
+ jKNXSecureKeyring: {}
78
81
  };
79
82
 
80
83
  class KNXClient extends EventEmitter {
@@ -86,13 +89,13 @@ class KNXClient extends EventEmitter {
86
89
  }
87
90
 
88
91
  super();
89
- this._clientTunnelSeqNumber = 0;
92
+ this._clientTunnelSeqNumber = -1;
90
93
  this._options = options;//Object.assign(optionsDefaults, options);
91
94
  this._options.connectionKeepAliveTimeout = KNXConstants.KNX_CONSTANTS.CONNECTION_ALIVE_TIME,
92
95
  this._localPort = null;
93
96
  this._peerHost = this._options.ipAddr;
94
97
  this._peerPort = this._options.ipPort;
95
- this._timer = null;
98
+ this._connectionTimeoutTimer = null;
96
99
  this._heartbeatFailures = 0;
97
100
  this.max_HeartbeatFailures = 3;
98
101
  this._heartbeatTimer = null;
@@ -101,6 +104,7 @@ class KNXClient extends EventEmitter {
101
104
  this._processInboundMessage = this._processInboundMessage.bind(this);
102
105
  this._clientSocket = null;
103
106
  this.sysLogger = null;
107
+ this.jKNXSecureKeyring = this._options.jKNXSecureKeyring; // 28/12/2021 Contains the Keyring JSON object
104
108
  try {
105
109
  this.sysLogger = require("./KnxLog.js").get({ loglevel: this._options.loglevel }); // 08/04/2021 new logger to adhere to the loglevel selected in the config-window
106
110
  } catch (error) {
@@ -169,17 +173,17 @@ class KNXClient extends EventEmitter {
169
173
  });
170
174
  }
171
175
 
172
- this._clientTunnelSeqNumber = 0;
176
+ this._clientTunnelSeqNumber = -1;
173
177
  this._channelID = null;
174
178
  this._connectionState = STATE.DISCONNECTED;
175
- this._tunnelReqTimer = new Map();
179
+ this._tunnelReqTimer = null;
176
180
  this._numFailedTelegramACK = 0; // 25/12/2021 Keep count of the failed tunnelig ACK telegrams
177
181
 
178
182
  }
179
183
  get channelID() {
180
184
  return this._channelID;
181
185
  }
182
- // Transform the plain value "data" into a KNXDataBuffer. The datapoints without "null" are SixBits
186
+ // 16/12/2021 Transform the plain value "data" into a KNXDataBuffer. The datapoints without "null" are SixBits
183
187
  // dataPointsSixBits = {
184
188
  // DPT1,
185
189
  // DPT2,
@@ -240,6 +244,7 @@ class KNXClient extends EventEmitter {
240
244
  });
241
245
  }
242
246
  send(knxPacket) {
247
+
243
248
  // Logging
244
249
  if (this.sysLogger !== undefined && this.sysLogger !== null) {
245
250
  try {
@@ -279,7 +284,7 @@ class KNXClient extends EventEmitter {
279
284
  } catch (error) {
280
285
  if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.error("Sending KNX packet: Send UDP Catch error: " + error.message + " " + typeof (knxPacket) + " seqCounter:" + knxPacket.seqCounter);
281
286
  try {
282
- //this.emit(KNXClientEvents.error, error);
287
+ this.emit(KNXClientEvents.error, error);
283
288
  } catch (error) {
284
289
  }
285
290
 
@@ -292,15 +297,12 @@ class KNXClient extends EventEmitter {
292
297
  if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.error("Sending KNX packet: Send TCP sending error: " + err.message || "Undef error");
293
298
  this.emit(KNXClientEvents.error, err);
294
299
  }
295
-
296
300
  });
297
301
  } catch (error) {
298
302
  if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.error("Sending KNX packet: Send TCP Catch error: " + error.message || "Undef error");
299
303
  try {
300
- //this.emit(KNXClientEvents.error, error);
301
- } catch (error) {
302
- }
303
-
304
+ this.emit(KNXClientEvents.error, error);
305
+ } catch (error) { }
304
306
  }
305
307
  }
306
308
  }
@@ -342,9 +344,11 @@ class KNXClient extends EventEmitter {
342
344
  cEMIMessage.control.priority = 3;
343
345
  cEMIMessage.control.addressType = 1;
344
346
  cEMIMessage.control.hopCount = 6;
347
+ this._incSeqNumber(); // 26/12/2021
345
348
  const seqNum = this._getSeqNumber();
346
349
  const knxPacketRequest = KNXProtocol.KNXProtocol.newKNXTunnelingRequest(this._channelID, seqNum, cEMIMessage);
347
- if (!this._options.suppress_ack_ldatareq) this._setTimerAndCallback(knxPacketRequest);
350
+ if (!this._options.suppress_ack_ldatareq) this._setTimerWaitingForACK(knxPacketRequest);
351
+ //if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.error("this._tunnelReqTimer "+ this._tunnelReqTimer.size);
348
352
  this.send(knxPacketRequest);
349
353
  // 06/12/2021 Echo the sent telegram. Last parameter is the echo true/false
350
354
  try {
@@ -386,9 +390,10 @@ class KNXClient extends EventEmitter {
386
390
  cEMIMessage.control.priority = 3;
387
391
  cEMIMessage.control.addressType = 1;
388
392
  cEMIMessage.control.hopCount = 6;
393
+ this._incSeqNumber(); // 26/12/2021
389
394
  const seqNum = this._getSeqNumber();
390
395
  const knxPacketRequest = KNXProtocol.KNXProtocol.newKNXTunnelingRequest(this._channelID, seqNum, cEMIMessage);
391
- if (!this._options.suppress_ack_ldatareq) this._setTimerAndCallback(knxPacketRequest);
396
+ if (!this._options.suppress_ack_ldatareq) this._setTimerWaitingForACK(knxPacketRequest);
392
397
  this.send(knxPacketRequest);
393
398
  // 06/12/2021 Echo the sent telegram. Last parameter is the echo true/false
394
399
  try {
@@ -427,9 +432,10 @@ class KNXClient extends EventEmitter {
427
432
  cEMIMessage.control.priority = 3;
428
433
  cEMIMessage.control.addressType = 1;
429
434
  cEMIMessage.control.hopCount = 6;
435
+ this._incSeqNumber(); // 26/12/2021
430
436
  const seqNum = this._getSeqNumber();
431
437
  const knxPacketRequest = KNXProtocol.KNXProtocol.newKNXTunnelingRequest(this._channelID, seqNum, cEMIMessage);
432
- if (!this._options.suppress_ack_ldatareq) this._setTimerAndCallback(knxPacketRequest);
438
+ if (!this._options.suppress_ack_ldatareq) this._setTimerWaitingForACK(knxPacketRequest);
433
439
  this.send(knxPacketRequest);
434
440
  // 06/12/2021 Echo the sent telegram. Last parameter is the echo true/false
435
441
  try {
@@ -475,9 +481,10 @@ class KNXClient extends EventEmitter {
475
481
  cEMIMessage.control.priority = 3;
476
482
  cEMIMessage.control.addressType = 1;
477
483
  cEMIMessage.control.hopCount = 6;
484
+ this._incSeqNumber(); // 26/12/2021
478
485
  const seqNum = this._getSeqNumber();
479
486
  const knxPacketRequest = KNXProtocol.KNXProtocol.newKNXTunnelingRequest(this._channelID, seqNum, cEMIMessage);
480
- if (!this._options.suppress_ack_ldatareq) this._setTimerAndCallback(knxPacketRequest);
487
+ if (!this._options.suppress_ack_ldatareq) this._setTimerWaitingForACK(knxPacketRequest);
481
488
  this.send(knxPacketRequest);
482
489
  // 06/12/2021 Echo the sent telegram. Last parameter is the echo true/false
483
490
  try {
@@ -523,8 +530,8 @@ class KNXClient extends EventEmitter {
523
530
  if (this._clientSocket == null) {
524
531
  throw new Error('No client socket defined');
525
532
  }
526
- this._timer = setTimeout(() => {
527
- this._timer = null;
533
+ this._connectionTimeoutTimer = setTimeout(() => {
534
+ this._connectionTimeoutTimer = null;
528
535
  }, 1000 * KNXConstants.KNX_CONSTANTS.DEVICE_CONFIGURATION_REQUEST_TIMEOUT);
529
536
  this._awaitingResponseType = KNXConstants.KNX_CONSTANTS.DESCRIPTION_RESPONSE;
530
537
  this._sendDescriptionRequestMessage(host, port);
@@ -546,8 +553,9 @@ class KNXClient extends EventEmitter {
546
553
 
547
554
  this._connectionState = STATE.CONNECTING;
548
555
  this._numFailedTelegramACK = 0; // 25/12/2021 Reset the failed ACK counter
556
+ this._clearToSend = true; // 26/12/2021 allow to send
549
557
 
550
- if (this._timer !== null) clearTimeout(this._timer);
558
+ if (this._connectionTimeoutTimer !== null) clearTimeout(this._connectionTimeoutTimer);
551
559
 
552
560
  // Emit connecting
553
561
  this.emit(KNXClientEvents.connecting, this._options);
@@ -557,8 +565,8 @@ class KNXClient extends EventEmitter {
557
565
 
558
566
  // Unicast, need to explicitly create the connection
559
567
  const timeoutError = new Error(`Connection timeout to ${this._peerHost}:${this._peerPort}`);
560
- this._timer = setTimeout(() => {
561
- this._timer = null;
568
+ this._connectionTimeoutTimer = setTimeout(() => {
569
+ this._connectionTimeoutTimer = null;
562
570
  try {
563
571
  this.emit(KNXClientEvents.error, timeoutError);
564
572
  } catch (error) {
@@ -566,7 +574,7 @@ class KNXClient extends EventEmitter {
566
574
 
567
575
  }, 1000 * KNXConstants.KNX_CONSTANTS.CONNECT_REQUEST_TIMEOUT);
568
576
  this._awaitingResponseType = KNXConstants.KNX_CONSTANTS.CONNECT_RESPONSE;
569
- this._clientTunnelSeqNumber = 0;
577
+ this._clientTunnelSeqNumber = -1;
570
578
  this._sendConnectRequestMessage(new TunnelCRI.TunnelCRI(knxLayer));
571
579
 
572
580
  } else if (this._options.hostProtocol === "TunnelTCP") {
@@ -581,15 +589,14 @@ class KNXClient extends EventEmitter {
581
589
  // }, 1000 * KNXConstants.KNX_CONSTANTS.CONNECT_REQUEST_TIMEOUT);
582
590
  conn._awaitingResponseType = KNXConstants.KNX_CONSTANTS.CONNECT_RESPONSE;
583
591
  conn._clientTunnelSeqNumber = 0;
584
- if (conn._options.isSecureKNXEnabled) conn._sendSecureSessionRequestMessage(new TunnelCRI.TunnelCRI(knxLayer));
592
+ if (conn._options.isSecureKNXEnabled) conn._sendSecureSessionRequestMessage(new TunnelCRI.TunnelCRI(knxLayer), conn.jKNXSecureKeyring);
585
593
  });
586
594
 
587
-
588
595
  } else {
589
596
 
590
597
  // Multicast
591
598
  this._connectionState = STATE.CONNECTED;
592
- this._clientTunnelSeqNumber = 0;
599
+ this._clientTunnelSeqNumber = -1;
593
600
  try {
594
601
  this.emit(KNXClientEvents.connected, this._options);
595
602
  } catch (error) {
@@ -607,7 +614,7 @@ class KNXClient extends EventEmitter {
607
614
  this._heartbeatTimer = setTimeout(() => {
608
615
  this._heartbeatTimer = null;
609
616
  try {
610
- console.log("BANANA OH! getConnectionStatus Timeout", this._heartbeatFailures, "su", this.max_HeartbeatFailures);
617
+ if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.error("KNXClient: getConnectionStatus Timeout " + this._heartbeatFailures + " out of " + this.max_HeartbeatFailures);
611
618
  //this.emit(KNXClientEvents.error, timeoutError);
612
619
  } catch (error) {
613
620
  }
@@ -631,14 +638,11 @@ class KNXClient extends EventEmitter {
631
638
  }
632
639
  this.stopHeartBeat();
633
640
  this._connectionState = STATE.DISCONNECTING;
634
- this._timer = setTimeout(() => {
635
- this._timer = null;
636
- }, 1000 * KNXConstants.KNX_CONSTANTS.CONNECT_REQUEST_TIMEOUT);
637
641
  this._awaitingResponseType = KNXConstants.KNX_CONSTANTS.DISCONNECT_RESPONSE;
638
642
  this._sendDisconnectRequestMessage(this._channelID);
639
- this._timerTimeoutSendDisconnectRequestMessage = setTimeout(() => {
640
- this._setDisconnected();
641
- }, 1000 * KNXConstants.KNX_CONSTANTS.CONNECT_REQUEST_TIMEOUT);
643
+ //this._timerTimeoutSendDisconnectRequestMessage = setTimeout(() => {
644
+ this._setDisconnected();
645
+ //}, 1000 * KNXConstants.KNX_CONSTANTS.CONNECT_REQUEST_TIMEOUT);
642
646
  }
643
647
  isConnected() {
644
648
  return this._connectionState === STATE.CONNECTED;
@@ -646,7 +650,8 @@ class KNXClient extends EventEmitter {
646
650
  _setDisconnected() {
647
651
  if (this._timerTimeoutSendDisconnectRequestMessagetimer !== null) clearTimeout(this._timerTimeoutSendDisconnectRequestMessagetimer);
648
652
  this._timerTimeoutSendDisconnectRequestMessage = null;
649
- if (this._timer !== null) clearTimeout(this._timer);
653
+ if (this._connectionTimeoutTimer !== null) clearTimeout(this._connectionTimeoutTimer);
654
+ if (this._tunnelReqTimer !== null) clearTimeout(this._tunnelReqTimer);
650
655
  this.stopHeartBeat();
651
656
  this._connectionState = STATE.DISCONNECTED;
652
657
  try {
@@ -654,16 +659,9 @@ class KNXClient extends EventEmitter {
654
659
  } catch (error) {
655
660
  }
656
661
 
657
- // 25/12/2021 Stops all awaiting ACK timers
658
- for (const [key, oTimer] of this._tunnelReqTimer.entries()) {
659
- try {
660
- clearTimeout(oTimer);
661
- } catch (error) { }
662
- }
663
- this._tunnelReqTimer.clear();
664
- this._clientTunnelSeqNumber = 0;
662
+ this._clientTunnelSeqNumber = -1;
663
+ this._clearToSend = true; // 26/12/2021 allow to send
665
664
  this._channelID = null;
666
- this._tunnelReqTimer = new Map();
667
665
 
668
666
  // 08/12/2021
669
667
  try {
@@ -682,50 +680,79 @@ class KNXClient extends EventEmitter {
682
680
  _getSeqNumber() {
683
681
  return this._clientTunnelSeqNumber;
684
682
  }
683
+ // 26/12/2021 Handle the busy state, for example while waiting for ACK
684
+ _getClearToSend() {
685
+ return (this._clearToSend !== undefined ? this._clearToSend : true);
686
+ }
687
+
685
688
  _incSeqNumber(seq) {
686
- this._clientTunnelSeqNumber = seq ? seq + 1 : this._clientTunnelSeqNumber + 1;
689
+ this._clientTunnelSeqNumber++;
687
690
  if (this._clientTunnelSeqNumber > 255) {
688
691
  this._clientTunnelSeqNumber = 0;
689
692
  }
690
693
  return this._clientTunnelSeqNumber;
691
694
  }
692
-
693
- _keyFromCEMIMessage(cEMIMessage) {
694
- return cEMIMessage.dstAddress.toString();
695
- }
696
- _setTimerAndCallback(knxTunnelingRequest) {
695
+ // _keyFromCEMIMessage(cEMIMessage) {
696
+ // return cEMIMessage.dstAddress.toString();
697
+ // }
698
+ _setTimerWaitingForACK(knxTunnelingRequest) {
697
699
  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.set(knxTunnelingRequest.seqCounter, setTimeout(() => {
699
- this._tunnelReqTimer.delete(knxTunnelingRequest.seqCounter);
700
+ if (this._tunnelReqTimer !== null) clearTimeout(this._tunnelReqTimer);
701
+ this._clearToSend = false; // 26/12/2021 stop sending until ACK received
702
+ this._tunnelReqTimer = setTimeout(() => {
700
703
  try {
701
704
  this._numFailedTelegramACK += 1;
702
- if (this._numFailedTelegramACK > 3) {
705
+ if (this._numFailedTelegramACK > 2) {
703
706
  this._numFailedTelegramACK = 0;
707
+ this._clearToSend = true;
704
708
  this.emit(KNXClientEvents.error, timeoutErr);
705
709
  } else {
706
- if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.error("KNXClient: _setTimerAndCallback: " + (timeoutErr.message || "Undef error") + " " + this._numFailedTelegramACK + " of 3 times before emitting error.");
710
+ // 26/12/2021 // If no ACK received, resend the datagram once with the same sequence number
711
+ this._setTimerWaitingForACK(knxTunnelingRequest);
712
+ this.send(knxTunnelingRequest);
713
+ 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
714
  }
708
- } catch (error) {
709
- }
710
- }, KNXConstants.KNX_CONSTANTS.TUNNELING_REQUEST_TIMEOUT * 1000));
715
+ } catch (error) { }
716
+ }, KNXConstants.KNX_CONSTANTS.TUNNELING_REQUEST_TIMEOUT * 1000);
717
+
711
718
  }
712
719
  _processInboundMessage(msg, rinfo) {
713
720
 
714
721
  try {
715
-
716
722
  // Composing debug string
717
- var sProcessInboundLog = "???";
718
723
  try {
719
- sProcessInboundLog = "Data received: " + msg.toString("hex");
720
- sProcessInboundLog += " srcAddress: " + JSON.stringify(rinfo);
721
- } catch (error) { }
722
- try {
723
- if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.trace("Received KNX packet: _processInboundMessage, " + sProcessInboundLog + " ChannelID:" + this._channelID || "??" + " Host:" + this._options.ipAddr + ":" + this._options.ipPort);
724
+ if (this.sysLogger !== undefined && this.sysLogger !== null) {
725
+ var sProcessInboundLog = "???";
726
+ try {
727
+ sProcessInboundLog = "Data received: " + msg.toString("hex");
728
+ sProcessInboundLog += " srcAddress: " + JSON.stringify(rinfo);
729
+ } catch (error) { }
730
+ this.sysLogger.trace("Received KNX packet: _processInboundMessage, " + sProcessInboundLog + " ChannelID:" + this._channelID || "??" + " Host:" + this._options.ipAddr + ":" + this._options.ipPort);
731
+ }
724
732
  } catch (error) { }
725
733
 
734
+ // BUGFIXING https://github.com/Supergiovane/node-red-contrib-knx-ultimate/issues/162
735
+ //msg = Buffer.from("0610053000102900b06011fe11150080","hex");
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
  }
@@ -737,14 +764,13 @@ class KNXClient extends EventEmitter {
737
764
  }
738
765
  else if (knxHeader.service_type === KNXConstants.KNX_CONSTANTS.CONNECT_RESPONSE) {
739
766
  if (this._connectionState === STATE.CONNECTING) {
740
- if (this._timer !== null) clearTimeout(this._timer);
741
- this._timer = null;
767
+ if (this._connectionTimeoutTimer !== null) clearTimeout(this._connectionTimeoutTimer);
768
+ this._connectionTimeoutTimer = null;
742
769
  const knxConnectResponse = knxMessage;
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
828
  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
- try {
810
- if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.debug("Received KNX packet: TUNNELING: L_DATA_IND, " + sDebugString + " ChannelID:" + this._channelID + " seqCounter:" + knxTunnelingRequest.seqCounter + " Host:" + this._options.ipAddr + ":" + this._options.ipPort);
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
- else if (knxHeader.service_type === KNXConstants.KNX_CONSTANTS.TUNNELING_ACK) {
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
- this._incSeqNumber(knxTunnelingAck.seqCounter);
841
-
842
- if (this._tunnelReqTimer.has(knxTunnelingAck.seqCounter)) {
843
- if (this._tunnelReqTimer.get(knxTunnelingAck.seqCounter) !== null) {
844
- clearTimeout(this._tunnelReqTimer.get(knxTunnelingAck.seqCounter));
845
- this._tunnelReqTimer.delete(knxTunnelingAck.seqCounter);
846
- }
847
- this._numFailedTelegramACK = 0; // 25/12/2021 clear the current ACK failed telegram number
848
- try {
849
- 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);
850
- } catch (error) { }
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) this.sysLogger.debug("Received KNX packet: ROUTING: L_DATA_IND, " + sDebugString + " Host:" + this._options.ipAddr + ":" + this._options.ipPort);
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 {
@@ -916,7 +942,7 @@ class KNXClient extends EventEmitter {
916
942
  }
917
943
  }
918
944
  else {
919
- if (this._timer !== null) clearTimeout(this._timer);
945
+ if (this._connectionTimeoutTimer !== null) clearTimeout(this._connectionTimeoutTimer);
920
946
  }
921
947
  }
922
948
  try {
@@ -928,10 +954,12 @@ class KNXClient extends EventEmitter {
928
954
  }
929
955
  catch (e) {
930
956
  try {
931
- if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.error("Received KNX packet: Error processing inbound message: " + e.message + " " + sProcessInboundLog + " ChannelID:" + this._channelID + " Host:" + this._options.ipAddr + ":" + this._options.ipPort);
957
+ if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.error("Received KNX packet: Error processing inbound message: " + e.message + " " + sProcessInboundLog + " ChannelID:" + this._channelID + " Host:" + this._options.ipAddr + ":" + this._options.ipPort + ". This means that KNX-Ultimate received a malformed Header or CEMI message from your KNX Gateway.");
932
958
  } catch (error) { }
933
959
  try {
934
- this.emit(KNXClientEvents.error, e);
960
+ // 05/01/2022 Avoid disconnecting, because there are many bugged knx gateways out there!
961
+ //this.emit(KNXClientEvents.error, e);
962
+ //this._setDisconnected();
935
963
  } catch (error) { }
936
964
 
937
965
  }
@@ -942,7 +970,6 @@ class KNXClient extends EventEmitter {
942
970
  this.send(KNXProtocol.KNXProtocol.newKNXDescriptionRequest(new HPAI.HPAI(this._options.localIPAddress)));
943
971
  }
944
972
  _sendSearchRequestMessage() {
945
- console.log('_sendSearchRequestMessage', this._options.localIPAddress, this._localPort);
946
973
  this.send(KNXProtocol.KNXProtocol.newKNXSearchRequest(new HPAI.HPAI(this._options.localIPAddress, this._localPort)), KNXConstants.KNX_CONSTANTS.KNX_PORT, KNXConstants.KNX_CONSTANTS.KNX_IP);
947
974
  }
948
975
  _sendConnectRequestMessage(cri) {
@@ -957,9 +984,9 @@ class KNXClient extends EventEmitter {
957
984
  _sendDisconnectResponseMessage(channelID, status = KNXConstants.ConnectionStatus.E_NO_ERROR) {
958
985
  this.send(KNXProtocol.KNXProtocol.newKNXDisconnectResponse(channelID, status));
959
986
  }
960
- _sendSecureSessionRequestMessage(cri) {
987
+ _sendSecureSessionRequestMessage(cri, jKNXSecureKeyring) {
961
988
  let oHPAI = new HPAI.HPAI("0.0.0.0", 0, this._options.hostProtocol === "TunnelTCP" ? KNXConstants.KNX_CONSTANTS.IPV4_TCP : KNXConstants.KNX_CONSTANTS.IPV4_UDP);
962
- this.send(KNXProtocol.KNXProtocol.newKNXSecureSessionRequest(cri, oHPAI));
989
+ this.send(KNXProtocol.KNXProtocol.newKNXSecureSessionRequest(cri, oHPAI, jKNXSecureKeyring));
963
990
  }
964
991
  }
965
992
 
@@ -1,13 +1,13 @@
1
1
  'use strict';
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.KNXConnectResponse = void 0;
4
- const KNXConstants_1 = require("./KNXConstants");
5
- const KNXPacket_1 = require("./KNXPacket");
6
- const HPAI_1 = require("./HPAI");
7
- const CRD_1 = require("./CRD");
8
- class KNXConnectResponse extends KNXPacket_1.KNXPacket {
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(KNXConstants_1.KNX_CONSTANTS.CONNECT_RESPONSE, hpai == null ? 2 : 2 + hpai.length + crd.length);
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 = HPAI_1.HPAI.createFromBuffer(buffer, offset);
24
+ hpai = HPAI.HPAI.createFromBuffer(buffer, offset);
25
25
  offset += hpai.length;
26
- crd = CRD_1.CRD.createFromBuffer(buffer, offset);
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 KNXConstants_1.KNX_CONSTANTS.E_SEQUENCE_NUMBER:
32
+ case KNXConstants.KNX_CONSTANTS.E_SEQUENCE_NUMBER:
33
33
  return 'Invalid Sequence Number';
34
- case KNXConstants_1.KNX_CONSTANTS.E_CONNECTION_TYPE:
34
+ case KNXConstants.KNX_CONSTANTS.E_CONNECTION_TYPE:
35
35
  return 'Invalid Connection Type';
36
- case KNXConstants_1.KNX_CONSTANTS.E_CONNECTION_OPTION:
36
+ case KNXConstants.KNX_CONSTANTS.E_CONNECTION_OPTION:
37
37
  return 'Invalid Connection Option';
38
- case KNXConstants_1.KNX_CONSTANTS.E_NO_MORE_CONNECTIONS:
38
+ case KNXConstants.KNX_CONSTANTS.E_NO_MORE_CONNECTIONS:
39
39
  return 'No More Connections';
40
- case KNXConstants_1.KNX_CONSTANTS.E_DATA_CONNECTION:
40
+ case KNXConstants.KNX_CONSTANTS.E_DATA_CONNECTION:
41
41
  return 'Invalid Data Connection';
42
- case KNXConstants_1.KNX_CONSTANTS.E_KNX_CONNECTION:
42
+ case KNXConstants.KNX_CONSTANTS.E_KNX_CONNECTION:
43
43
  return 'Invalid KNX Connection';
44
- case KNXConstants_1.KNX_CONSTANTS.E_TUNNELING_LAYER:
44
+ case KNXConstants.KNX_CONSTANTS.E_TUNNELING_LAYER:
45
45
  return 'Invalid Tunneling Layer';
46
46
  default:
47
47
  return `Unknown error ${status}`;