node-red-contrib-my-tools 1.0.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.
Files changed (67) hide show
  1. package/README.txt +69 -0
  2. package/node-red-contrib-mysql-extended-test/mysql-extended.html +443 -0
  3. package/node-red-contrib-mysql-extended-test/mysql-extended.js +355 -0
  4. package/node-red-contrib-rfid-helper/rfid-lazy.html +153 -0
  5. package/node-red-contrib-rfid-helper/rfid-lazy.js +361 -0
  6. package/node-red-contrib-s7-plus/LICENSE +235 -0
  7. package/node-red-contrib-s7-plus/README.md +141 -0
  8. package/node-red-contrib-s7-plus/examples/read-multiple-values-flow.json +346 -0
  9. package/node-red-contrib-s7-plus/examples/read-write-test-flow.json +172 -0
  10. package/node-red-contrib-s7-plus/examples/write-single-values-flow.json +5583 -0
  11. package/node-red-contrib-s7-plus/lib/s7plus/browse/README.md +72 -0
  12. package/node-red-contrib-s7-plus/lib/s7plus/browse/areas.js +36 -0
  13. package/node-red-contrib-s7-plus/lib/s7plus/browse/datatypes.js +91 -0
  14. package/node-red-contrib-s7-plus/lib/s7plus/browse/flat-browser.js +433 -0
  15. package/node-red-contrib-s7-plus/lib/s7plus/browse/index.js +22 -0
  16. package/node-red-contrib-s7-plus/lib/s7plus/browse/lazy.js +397 -0
  17. package/node-red-contrib-s7-plus/lib/s7plus/browse/node-id.js +22 -0
  18. package/node-red-contrib-s7-plus/lib/s7plus/browse/resolve-symbolic.js +181 -0
  19. package/node-red-contrib-s7-plus/lib/s7plus/browse/vte-helpers.js +49 -0
  20. package/node-red-contrib-s7-plus/lib/s7plus/buffer-stream.js +96 -0
  21. package/node-red-contrib-s7-plus/lib/s7plus/client.js +1238 -0
  22. package/node-red-contrib-s7-plus/lib/s7plus/constants.js +155 -0
  23. package/node-red-contrib-s7-plus/lib/s7plus/crc/index.js +3 -0
  24. package/node-red-contrib-s7-plus/lib/s7plus/crc/s7-crc32.js +70 -0
  25. package/node-red-contrib-s7-plus/lib/s7plus/crc/symbol-crc.js +271 -0
  26. package/node-red-contrib-s7-plus/lib/s7plus/debug.js +88 -0
  27. package/node-red-contrib-s7-plus/lib/s7plus/explore-result.js +41 -0
  28. package/node-red-contrib-s7-plus/lib/s7plus/item-address.js +55 -0
  29. package/node-red-contrib-s7-plus/lib/s7plus/pdu-explore.js +77 -0
  30. package/node-red-contrib-s7-plus/lib/s7plus/pdu-messages.js +359 -0
  31. package/node-red-contrib-s7-plus/lib/s7plus/pobject.js +197 -0
  32. package/node-red-contrib-s7-plus/lib/s7plus/pvalue-codec.js +435 -0
  33. package/node-red-contrib-s7-plus/lib/s7plus/pvalue.js +653 -0
  34. package/node-red-contrib-s7-plus/lib/s7plus/pvar-lists.js +336 -0
  35. package/node-red-contrib-s7-plus/lib/s7plus/read-result.js +91 -0
  36. package/node-red-contrib-s7-plus/lib/s7plus/s7p.js +266 -0
  37. package/node-red-contrib-s7-plus/lib/s7plus/tag-routing.js +30 -0
  38. package/node-red-contrib-s7-plus/lib/s7plus/transport/cotp-stream.js +335 -0
  39. package/node-red-contrib-s7-plus/lib/s7plus/transport/s7-transport.js +335 -0
  40. package/node-red-contrib-s7-plus/nodes/icons/s7complus.png +0 -0
  41. package/node-red-contrib-s7-plus/nodes/icons/s7complus.svg +17 -0
  42. package/node-red-contrib-s7-plus/nodes/s7complus-endpoint.js +825 -0
  43. package/node-red-contrib-s7-plus/nodes/s7complus-explore.js +91 -0
  44. package/node-red-contrib-s7-plus/nodes/s7complus-in.js +255 -0
  45. package/node-red-contrib-s7-plus/nodes/s7complus-out.js +182 -0
  46. package/node-red-contrib-s7-plus/nodes/s7complus.html +1541 -0
  47. package/node-red-contrib-s7-plus/nodes/s7complus.js +10 -0
  48. package/node-red-contrib-s7-plus/package.json +50 -0
  49. package/node-red-contrib-s7-plus/plc/s7-1500/DB_Arrays.db +17 -0
  50. package/node-red-contrib-s7-plus/plc/s7-1500/DB_Binary.db +16 -0
  51. package/node-red-contrib-s7-plus/plc/s7-1500/DB_BitStrings.db +36 -0
  52. package/node-red-contrib-s7-plus/plc/s7-1500/DB_CharacterStrings.db +42 -0
  53. package/node-red-contrib-s7-plus/plc/s7-1500/DB_DateAndTime.db +70 -0
  54. package/node-red-contrib-s7-plus/plc/s7-1500/DB_FloatingPoint.db +42 -0
  55. package/node-red-contrib-s7-plus/plc/s7-1500/DB_Integers.db +72 -0
  56. package/node-red-contrib-s7-plus/plc/s7-1500/DB_Timers.db +40 -0
  57. package/node-red-contrib-s7-plus/scripts/example-flow-shared.js +39 -0
  58. package/node-red-contrib-s7-plus/scripts/generate-read-multiple-flow.js +331 -0
  59. package/node-red-contrib-s7-plus/scripts/generate-rw-test-flow.js +690 -0
  60. package/node-red-contrib-s7-plus/scripts/generate-write-flow.js +476 -0
  61. package/node-red-contrib-s7-plus/scripts/layout-write-flow.js +156 -0
  62. package/node-red-contrib-s7-plus/scripts/run-tests.js +16 -0
  63. package/node-red-flowgobal-change/variable-change.html +425 -0
  64. package/node-red-flowgobal-change/variable-change.js +92 -0
  65. package/node-red-ui_media_viewer/ui_media_viewer.html +87 -0
  66. package/node-red-ui_media_viewer/ui_media_viewer.js +136 -0
  67. package/package.json +12 -0
