node-red-contrib-knx-ultimate 1.3.33 → 1.3.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/CHANGELOG.md +9 -1
  2. package/KNXEngine/KNXClient.js +87 -80
  3. package/KNXEngine/KnxLog.js +2 -0
  4. package/nodes/knxUltimate-config.js +40 -33
  5. package/nodes/knxUltimate.js +7 -7
  6. package/nodes/knxUltimateGlobalContext.js +9 -2
  7. package/nodes/knxUltimateLoadControl.js +7 -7
  8. package/nodes/knxUltimateLogger.js +4 -2
  9. package/nodes/knxUltimateSceneController.js +11 -10
  10. package/nodes/knxUltimateWatchDog.js +2 -2
  11. package/package.json +1 -1
  12. package/knxultimate-api2/index.js +0 -22
  13. package/knxultimate-api2/src/Address.js +0 -116
  14. package/knxultimate-api2/src/Connection.js +0 -458
  15. package/knxultimate-api2/src/Datapoint.js +0 -143
  16. package/knxultimate-api2/src/FSM.js +0 -847
  17. package/knxultimate-api2/src/IpRoutingConnection.js +0 -83
  18. package/knxultimate-api2/src/IpTunnelingConnection.js +0 -65
  19. package/knxultimate-api2/src/KNXsecureKeyring.js +0 -575
  20. package/knxultimate-api2/src/KnxConstants.js +0 -261
  21. package/knxultimate-api2/src/KnxLog.js +0 -69
  22. package/knxultimate-api2/src/KnxProtocol.js +0 -1025
  23. package/knxultimate-api2/src/RawMod/CheckResourceAvailable.js +0 -9
  24. package/knxultimate-api2/src/RawMod/CustomMessageHandlerTemplates.js +0 -82
  25. package/knxultimate-api2/src/RawMod/CustomMsgHandlers.js +0 -148
  26. package/knxultimate-api2/src/RawMod/ErrorHandler.js +0 -108
  27. package/knxultimate-api2/src/RawMod/Errors.js +0 -93
  28. package/knxultimate-api2/src/RawMod/Handlers.js +0 -143
  29. package/knxultimate-api2/src/RawMod/KnxAddress.js +0 -374
  30. package/knxultimate-api2/src/RawMod/KnxDeviceResourceInformation.js +0 -7557
  31. package/knxultimate-api2/src/RawMod/KnxMessageTemplates.js +0 -204
  32. package/knxultimate-api2/src/RawMod/KnxNetProtocol.js +0 -201
  33. package/knxultimate-api2/src/RawMod/KnxNetProtocolExtra.js +0 -131
  34. package/knxultimate-api2/src/RawMod/KnxNetRebuildMessageBytes.js +0 -138
  35. package/knxultimate-api2/src/RawMod/KnxOperations/LoadStateMachine.js +0 -48
  36. package/knxultimate-api2/src/RawMod/KnxOperations/RestartDevice.js +0 -181
  37. package/knxultimate-api2/src/RawMod/KnxOperations/RunStateMachine.js +0 -48
  38. package/knxultimate-api2/src/RawMod/KnxParseTpci.js +0 -163
  39. package/knxultimate-api2/src/RawMod/RawMod.js +0 -88
  40. package/knxultimate-api2/src/RawMod/__KnxReadOperations/KnxReadApplicationID.js +0 -112
  41. package/knxultimate-api2/src/RawMod/__KnxReadOperations/KnxReadDevMem.js +0 -340
  42. package/knxultimate-api2/src/RawMod/__KnxReadOperations/KnxReadDeviceADC.js +0 -324
  43. package/knxultimate-api2/src/RawMod/__KnxReadOperations/KnxReadDeviceAddress.js +0 -218
  44. package/knxultimate-api2/src/RawMod/__KnxReadOperations/KnxReadDeviceResource.js +0 -238
  45. package/knxultimate-api2/src/RawMod/__KnxReadOperations/KnxReadGroupAddrTblLoadstate.js +0 -84
  46. package/knxultimate-api2/src/RawMod/__KnxReadOperations/KnxReadGroupAssociationTblLoadstate.js +0 -84
  47. package/knxultimate-api2/src/RawMod/__KnxReadOperations/KnxReadManufacturerID.js +0 -96
  48. package/knxultimate-api2/src/RawMod/__KnxReadOperations/KnxReadMaskversion.js +0 -317
  49. package/knxultimate-api2/src/RawMod/__KnxReadOperations/KnxReadOrderNumber.js +0 -96
  50. package/knxultimate-api2/src/RawMod/__KnxReadOperations/KnxReadProgmodeStatus.js +0 -88
  51. package/knxultimate-api2/src/RawMod/__KnxReadOperations/KnxReadPropertyValue.js +0 -336
  52. package/knxultimate-api2/src/RawMod/__KnxReadOperations/KnxReadSerialNumber.js +0 -99
  53. package/knxultimate-api2/src/RawMod/__KnxReadOperations/__KnxReadResourceViaMemory.js +0 -12
  54. package/knxultimate-api2/src/RawMod/__KnxReadOperations/__KnxReadResourceViaProperty.js +0 -15
  55. package/knxultimate-api2/src/RawMod/__KnxWriteOperations/KnxSetDeviceAddress.js +0 -150
  56. package/knxultimate-api2/src/RawMod/__KnxWriteOperations/KnxSetProgmodeStatus.js +0 -73
  57. package/knxultimate-api2/src/RawMod/__KnxWriteOperations/KnxWriteDevMem.js +0 -343
  58. package/knxultimate-api2/src/RawMod/__KnxWriteOperations/KnxWriteDeviceResource.js +0 -204
  59. package/knxultimate-api2/src/RawMod/__KnxWriteOperations/KnxWritePropertyValue.js +0 -348
  60. package/knxultimate-api2/src/RawMod/__KnxWriteOperations/__KnxWriteResourceViaMemory.js +0 -11
  61. package/knxultimate-api2/src/RawMod/__KnxWriteOperations/__KnxWriteResourceViaProperty.js +0 -15
  62. package/knxultimate-api2/src/dptlib/dpt1.js +0 -201
  63. package/knxultimate-api2/src/dptlib/dpt10.js +0 -106
  64. package/knxultimate-api2/src/dptlib/dpt11.js +0 -84
  65. package/knxultimate-api2/src/dptlib/dpt12.js +0 -63
  66. package/knxultimate-api2/src/dptlib/dpt13.js +0 -77
  67. package/knxultimate-api2/src/dptlib/dpt14.js +0 -191
  68. package/knxultimate-api2/src/dptlib/dpt15.js +0 -24
  69. package/knxultimate-api2/src/dptlib/dpt16.js +0 -67
  70. package/knxultimate-api2/src/dptlib/dpt17.js +0 -25
  71. package/knxultimate-api2/src/dptlib/dpt18.js +0 -96
  72. package/knxultimate-api2/src/dptlib/dpt19.js +0 -62
  73. package/knxultimate-api2/src/dptlib/dpt2.js +0 -132
  74. package/knxultimate-api2/src/dptlib/dpt20.js +0 -52
  75. package/knxultimate-api2/src/dptlib/dpt213.js +0 -156
  76. package/knxultimate-api2/src/dptlib/dpt22.js +0 -145
  77. package/knxultimate-api2/src/dptlib/dpt222.js +0 -158
  78. package/knxultimate-api2/src/dptlib/dpt232.js +0 -58
  79. package/knxultimate-api2/src/dptlib/dpt237.js +0 -92
  80. package/knxultimate-api2/src/dptlib/dpt238.js +0 -73
  81. package/knxultimate-api2/src/dptlib/dpt242.js +0 -84
  82. package/knxultimate-api2/src/dptlib/dpt249.js +0 -87
  83. package/knxultimate-api2/src/dptlib/dpt251.js +0 -76
  84. package/knxultimate-api2/src/dptlib/dpt3.js +0 -90
  85. package/knxultimate-api2/src/dptlib/dpt4.js +0 -58
  86. package/knxultimate-api2/src/dptlib/dpt5.js +0 -70
  87. package/knxultimate-api2/src/dptlib/dpt6.js +0 -42
  88. package/knxultimate-api2/src/dptlib/dpt7.js +0 -150
  89. package/knxultimate-api2/src/dptlib/dpt8.js +0 -94
  90. package/knxultimate-api2/src/dptlib/dpt9.js +0 -212
  91. package/knxultimate-api2/src/dptlib/dpt999.js +0 -61
  92. package/knxultimate-api2/src/dptlib/index.js +0 -185
  93. package/knxultimate-api2/src/superKNX.js +0 -117
  94. package/nodes/knxUltimate-config API2.js +0 -1829
