@atelieruldetehnologii/node-red-custome-solutions 0.62.22

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 (107) hide show
  1. package/NOTICE +56 -0
  2. package/PROPRIETARY-LICENSE.txt +157 -0
  3. package/README.md +105 -0
  4. package/TERMS-AND-CONDITIONS.md +311 -0
  5. package/advantech-read/advantech-read.html +775 -0
  6. package/advantech-read/advantech-read.js +449 -0
  7. package/advantech-write/advantech-write.html +413 -0
  8. package/advantech-write/advantech-write.js +338 -0
  9. package/bess-control/bess-control.html +569 -0
  10. package/bess-control/bess-control.js +541 -0
  11. package/bess-control/lib/allocation.js +149 -0
  12. package/bess-control/lib/batteries.js +86 -0
  13. package/bess-control/lib/helpers.js +157 -0
  14. package/bess-control/lib/messages.js +131 -0
  15. package/bess-control/lib/runtime.js +156 -0
  16. package/carlo-gavazzi/carlo-gavazzi.html +4327 -0
  17. package/carlo-gavazzi/carlo-gavazzi.js +3081 -0
  18. package/control-export/control-export.html +3644 -0
  19. package/control-export/control-export.js +2192 -0
  20. package/control-reactive/control-reactive.html +3136 -0
  21. package/control-reactive/control-reactive.js +2124 -0
  22. package/fronius-emulator/README.md +258 -0
  23. package/fronius-emulator/fronius-emulator.html +170 -0
  24. package/fronius-emulator/fronius-emulator.js +520 -0
  25. package/fronius-emulator/lib/binary-codec.js +65 -0
  26. package/fronius-emulator/lib/fronius-register-map.js +185 -0
  27. package/fronius-emulator/lib/modbus-parser.js +61 -0
  28. package/fronius-emulator/lib/modbus-tcp-server.js +224 -0
  29. package/fronius-emulator/lib/validation.js +206 -0
  30. package/fronius-emulator/lib/virtual-meter.js +132 -0
  31. package/fronius-read/fronius-read.html +3944 -0
  32. package/fronius-read/fronius-read.js +1466 -0
  33. package/fronius-read/lib/inverter-profiles.js +711 -0
  34. package/fronius-read/lib/sunspec-core.js +303 -0
  35. package/fronius-read/lib/sunspec-model-parsers.js +845 -0
  36. package/fronius-write/fronius-write.html +1789 -0
  37. package/fronius-write/fronius-write.js +2531 -0
  38. package/influxdb/influxdb.html +1077 -0
  39. package/influxdb/influxdb.js +1487 -0
  40. package/janitza/janitza.html +2562 -0
  41. package/janitza/janitza.js +1500 -0
  42. package/janitza/lib/janitza-profiles.js +371 -0
  43. package/lib/a3-test-server.js +199 -0
  44. package/lib/adam-6000-profiles.js +173 -0
  45. package/lib/licensing/constants.js +103 -0
  46. package/lib/licensing/device-id.js +251 -0
  47. package/lib/licensing/errors.js +21 -0
  48. package/lib/licensing/license-client.js +377 -0
  49. package/lib/licensing/license-state.js +50 -0
  50. package/lib/licensing/node-guard.js +150 -0
  51. package/lib/licensing/package-integrity.js +167 -0
  52. package/lib/licensing/package-integrity.json +513 -0
  53. package/lib/licensing/public-key.pem +3 -0
  54. package/lib/licensing/public-key.pem.example +2 -0
  55. package/lib/licensing/public-keys.js +18 -0
  56. package/lib/licensing/storage.js +63 -0
  57. package/lib/licensing/token-verifier.js +84 -0
  58. package/lib/numbers.js +26 -0
  59. package/license/atelier-license.html +88 -0
  60. package/license/atelier-license.js +170 -0
  61. package/modbus-tcp-discover/modbus-tcp-discover.html +190 -0
  62. package/modbus-tcp-discover/modbus-tcp-discover.js +706 -0
  63. package/multi-battery/multi-battery.html +649 -0
  64. package/multi-battery/multi-battery.js +668 -0
  65. package/multi-grid/multi-grid.html +745 -0
  66. package/multi-grid/multi-grid.js +1392 -0
  67. package/multi-inverter/lib/engine-core.js +237 -0
  68. package/multi-inverter/multi-inverter.html +2674 -0
  69. package/multi-inverter/multi-inverter.js +1393 -0
  70. package/package.json +109 -0
  71. package/phoenix-contact/lib/eem-ma370-advanced.js +175 -0
  72. package/phoenix-contact/lib/eem-ma370.js +138 -0
  73. package/phoenix-contact/lib/integrations.js +149 -0
  74. package/phoenix-contact/lib/phoenix-contact-profile.js +35030 -0
  75. package/phoenix-contact/phoenix-contact.html +840 -0
  76. package/phoenix-contact/phoenix-contact.js +679 -0
  77. package/pv-generator/pv-generator.html +284 -0
  78. package/pv-generator/pv-generator.js +387 -0
  79. package/pylontech-read/pylontech-read.html +763 -0
  80. package/pylontech-read/pylontech-read.js +518 -0
  81. package/pylontech-write/pylontech-write.html +405 -0
  82. package/pylontech-write/pylontech-write.js +546 -0
  83. package/scada-aggregator/lib/aggregate.js +72 -0
  84. package/scada-aggregator/lib/groups.js +39 -0
  85. package/scada-aggregator/scada-aggregator.html +108 -0
  86. package/scada-aggregator/scada-aggregator.js +117 -0
  87. package/scada-server/lib/aggregator-map.js +58 -0
  88. package/scada-server/lib/encoding.js +235 -0
  89. package/scada-server/lib/modbus-server.js +492 -0
  90. package/scada-server/lib/object-path.js +18 -0
  91. package/scada-server/lib/register-map.js +288 -0
  92. package/scada-server/scada-server.html +1419 -0
  93. package/scada-server/scada-server.js +704 -0
  94. package/scripts/check-syntax.js +66 -0
  95. package/scripts/package-integrity.js +46 -0
  96. package/scripts/package-release.js +116 -0
  97. package/scripts/run-tests.js +2178 -0
  98. package/scripts/tgz-integrity.js +74 -0
  99. package/sma-read/lib/sunspec-core.js +83 -0
  100. package/sma-read/lib/sunspec-model-parsers.js +853 -0
  101. package/sma-read/sma-read.html +659 -0
  102. package/sma-read/sma-read.js +458 -0
  103. package/sma-write/sma-write.html +105 -0
  104. package/sma-write/sma-write.js +270 -0
  105. package/victron-read/lib/mqtt-state.js +176 -0
  106. package/victron-read/victron-read.html +1074 -0
  107. package/victron-read/victron-read.js +1222 -0