@@ -0,0 +1,653 @@
1
+ 'use strict';
2
+
3
+ const S7p = require('./s7p');
4
+ const { Datatype } = require('./constants');
5
+
6
+ const FLAGS_ARRAY = 0x10;
7
+
8
+ function writeTypeHeader(buf, flags, dt) {
9
+ return S7p.encodeByte(buf, flags) + S7p.encodeByte(buf, dt);
10
+ }
11
+
12
+ class PValue {
13
+ serialize(buf) { throw new Error('abstract'); }
14
+ toJs() { return null; }
15
+ }
16
+
17
+ class ValueNull extends PValue {
18
+ serialize(buf) { return writeTypeHeader(buf, 0, Datatype.Null); }
19
+ toJs() { return null; }
20
+ }
21
+
22
+ class ValueBool extends PValue {
23
+ constructor(v, flags = 0) { super(); this.v = !!v; this.flags = flags; }
24
+ serialize(buf) {
25
+ let n = writeTypeHeader(buf, this.flags, Datatype.Bool);
26
+ n += S7p.encodeByte(buf, this.v ? 1 : 0);
27
+ return n;
28
+ }
29
+ toJs() { return this.v; }
30
+ }
31
+
32
+ class ValueUSInt extends PValue {
33
+ constructor(v, flags = 0) { super(); this.v = v & 0xff; this.flags = flags; }
34
+ serialize(buf) {
35
+ let n = writeTypeHeader(buf, this.flags, Datatype.USInt);
36
+ n += S7p.encodeByte(buf, this.v);
37
+ return n;
38
+ }
39
+ toJs() { return this.v; }
40
+ }
41
+
42
+ class ValueUInt extends PValue {
43
+ constructor(v, flags = 0) { super(); this.v = v & 0xffff; this.flags = flags; }
44
+ serialize(buf) {
45
+ let n = writeTypeHeader(buf, this.flags, Datatype.UInt);
46
+ n += S7p.encodeUInt16(buf, this.v);
47
+ return n;
48
+ }
49
+ toJs() { return this.v; }
50
+ }
51
+
52
+ class ValueUDInt extends PValue {
53
+ constructor(v, flags = 0) { super(); this.v = v >>> 0; this.flags = flags; }
54
+ serialize(buf) {
55
+ let n = writeTypeHeader(buf, this.flags, Datatype.UDInt);
56
+ n += S7p.encodeUInt32Vlq(buf, this.v);
57
+ return n;
58
+ }
59
+ toJs() { return this.v; }
60
+ }
61
+
62
+ class ValueSInt extends PValue {
63
+ constructor(v, flags = 0) { super(); this.v = (v << 24) >> 24; this.flags = flags; }
64
+ serialize(buf) {
65
+ let n = writeTypeHeader(buf, this.flags, Datatype.SInt);
66
+ n += S7p.encodeByte(buf, this.v & 0xff);
67
+ return n;
68
+ }
69
+ toJs() { return this.v; }
70
+ }
71
+
72
+ class ValueInt extends PValue {
73
+ constructor(v, flags = 0) { super(); this.v = v | 0; this.flags = flags; }
74
+ serialize(buf) {
75
+ let n = writeTypeHeader(buf, this.flags, Datatype.Int);
76
+ const u = this.v & 0xffff;
77
+ n += S7p.encodeUInt16(buf, u);
78
+ return n;
79
+ }
80
+ toJs() { return this.v; }
81
+ }
82
+
83
+ class ValueDInt extends PValue {
84
+ constructor(v, flags = 0) { super(); this.v = v | 0; this.flags = flags; }
85
+ serialize(buf) {
86
+ let n = writeTypeHeader(buf, this.flags, Datatype.DInt);
87
+ n += S7p.encodeInt32Vlq(buf, this.v);
88
+ return n;
89
+ }
90
+ toJs() { return this.v; }
91
+ }
92
+
93
+ class ValueReal extends PValue {
94
+ constructor(v, flags = 0) { super(); this.v = v; this.flags = flags; }
95
+ serialize(buf) {
96
+ let n = writeTypeHeader(buf, this.flags, Datatype.Real);
97
+ n += S7p.encodeFloat(buf, this.v);
98
+ return n;
99
+ }
100
+ toJs() { return this.v; }
101
+ }
102
+
103
+ class ValueLReal extends PValue {
104
+ constructor(v, flags = 0) { super(); this.v = v; this.flags = flags; }
105
+ serialize(buf) {
106
+ let n = writeTypeHeader(buf, this.flags, Datatype.LReal);
107
+ n += S7p.encodeDouble(buf, this.v);
108
+ return n;
109
+ }
110
+ toJs() { return this.v; }
111
+ }
112
+
113
+ class ValueRID extends PValue {
114
+ constructor(v, flags = 0) { super(); this.v = v >>> 0; this.flags = flags; }
115
+ serialize(buf) {
116
+ let n = writeTypeHeader(buf, this.flags, Datatype.RID);
117
+ n += S7p.encodeUInt32(buf, this.v);
118
+ return n;
119
+ }
120
+ toJs() { return this.v; }
121
+ }
122
+
123
+ class ValueAID extends PValue {
124
+ constructor(v, flags = 0) { super(); this.v = v >>> 0; this.flags = flags; }
125
+ serialize(buf) {
126
+ let n = writeTypeHeader(buf, this.flags, Datatype.AID);
127
+ n += S7p.encodeUInt32Vlq(buf, this.v);
128
+ return n;
129
+ }
130
+ toJs() { return this.v; }
131
+ }
132
+
133
+ class ValueULInt extends PValue {
134
+ constructor(v, flags = 0) { super(); this.v = typeof v === 'bigint' ? v : BigInt(v); this.flags = flags; }
135
+ serialize(buf) {
136
+ let n = writeTypeHeader(buf, this.flags, Datatype.ULInt);
137
+ n += S7p.encodeUInt64Vlq(buf, this.v);
138
+ return n;
139
+ }
140
+ toJs() { return this.v; }
141
+ }
142
+
143
+ class ValueLInt extends PValue {
144
+ constructor(v, flags = 0) { super(); this.v = typeof v === 'bigint' ? v : BigInt(v); this.flags = flags; }
145
+ serialize(buf) {
146
+ let n = writeTypeHeader(buf, this.flags, Datatype.LInt);
147
+ // VLQ int64 encode not implemented in S7p.encodeUInt64Vlq for signed; reuse for now
148
+ n += S7p.encodeUInt64Vlq(buf, this.v < 0n ? this.v + 0x10000000000000000n : this.v);
149
+ return n;
150
+ }
151
+ toJs() { return this.v; }
152
+ }
153
+
154
+ class ValueByte extends PValue {
155
+ constructor(v, flags = 0) { super(); this.v = v & 0xff; this.flags = flags; }
156
+ serialize(buf) {
157
+ let n = writeTypeHeader(buf, this.flags, Datatype.Byte);
158
+ n += S7p.encodeByte(buf, this.v);
159
+ return n;
160
+ }
161
+ toJs() { return this.v; }
162
+ }
163
+
164
+ class ValueWord extends PValue {
165
+ constructor(v, flags = 0) { super(); this.v = v & 0xffff; this.flags = flags; }
166
+ serialize(buf) {
167
+ let n = writeTypeHeader(buf, this.flags, Datatype.Word);
168
+ n += S7p.encodeUInt16(buf, this.v);
169
+ return n;
170
+ }
171
+ toJs() { return this.v; }
172
+ }
173
+
174
+ class ValueDWord extends PValue {
175
+ constructor(v, flags = 0) { super(); this.v = v >>> 0; this.flags = flags; }
176
+ serialize(buf) {
177
+ let n = writeTypeHeader(buf, this.flags, Datatype.DWord);
178
+ n += S7p.encodeUInt32(buf, this.v);
179
+ return n;
180
+ }
181
+ toJs() { return this.v; }
182
+ }
183
+
184
+ class ValueLWord extends PValue {
185
+ constructor(v, flags = 0) { super(); this.v = typeof v === 'bigint' ? v : BigInt(v); this.flags = flags; }
186
+ serialize(buf) {
187
+ let n = writeTypeHeader(buf, this.flags, Datatype.LWord);
188
+ n += S7p.encodeUInt64(buf, this.v);
189
+ return n;
190
+ }
191
+ toJs() { return this.v; }
192
+ }
193
+
194
+ class ValueTimestamp extends PValue {
195
+ constructor(v, flags = 0) { super(); this.v = typeof v === 'bigint' ? v : BigInt(v); this.flags = flags; }
196
+ serialize(buf) {
197
+ let n = writeTypeHeader(buf, this.flags, Datatype.Timestamp);
198
+ n += S7p.encodeUInt64(buf, this.v);
199
+ return n;
200
+ }
201
+ toJs() { return this.v; }
202
+ }
203
+
204
+ class ValueTimespan extends PValue {
205
+ constructor(v, flags = 0) { super(); this.v = typeof v === 'bigint' ? v : BigInt(v); this.flags = flags; }
206
+ serialize(buf) {
207
+ let n = writeTypeHeader(buf, this.flags, Datatype.Timespan);
208
+ n += S7p.encodeUInt64Vlq(buf, this.v < 0n ? this.v + 0x10000000000000000n : this.v);
209
+ return n;
210
+ }
211
+ toJs() { return this.v; }
212
+ }
213
+
214
+ class ValueBlob extends PValue {
215
+ constructor(_id, data, flags = 0) {
216
+ super();
217
+ this.data = Buffer.from(data);
218
+ this.flags = flags;
219
+ }
220
+ serialize(buf) {
221
+ let n = writeTypeHeader(buf, this.flags, Datatype.Blob);
222
+ n += S7p.encodeUInt32Vlq(buf, this.data.length);
223
+ n += buf.writeBytes(this.data);
224
+ return n;
225
+ }
226
+ toJs() { return this.data; }
227
+ }
228
+
229
+ class ValueWString extends PValue {
230
+ constructor(s, flags = 0) {
231
+ super();
232
+ this.s = s;
233
+ this.flags = flags;
234
+ }
235
+ serialize(buf) {
236
+ const b = Buffer.from(this.s, 'utf8');
237
+ let n = writeTypeHeader(buf, this.flags, Datatype.WString);
238
+ n += S7p.encodeUInt32Vlq(buf, b.length);
239
+ n += buf.writeBytes(b);
240
+ return n;
241
+ }
242
+ toJs() { return this.s; }
243
+ }
244
+
245
+ class ValueUSIntArray extends PValue {
246
+ constructor(arr, flags = FLAGS_ARRAY) {
247
+ super();
248
+ this.arr = arr;
249
+ this.flags = flags;
250
+ }
251
+ serialize(buf) {
252
+ let n = writeTypeHeader(buf, this.flags, Datatype.USInt);
253
+ n += S7p.encodeUInt32Vlq(buf, this.arr.length);
254
+ for (const v of this.arr) n += S7p.encodeByte(buf, v);
255
+ return n;
256
+ }
257
+ toJs() { return this.arr; }
258
+ }
259
+
260
+ class ValueUIntArray extends PValue {
261
+ constructor(arr, flags = FLAGS_ARRAY) {
262
+ super();
263
+ this.arr = arr;
264
+ this.flags = flags;
265
+ }
266
+ serialize(buf) {
267
+ let n = writeTypeHeader(buf, this.flags, Datatype.UInt);
268
+ n += S7p.encodeUInt32Vlq(buf, this.arr.length);
269
+ for (const v of this.arr) n += S7p.encodeUInt16(buf, v);
270
+ return n;
271
+ }
272
+ toJs() { return this.arr; }
273
+ }
274
+
275
+ class ValueArray extends PValue {
276
+ constructor(arr, datatype, flags = FLAGS_ARRAY) {
277
+ super();
278
+ this.arr = arr;
279
+ this.datatype = datatype;
280
+ this.flags = flags;
281
+ }
282
+ serialize() { throw new Error('Generic ValueArray serialize not implemented'); }
283
+ toJs() { return this.arr; }
284
+ }
285
+
286
+ // Packed-struct ID range (system datatypes like DTL are transmitted as a
287
+ // single packed byte array instead of element-by-element). See
288
+ // _deserializeStruct and the S7CommPlusDriver reference.
289
+ function isPackedStructId(id) {
290
+ return (id > 0x90000000 && id < 0x9fffffff) || (id > 0x02000000 && id < 0x02ffffff);
291
+ }
292
+
293
+ // Default transport flag for a packed struct write (bit 1 "AlwaysSet").
294
+ const PACKED_STRUCT_TRANSPORT_FLAGS_DEFAULT = 2;
295
+
296
+ class ValueStruct extends PValue {
297
+ constructor(id, flags = 0) {
298
+ super();
299
+ this.id = id >>> 0;
300
+ this.flags = flags;
301
+ this.elements = new Map();
302
+ // Only meaningful for packed structs (e.g. DTL). The interface
303
+ // timestamp must match the PLC's type version exactly, otherwise
304
+ // a write is rejected with InvalidTimestampInTypeSafeBlob.
305
+ this.packedInterfaceTimestamp = 0n;
306
+ this.packedTransportFlags = PACKED_STRUCT_TRANSPORT_FLAGS_DEFAULT;
307
+ }
308
+ addStructElement(id, val) { this.elements.set(id, val); }
309
+ getStructElement(id) { return this.elements.get(id); }
310
+ serialize(buf) {
311
+ let n = writeTypeHeader(buf, this.flags, Datatype.Struct);
312
+ n += S7p.encodeUInt32(buf, this.id);
313
+
314
+ if (isPackedStructId(this.id)) {
315
+ // Packed struct: interface timestamp + transport flags + a raw
316
+ // byte array (no per-element headers). Mirrors the C# reference
317
+ // ValueStruct.Serialize for system datatypes.
318
+ for (const [, v] of this.elements) {
319
+ n += S7p.encodeUInt64(buf, this.packedInterfaceTimestamp);
320
+ n += S7p.encodeUInt32Vlq(buf, this.packedTransportFlags >>> 0);
321
+ const bytes = Buffer.isBuffer(v) ? v : (v && v.toJs ? v.toJs() : null);
322
+ if (!Buffer.isBuffer(bytes)) {
323
+ throw new Error('Packed struct element must be a Buffer (ValueBlob)');
324
+ }
325
+ n += S7p.encodeUInt32Vlq(buf, bytes.length);
326
+ n += buf.writeBytes(bytes);
327
+ }
328
+ return n;
329
+ }
330
+
331
+ for (const [k, v] of this.elements) {
332
+ n += S7p.encodeUInt32Vlq(buf, k >>> 0);
333
+ n += v.serialize(buf);
334
+ }
335
+ n += S7p.encodeByte(buf, 0);
336
+ return n;
337
+ }
338
+
339
+ toJs() {
340
+ const o = {};
341
+ for (const [k, v] of this.elements) o[k] = v.toJs();
342
+ return o;
343
+ }
344
+ }
345
+
346
+ const FLAGS_ADDRESSARRAY = 0x20;
347
+ const FLAGS_SPARSEARRAY = 0x40;
348
+
349
+ function deserialize(buf, disableVlq = false) {
350
+ let flags, datatype;
351
+ if (!disableVlq) {
352
+ flags = buf.readByte();
353
+ datatype = buf.readByte();
354
+ } else {
355
+ buf.readByte();
356
+ flags = buf.readByte();
357
+ buf.readByte();
358
+ datatype = buf.readByte();
359
+ }
360
+ if (flags === null || datatype === null) return null;
361
+
362
+ if (flags === FLAGS_ARRAY || flags === FLAGS_ADDRESSARRAY) {
363
+ return _deserializeArray(buf, datatype, flags, disableVlq);
364
+ }
365
+ if (flags === FLAGS_SPARSEARRAY) {
366
+ return _deserializeSparseArray(buf, datatype, flags, disableVlq);
367
+ }
368
+
369
+ switch (datatype) {
370
+ case Datatype.Null: return new ValueNull();
371
+ case Datatype.Bool: {
372
+ const v = buf.readByte();
373
+ return new ValueBool(!!v, flags);
374
+ }
375
+ case Datatype.USInt: return new ValueUSInt(buf.readByte() ?? 0, flags);
376
+ case Datatype.UInt: {
377
+ const r = S7p.decodeUInt16(buf);
378
+ return new ValueUInt(r.v, flags);
379
+ }
380
+ case Datatype.UDInt: {
381
+ const r = disableVlq ? S7p.decodeUInt32(buf) : S7p.decodeUInt32Vlq(buf);
382
+ return new ValueUDInt(r.v, flags);
383
+ }
384
+ case Datatype.ULInt: {
385
+ const r = disableVlq ? S7p.decodeUInt64(buf) : S7p.decodeUInt64Vlq(buf);
386
+ return new ValueULInt(r.v, flags);
387
+ }
388
+ case Datatype.SInt: {
389
+ const b = buf.readByte() ?? 0;
390
+ return new ValueSInt(b & 0x80 ? b - 256 : b, flags);
391
+ }
392
+ case Datatype.Int: {
393
+ const r = S7p.decodeInt16(buf);
394
+ return new ValueInt(r.v, flags);
395
+ }
396
+ case Datatype.DInt: {
397
+ const r = disableVlq ? S7p.decodeUInt32(buf) : S7p.decodeInt32Vlq(buf);
398
+ return new ValueDInt(disableVlq ? (r.v | 0) : r.v, flags);
399
+ }
400
+ case Datatype.LInt: {
401
+ const r = disableVlq ? S7p.decodeInt64(buf) : S7p.decodeInt64Vlq(buf);
402
+ return new ValueLInt(r.v, flags);
403
+ }
404
+ case Datatype.Byte: return new ValueByte(buf.readByte() ?? 0, flags);
405
+ case Datatype.Word: {
406
+ const r = S7p.decodeUInt16(buf);
407
+ return new ValueWord(r.v, flags);
408
+ }
409
+ case Datatype.DWord: {
410
+ const r = S7p.decodeUInt32(buf);
411
+ return new ValueDWord(r.v, flags);
412
+ }
413
+ case Datatype.LWord: {
414
+ const r = S7p.decodeUInt64(buf);
415
+ return new ValueLWord(r.v, flags);
416
+ }
417
+ case Datatype.Real: {
418
+ const r = S7p.decodeFloat(buf);
419
+ return new ValueReal(r.v, flags);
420
+ }
421
+ case Datatype.LReal: {
422
+ const r = S7p.decodeDouble(buf);
423
+ return new ValueLReal(r.v, flags);
424
+ }
425
+ case Datatype.Timestamp: {
426
+ const r = S7p.decodeUInt64(buf);
427
+ return new ValueTimestamp(r.v, flags);
428
+ }
429
+ case Datatype.Timespan: {
430
+ const r = disableVlq ? S7p.decodeInt64(buf) : S7p.decodeInt64Vlq(buf);
431
+ return new ValueTimespan(r.v, flags);
432
+ }
433
+ case Datatype.RID: {
434
+ const r = S7p.decodeUInt32(buf);
435
+ return new ValueRID(r.v, flags);
436
+ }
437
+ case Datatype.AID: {
438
+ const r = disableVlq ? S7p.decodeUInt32(buf) : S7p.decodeUInt32Vlq(buf);
439
+ return new ValueAID(r.v, flags);
440
+ }
441
+ case Datatype.Blob: {
442
+ const len = (disableVlq ? S7p.decodeUInt32(buf) : S7p.decodeUInt32Vlq(buf)).v;
443
+ const data = buf.readBytes(len);
444
+ return new ValueBlob(0, data || Buffer.alloc(0), flags);
445
+ }
446
+ case Datatype.WString: {
447
+ const len = (disableVlq ? S7p.decodeUInt32(buf) : S7p.decodeUInt32Vlq(buf)).v;
448
+ const data = buf.readBytes(len);
449
+ return new ValueWString(data ? data.toString('utf8') : '', flags);
450
+ }
451
+ case Datatype.Struct:
452
+ return _deserializeStruct(buf, flags, disableVlq);
453
+ default:
454
+ throw new Error(`Unsupported datatype 0x${datatype.toString(16)}`);
455
+ }
456
+ }
457
+
458
+ function _arrSize(buf, disableVlq) {
459
+ return (disableVlq ? S7p.decodeUInt32(buf) : S7p.decodeUInt32Vlq(buf)).v;
460
+ }
461
+
462
+ function _deserializeArray(buf, datatype, flags, disableVlq) {
463
+ const len = _arrSize(buf, disableVlq);
464
+ const arr = [];
465
+ switch (datatype) {
466
+ case Datatype.Bool:
467
+ for (let i = 0; i < len; i++) arr.push(!!(buf.readByte() ?? 0));
468
+ break;
469
+ case Datatype.USInt:
470
+ case Datatype.Byte:
471
+ for (let i = 0; i < len; i++) arr.push(buf.readByte() ?? 0);
472
+ return new ValueUSIntArray(arr, flags);
473
+ case Datatype.SInt:
474
+ for (let i = 0; i < len; i++) {
475
+ const b = buf.readByte() ?? 0;
476
+ arr.push(b & 0x80 ? b - 256 : b);
477
+ }
478
+ break;
479
+ case Datatype.UInt:
480
+ case Datatype.Word:
481
+ for (let i = 0; i < len; i++) arr.push(S7p.decodeUInt16(buf).v);
482
+ break;
483
+ case Datatype.Int:
484
+ for (let i = 0; i < len; i++) arr.push(S7p.decodeInt16(buf).v);
485
+ break;
486
+ case Datatype.UDInt:
487
+ for (let i = 0; i < len; i++) arr.push((disableVlq ? S7p.decodeUInt32(buf) : S7p.decodeUInt32Vlq(buf)).v);
488
+ break;
489
+ case Datatype.DInt:
490
+ for (let i = 0; i < len; i++) arr.push((disableVlq ? S7p.decodeUInt32(buf) : S7p.decodeInt32Vlq(buf)).v);
491
+ break;
492
+ case Datatype.DWord:
493
+ case Datatype.RID:
494
+ for (let i = 0; i < len; i++) arr.push(S7p.decodeUInt32(buf).v);
495
+ break;
496
+ case Datatype.AID:
497
+ for (let i = 0; i < len; i++) arr.push((disableVlq ? S7p.decodeUInt32(buf) : S7p.decodeUInt32Vlq(buf)).v);
498
+ break;
499
+ case Datatype.ULInt:
500
+ for (let i = 0; i < len; i++) arr.push((disableVlq ? S7p.decodeUInt64(buf) : S7p.decodeUInt64Vlq(buf)).v);
501
+ break;
502
+ case Datatype.LInt:
503
+ for (let i = 0; i < len; i++) arr.push((disableVlq ? S7p.decodeInt64(buf) : S7p.decodeInt64Vlq(buf)).v);
504
+ break;
505
+ case Datatype.LWord:
506
+ case Datatype.Timestamp:
507
+ for (let i = 0; i < len; i++) arr.push(S7p.decodeUInt64(buf).v);
508
+ break;
509
+ case Datatype.Timespan:
510
+ for (let i = 0; i < len; i++) arr.push((disableVlq ? S7p.decodeInt64(buf) : S7p.decodeInt64Vlq(buf)).v);
511
+ break;
512
+ case Datatype.Real:
513
+ for (let i = 0; i < len; i++) arr.push(S7p.decodeFloat(buf).v);
514
+ break;
515
+ case Datatype.LReal:
516
+ for (let i = 0; i < len; i++) arr.push(S7p.decodeDouble(buf).v);
517
+ break;
518
+ case Datatype.Blob:
519
+ for (let i = 0; i < len; i++) {
520
+ const sz = (disableVlq ? S7p.decodeUInt32(buf) : S7p.decodeUInt32Vlq(buf)).v;
521
+ arr.push(buf.readBytes(sz) || Buffer.alloc(0));
522
+ }
523
+ break;
524
+ case Datatype.WString:
525
+ for (let i = 0; i < len; i++) {
526
+ const sz = (disableVlq ? S7p.decodeUInt32(buf) : S7p.decodeUInt32Vlq(buf)).v;
527
+ const data = buf.readBytes(sz);
528
+ arr.push(data ? data.toString('utf8') : '');
529
+ }
530
+ break;
531
+ default:
532
+ throw new Error(`Unsupported array datatype 0x${datatype.toString(16)}`);
533
+ }
534
+ return new ValueArray(arr, datatype, flags);
535
+ }
536
+
537
+ function _deserializeSparseArray(buf, datatype, flags, disableVlq) {
538
+ const entries = new Map();
539
+ let key = (disableVlq ? S7p.decodeUInt32(buf) : S7p.decodeUInt32Vlq(buf)).v;
540
+ while (key > 0) {
541
+ let v;
542
+ switch (datatype) {
543
+ case Datatype.UDInt:
544
+ v = (disableVlq ? S7p.decodeUInt32(buf) : S7p.decodeUInt32Vlq(buf)).v; break;
545
+ case Datatype.DInt:
546
+ v = (disableVlq ? S7p.decodeUInt32(buf) : S7p.decodeInt32Vlq(buf)).v; break;
547
+ case Datatype.Blob: {
548
+ const sz = (disableVlq ? S7p.decodeUInt32(buf) : S7p.decodeUInt32Vlq(buf)).v;
549
+ v = buf.readBytes(sz) || Buffer.alloc(0); break;
550
+ }
551
+ case Datatype.WString: {
552
+ const sz = (disableVlq ? S7p.decodeUInt32(buf) : S7p.decodeUInt32Vlq(buf)).v;
553
+ const data = buf.readBytes(sz);
554
+ v = data ? data.toString('utf8') : ''; break;
555
+ }
556
+ default:
557
+ throw new Error(`Unsupported sparse array datatype 0x${datatype.toString(16)}`);
558
+ }
559
+ entries.set(key, v);
560
+ key = (disableVlq ? S7p.decodeUInt32(buf) : S7p.decodeUInt32Vlq(buf)).v;
561
+ }
562
+ return new ValueArray([...entries.entries()], datatype, flags);
563
+ }
564
+
565
+ function _deserializeStruct(buf, flags, disableVlq) {
566
+ const id = S7p.decodeUInt32(buf).v;
567
+ const stru = new ValueStruct(id, flags);
568
+ if (isPackedStructId(id)) {
569
+ // Capture the interface timestamp and transport flags so the write
570
+ // path can echo them back unchanged (required by the PLC for DTL).
571
+ stru.packedInterfaceTimestamp = S7p.decodeUInt64(buf).v;
572
+ const tf = disableVlq ? S7p.decodeUInt32(buf) : S7p.decodeUInt32Vlq(buf);
573
+ stru.packedTransportFlags = tf.v;
574
+ let ec = disableVlq ? S7p.decodeUInt32(buf) : S7p.decodeUInt32Vlq(buf);
575
+ if (tf.v & (1 << 10)) {
576
+ ec = disableVlq ? S7p.decodeUInt32(buf) : S7p.decodeUInt32Vlq(buf);
577
+ }
578
+ const barr = Buffer.alloc(ec.v);
579
+ for (let i = 0; i < ec.v; i++) barr[i] = buf.readByte() ?? 0;
580
+ stru.addStructElement(id, new ValueBlob(0, barr));
581
+ } else {
582
+ let key = disableVlq ? S7p.decodeUInt32(buf) : S7p.decodeUInt32Vlq(buf);
583
+ while (key.v > 0) {
584
+ stru.addStructElement(key.v, deserialize(buf, disableVlq));
585
+ key = disableVlq ? S7p.decodeUInt32(buf) : S7p.decodeUInt32Vlq(buf);
586
+ }
587
+ }
588
+ return stru;
589
+ }
590
+
591
+ function encodeObjectQualifier(buf) {
592
+ let ret = 0;
593
+ const { Ids } = require('./constants');
594
+ ret += S7p.encodeUInt32(buf, Ids.ObjectQualifier);
595
+ ret += S7p.encodeUInt32Vlq(buf, Ids.ParentRID);
596
+ ret += new ValueRID(0).serialize(buf);
597
+ ret += S7p.encodeUInt32Vlq(buf, Ids.CompositionAID);
598
+ ret += new ValueAID(0).serialize(buf);
599
+ ret += S7p.encodeUInt32Vlq(buf, Ids.KeyQualifier);
600
+ ret += new ValueUDInt(0).serialize(buf);
601
+ ret += S7p.encodeByte(buf, 0);
602
+ return ret;
603
+ }
604
+
605
+ function valueFromJs(val, datatypeHint) {
606
+ if (typeof val === 'boolean') return new ValueBool(val);
607
+ if (typeof val === 'number') {
608
+ if (Number.isInteger(val)) {
609
+ if (datatypeHint === 'real' || datatypeHint === 'float') return new ValueReal(val);
610
+ if (val >= -128 && val <= 127 && datatypeHint === 'sint') return new ValueSInt(val);
611
+ if (val >= 0 && val <= 255 && datatypeHint === 'usint') return new ValueUSInt(val);
612
+ if (val >= -32768 && val <= 32767 && datatypeHint === 'int') return new ValueInt(val);
613
+ return new ValueDInt(val);
614
+ }
615
+ return new ValueReal(val);
616
+ }
617
+ if (typeof val === 'string') return new ValueWString(val);
618
+ if (Buffer.isBuffer(val)) return new ValueBlob(0, val);
619
+ throw new Error('Cannot encode value type');
620
+ }
621
+
622
+ module.exports = {
623
+ deserialize,
624
+ encodeObjectQualifier,
625
+ valueFromJs,
626
+ isPackedStructId,
627
+ ValueNull,
628
+ ValueBool,
629
+ ValueUSInt,
630
+ ValueUInt,
631
+ ValueUDInt,
632
+ ValueULInt,
633
+ ValueSInt,
634
+ ValueInt,
635
+ ValueDInt,
636
+ ValueLInt,
637
+ ValueByte,
638
+ ValueWord,
639
+ ValueDWord,
640
+ ValueLWord,
641
+ ValueReal,
642
+ ValueLReal,
643
+ ValueTimestamp,
644
+ ValueTimespan,
645
+ ValueRID,
646
+ ValueAID,
647
+ ValueBlob,
648
+ ValueWString,
649
+ ValueUSIntArray,
650
+ ValueUIntArray,
651
+ ValueArray,
652
+ ValueStruct
653
+ };