node-red-contrib-tcp-client-server-avd 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -26,10 +26,11 @@ npm install
26
26
  ### TCP Client Mode
27
27
  - Automatisch verbinden bij flow start (optioneel)
28
28
  - Handmatig verbinden/verbreken via messages
29
- - Automatische herconnectie met configureerbare instellingen
29
+ - Robuuste automatische herconnectie (detectie via error, close en write-fouten)
30
+ - Snelle herverbinding (standaard 2 sec, minimum 1 sec)
30
31
  - Ondersteuning voor verschillende dataformaten (String, Buffer, JSON, Hex)
31
32
  - Message delimiter ondersteuning voor message framing
32
- - Keep-alive optie
33
+ - Keep-alive optie (aanbevolen voor detectie van half-open verbindingen)
33
34
 
34
35
  ### TCP Server Mode
35
36
  - Automatisch starten bij flow start (optioneel)
@@ -198,6 +199,15 @@ Als er geen topic is opgegeven, wordt de payload automatisch verzonden.
198
199
  }
199
200
  ```
200
201
 
202
+ ### ClientId bepalen (Server Mode)
203
+
204
+ Om naar een specifieke client te sturen heb je de `clientId` nodig. Deze is beschikbaar in:
205
+
206
+ 1. **`client/connected`** – bij elke nieuwe clientverbinding
207
+ 2. **`data`** – bij elk ontvangen bericht (via `msg.clientId`)
208
+
209
+ Bewaar de `clientId` uit een van deze messages en gebruik deze in je `send` message met `clientId: msg.clientId`.
210
+
201
211
  ## Configuratie Opties
202
212
 
203
213
  ### Client Mode
@@ -207,14 +217,14 @@ Als er geen topic is opgegeven, wordt de payload automatisch verzonden.
207
217
  - **IP Versie**: IPv4 of IPv6 (standaard: IPv4)
208
218
  - **Auto Verbinden**: Automatisch verbinden bij flow start (standaard: true)
209
219
  - **Herconnectie**: Automatische herconnectie bij verbroken verbinding (standaard: true)
210
- - **Reconnect Interval**: Tijd tussen reconnect pogingen in seconden (standaard: 5)
220
+ - **Reconnect Interval**: Tijd tussen reconnect pogingen in seconden (standaard: 2, minimum: 1)
211
221
  - **Max Reconnect Pogingen**: Maximum aantal reconnect pogingen (0 = oneindig, standaard: 0)
212
- - **Connection Timeout**: Timeout voor connectiepogingen in seconden (standaard: 10)
222
+ - **Connection Timeout**: Timeout voor het opzetten van de verbinding in seconden (standaard: 10). Wordt na succesvol verbinden uitgeschakeld; geen idle-timeout.
213
223
  - **Input Format**: Data formaat voor verzenden (String, Buffer, JSON, Hex String)
214
224
  - **Output Format**: Data formaat voor ontvangen (String, Buffer, JSON, Hex String)
215
225
  - **Encoding**: Character encoding voor String format (UTF-8, ASCII, Latin1, Base64)
216
226
  - **Message Delimiter**: Optionele delimiter voor message framing (bijv. `\n` of `\r\n`)
217
- - **Keep-Alive**: TCP keep-alive optie (standaard: false)
227
+ - **Keep-Alive**: TCP keep-alive optie (standaard: false). Aanbevolen voor vroegtijdige detectie van verbroken verbindingen.
218
228
 
219
229
  ### Server Mode
220
230
 
@@ -228,7 +238,7 @@ Als er geen topic is opgegeven, wordt de payload automatisch verzonden.
228
238
  - **Output Format**: Data formaat voor ontvangen (String, Buffer, JSON, Hex String)
229
239
  - **Encoding**: Character encoding voor String format (UTF-8, ASCII, Latin1, Base64)
230
240
  - **Message Delimiter**: Optionele delimiter voor message framing (bijv. `\n` of `\r\n`)
231
- - **Keep-Alive**: TCP keep-alive optie (standaard: false)
241
+ - **Keep-Alive**: TCP keep-alive optie (standaard: false). Aanbevolen voor vroegtijdige detectie van verbroken verbindingen.
232
242
 
233
243
  ## Status Weergave
234
244
 
@@ -286,7 +296,7 @@ Een TCP client met automatische herconnectie.
286
296
  - Port: 8080
287
297
  - Auto Verbinden: aan
288
298
  - Herconnectie: aan
289
- - Reconnect Interval: 5 seconden
299
+ - Reconnect Interval: 2 seconden (of 1 voor snellere herverbinding)
290
300
  - Max Reconnect Pogingen: 0 (oneindig)
291
301
 
292
302
  ### Voorbeeld 4: Server met Meerdere Clients
@@ -300,10 +310,15 @@ Een TCP server die data ontvangt van meerdere clients en responses terugstuurt.
300
310
 
301
311
  **Function Node code:**
302
312
  ```javascript