@@ -0,0 +1,492 @@
1
+ "use strict";
2
+
3
+
4
+ const net = require("net");
5
+
6
+
7
+ function normalizeIp(address) {
8
+
9
+ const raw = String(address || "").trim();
10
+
11
+ if (!raw) {
12
+ return null;
13
+ }
14
+
15
+ if (raw.startsWith("::ffff:")) {
16
+ return raw.slice(7);
17
+ }
18
+
19
+ return raw;
20
+
21
+ }
22
+
23
+
24
+ function notify(options, key, payload) {
25
+
26
+ if (typeof options[key] === "function") {
27
+ options[key](payload);
28
+ }
29
+
30
+ }
31
+
32
+
33
+ function exceptionResponse(transactionId, unitId, functionCode, exceptionCode) {
34
+
35
+ const pdu = Buffer.from([functionCode | 0x80, exceptionCode]);
36
+
37
+ const response = Buffer.allocUnsafe(7 + pdu.length);
38
+
39
+ response.writeUInt16BE(transactionId, 0);
40
+
41
+ response.writeUInt16BE(0, 2);
42
+
43
+ response.writeUInt16BE(pdu.length + 1, 4);
44
+
45
+ response.writeUInt8(unitId, 6);
46
+
47
+ pdu.copy(response, 7);
48
+
49
+ return response;
50
+
51
+ }
52
+
53
+
54
+ function registerResponse(transactionId, unitId, functionCode, words) {
55
+
56
+ const byteCount = words.length * 2;
57
+
58
+ const pdu = Buffer.allocUnsafe(2 + byteCount);
59
+
60
+ pdu.writeUInt8(functionCode & 0xFF, 0);
61
+
62
+ pdu.writeUInt8(byteCount, 1);
63
+
64
+
65
+ words.forEach(function (word, index) {
66
+
67
+ pdu.writeUInt16BE(word & 0xFFFF, 2 + (index * 2));
68
+
69
+ });
70
+
71
+
72
+ const response = Buffer.allocUnsafe(7 + pdu.length);
73
+
74
+ response.writeUInt16BE(transactionId, 0);
75
+
76
+ response.writeUInt16BE(0, 2);
77
+
78
+ response.writeUInt16BE(pdu.length + 1, 4);
79
+
80
+ response.writeUInt8(unitId, 6);
81
+
82
+ pdu.copy(response, 7);
83
+
84
+ return response;
85
+
86
+ }
87
+
88
+
89
+ function writeSingleRegisterResponse(transactionId, unitId, address, value) {
90
+
91
+ const pdu = Buffer.allocUnsafe(5);
92
+
93
+ pdu.writeUInt8(6, 0);
94
+
95
+ pdu.writeUInt16BE(address & 0xFFFF, 1);
96
+
97
+ pdu.writeUInt16BE(value & 0xFFFF, 3);
98
+
99
+
100
+ const response = Buffer.allocUnsafe(7 + pdu.length);
101
+
102
+ response.writeUInt16BE(transactionId, 0);
103
+
104
+ response.writeUInt16BE(0, 2);
105
+
106
+ response.writeUInt16BE(pdu.length + 1, 4);
107
+
108
+ response.writeUInt8(unitId, 6);
109
+
110
+ pdu.copy(response, 7);
111
+
112
+ return response;
113
+
114
+ }
115
+
116
+
117
+ function writeMultipleRegistersResponse(transactionId, unitId, startAddress, quantity) {
118
+
119
+ const pdu = Buffer.allocUnsafe(5);
120
+
121
+ pdu.writeUInt8(16, 0);
122
+
123
+ pdu.writeUInt16BE(startAddress & 0xFFFF, 1);
124
+
125
+ pdu.writeUInt16BE(quantity & 0xFFFF, 3);
126
+
127
+
128
+ const response = Buffer.allocUnsafe(7 + pdu.length);
129
+
130
+ response.writeUInt16BE(transactionId, 0);
131
+
132
+ response.writeUInt16BE(0, 2);
133
+
134
+ response.writeUInt16BE(pdu.length + 1, 4);
135
+
136
+ response.writeUInt8(unitId, 6);
137
+
138
+ pdu.copy(response, 7);
139
+
140
+ return response;
141
+
142
+ }
143
+
144
+
145
+ function createModbusServer(options) {
146
+
147
+ const maxConnections = Math.max(1, Number(options.maxConnections || 20));
148
+ const socketIdleTimeoutMs = Math.max(500, Number(options.socketIdleTimeoutMs || 30000));
149
+ const rateLimitPerSecond = Math.max(0, Number(options.rateLimitPerSecond || 0));
150
+
151
+ let server = null;
152
+ let clientCount = 0;
153
+ const sockets = new Set();
154
+ const requestsByClient = new Map();
155
+
156
+ function emitProtocolIssue(code, details) {
157
+
158
+ notify(options, "onProtocolIssue", Object.assign({
159
+ code: code,
160
+ timestampMs: Date.now()
161
+ }, details || {}));
162
+
163
+ }
164
+
165
+ function isRateLimited(remoteAddress) {
166
+
167
+ if (!rateLimitPerSecond || !remoteAddress) {
168
+ return false;
169
+ }
170
+
171
+ const now = Date.now();
172
+ const existing = requestsByClient.get(remoteAddress) || { windowStartMs: now, count: 0 };
173
+
174
+ if ((now - existing.windowStartMs) >= 1000) {
175
+ existing.windowStartMs = now;
176
+ existing.count = 0;
177
+ }
178
+
179
+ existing.count += 1;
180
+ requestsByClient.set(remoteAddress, existing);
181
+
182
+ return existing.count > rateLimitPerSecond;
183
+
184
+ }
185
+
186
+ function start() {
187
+
188
+ if (server) {
189
+ return Promise.resolve();
190
+ }
191
+
192
+ server = net.createServer(function (socket) {
193
+
194
+ const remoteAddress = normalizeIp(socket.remoteAddress);
195
+
196
+ if (clientCount >= maxConnections) {
197
+ emitProtocolIssue("max_connections_exceeded", { remoteAddress: remoteAddress });
198
+ socket.destroy();
199
+ return;
200
+ }
201
+
202
+ sockets.add(socket);
203
+ clientCount += 1;
204
+ notify(options, "onClientChange", clientCount);
205
+ notify(options, "onClientConnected", {
206
+ remoteAddress: remoteAddress,
207
+ remotePort: socket.remotePort || null,
208
+ timestampMs: Date.now(),
209
+ clientCount: clientCount
210
+ });
211
+
212
+ let rxBuffer = Buffer.alloc(0);
213
+
214
+ socket.setTimeout(socketIdleTimeoutMs);
215
+
216
+ socket.on("timeout", function () {
217
+ emitProtocolIssue("socket_idle_timeout", { remoteAddress: remoteAddress });
218
+ socket.destroy();
219
+ });
220
+
221
+ socket.on("data", function (chunk) {
222
+
223
+ try {
224
+
225
+ if (!Buffer.isBuffer(chunk) || !chunk.length) {
226
+ return;
227
+ }
228
+
229
+ rxBuffer = rxBuffer.length ? Buffer.concat([rxBuffer, chunk]) : chunk;
230
+
231
+ while (rxBuffer.length >= 7) {
232
+
233
+ const length = rxBuffer.readUInt16BE(4);
234
+ const frameLength = 6 + length;
235
+
236
+ if (length < 2) {
237
+ emitProtocolIssue("invalid_mbap_length", { remoteAddress: remoteAddress, length: length });
238
+ rxBuffer = Buffer.alloc(0);
239
+ break;
240
+ }
241
+
242
+ if (rxBuffer.length < frameLength) {
243
+ break;
244
+ }
245
+
246
+ const frame = rxBuffer.subarray(0, frameLength);
247
+ rxBuffer = rxBuffer.subarray(frameLength);
248
+
249
+ if (frame.length < 12) {
250
+ emitProtocolIssue("short_frame", { remoteAddress: remoteAddress, frameLength: frame.length });
251
+ continue;
252
+ }
253
+
254
+ const transactionId = frame.readUInt16BE(0);
255
+ const protocolId = frame.readUInt16BE(2);
256
+ const unitId = frame.readUInt8(6);
257
+ const functionCode = frame.readUInt8(7);
258
+
259
+ if (protocolId !== 0) {
260
+ emitProtocolIssue("invalid_protocol_id", { remoteAddress: remoteAddress, protocolId: protocolId });
261
+ socket.write(exceptionResponse(transactionId, unitId, functionCode || 0, 4));
262
+ continue;
263
+ }
264
+
265
+ if (options.unitId !== 0 && unitId !== options.unitId) {
266
+ emitProtocolIssue("unit_id_mismatch", { remoteAddress: remoteAddress, expectedUnitId: options.unitId, actualUnitId: unitId });
267
+ socket.write(exceptionResponse(transactionId, unitId, functionCode, 11));
268
+ continue;
269
+ }
270
+
271
+ if (functionCode !== 3 && functionCode !== 4 && functionCode !== 6 && functionCode !== 16) {
272
+ emitProtocolIssue("unsupported_function", { remoteAddress: remoteAddress, functionCode: functionCode });
273
+ socket.write(exceptionResponse(transactionId, unitId, functionCode, 1));
274
+ continue;
275
+ }
276
+
277
+ if (isRateLimited(remoteAddress)) {
278
+ emitProtocolIssue("rate_limited", { remoteAddress: remoteAddress, rateLimitPerSecond: rateLimitPerSecond });
279
+ socket.write(exceptionResponse(transactionId, unitId, functionCode, 6));
280
+ continue;
281
+ }
282
+
283
+ const startAddress = frame.readUInt16BE(8);
284
+
285
+ if (functionCode === 6) {
286
+ const value = frame.readUInt16BE(10);
287
+
288
+ if (typeof options.writeSingleRegister !== "function") {
289
+ emitProtocolIssue("write_not_supported", { remoteAddress: remoteAddress, functionCode: functionCode });
290
+ socket.write(exceptionResponse(transactionId, unitId, functionCode, 1));
291
+ continue;
292
+ }
293
+
294
+ notify(options, "onWrite", {
295
+ remoteAddress: remoteAddress,
296
+ unitId: unitId,
297
+ functionCode: functionCode,
298
+ startAddress: startAddress,
299
+ quantity: 1,
300
+ values: [value],
301
+ timestampMs: Date.now()
302
+ });
303
+
304
+ const writeResult = options.writeSingleRegister(startAddress, value);
305
+
306
+ if (writeResult && typeof writeResult === "object" && writeResult.exceptionCode) {
307
+ emitProtocolIssue(writeResult.issueCode || "write_exception", {
308
+ remoteAddress: remoteAddress,
309
+ startAddress: startAddress,
310
+ quantity: 1,
311
+ exceptionCode: writeResult.exceptionCode
312
+ });
313
+ socket.write(exceptionResponse(transactionId, unitId, functionCode, writeResult.exceptionCode));
314
+ continue;
315
+ }
316
+
317
+ socket.write(writeSingleRegisterResponse(transactionId, unitId, startAddress, value));
318
+ continue;
319
+ }
320
+
321
+ const quantity = frame.readUInt16BE(10);
322
+
323
+ if (functionCode === 16) {
324
+ const byteCount = frame.readUInt8(12);
325
+
326
+ if (quantity < 1 || quantity > 123 || byteCount !== quantity * 2 || frame.length < (13 + byteCount)) {
327
+ emitProtocolIssue("invalid_write_multiple", { remoteAddress: remoteAddress, quantity: quantity, byteCount: byteCount });
328
+ socket.write(exceptionResponse(transactionId, unitId, functionCode, 3));
329
+ continue;
330
+ }
331
+
332
+ if (typeof options.writeHoldingRegisters !== "function") {
333
+ emitProtocolIssue("write_not_supported", { remoteAddress: remoteAddress, functionCode: functionCode });
334
+ socket.write(exceptionResponse(transactionId, unitId, functionCode, 1));
335
+ continue;
336
+ }
337
+
338
+ const values = [];
339
+ for (let i = 0; i < quantity; i++) {
340
+ values.push(frame.readUInt16BE(13 + (i * 2)));
341
+ }
342
+
343
+ notify(options, "onWrite", {
344
+ remoteAddress: remoteAddress,
345
+ unitId: unitId,
346
+ functionCode: functionCode,
347
+ startAddress: startAddress,
348
+ quantity: quantity,
349
+ values: values,
350
+ timestampMs: Date.now()
351
+ });
352
+
353
+ const writeResult = options.writeHoldingRegisters(startAddress, values);
354
+
355
+ if (writeResult && typeof writeResult === "object" && writeResult.exceptionCode) {
356
+ emitProtocolIssue(writeResult.issueCode || "write_exception", {
357
+ remoteAddress: remoteAddress,
358
+ startAddress: startAddress,
359
+ quantity: quantity,
360
+ exceptionCode: writeResult.exceptionCode
361
+ });
362
+ socket.write(exceptionResponse(transactionId, unitId, functionCode, writeResult.exceptionCode));
363
+ continue;
364
+ }
365
+
366
+ socket.write(writeMultipleRegistersResponse(transactionId, unitId, startAddress, quantity));
367
+ continue;
368
+ }
369
+
370
+ if (quantity < 1 || quantity > 125) {
371
+ emitProtocolIssue("invalid_quantity", { remoteAddress: remoteAddress, quantity: quantity });
372
+ socket.write(exceptionResponse(transactionId, unitId, functionCode, 3));
373
+ continue;
374
+ }
375
+
376
+ notify(options, "onRead", {
377
+ remoteAddress: remoteAddress,
378
+ unitId: unitId,
379
+ functionCode: functionCode,
380
+ startAddress: startAddress,
381
+ quantity: quantity,
382
+ timestampMs: Date.now()
383
+ });
384
+
385
+ const readResult = options.readHoldingRegisters(startAddress, quantity);
386
+
387
+ if (readResult && typeof readResult === "object" && !Array.isArray(readResult) && readResult.exceptionCode) {
388
+ emitProtocolIssue(readResult.issueCode || "read_exception", {
389
+ remoteAddress: remoteAddress,
390
+ startAddress: startAddress,
391
+ quantity: quantity,
392
+ exceptionCode: readResult.exceptionCode
393
+ });
394
+ socket.write(exceptionResponse(transactionId, unitId, functionCode, readResult.exceptionCode));
395
+ continue;
396
+ }
397
+
398
+ const words = Array.isArray(readResult) ? readResult : [];
399
+ socket.write(registerResponse(transactionId, unitId, functionCode, words));
400
+
401
+ }
402
+
403
+ } catch (err) {
404
+
405
+ emitProtocolIssue("parser_error", { remoteAddress: remoteAddress, message: err.message });
406
+ notify(options, "onError", err);
407
+
408
+ }
409
+
410
+ });
411
+
412
+ socket.on("close", function () {
413
+
414
+ sockets.delete(socket);
415
+ clientCount = Math.max(0, clientCount - 1);
416
+ notify(options, "onClientChange", clientCount);
417
+ notify(options, "onClientDisconnected", {
418
+ remoteAddress: remoteAddress,
419
+ timestampMs: Date.now(),
420
+ clientCount: clientCount
421
+ });
422
+
423
+ });
424
+
425
+ socket.on("error", function (err) {
426
+ emitProtocolIssue("socket_error", { remoteAddress: remoteAddress, message: err.message });
427
+ notify(options, "onError", err);
428
+ });
429
+
430
+ });
431
+
432
+ return new Promise(function (resolve, reject) {
433
+
434
+ function handleListenError(err) {
435
+ server = null;
436
+ reject(err);
437
+ }
438
+
439
+ server.once("error", handleListenError);
440
+
441
+ server.listen(options.port, options.host, function () {
442
+
443
+ server.off("error", handleListenError);
444
+ resolve();
445
+
446
+ });
447
+
448
+ });
449
+
450
+ }
451
+
452
+ function stop() {
453
+
454
+ if (!server) {
455
+ return Promise.resolve();
456
+ }
457
+
458
+ const current = server;
459
+ server = null;
460
+
461
+ return new Promise(function (resolve) {
462
+
463
+ sockets.forEach(function (socket) {
464
+ socket.destroy();
465
+ });
466
+
467
+ current.close(function () {
468
+ clientCount = 0;
469
+ sockets.clear();
470
+ requestsByClient.clear();
471
+ notify(options, "onClientChange", clientCount);
472
+ resolve();
473
+ });
474
+
475
+ });
476
+
477
+ }
478
+
479
+ return {
480
+ start,
481
+ stop,
482
+ address: function () {
483
+ return server ? server.address() : null;
484
+ }
485
+ };
486
+
487
+ }
488
+
489
+
490
+ module.exports = {
491
+ createModbusServer
492
+ };
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+
3
+
4
+ function getByPath(source, path) {
5
+
6
+ if (!source || !path) {
7
+ return undefined;
8
+ }
9
+
10
+ return String(path).split(".").reduce(function (acc, key) {
11
+ return acc != null ? acc[key] : undefined;
12
+ }, source);
13
+ }
14
+
15
+
16
+ module.exports = {
17
+ getByPath
18
+ };