package/CHANGELOG.md CHANGED
@@ -7,11 +7,19 @@
7
7
  # CHANGELOG
8
8
 
9
9
  <p>
10
- <b>Version 1.3.33</b> - March 2022<br/>
10
+ <b>Version 1.3.34</b> - March 2022<br/>
11
11
  - Reset handlers by removing/adding every time the connection is set by "new" directive.<br/>
12
12
  - Fixed an issue causing glitches, when the disconnection is requested by the KNX interface instead of KNX-Ultimate.<br/>
13
13
  - Fixed an issue occurring when the disconnection is started from KNX-Ultimate by the DISCONNECT_REQUEST, but the KNX Interface fails to send the DISCONNECT_RESPONSE to confirm the disconnection.<br/>
14
14
  - Updated knxUltimate-config.js to actively disconnect and close the socket when the disconnection is requested by the KNX Interface. All other cases (disconnection by ethernet cable, disconnection by unreachable KNX Interface, disconnection by temporary out of access, disconnection by means of user intervention, disconnection by Watchdog node etc...) are not affected by this issue.<br/>
15
+ - Optimized memory allocation to allow the garbage collector to get rid of unref variables.<br/>
16
+ - Scene controller: fixed node status issues.<br/>
17
+ - Load control: code revision.<br/>
18
+ - Logger: code revision.<br/>
19
+ - Watchdog: code revision.<br/>
20
+ - Device node: code revision.<br/>
21
+ - Global Context: code revision.<br/>
22
+ - Wiki: merged Global Context node sample, into one single page for better readability.<br/>
15
23
  </p>
16
24
  <p>
17
25
  <b>Version 1.3.32</b> - February 2022<br/>