303
- // Echo de data terug naar dezelfde client
304
- msg.topic = "send";
305
- msg.payload = "Echo: " + msg.payload;
306
- return msg;
313
+ // Echo de data terug naar dezelfde client (clientId uit ontvangen bericht)
314
+ if (msg.topic === "data") {
315
+ return {
316
+ topic: "send",
317
+ clientId: msg.clientId,
318
+ payload: "Echo: " + msg.payload
319
+ };
320
+ }
321
+ return null;
307
322
  ```
308
323
 
309
324
  ## Troubleshooting
@@ -341,6 +356,13 @@ MIT
341
356
 
342
357
  ## Versie Geschiedenis
343
358
 
359
+ ### Versie 1.1.0
360
+ - Robuuste verbindingscontrole: error handler triggert socket.destroy() voor betrouwbare herverbinding
361
+ - Write-error detectie: bij mislukte verzending wordt herverbinding gestart
362
+ - Snellere herverbinding: standaard 2 sec, minimum 1 sec
363
+ - Geen idle-timeout na verbinden: verbinding blijft open zolang beide partijen verbonden zijn
364
+ - Voorkomen dubbele reconnect en race conditions
365
+
344
366
  ### Versie 1.0.0
345
367
  - Initiele release
346
368
  - TCP Client functionaliteit
@@ -11,7 +11,7 @@
11
11
  clientIpVersion: { value: "4" },
12
12
  clientAutoConnect: { value: true },
13
13
  clientReconnect: { value: true },
14
- clientReconnectInterval: { value: 5, validate: function(v) { return /^\d+$/.test(v) && v >= 0; } },
14
+ clientReconnectInterval: { value: 2, validate: function(v) { return /^\d+$/.test(v) && v >= 1; } },
15
15
  clientMaxReconnectAttempts: { value: 0, validate: function(v) { return /^\d+$/.test(v) && v >= 0; } },
16
16
  clientConnectionTimeout: { value: 10, validate: function(v) { return /^\d+$/.test(v) && v > 0; } },
17
17
  clientInputFormat: { value: "string" },
@@ -118,7 +118,7 @@
118
118
 
119
119
  <div class="form-row">
120
120
  <label for="node-input-clientReconnectInterval"><i class="fa fa-clock-o"></i> Reconnect Interval (sec)</label>
121
- <input type="number" id="node-input-clientReconnectInterval" placeholder="5" min="0">
121
+ <input type="number" id="node-input-clientReconnectInterval" placeholder="2" min="1" title="Minimum 1 seconde voor snelle herverbinding">
122
122
  </div>
123
123
 
124
124
  <div class="form-row">
@@ -118,7 +118,7 @@ module.exports = function(RED) {
118
118
  ipVersion: config.clientIpVersion || "4",
119
119
  autoConnect: config.clientAutoConnect !== false,
120
120
  reconnect: config.clientReconnect !== false,
121
- reconnectInterval: parseInt(config.clientReconnectInterval) || 5,
121
+ reconnectInterval: Math.max(1, parseInt(config.clientReconnectInterval) || 2),
122
122
  maxReconnectAttempts: parseInt(config.clientMaxReconnectAttempts) || 0,
123
123
  connectionTimeout: parseInt(config.clientConnectionTimeout) || 10,
124
124
  inputFormat: config.clientInputFormat || "string",
@@ -257,6 +257,9 @@ module.exports = function(RED) {
257
257
 
258
258
  socket.on('close', function(hadError) {
259
259
  node.clientConnected = false;
260
+ if (node.clientSocket === socket) {
261
+ node.clientSocket = null;
262
+ }
260
263
  node.status({ fill: "red", shape: "ring", text: "verbinding gesloten" });
261
264
 
262
265
  const msg = {
@@ -267,11 +270,15 @@ module.exports = function(RED) {
267
270
  };
268
271
  node.send(msg);
269
272
 
270
- if (node.clientConfig.reconnect && (node.clientConfig.maxReconnectAttempts === 0 || node.clientReconnectAttempts < node.clientConfig.maxReconnectAttempts)) {
273
+ // Robuuste herverbinding: alleen starten als nog geen timer loopt
274
+ if (!node.clientReconnectTimer && node.clientConfig.reconnect &&
275
+ (node.clientConfig.maxReconnectAttempts === 0 || node.clientReconnectAttempts < node.clientConfig.maxReconnectAttempts)) {
271
276
  node.clientReconnectAttempts++;
277
+ const intervalMs = node.clientConfig.reconnectInterval * 1000;
272
278
  node.clientReconnectTimer = setTimeout(function() {
279
+ node.clientReconnectTimer = null;
273
280
  clientConnect();
274
- }, node.clientConfig.reconnectInterval * 1000);
281
+ }, intervalMs);
275
282
  node.status({ fill: "yellow", shape: "ring", text: `herconnectie in ${node.clientConfig.reconnectInterval}s...` });
276
283
  }
277
284
  });
@@ -287,6 +294,8 @@ module.exports = function(RED) {
287
294
  error: err.message
288
295
  };
289
296
  node.send(msg);
297
+ // Socket vernietigen zodat 'close' wordt getriggerd en herverbinding start
298
+ try { socket.destroy(); } catch (e) { /* negeer */ }
290
299
  });
291
300
 
292
301
  socket.on('timeout', function() {
@@ -330,9 +339,17 @@ module.exports = function(RED) {
330
339
  toSend = Buffer.concat([formatted, delim]);
331
340
  }
332
341
 
333
- node.clientSocket.write(toSend);
342
+ node.clientSocket.write(toSend, function(err) {
343
+ if (err) {
344
+ node.clientConnected = false;
345
+ node.error("Verzenden mislukt: " + err.message);
346
+ try { node.clientSocket.destroy(); } catch (e) { /* negeer */ }
347
+ }
348
+ });
334
349
  } catch (err) {
350
+ node.clientConnected = false;
335
351
  node.error("Fout bij verzenden: " + err.message);
352
+ try { if (node.clientSocket) node.clientSocket.destroy(); } catch (e) { /* negeer */ }
336
353
  }
337
354
  }
338
355
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-tcp-client-server-avd",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Node-RED node voor TCP client en/of server functionaliteit",
5
5
  "keywords": [
6
6
  "node-red",
@@ -14,7 +14,7 @@
14
14
  "tcp-client-server-avd": "nodes/tcp-client-server.js"
15
15
  }
16
16
  },
17
- "author": "",
17
+ "author": "Arie van Dijke",
18
18
  "license": "MIT",
19
19
  "engines": {
20
20
  "node": ">=12.0.0"