@@ -94,8 +94,8 @@ class KNXClient extends EventEmitter {
94
94
  super();
95
95
  this._clientTunnelSeqNumber = -1;
96
96
  this._options = options;//Object.assign(optionsDefaults, options);
97
- this._options.connectionKeepAliveTimeout = KNXConstants.KNX_CONSTANTS.CONNECTION_ALIVE_TIME,
98
- this._localPort = null;
97
+ this._options.connectionKeepAliveTimeout = KNXConstants.KNX_CONSTANTS.CONNECTION_ALIVE_TIME;
98
+ //this._localPort = null;
99
99
  this._peerHost = this._options.ipAddr;
100
100
  this._peerPort = this._options.ipPort;
101
101
  this._connectionTimeoutTimer = null;
@@ -125,8 +125,6 @@ class KNXClient extends EventEmitter {
125
125
 
126
126
  // 12/03/2022 Remove all listeners
127
127
  this.removeAllListeners();
128
-
129
- let conn = this;
130
128
  // 07/12/2021 Based on protocol instantiate the right socket
131
129
  if (this._options.hostProtocol === "TunnelUDP") {
132
130
  this._clientSocket = dgram.createSocket({ type: 'udp4', reuseAddr: false });
@@ -134,11 +132,12 @@ class KNXClient extends EventEmitter {
134
132
  this._clientSocket.on(SocketEvents.message, this._processInboundMessage);
135
133
  this._clientSocket.on(SocketEvents.error, error => this.emit(KNXClientEvents.error, error));
136
134
  this._clientSocket.on(SocketEvents.close, info => this.emit(KNXClientEvents.close, info));
137
- this._clientSocket.bind({ address: this._options.localIPAddress, port: this._options._peerPort }, () => {
135
+ let conn = this;
136
+ this._clientSocket.bind({ address: this._options.localIPAddress, port: this._options._peerPort }, function () {
138
137
  try {
139
138
  conn._clientSocket.setTTL(128);
140
139
  } catch (error) {
141
- if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.error("UDP: Error setting SetTTL " + error.message || "");
140
+ if (conn.sysLogger !== undefined && conn.sysLogger !== null) conn.sysLogger.error("UDP: Error setting SetTTL " + error.message || "");
142
141
  }
143
142
  });
144
143
 
@@ -154,38 +153,39 @@ class KNXClient extends EventEmitter {
154
153
  this._clientSocket.on(SocketEvents.close, info => this.emit(KNXClientEvents.close, info));
155
154
 
156
155
  } else if (this._options.hostProtocol === "Multicast") {
157
- let conn = this;
158
156
  this._clientSocket = dgram.createSocket({ type: 'udp4', reuseAddr: true });
159
157
  this._clientSocket.removeAllListeners(); // 12/03/2022 Remove all listeners
160
158
  this._clientSocket.on(SocketEvents.listening, function () {
161
- try {
162
- conn._clientSocket.addMembership(conn._peerHost, conn._options.localIPAddress);
163
- } catch (err) {
164
- if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.error("Multicast: cannot add membership (%s)", err);
165
- try {
166
- this.emit(KNXClientEvents.error, err);
167
- } catch (error) { }
168
- return;
169
- }
159
+
170
160
  });
161
+ let conn = this;
171
162
  this._clientSocket.on(SocketEvents.message, this._processInboundMessage);
172
163
  this._clientSocket.on(SocketEvents.error, error => this.emit(KNXClientEvents.error, error));
173
164
  this._clientSocket.on(SocketEvents.close, info => this.emit(KNXClientEvents.close, info));
174
- this._clientSocket.bind(this._peerPort, () => {
165
+ this._clientSocket.bind(this._peerPort, function () {
175
166
  try {
176
167
  conn._clientSocket.setMulticastTTL(128);
177
- conn._clientSocket.setMulticastInterface(this._options.localIPAddress);
168
+ conn._clientSocket.setMulticastInterface(conn._options.localIPAddress);
178
169
  } catch (error) {
179
- if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.error("Multicast: Error setting SetTTL " + error.message || "");
170
+ if (conn.sysLogger !== undefined && conn.sysLogger !== null) conn.sysLogger.error("Multicast: Error setting SetTTL " + error.message || "");
180
171
  }
181
- this._localPort = this._clientSocket.address().port;// 07/12/2021 Get the local port used bu the socket
172
+ try {
173
+ conn._clientSocket.addMembership(conn._peerHost, conn._options.localIPAddress);
174
+ } catch (err) {
175
+ if (conn.sysLogger !== undefined && conn.sysLogger !== null) conn.sysLogger.error("Multicast: cannot add membership (%s)", err);
176
+ try {
177
+ conn.emit(KNXClientEvents.error, err);
178
+ } catch (error) { }
179
+ return;
180
+ }
181
+ //this._localPort = this._clientSocket.address().port;// 07/12/2021 Get the local port used bu the socket
182
182
  });
183
183
  }
184
184
 
185
185
  this._clientTunnelSeqNumber = -1;
186
186
  this._channelID = null;
187
187
  this._connectionState = STATE.DISCONNECTED;
188
- this._tunnelReqTimer = null;
188
+ this._timerWaitingForACK = null;
189
189
  this._numFailedTelegramACK = 0; // 25/12/2021 Keep count of the failed tunnelig ACK telegrams
190
190
 
191
191
  }
@@ -237,21 +237,21 @@ class KNXClient extends EventEmitter {
237
237
  }
238
238
  return new KNXDataBuffer(adpu.data, IDataPoint);
239
239
  }
240
- bindSocketPortAsync(port = KNXConstants.KNX_CONSTANTS.KNX_PORT, host = '0.0.0.0') {
241
- return new Promise((resolve, reject) => {
242
- try {
243
- this._clientSocket.bind(port, host, () => {
244
- this._clientSocket.setMulticastInterface(host);
245
- this._clientSocket.setMulticastTTL(128);
246
- this._options.localIPAddress = host;
247
- resolve();
248
- });
249
- }
250
- catch (err) {
251
- reject(err);
252
- }
253
- });
254
- }
240
+ // bindSocketPortAsync(port = KNXConstants.KNX_CONSTANTS.KNX_PORT, host = '0.0.0.0') {
241
+ // return new Promise((resolve, reject) => {
242
+ // try {
243
+ // this._clientSocket.bind(port, host, () => {
244
+ // this._clientSocket.setMulticastInterface(host);
245
+ // this._clientSocket.setMulticastTTL(128);
246
+ // this._options.localIPAddress = host;
247
+ // resolve();
248
+ // });
249
+ // }
250
+ // catch (err) {
251
+ // reject(err);
252
+ // }
253
+ // });
254
+ // }
255
255
  send(knxPacket) {
256
256
 
257
257
  // Logging
@@ -318,10 +318,8 @@ class KNXClient extends EventEmitter {
318
318
 
319
319
  /**
320
320
  *
321
- * @param {KNXAddress} srcAddress
322
321
  * @param {KNXAddress} dstAddress
323
322
  * @param {KNXDataBuffer} data
324
- * @param {function} cb
325
323
  */
326
324
  // sendWriteRequest(dstAddress, data) {
327
325
  write(dstAddress, data, dptid) {
@@ -525,35 +523,35 @@ class KNXClient extends EventEmitter {
525
523
  clearTimeout(this._heartbeatTimer);
526
524
  }
527
525
  }
528
- isDiscoveryRunning() {
529
- return this._discovery_timer != null;
530
- }
531
- startDiscovery() {
532
- if (this.isDiscoveryRunning()) {
533
- throw new Error('Discovery already running');
534
- }
535
- this._discovery_timer = setTimeout(() => {
536
- this._discovery_timer = null;
537
- }, 1000 * KNXConstants.KNX_CONSTANTS.SEARCH_TIMEOUT);
538
- this._sendSearchRequestMessage();
539
- }
540
- stopDiscovery() {
541
- if (!this.isDiscoveryRunning()) {
542
- return;
543
- }
544
- if (this._discovery_timer !== null) clearTimeout(this._discovery_timer);
545
- this._discovery_timer = null;
546
- }
547
- getDescription(host, port) {
548
- if (this._clientSocket == null) {
549
- throw new Error('No client socket defined');
550
- }
551
- this._connectionTimeoutTimer = setTimeout(() => {
552
- this._connectionTimeoutTimer = null;
553
- }, 1000 * KNXConstants.KNX_CONSTANTS.DEVICE_CONFIGURATION_REQUEST_TIMEOUT);
554
- this._awaitingResponseType = KNXConstants.KNX_CONSTANTS.DESCRIPTION_RESPONSE;
555
- this._sendDescriptionRequestMessage(host, port);
556
- }
526
+ // isDiscoveryRunning() {
527
+ // return this._discovery_timer != null;
528
+ // }
529
+ // startDiscovery() {
530
+ // if (this.isDiscoveryRunning()) {
531
+ // throw new Error('Discovery already running');
532
+ // }
533
+ // this._discovery_timer = setTimeout(() => {
534
+ // this._discovery_timer = null;
535
+ // }, 1000 * KNXConstants.KNX_CONSTANTS.SEARCH_TIMEOUT);
536
+ // this._sendSearchRequestMessage();
537
+ // }
538
+ // stopDiscovery() {
539
+ // if (!this.isDiscoveryRunning()) {
540
+ // return;
541
+ // }
542
+ // if (this._discovery_timer !== null) clearTimeout(this._discovery_timer);
543
+ // this._discovery_timer = null;
544
+ // }
545
+ // getDescription(host, port) {
546
+ // if (this._clientSocket == null) {
547
+ // throw new Error('No client socket defined');
548
+ // }
549
+ // this._connectionTimeoutTimer = setTimeout(() => {
550
+ // this._connectionTimeoutTimer = null;
551
+ // }, 1000 * KNXConstants.KNX_CONSTANTS.DEVICE_CONFIGURATION_REQUEST_TIMEOUT);
552
+ // this._awaitingResponseType = KNXConstants.KNX_CONSTANTS.DESCRIPTION_RESPONSE;
553
+ // this._sendDescriptionRequestMessage(host, port);
554
+ // }
557
555
  Connect(knxLayer = TunnelCRI.TunnelTypes.TUNNEL_LINKLAYER) {
558
556
 
559
557
  if (this._clientSocket == null) {
@@ -600,7 +598,7 @@ class KNXClient extends EventEmitter {
600
598
  // TCP
601
599
  const timeoutError = new Error(`Connection timeout to ${this._peerHost}:${this._peerPort}`);
602
600
  let conn = this;
603
- this._clientSocket.connect({ port: this._peerPort, host: this._peerHost, localAddress: this._options.localAddress }, function () {
601
+ this._clientSocket.connect( this._peerPort, this._peerHost, function () {
604
602
  // conn._timer = setTimeout(() => {
605
603
  // conn._timer = null;
606
604
  // conn.emit(KNXClientEvents.error, timeoutError);
@@ -614,6 +612,11 @@ class KNXClient extends EventEmitter {
614
612
 
615
613
  // Multicast
616
614
  this._connectionState = STATE.CONNECTED;
615
+
616
+ // 16/03/2022 These two are referring to tunneling connection, but i set it here as well. Non si sa mai.
617
+ this._numFailedTelegramACK = 0; // 25/12/2021 Reset the failed ACK counter
618
+ this._clearToSend = true; // 26/12/2021 allow to send
619
+
617
620
  this._clientTunnelSeqNumber = -1;
618
621
  try {
619
622
  this.emit(KNXClientEvents.connected, this._options);
@@ -659,7 +662,7 @@ class KNXClient extends EventEmitter {
659
662
  this._awaitingResponseType = KNXConstants.KNX_CONSTANTS.DISCONNECT_RESPONSE;
660
663
  this._sendDisconnectRequestMessage(this._channelID);
661
664
  // 12/03/2021 Set disconnected if not already set by DISCONNECT_RESPONSE sent from the IP Interface
662
- setTimeout(() => {
665
+ let t = setTimeout(() => { // 21/03/2022 fixed possible memory leak. Previously was setTimeout without "let t = ".
663
666
  if (this._connectionState !== STATE.DISCONNECTED) this._setDisconnected("Forced call from KNXClient Disconnect() function, because the KNX Interface hasn't sent the DISCONNECT_RESPONSE in time.");
664
667
  }, 2000);
665
668
  }
@@ -673,10 +676,9 @@ class KNXClient extends EventEmitter {
673
676
  }
674
677
  this._connectionState = STATE.DISCONNECTED;
675
678
  this.stopHeartBeat();
676
- if (this._timerTimeoutSendDisconnectRequestMessagetimer !== null) clearTimeout(this._timerTimeoutSendDisconnectRequestMessagetimer);
677
679
  this._timerTimeoutSendDisconnectRequestMessage = null;
678
680
  if (this._connectionTimeoutTimer !== null) clearTimeout(this._connectionTimeoutTimer);
679
- if (this._tunnelReqTimer !== null) clearTimeout(this._tunnelReqTimer);
681
+ if (this._timerWaitingForACK !== null) clearTimeout(this._timerWaitingForACK);
680
682
  this._clientTunnelSeqNumber = -1;
681
683
  this._channelID = null;
682
684
 
@@ -689,13 +691,12 @@ class KNXClient extends EventEmitter {
689
691
  this.emit(KNXClientEvents.disconnected, this._options.ipAddr + ":" + this._options.ipPort + " " + _sReason);
690
692
  } catch (error) {
691
693
  }
692
- this._clearToSend = true; // 26/12/2021 allow to send
693
-
694
+ this._clearToSend = true; // 26/12/2021 allow to send
694
695
  }
695
696
  _runHeartbeat() {
696
697
  if (this._heartbeatRunning) {
697
698
  this.getConnectionStatus();
698
- setTimeout(() => {
699
+ let t = setTimeout(() => { // 21/03/2022 fixed possible memory leak. Previously was setTimeout without "let t = ".
699
700
  this._runHeartbeat();
700
701
  }, 1000 * this._options.connectionKeepAliveTimeout);
701
702
  }
@@ -719,10 +720,10 @@ class KNXClient extends EventEmitter {
719
720
  // return cEMIMessage.dstAddress.toString();
720
721
  // }
721
722
  _setTimerWaitingForACK(knxTunnelingRequest) {
722
- 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"}`);
723
- if (this._tunnelReqTimer !== null) clearTimeout(this._tunnelReqTimer);
724
723
  this._clearToSend = false; // 26/12/2021 stop sending until ACK received
725
- this._tunnelReqTimer = setTimeout(() => {
724
+ 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"}`);
725
+ if (this._timerWaitingForACK !== null) clearTimeout(this._timerWaitingForACK);
726
+ this._timerWaitingForACK = setTimeout(() => {
726
727
  try {
727
728
  this._numFailedTelegramACK += 1;
728
729
  if (this._numFailedTelegramACK > 2) {
@@ -797,6 +798,12 @@ class KNXClient extends EventEmitter {
797
798
  this._setDisconnected("Connect response error " + knxConnectResponse.status);
798
799
  return;
799
800
  }
801
+
802
+ // 16/03/2022
803
+ if (this._timerWaitingForACK !== null) clearTimeout(this._timerWaitingForACK);
804
+ this._numFailedTelegramACK = 0; // 16/03/2022 Reset the failed ACK counter
805
+ this._clearToSend = true; // 16/03/2022 allow to send
806
+
800
807
  this._connectionState = STATE.CONNECTED;
801
808
  this._channelID = knxConnectResponse.channelID;
802
809
  try {
@@ -837,7 +844,7 @@ class KNXClient extends EventEmitter {
837
844
  this._connectionState = STATE.DISCONNECTING;
838
845
  this._sendDisconnectResponseMessage(knxDisconnectRequest.channelID);
839
846
  // 12/03/2021 Added 1 sec delay.
840
- setTimeout(() => {
847
+ let t = setTimeout(() => { // 21/03/2022 fixed possible memory leak. Previously was setTimeout without "let t = ".
841
848
  this._setDisconnected("Received KNX packet: DISCONNECT_REQUEST, ChannelID:" + this._channelID + " Host:" + this._options.ipAddr + ":" + this._options.ipPort);
842
849
  }, 1000);
843
850
  }
@@ -896,7 +903,7 @@ class KNXClient extends EventEmitter {
896
903
  // Check the received ACK sequence number
897
904
  if (!this._options.suppress_ack_ldatareq) {
898
905
  if (knxTunnelingAck.seqCounter === this._getSeqNumber()) {
899
- if (this._tunnelReqTimer !== null) clearTimeout(this._tunnelReqTimer);
906
+ if (this._timerWaitingForACK !== null) clearTimeout(this._timerWaitingForACK);
900
907
  this._numFailedTelegramACK = 0; // 25/12/2021 clear the current ACK failed telegram number
901
908
  this._clearToSend = true; // I'm ready to send a new datagram now
902
909
  try {
@@ -996,7 +1003,7 @@ class KNXClient extends EventEmitter {
996
1003
  this.send(KNXProtocol.KNXProtocol.newKNXDescriptionRequest(new HPAI.HPAI(this._options.localIPAddress)));
997
1004
  }
998
1005
  _sendSearchRequestMessage() {
999
- this.send(KNXProtocol.KNXProtocol.newKNXSearchRequest(new HPAI.HPAI(this._options.localIPAddress, this._localPort)), KNXConstants.KNX_CONSTANTS.KNX_PORT, KNXConstants.KNX_CONSTANTS.KNX_IP);
1006
+ //this.send(KNXProtocol.KNXProtocol.newKNXSearchRequest(new HPAI.HPAI(this._options.localIPAddress, this._localPort)), KNXConstants.KNX_CONSTANTS.KNX_PORT, KNXConstants.KNX_CONSTANTS.KNX_IP);
1000
1007
  }
1001
1008
  _sendConnectRequestMessage(cri) {
1002
1009
  this.send(KNXProtocol.KNXProtocol.newKNXConnectRequest(cri));
@@ -1,6 +1,8 @@
1
1
  /**
2
2
  * (C) 2021 Supergiovane
3
3
  */
4
+ "use strict";
5
+
4
6
  const util = require('util')
5
7
  const possibleLEvels = ['silent', 'error', 'warn', 'info', 'debug', 'trace'];
6
8
  let logger
@@ -1,3 +1,5 @@
1
+
2
+
1
3
  // const knx = require('./../knxultimate-api2');
2
4
  // const dptlib = require('./../knxultimate-api2/src/dptlib');
3
5
  const knx = require("./../KNXEngine");
@@ -11,23 +13,23 @@ var fs = require('fs');
11
13
 
12
14
 
13
15
  //Helpers
14
- sortBy = (field) => (a, b) => {
16
+ let sortBy = (field) => (a, b) => {
15
17
  if (a[field] > b[field]) { return 1 } else { return -1 }
16
18
  };
17
19
 
18
20
 
19
- onlyDptKeys = (kv) => {
21
+ let onlyDptKeys = (kv) => {
20
22
  return kv[0].startsWith("DPT")
21
23
  };
22
24
 
23
- extractBaseNo = (kv) => {
25
+ let extractBaseNo = (kv) => {
24
26
  return {
25
27
  subtypes: kv[1].subtypes,
26
28
  base: parseInt(kv[1].id.replace("DPT", ""))
27
29
  }
28
30
  };
29
31
 
30
- convertSubtype = (baseType) => (kv) => {
32
+ let convertSubtype = (baseType) => (kv) => {
31
33
  let value = `${baseType.base}.${kv[0]}`;
32
34
  //let sRet = value + " " + kv[1].name + (kv[1].unit === undefined ? "" : " (" + kv[1].unit + ")");
33
35
  let sRet = value + " " + kv[1].name;
@@ -47,7 +49,7 @@ convertSubtype = (baseType) => (kv) => {
47
49
  // }
48
50
 
49
51
 
50
- toConcattedSubtypes = (acc, baseType) => {
52
+ let toConcattedSubtypes = (acc, baseType) => {
51
53
  let subtypes =
52
54
  Object.entries(baseType.subtypes)
53
55
  .sort(sortBy(0))
@@ -59,6 +61,8 @@ toConcattedSubtypes = (acc, baseType) => {
59
61
 
60
62
  module.exports = (RED) => {
61
63
 
64
+ "use strict";
65
+
62
66
  RED.httpAdmin.get("/knxUltimateDpts", RED.auth.needsPermission('knxUltimate-config.read'), function (req, res) {
63
67
  const dpts =
64
68
  Object.entries(dptlib)
@@ -135,11 +139,12 @@ return msg;`, "helplink": "https://github.com/Supergiovane/node-red-contrib-knx-
135
139
  node.userDir = path.join(RED.settings.userDir, "knxultimatestorage"); // 04/04/2021 Supergiovane: Storage for service files
136
140
  node.exposedGAs = [];
137
141
  node.loglevel = config.loglevel !== undefined ? config.loglevel : "error"; // 18/02/2020 Loglevel default error
142
+ node.sysLogger = null; // 20/03/2022 Default
138
143
  try {
139
- node.sysLogger = null;
140
144
  node.sysLogger = require("./utils/sysLogger.js").get({ loglevel: node.loglevel }); // 08/04/2021 new logger to adhere to the loglevel selected in the config-window
141
145
  } catch (error) { }
142
146
  // 12/11/2021 Connect at start delay
147
+ node.autoReconnect = true; // 20/03/2022 Default
143
148
  if (config.autoReconnect === "no" || config.autoReconnect === false) {
144
149
  node.autoReconnect = false;
145
150
  } else {
@@ -155,7 +160,8 @@ return msg;`, "helplink": "https://github.com/Supergiovane/node-red-contrib-knx-
155
160
  node.knxConnectionProperties = null; // Retains the connection properties
156
161
  node.allowLauch_initKNXConnection = true; // See the node.timerKNXUltimateCheckState function
157
162
  node.timerClearTelegramQueue = null; // Timer to clear the telegram's queue after long disconnection
158
-
163
+ node.hostProtocol = "TunnelUDP"; // 20/03/2022 Default
164
+ node.knxConnection = null; // 20/03/2022 Default
159
165
  // 15/12/2021
160
166
  node.adaptProtocolBasedOnIP = () => {
161
167
  // Auto set protocol based on IP
@@ -192,7 +198,7 @@ return msg;`, "helplink": "https://github.com/Supergiovane/node-red-contrib-knx-
192
198
  node.startTimerClearTelegramQueue = () => {
193
199
  if (node.timerClearTelegramQueue === null) {
194
200
  node.timerClearTelegramQueue = setTimeout(() => {
195
- setTimeout(() => {
201
+ let t = setTimeout(() => { // 21/03/2022 fixed possible memory leak. Previously was setTimeout without "let t = ".
196
202
  node.setAllClientsStatus("Queue", "grey", "Deleted TX");
197
203
  }, 200);
198
204
  node.telegramsQueue = [];
@@ -207,6 +213,7 @@ return msg;`, "helplink": "https://github.com/Supergiovane/node-red-contrib-knx-
207
213
  // 15/11/2021 Function to load the keyring file exported from ETS
208
214
  //
209
215
  //
216
+ node.jKNXSecureKeyring = null;
210
217
  try {
211
218
  (async () => {
212
219
  if (node.knxSecureSelected) {
@@ -220,7 +227,7 @@ return msg;`, "helplink": "https://github.com/Supergiovane/node-red-contrib-knx-
220
227
  if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.error("KNXUltimate-config: KNX Secure: error parsing the keyring XML: " + error.message);
221
228
  node.jKNXSecureKeyring = null;
222
229
  node.knxSecureSelected = false;
223
- setTimeout(() => node.setAllClientsStatus("Error", "red", "KNX Secure " + error.message), 2000);
230
+ let t = setTimeout(() => node.setAllClientsStatus("Error", "red", "KNX Secure " + error.message), 2000); // 21/03/2022 fixed possible memory leak. Previously was setTimeout without "let t = ".
224
231
  }
225
232
 
226
233
 
@@ -323,7 +330,6 @@ return msg;`, "helplink": "https://github.com/Supergiovane/node-red-contrib-knx-
323
330
  var sGA = "";
324
331
  var sDPT = "";
325
332
  var sName = "";
326
- var sNodeID = "";
327
333
  let sOptions = "";
328
334
  try {
329
335
  if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.info("KNXUltimate-config: Total knx-ultimate nodes: " + _node.nodeClients.length || 0);
@@ -506,7 +512,7 @@ return msg;`, "helplink": "https://github.com/Supergiovane/node-red-contrib-knx-
506
512
  if (oExposedGA !== undefined) {
507
513
 
508
514
  // Retrieve the value from exposedGAs
509
- let msg = buildInputMessage({ _srcGA: "", _destGA: oClient.topic, _event: "GroupValue_Response", _Rawvalue: new Buffer.from(oExposedGA.rawValue.data), _inputDpt: oClient.dpt, _devicename: oClient.name ? oClient.name : "", _outputtopic: oClient.outputtopic, _oNode: oClient })
515
+ let msg = buildInputMessage({ _srcGA: "", _destGA: oClient.topic, _event: "GroupValue_Response", _Rawvalue: Buffer.from(oExposedGA.rawValue.data), _inputDpt: oClient.dpt, _devicename: oClient.name ? oClient.name : "", _outputtopic: oClient.outputtopic, _oNode: oClient })
510
516
  oClient.previouspayload = ""; // 05/04/2021 Added previous payload
511
517
  oClient.currentPayload = msg.payload;
512
518
  oClient.setNodeStatus({ fill: "grey", shape: "dot", text: "Update value from persist file", payload: oClient.currentPayload, GA: oClient.topic, dpt: oClient.dpt, devicename: oClient.name || "" });
@@ -596,7 +602,7 @@ return msg;`, "helplink": "https://github.com/Supergiovane/node-red-contrib-knx-
596
602
  node.Disconnect();
597
603
  // node.setKnxConnectionProperties(); // 28/12/2021 Commented
598
604
  node.setAllClientsStatus("CONFIG", "yellow", "KNXUltimage-config:setGatewayConfig: disconnected by new setting...");
599
- if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.debug("KNXUltimage-config:setGatewayConfig: disconnected by setGatewayConfig. AutoReconnect = " + oldReconnect);
605
+ if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.debug("KNXUltimage-config:setGatewayConfig: disconnected by setGatewayConfig.");
600
606
  } catch (error) { }
601
607
 
602
608
  };
@@ -619,7 +625,7 @@ return msg;`, "helplink": "https://github.com/Supergiovane/node-red-contrib-knx-
619
625
  try {
620
626
  node.autoReconnect = false;
621
627
  node.Disconnect();
622
- setTimeout(() => {
628
+ let t = setTimeout(() => { // 21/03/2022 fixed possible memory leak. Previously was setTimeout without "let t = ".
623
629
  node.setAllClientsStatus("CONFIG", "yellow", "Forced GW disconnection and stop reconnection attempts, from watchdog.");
624
630
  }, 2000);
625
631
  } catch (error) { }
@@ -759,10 +765,10 @@ return msg;`, "helplink": "https://github.com/Supergiovane/node-red-contrib-knx-
759
765
  if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.error("knxUltimate-config: Disconnected by: " + (err.message === undefined ? err : err.message));
760
766
  });
761
767
  // Call discoverCB when a knx gateway has been discovered.
762
- node.knxConnection.on(knx.KNXClient.KNXClientEvents.discover, info => {
763
- const [ip, port] = info.split(":");
764
- discoverCB(ip, port);
765
- });
768
+ // node.knxConnection.on(knx.KNXClient.KNXClientEvents.discover, info => {
769
+ // const [ip, port] = info.split(":");
770
+ // discoverCB(ip, port);
771
+ // });
766
772
  node.knxConnection.on(knx.KNXClient.KNXClientEvents.disconnected, info => {
767
773
  saveExposedGAs(); // 13/12/2021 save the current values of GA payload
768
774
  node.startTimerClearTelegramQueue(); // 21/01/2022 Clear the telegram queue after a while
@@ -785,7 +791,7 @@ return msg;`, "helplink": "https://github.com/Supergiovane/node-red-contrib-knx-
785
791
  // Start the timer to do initial read.
786
792
  if (node.timerDoInitialRead !== null) clearTimeout(node.timerDoInitialRead);
787
793
  node.timerDoInitialRead = setTimeout(DoInitialReadFromKNXBusOrFile, 6000); // 17/02/2020 Do initial read of all nodes requesting initial read
788
- setTimeout(() => {
794
+ let t = setTimeout(() => { // 21/03/2022 fixed possible memory leak. Previously was setTimeout without "let t = ".
789
795
  node.setAllClientsStatus("Connected.", "green", "On duty.")
790
796
  }, 500);
791
797
  if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.info("knxUltimate-config: Connected to %o", info);
@@ -813,7 +819,8 @@ return msg;`, "helplink": "https://github.com/Supergiovane/node-red-contrib-knx-
813
819
  } catch (error) {
814
820
  if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.error("KNXUltimate-config: Error in instantiating knxConnection " + error.message + ". Node " + node.name);
815
821
  node.linkStatus = "disconnected";
816
- setTimeout(() => node.setAllClientsStatus("Error in instantiating knxConnection " + error, "red", "Error"), 200);
822
+ // 21/03/2022 fixed possible memory leak. Previously was setTimeout without "let t = ".
823
+ let t = setTimeout(() => node.setAllClientsStatus("Error in instantiating knxConnection " + error, "red", "Error"), 200);
817
824
  }
818
825
 
819
826
  };
@@ -824,7 +831,7 @@ return msg;`, "helplink": "https://github.com/Supergiovane/node-red-contrib-knx-
824
831
  function handleBusEvents(_datagram, _echoed) {
825
832
 
826
833
 
827
- // _rawValue
834
+ let _rawValue = null;
828
835
  try {
829
836
  _rawValue = _datagram.cEMIMessage.npdu.dataValue;
830
837
  } catch (error) {
@@ -832,15 +839,15 @@ return msg;`, "helplink": "https://github.com/Supergiovane/node-red-contrib-knx-
832
839
  }
833
840
 
834
841
 
835
- // _evt
842
+ let _evt = null;
836
843
  if (_datagram.cEMIMessage.npdu.isGroupRead) _evt = "GroupValue_Read";
837
844
  if (_datagram.cEMIMessage.npdu.isGroupResponse) _evt = "GroupValue_Response";
838
845
  if (_datagram.cEMIMessage.npdu.isGroupWrite) _evt = "GroupValue_Write";
839
846
 
840
- // _src
847
+ let _src = null;
841
848
  _src = _datagram.cEMIMessage.srcAddress.toString();
842
849
 
843
- // _dest
850
+ let _dest = null;
844
851
  _dest = _datagram.cEMIMessage.dstAddress.toString();
845
852
 
846
853
  let isRepeated = _datagram.cEMIMessage.control.repeat === 1 ? false : true;
@@ -945,10 +952,12 @@ return msg;`, "helplink": "https://github.com/Supergiovane/node-red-contrib-knx-
945
952
  } else if (input.listenallga == true) {
946
953
 
947
954
  // Get the GA from CVS
948
- let oGA;
949
- try {
950
- oGA = node.csv.filter(sga => sga.ga == _dest)[0];
951
- } catch (error) { }
955
+ let oGA = undefined;
956
+ if (node.csv !== undefined) {
957
+ try {
958
+ oGA = node.csv.filter(sga => sga.ga == _dest)[0];
959
+ } catch (error) { }
960
+ }
952
961
 
953
962
  // 25/10/2019 TRY TO AUTO DECODE IF Group address not found in the CSV
954
963
  let msg = buildInputMessage({ _srcGA: _src, _destGA: _dest, _event: _evt, _Rawvalue: _rawValue, _inputDpt: (typeof oGA === "undefined") ? null : oGA.dpt, _devicename: (typeof oGA === "undefined") ? input.name || "" : oGA.devicename, _outputtopic: _dest, _oNode: input });
@@ -1251,7 +1260,7 @@ return msg;`, "helplink": "https://github.com/Supergiovane/node-red-contrib-knx-
1251
1260
  }
1252
1261
 
1253
1262
  // 14/08/2019 If the node has payload same as the received telegram, return false
1254
- checkRBEInputFromKNXBusAllowSend = (_node, _KNXTelegramPayload) => {
1263
+ function checkRBEInputFromKNXBusAllowSend(_node, _KNXTelegramPayload) {
1255
1264
  if (_node.inputRBE !== true) return true;
1256
1265
 
1257
1266
  return !_.isEqual(_node.currentPayload, _KNXTelegramPayload);
@@ -1350,7 +1359,7 @@ return msg;`, "helplink": "https://github.com/Supergiovane/node-red-contrib-knx-
1350
1359
 
1351
1360
  if (dpt !== null && _Rawvalue !== null) {
1352
1361
  try {
1353
- var jsValue = dptlib.fromBuffer(_Rawvalue, dpt)
1362
+ jsValue = dptlib.fromBuffer(_Rawvalue, dpt)
1354
1363
  if (jsValue === null) {
1355
1364
  if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.error("knxUltimate-config: buildInputMessage: received a wrong datagram form KNX BUS, from device " + _srcGA + " Destination " + _destGA + " Event " + _event + " GA's Datapoint " + (_inputDpt === null ? "THE ETS FILE HAS NOT BEEN IMPORTED, SO I'M TRYING TO FIGURE OUT WHAT DATAPOINT BELONGS THIS GROUP ADDRESS. DON'T BLAME ME IF I'M WRONG, INSTEAD, IMPORT THE ETS FILE!" : _inputDpt) + " Devicename " + _devicename + " Topic " + _outputtopic + " NodeID " + _oNode.id || "");
1356
1365
  }
@@ -1720,7 +1729,6 @@ return msg;`, "helplink": "https://github.com/Supergiovane/node-red-contrib-knx-
1720
1729
 
1721
1730
  let msg = {
1722
1731
  topic: _msg.grpaddr,//input.topic,
1723
- payload: _msg.payload,
1724
1732
  devicename: (typeof oGA === "undefined") ? input.name || "" : oGA.devicename,
1725
1733
  payload: _msg.payload,
1726
1734
  knx: { event: sEvent, dpt: _msg.dpt, destination: _msg.grpaddr },
@@ -1739,7 +1747,6 @@ return msg;`, "helplink": "https://github.com/Supergiovane/node-red-contrib-knx-
1739
1747
 
1740
1748
  let msg = {
1741
1749
  topic: input.outputtopic,
1742
- payload: _msg.payload,
1743
1750
  devicename: input.name ? input.name : "",
1744
1751
  payload: _msg.payload,
1745
1752
  knx: { event: sEvent, dpt: _msg.dpt, destination: _msg.grpaddr },
@@ -1774,7 +1781,7 @@ return msg;`, "helplink": "https://github.com/Supergiovane/node-red-contrib-knx-
1774
1781
  // If the node is disconnected, wait another cycle, then reconnects
1775
1782
  if (node.allowLauch_initKNXConnection && node.autoReconnect) {
1776
1783
  node.allowLauch_initKNXConnection = false;
1777
- setTimeout(() => {
1784
+ let t = setTimeout(() => { // 21/03/2022 fixed possible memory leak. Previously was setTimeout without "let t = ".
1778
1785
  node.setAllClientsStatus("Auto reconnect in progress...", "grey", "");
1779
1786
  }, 100);
1780
1787
  if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.debug("knxUltimate-config: Auto Reconect by timerKNXUltimateCheckState in progress. node.LinkStatus:" + node.linkStatus + ", node.autoReconnect:" + node.autoReconnect);
@@ -1783,7 +1790,7 @@ return msg;`, "helplink": "https://github.com/Supergiovane/node-red-contrib-knx-
1783
1790
  }
1784
1791
  if (node.linkStatus === "disconnected" && node.autoReconnect) {
1785
1792
  node.allowLauch_initKNXConnection = true; // Next cycle, launch initKNXConnection, so it pauses more and leave more time
1786
- setTimeout(() => {
1793
+ let t = setTimeout(() => { // 21/03/2022 fixed possible memory leak. Previously was setTimeout without "let t = ".
1787
1794
  node.setAllClientsStatus("Next cycle will reconnect...", "grey", "");
1788
1795
  }, 1000);
1789
1796
  if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.debug("knxUltimate-config: Waiting next cycle to reconect. node.LinkStatus:" + node.linkStatus + ", node.autoReconnect:" + node.autoReconnect);