njs-modbus 1.3.1 → 1.3.2

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/dist/index.mjs DELETED
@@ -1,2108 +0,0 @@
1
- import EventEmitter from 'node:events';
2
- import { SerialPort } from 'serialport';
3
- import { Socket, createServer } from 'node:net';
4
- import { createSocket } from 'node:dgram';
5
-
6
- var ErrorCode;
7
- (function (ErrorCode) {
8
- ErrorCode[ErrorCode["ILLEGAL_FUNCTION"] = 1] = "ILLEGAL_FUNCTION";
9
- ErrorCode[ErrorCode["ILLEGAL_DATA_ADDRESS"] = 2] = "ILLEGAL_DATA_ADDRESS";
10
- ErrorCode[ErrorCode["ILLEGAL_DATA_VALUE"] = 3] = "ILLEGAL_DATA_VALUE";
11
- ErrorCode[ErrorCode["SERVER_DEVICE_FAILURE"] = 4] = "SERVER_DEVICE_FAILURE";
12
- ErrorCode[ErrorCode["ACKNOWLEDGE"] = 5] = "ACKNOWLEDGE";
13
- ErrorCode[ErrorCode["SERVER_DEVICE_BUSY"] = 6] = "SERVER_DEVICE_BUSY";
14
- ErrorCode[ErrorCode["MEMORY_PARITY_ERROR"] = 8] = "MEMORY_PARITY_ERROR";
15
- ErrorCode[ErrorCode["GATEWAY_PATH_UNAVAILABLE"] = 10] = "GATEWAY_PATH_UNAVAILABLE";
16
- ErrorCode[ErrorCode["GATEWAY_TARGET_DEVICE_FAILED_TO_RESPOND"] = 11] = "GATEWAY_TARGET_DEVICE_FAILED_TO_RESPOND";
17
- })(ErrorCode || (ErrorCode = {}));
18
- const PREFIX = 'MODBUS_ERROR_CODE_';
19
- function getErrorByCode(code) {
20
- return new Error(PREFIX + code);
21
- }
22
- function getCodeByError(err) {
23
- if (err.message.startsWith(PREFIX)) {
24
- return Number(err.message.slice(PREFIX.length));
25
- }
26
- return ErrorCode.SERVER_DEVICE_FAILURE;
27
- }
28
-
29
- class AbstractPhysicalLayer extends EventEmitter {
30
- }
31
-
32
- class SerialPhysicalLayer extends AbstractPhysicalLayer {
33
- get isOpen() {
34
- return this._serialport.isOpen;
35
- }
36
- get destroyed() {
37
- return this._destroyed;
38
- }
39
- get baudRate() {
40
- return this._baudRate;
41
- }
42
- constructor(options) {
43
- super();
44
- Object.defineProperty(this, "TYPE", {
45
- enumerable: true,
46
- configurable: true,
47
- writable: true,
48
- value: 'SERIAL'
49
- });
50
- Object.defineProperty(this, "_serialport", {
51
- enumerable: true,
52
- configurable: true,
53
- writable: true,
54
- value: void 0
55
- });
56
- Object.defineProperty(this, "_destroyed", {
57
- enumerable: true,
58
- configurable: true,
59
- writable: true,
60
- value: false
61
- });
62
- Object.defineProperty(this, "_baudRate", {
63
- enumerable: true,
64
- configurable: true,
65
- writable: true,
66
- value: void 0
67
- });
68
- this._serialport = new SerialPort(Object.assign(Object.assign({}, options), { autoOpen: false }));
69
- this._baudRate = options.baudRate;
70
- }
71
- open() {
72
- if (this.destroyed) {
73
- return Promise.reject(new Error('Port is destroyed'));
74
- }
75
- return new Promise((resolve, reject) => {
76
- this._serialport.open((error) => {
77
- if (error) {
78
- reject(error);
79
- }
80
- else {
81
- this._serialport.on('data', (data) => {
82
- this.emit('data', data, (data) => this.write(data));
83
- });
84
- this._serialport.on('error', (error) => {
85
- this.emit('error', error);
86
- });
87
- this._serialport.on('close', () => {
88
- this._serialport.removeAllListeners();
89
- this.emit('close');
90
- });
91
- resolve();
92
- }
93
- });
94
- });
95
- }
96
- write(data) {
97
- return new Promise((resolve, reject) => {
98
- if (this.isOpen) {
99
- this._serialport.write(data, (error) => {
100
- if (error) {
101
- reject(error);
102
- }
103
- else {
104
- this.emit('write', data);
105
- resolve();
106
- }
107
- });
108
- }
109
- else {
110
- reject(new Error('Port is not open'));
111
- }
112
- });
113
- }
114
- close() {
115
- return new Promise((resolve) => {
116
- this._serialport.removeAllListeners();
117
- this._serialport.close(() => {
118
- resolve();
119
- });
120
- });
121
- }
122
- destroy() {
123
- this._destroyed = true;
124
- this.removeAllListeners();
125
- return this.close();
126
- }
127
- }
128
-
129
- class TcpClientPhysicalLayer extends AbstractPhysicalLayer {
130
- get isOpen() {
131
- return this._isOpen;
132
- }
133
- get destroyed() {
134
- return this._destroyed;
135
- }
136
- constructor(options) {
137
- super();
138
- Object.defineProperty(this, "TYPE", {
139
- enumerable: true,
140
- configurable: true,
141
- writable: true,
142
- value: 'NET'
143
- });
144
- Object.defineProperty(this, "_socket", {
145
- enumerable: true,
146
- configurable: true,
147
- writable: true,
148
- value: void 0
149
- });
150
- Object.defineProperty(this, "_isOpen", {
151
- enumerable: true,
152
- configurable: true,
153
- writable: true,
154
- value: false
155
- });
156
- Object.defineProperty(this, "_destroyed", {
157
- enumerable: true,
158
- configurable: true,
159
- writable: true,
160
- value: false
161
- });
162
- this._socket = new Socket(options);
163
- }
164
- open(options) {
165
- if (this.destroyed) {
166
- return Promise.reject(new Error('Port is destroyed'));
167
- }
168
- return new Promise((resolve, reject) => {
169
- let called = false;
170
- this._socket.connect(options !== null && options !== void 0 ? options : { port: 502 }, () => {
171
- called = true;
172
- this._isOpen = true;
173
- this._socket.on('data', (data) => {
174
- this.emit('data', data, (data) => this.write(data));
175
- });
176
- this._socket.on('close', () => {
177
- this._isOpen = false;
178
- this._socket.removeAllListeners();
179
- this.emit('close');
180
- });
181
- resolve();
182
- });
183
- this._socket.on('error', (error) => {
184
- if (called) {
185
- this.emit('error', error);
186
- }
187
- else {
188
- reject(error);
189
- }
190
- });
191
- });
192
- }
193
- write(data) {
194
- return new Promise((resolve, reject) => {
195
- if (this.isOpen) {
196
- this._socket.write(data, (error) => {
197
- if (error) {
198
- reject(error);
199
- }
200
- else {
201
- this.emit('write', data);
202
- resolve();
203
- }
204
- });
205
- }
206
- else {
207
- reject(new Error('Port is not open'));
208
- }
209
- });
210
- }
211
- close() {
212
- return new Promise((resolve) => {
213
- this._isOpen = false;
214
- this._socket.removeAllListeners();
215
- this._socket.destroy();
216
- resolve();
217
- });
218
- }
219
- destroy() {
220
- this._destroyed = true;
221
- this.removeAllListeners();
222
- return this.close();
223
- }
224
- }
225
-
226
- class TcpServerPhysicalLayer extends AbstractPhysicalLayer {
227
- get isOpen() {
228
- return this._isOpen;
229
- }
230
- get destroyed() {
231
- return this._destroyed;
232
- }
233
- constructor(options) {
234
- super();
235
- Object.defineProperty(this, "TYPE", {
236
- enumerable: true,
237
- configurable: true,
238
- writable: true,
239
- value: 'NET'
240
- });
241
- Object.defineProperty(this, "_server", {
242
- enumerable: true,
243
- configurable: true,
244
- writable: true,
245
- value: void 0
246
- });
247
- Object.defineProperty(this, "_isOpen", {
248
- enumerable: true,
249
- configurable: true,
250
- writable: true,
251
- value: false
252
- });
253
- Object.defineProperty(this, "_destroyed", {
254
- enumerable: true,
255
- configurable: true,
256
- writable: true,
257
- value: false
258
- });
259
- Object.defineProperty(this, "_sockets", {
260
- enumerable: true,
261
- configurable: true,
262
- writable: true,
263
- value: new Set()
264
- });
265
- this._server = createServer(options, (socket) => {
266
- this._sockets.add(socket);
267
- socket.on('data', (data) => {
268
- this.emit('data', data, (data) => new Promise((resolve, reject) => {
269
- socket.write(data, (error) => {
270
- if (error) {
271
- reject(error);
272
- }
273
- else {
274
- resolve();
275
- }
276
- });
277
- }));
278
- });
279
- socket.once('close', () => {
280
- socket.removeAllListeners();
281
- this._sockets.delete(socket);
282
- });
283
- });
284
- }
285
- open(options) {
286
- if (this.destroyed) {
287
- return Promise.reject(new Error('Port is destroyed'));
288
- }
289
- return new Promise((resolve, reject) => {
290
- var _a;
291
- let called = false;
292
- this._server.listen(Object.assign(Object.assign({}, options), { port: (_a = options === null || options === void 0 ? void 0 : options.port) !== null && _a !== void 0 ? _a : 502 }), () => {
293
- called = true;
294
- this._isOpen = true;
295
- this._sockets.clear();
296
- this._server.on('close', () => {
297
- this._isOpen = false;
298
- this._server.removeAllListeners();
299
- for (const socket of this._sockets) {
300
- socket.removeAllListeners();
301
- }
302
- this.emit('close');
303
- });
304
- resolve();
305
- });
306
- this._server.on('error', (error) => {
307
- if (called) {
308
- this.emit('error', error);
309
- }
310
- else {
311
- reject(error);
312
- }
313
- });
314
- });
315
- }
316
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
317
- write(data) {
318
- return new Promise((resolve, reject) => {
319
- reject(new Error('Not supported'));
320
- });
321
- }
322
- close() {
323
- return new Promise((resolve) => {
324
- this._isOpen = false;
325
- this._server.removeAllListeners();
326
- for (const socket of this._sockets) {
327
- socket.removeAllListeners();
328
- }
329
- this._server.close(() => {
330
- resolve();
331
- });
332
- });
333
- }
334
- destroy() {
335
- this._destroyed = true;
336
- this.removeAllListeners();
337
- return this.close();
338
- }
339
- }
340
-
341
- class UdpPhysicalLayer extends AbstractPhysicalLayer {
342
- get isOpen() {
343
- return this._isOpen;
344
- }
345
- get destroyed() {
346
- return this._destroyed;
347
- }
348
- /**
349
- *
350
- * @param options
351
- * @param remote If omitted, as server.
352
- * Otherwise as client.
353
- */
354
- constructor(options, remote) {
355
- var _a, _b;
356
- super();
357
- Object.defineProperty(this, "TYPE", {
358
- enumerable: true,
359
- configurable: true,
360
- writable: true,
361
- value: 'NET'
362
- });
363
- Object.defineProperty(this, "_socket", {
364
- enumerable: true,
365
- configurable: true,
366
- writable: true,
367
- value: void 0
368
- });
369
- Object.defineProperty(this, "_isOpen", {
370
- enumerable: true,
371
- configurable: true,
372
- writable: true,
373
- value: false
374
- });
375
- Object.defineProperty(this, "_destroyed", {
376
- enumerable: true,
377
- configurable: true,
378
- writable: true,
379
- value: false
380
- });
381
- Object.defineProperty(this, "_port", {
382
- enumerable: true,
383
- configurable: true,
384
- writable: true,
385
- value: void 0
386
- });
387
- Object.defineProperty(this, "_address", {
388
- enumerable: true,
389
- configurable: true,
390
- writable: true,
391
- value: void 0
392
- });
393
- Object.defineProperty(this, "isServer", {
394
- enumerable: true,
395
- configurable: true,
396
- writable: true,
397
- value: void 0
398
- });
399
- this._socket = createSocket(Object.assign(Object.assign({}, options), { type: (_a = options === null || options === void 0 ? void 0 : options.type) !== null && _a !== void 0 ? _a : 'udp4' }), (msg, rinfo) => {
400
- this.emit('data', msg, (data) => new Promise((resolve, reject) => {
401
- this._socket.send(data, rinfo.port, rinfo.address, (error) => {
402
- if (error) {
403
- reject(error);
404
- }
405
- else {
406
- resolve();
407
- }
408
- });
409
- }));
410
- });
411
- this.isServer = !remote;
412
- this._port = (_b = remote === null || remote === void 0 ? void 0 : remote.port) !== null && _b !== void 0 ? _b : 502;
413
- this._address = remote === null || remote === void 0 ? void 0 : remote.address;
414
- }
415
- open(options) {
416
- if (this.destroyed) {
417
- return Promise.reject(new Error('Port is destroyed'));
418
- }
419
- return new Promise((resolve, reject) => {
420
- var _a;
421
- if (this.isServer) {
422
- let called = false;
423
- this._socket.bind(Object.assign(Object.assign({}, options), { port: (_a = options === null || options === void 0 ? void 0 : options.port) !== null && _a !== void 0 ? _a : 502 }), () => {
424
- called = true;
425
- this._isOpen = true;
426
- this._socket.on('close', () => {
427
- this._isOpen = false;
428
- this._socket.removeAllListeners();
429
- this.emit('close');
430
- });
431
- resolve();
432
- });
433
- this._socket.on('error', (error) => {
434
- if (called) {
435
- this.emit('error', error);
436
- }
437
- else {
438
- reject(error);
439
- }
440
- });
441
- }
442
- else {
443
- this._isOpen = true;
444
- resolve();
445
- }
446
- });
447
- }
448
- write(data) {
449
- return new Promise((resolve, reject) => {
450
- if (this.isOpen) {
451
- this._socket.send(data, this._port, this._address, (error) => {
452
- if (error) {
453
- reject(error);
454
- }
455
- else {
456
- this.emit('write', data);
457
- resolve();
458
- }
459
- });
460
- }
461
- else {
462
- reject(new Error('Port is not open'));
463
- }
464
- });
465
- }
466
- close() {
467
- return new Promise((resolve) => {
468
- this._isOpen = false;
469
- this._socket.removeAllListeners();
470
- this._socket.close(() => {
471
- resolve();
472
- });
473
- });
474
- }
475
- destroy() {
476
- this._destroyed = true;
477
- this.removeAllListeners();
478
- return this.close();
479
- }
480
- }
481
-
482
- class AbstractApplicationLayer extends EventEmitter {
483
- }
484
-
485
- function checkRange(value, range) {
486
- if (range) {
487
- if (typeof range[0] === 'number' && typeof range[1] === 'number') {
488
- if (range[0] < range[1]) {
489
- return (Array.isArray(value) ? value : [value]).every((n) => n >= range[0] && n <= range[1]);
490
- }
491
- }
492
- else if (range.length > 0) {
493
- for (const r of range) {
494
- if (r[0] < r[1]) {
495
- if ((Array.isArray(value) ? value : [value]).every((n) => n >= r[0] && n <= r[1])) {
496
- return true;
497
- }
498
- }
499
- }
500
- return false;
501
- }
502
- }
503
- return true;
504
- }
505
-
506
- const TABLE = [
507
- 0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241, 0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440, 0xcc01,
508
- 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40, 0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841, 0xd801, 0x18c0,
509
- 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40, 0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41, 0x1400, 0xd4c1, 0xd581,
510
- 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641, 0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040, 0xf001, 0x30c0, 0x3180, 0xf141,
511
- 0x3300, 0xf3c1, 0xf281, 0x3240, 0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441, 0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01,
512
- 0x3fc0, 0x3e80, 0xfe41, 0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840, 0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0,
513
- 0x2a80, 0xea41, 0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40, 0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681,
514
- 0x2640, 0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041, 0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
515
- 0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441, 0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41, 0xaa01,
516
- 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840, 0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41, 0xbe01, 0x7ec0,
517
- 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40, 0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640, 0x7200, 0xb2c1, 0xb381,
518
- 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041, 0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241, 0x9601, 0x56c0, 0x5780, 0x9741,
519
- 0x5500, 0x95c1, 0x9481, 0x5440, 0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40, 0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901,
520
- 0x59c0, 0x5880, 0x9841, 0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40, 0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0,
521
- 0x4c80, 0x8c41, 0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641, 0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081,
522
- 0x4040,
523
- ];
524
- function crc(data) {
525
- let crc = 0xffff;
526
- for (let index = 0; index < data.length; index++) {
527
- crc = (TABLE[(crc ^ data[index]) & 0xff] ^ (crc >> 8)) & 0xffff;
528
- }
529
- return crc;
530
- }
531
-
532
- /**
533
- * Get time interval between message frames witch well-known as 3.5T.
534
- * @param baudRate Serial port baud rate.
535
- * @param {number} [approximation=48] Approximate number of bits corresponding to 3.5T.
536
- * @returns `ms`.
537
- */
538
- function getThreePointFiveT(baudRate, approximation = 48) {
539
- return (approximation * 1000) / baudRate;
540
- }
541
-
542
- function lrc(data) {
543
- return (~data.reduce((sum, n) => sum + n, 0) + 1) & 0xff;
544
- }
545
-
546
- class RtuApplicationLayer extends AbstractApplicationLayer {
547
- constructor(physicalLayer,
548
- /**
549
- * The time interval between two frames, support two formats:
550
- * - bit: `48bit` as default
551
- * - millisecond: `20ms`
552
- */
553
- intervalBetweenFrames) {
554
- super();
555
- Object.defineProperty(this, "_waitingResponse", {
556
- enumerable: true,
557
- configurable: true,
558
- writable: true,
559
- value: void 0
560
- });
561
- Object.defineProperty(this, "_timerThreePointFive", {
562
- enumerable: true,
563
- configurable: true,
564
- writable: true,
565
- value: void 0
566
- });
567
- Object.defineProperty(this, "_bufferRx", {
568
- enumerable: true,
569
- configurable: true,
570
- writable: true,
571
- value: Buffer.alloc(0)
572
- });
573
- Object.defineProperty(this, "_removeAllListeners", {
574
- enumerable: true,
575
- configurable: true,
576
- writable: true,
577
- value: []
578
- });
579
- let threePointFiveT = 0;
580
- if (physicalLayer.TYPE === 'SERIAL') {
581
- if (intervalBetweenFrames && intervalBetweenFrames.endsWith('ms')) {
582
- threePointFiveT = Number(intervalBetweenFrames.slice(0, -2));
583
- }
584
- else {
585
- threePointFiveT = Math.ceil(physicalLayer.baudRate > 19200
586
- ? 1.8
587
- : getThreePointFiveT(physicalLayer.baudRate, intervalBetweenFrames ? Number(intervalBetweenFrames.slice(0, -3)) : 48));
588
- }
589
- }
590
- const handleData = (data, response) => {
591
- this._bufferRx = Buffer.concat([this._bufferRx, data]);
592
- if (this._waitingResponse) {
593
- this.framing(this._bufferRx, (error, frame) => {
594
- if (error && error.message === 'Insufficient data length') {
595
- return;
596
- }
597
- this._waitingResponse.callback(error, frame);
598
- this._bufferRx = Buffer.alloc(0);
599
- });
600
- }
601
- else {
602
- clearTimeout(this._timerThreePointFive);
603
- const handleData = () => {
604
- this.framing(this._bufferRx, (error, frame) => {
605
- if (!error) {
606
- this.emit('framing', frame, response);
607
- }
608
- this._bufferRx = Buffer.alloc(0);
609
- });
610
- };
611
- if (threePointFiveT) {
612
- this._timerThreePointFive = setTimeout(handleData, threePointFiveT);
613
- }
614
- else {
615
- handleData();
616
- }
617
- }
618
- };
619
- physicalLayer.on('data', handleData);
620
- this._removeAllListeners.push(() => {
621
- physicalLayer.removeListener('data', handleData);
622
- });
623
- const handleClose = () => {
624
- clearTimeout(this._timerThreePointFive);
625
- this._bufferRx = Buffer.alloc(0);
626
- };
627
- physicalLayer.on('close', handleClose);
628
- this._removeAllListeners.push(() => {
629
- physicalLayer.removeListener('close', handleClose);
630
- });
631
- }
632
- framing(buffer, callback) {
633
- if (buffer.length >= 4) {
634
- const frame = {
635
- unit: buffer[0],
636
- fc: buffer[1],
637
- data: Array.from(buffer.subarray(2, buffer.length - 2)),
638
- buffer,
639
- };
640
- if (this._waitingResponse) {
641
- for (const check of this._waitingResponse.preCheck) {
642
- const res = check(frame);
643
- if (typeof res === 'undefined') {
644
- callback(new Error('Insufficient data length'));
645
- return;
646
- }
647
- if (typeof res === 'number') {
648
- if (res < frame.data.length) {
649
- callback(new Error('Insufficient data length'));
650
- return;
651
- }
652
- if (res !== frame.data.length) {
653
- callback(new Error('Invalid response'));
654
- return;
655
- }
656
- }
657
- if (!res) {
658
- callback(new Error('Invalid response'));
659
- return;
660
- }
661
- }
662
- }
663
- const crcPassed = buffer.readUInt16LE(buffer.length - 2) === crc(buffer.subarray(0, buffer.length - 2));
664
- if (crcPassed) {
665
- callback(null, frame);
666
- }
667
- else {
668
- callback(new Error('CRC check failed'));
669
- }
670
- }
671
- else {
672
- callback(new Error('Insufficient data length'));
673
- }
674
- }
675
- startWaitingResponse(preCheck, callback) {
676
- this._waitingResponse = { preCheck, callback };
677
- clearTimeout(this._timerThreePointFive);
678
- this._bufferRx = Buffer.alloc(0);
679
- }
680
- stopWaitingResponse() {
681
- this._waitingResponse = undefined;
682
- }
683
- encode(data) {
684
- const buffer = Buffer.alloc(data.data.length + 4);
685
- buffer.writeUInt8(data.unit, 0);
686
- buffer.writeUInt8(data.fc, 1);
687
- data.data.forEach((num, index) => {
688
- buffer.writeUInt8(num, 2 + index);
689
- });
690
- buffer.writeUInt16LE(crc(buffer.subarray(0, -2)), buffer.length - 2);
691
- return buffer;
692
- }
693
- destroy() {
694
- this.removeAllListeners();
695
- for (const removeAllListener of this._removeAllListeners) {
696
- removeAllListener();
697
- }
698
- clearTimeout(this._timerThreePointFive);
699
- }
700
- }
701
-
702
- const CHAR_CODE = {
703
- COLON: ':'.charCodeAt(0),
704
- CR: '\r'.charCodeAt(0),
705
- LF: '\n'.charCodeAt(0),
706
- };
707
- class AsciiApplicationLayer extends AbstractApplicationLayer {
708
- constructor(physicalLayer) {
709
- super();
710
- Object.defineProperty(this, "_waitingResponse", {
711
- enumerable: true,
712
- configurable: true,
713
- writable: true,
714
- value: void 0
715
- });
716
- Object.defineProperty(this, "_status", {
717
- enumerable: true,
718
- configurable: true,
719
- writable: true,
720
- value: 'idle'
721
- });
722
- Object.defineProperty(this, "_frame", {
723
- enumerable: true,
724
- configurable: true,
725
- writable: true,
726
- value: []
727
- });
728
- Object.defineProperty(this, "_removeAllListeners", {
729
- enumerable: true,
730
- configurable: true,
731
- writable: true,
732
- value: []
733
- });
734
- const handleData = (data, response) => {
735
- data.forEach((value) => {
736
- switch (this._status) {
737
- case 'idle': {
738
- if (value === CHAR_CODE.COLON) {
739
- this._status = 'reception';
740
- this._frame = [];
741
- }
742
- break;
743
- }
744
- case 'reception': {
745
- if (value === CHAR_CODE.COLON) {
746
- this._frame = [];
747
- }
748
- else if (value === CHAR_CODE.CR) {
749
- this._status = 'waiting end';
750
- }
751
- else {
752
- this._frame.push(value);
753
- }
754
- break;
755
- }
756
- case 'waiting end': {
757
- if (value === CHAR_CODE.COLON) {
758
- this._status = 'reception';
759
- this._frame = [];
760
- }
761
- else {
762
- this._status = 'idle';
763
- if (value === CHAR_CODE.LF) {
764
- this.framing(Buffer.from(this._frame), (error, frame) => {
765
- if (this._waitingResponse) {
766
- this._waitingResponse.callback(error, frame);
767
- }
768
- else if (!error) {
769
- this.emit('framing', frame, response);
770
- }
771
- });
772
- }
773
- }
774
- break;
775
- }
776
- }
777
- });
778
- };
779
- physicalLayer.on('data', handleData);
780
- this._removeAllListeners.push(() => {
781
- physicalLayer.removeListener('data', handleData);
782
- });
783
- const handleClose = () => {
784
- this._status = 'idle';
785
- this._frame = [];
786
- };
787
- physicalLayer.on('close', handleClose);
788
- this._removeAllListeners.push(() => {
789
- physicalLayer.removeListener('close', handleClose);
790
- });
791
- }
792
- framing(_buffer, callback) {
793
- if (_buffer.length >= 6) {
794
- if (_buffer.length % 2 === 0) {
795
- const ascii = [];
796
- let num = '';
797
- for (const value of _buffer) {
798
- num += String.fromCharCode(value);
799
- if (num.length === 2) {
800
- ascii.push(Number('0x' + num));
801
- num = '';
802
- }
803
- }
804
- const buffer = Buffer.from(ascii);
805
- const frame = {
806
- unit: buffer[0],
807
- fc: buffer[1],
808
- data: Array.from(buffer.subarray(2, buffer.length - 1)),
809
- buffer: _buffer,
810
- };
811
- if (this._waitingResponse) {
812
- for (const check of this._waitingResponse.preCheck) {
813
- const res = check(frame);
814
- if (typeof res === 'undefined') {
815
- callback(new Error('Insufficient data length'));
816
- return;
817
- }
818
- if (typeof res === 'number') {
819
- if (res < frame.data.length) {
820
- callback(new Error('Insufficient data length'));
821
- return;
822
- }
823
- if (res !== frame.data.length) {
824
- callback(new Error('Invalid response'));
825
- return;
826
- }
827
- }
828
- if (!res) {
829
- callback(new Error('Invalid response'));
830
- return;
831
- }
832
- }
833
- }
834
- const lrcPassed = buffer[buffer.length - 1] === lrc(buffer.subarray(0, buffer.length - 1));
835
- if (lrcPassed) {
836
- callback(null, frame);
837
- }
838
- else {
839
- callback(new Error('LRC check failed'));
840
- }
841
- }
842
- else {
843
- callback(new Error('Invalid data'));
844
- }
845
- }
846
- else {
847
- callback(new Error('Insufficient data length'));
848
- }
849
- }
850
- startWaitingResponse(preCheck, callback) {
851
- this._waitingResponse = { preCheck, callback };
852
- this._status = 'idle';
853
- this._frame = [];
854
- }
855
- stopWaitingResponse() {
856
- this._waitingResponse = undefined;
857
- }
858
- encode(data) {
859
- const buffer = Buffer.alloc(data.data.length + 3);
860
- buffer.writeUInt8(data.unit, 0);
861
- buffer.writeUInt8(data.fc, 1);
862
- data.data.forEach((num, index) => {
863
- buffer.writeUInt8(num, 2 + index);
864
- });
865
- buffer.writeUInt8(lrc(buffer.subarray(0, -1)), buffer.length - 1);
866
- let frame = ':';
867
- for (const value of buffer) {
868
- frame += value.toString(16).toUpperCase().padStart(2, '0');
869
- }
870
- frame += '\r\n';
871
- return Buffer.from(frame);
872
- }
873
- destroy() {
874
- this.removeAllListeners();
875
- for (const removeAllListener of this._removeAllListeners) {
876
- removeAllListener();
877
- }
878
- }
879
- }
880
-
881
- class TcpApplicationLayer extends AbstractApplicationLayer {
882
- constructor(physicalLayer) {
883
- super();
884
- Object.defineProperty(this, "_waitingResponse", {
885
- enumerable: true,
886
- configurable: true,
887
- writable: true,
888
- value: void 0
889
- });
890
- Object.defineProperty(this, "_transactionId", {
891
- enumerable: true,
892
- configurable: true,
893
- writable: true,
894
- value: 1
895
- });
896
- Object.defineProperty(this, "_removeAllListeners", {
897
- enumerable: true,
898
- configurable: true,
899
- writable: true,
900
- value: []
901
- });
902
- const handleData = (data, response) => {
903
- this.framing(data, (error, frame) => {
904
- if (this._waitingResponse) {
905
- this._waitingResponse.callback(error, frame);
906
- }
907
- else if (!error) {
908
- this.emit('framing', frame, response);
909
- }
910
- });
911
- };
912
- physicalLayer.on('data', handleData);
913
- this._removeAllListeners.push(() => {
914
- physicalLayer.removeListener('data', handleData);
915
- });
916
- }
917
- framing(buffer, callback) {
918
- if (buffer.length >= 8) {
919
- if (buffer[2] === 0 && buffer[3] === 0 && buffer.readUInt16BE(4) === buffer.length - 6) {
920
- const frame = {
921
- transaction: buffer.readUInt16BE(0),
922
- unit: buffer[6],
923
- fc: buffer[7],
924
- data: Array.from(buffer.subarray(8)),
925
- buffer,
926
- };
927
- if (this._waitingResponse) {
928
- for (const check of this._waitingResponse.preCheck) {
929
- const res = check(frame);
930
- if (typeof res === 'undefined') {
931
- callback(new Error('Insufficient data length'));
932
- return;
933
- }
934
- if (typeof res === 'number') {
935
- if (res < frame.data.length) {
936
- callback(new Error('Insufficient data length'));
937
- return;
938
- }
939
- if (res !== frame.data.length) {
940
- callback(new Error('Invalid response'));
941
- return;
942
- }
943
- }
944
- if (!res) {
945
- callback(new Error('Invalid response'));
946
- return;
947
- }
948
- }
949
- }
950
- callback(null, frame);
951
- }
952
- else {
953
- callback(new Error('Invalid data'));
954
- }
955
- }
956
- else {
957
- callback(new Error('Insufficient data length'));
958
- }
959
- }
960
- startWaitingResponse(preCheck, callback) {
961
- this._waitingResponse = { preCheck, callback };
962
- }
963
- stopWaitingResponse() {
964
- this._waitingResponse = undefined;
965
- }
966
- encode(data) {
967
- var _a;
968
- const buffer = Buffer.alloc(data.data.length + 8);
969
- buffer.writeUInt16BE((_a = data.transaction) !== null && _a !== void 0 ? _a : this._transactionId, 0);
970
- buffer.writeUInt16BE(0, 2);
971
- buffer.writeUInt16BE(data.data.length + 2, 4);
972
- buffer.writeUInt8(data.unit, 6);
973
- buffer.writeUInt8(data.fc, 7);
974
- data.data.forEach((num, index) => {
975
- buffer.writeUInt8(num, 8 + index);
976
- });
977
- this._transactionId = (this._transactionId + 1) % 256 || 1;
978
- return buffer;
979
- }
980
- destroy() {
981
- this.removeAllListeners();
982
- for (const removeAllListener of this._removeAllListeners) {
983
- removeAllListener();
984
- }
985
- }
986
- }
987
-
988
- class ModbusMaster extends EventEmitter {
989
- get isOpen() {
990
- return this.physicalLayer.isOpen;
991
- }
992
- get destroyed() {
993
- return this.physicalLayer.destroyed;
994
- }
995
- constructor(applicationLayer, physicalLayer, timeout = 1000) {
996
- super();
997
- Object.defineProperty(this, "applicationLayer", {
998
- enumerable: true,
999
- configurable: true,
1000
- writable: true,
1001
- value: applicationLayer
1002
- });
1003
- Object.defineProperty(this, "physicalLayer", {
1004
- enumerable: true,
1005
- configurable: true,
1006
- writable: true,
1007
- value: physicalLayer
1008
- });
1009
- Object.defineProperty(this, "timeout", {
1010
- enumerable: true,
1011
- configurable: true,
1012
- writable: true,
1013
- value: timeout
1014
- });
1015
- Object.defineProperty(this, "writeFC1", {
1016
- enumerable: true,
1017
- configurable: true,
1018
- writable: true,
1019
- value: void 0
1020
- });
1021
- Object.defineProperty(this, "writeFC2", {
1022
- enumerable: true,
1023
- configurable: true,
1024
- writable: true,
1025
- value: void 0
1026
- });
1027
- Object.defineProperty(this, "writeFC3", {
1028
- enumerable: true,
1029
- configurable: true,
1030
- writable: true,
1031
- value: void 0
1032
- });
1033
- Object.defineProperty(this, "writeFC4", {
1034
- enumerable: true,
1035
- configurable: true,
1036
- writable: true,
1037
- value: void 0
1038
- });
1039
- Object.defineProperty(this, "writeFC5", {
1040
- enumerable: true,
1041
- configurable: true,
1042
- writable: true,
1043
- value: void 0
1044
- });
1045
- Object.defineProperty(this, "writeFC6", {
1046
- enumerable: true,
1047
- configurable: true,
1048
- writable: true,
1049
- value: void 0
1050
- });
1051
- Object.defineProperty(this, "writeFC15", {
1052
- enumerable: true,
1053
- configurable: true,
1054
- writable: true,
1055
- value: void 0
1056
- });
1057
- Object.defineProperty(this, "writeFC16", {
1058
- enumerable: true,
1059
- configurable: true,
1060
- writable: true,
1061
- value: void 0
1062
- });
1063
- Object.defineProperty(this, "handleFC17", {
1064
- enumerable: true,
1065
- configurable: true,
1066
- writable: true,
1067
- value: void 0
1068
- });
1069
- Object.defineProperty(this, "handleFC22", {
1070
- enumerable: true,
1071
- configurable: true,
1072
- writable: true,
1073
- value: void 0
1074
- });
1075
- Object.defineProperty(this, "handleFC23", {
1076
- enumerable: true,
1077
- configurable: true,
1078
- writable: true,
1079
- value: void 0
1080
- });
1081
- Object.defineProperty(this, "handleFC43_14", {
1082
- enumerable: true,
1083
- configurable: true,
1084
- writable: true,
1085
- value: void 0
1086
- });
1087
- this.writeFC1 = this.readCoils;
1088
- this.writeFC2 = this.readDiscreteInputs;
1089
- this.writeFC3 = this.readHoldingRegisters;
1090
- this.writeFC4 = this.readInputRegisters;
1091
- this.writeFC5 = this.writeSingleCoil;
1092
- this.writeFC6 = this.writeSingleRegister;
1093
- this.writeFC15 = this.writeMultipleCoils;
1094
- this.writeFC16 = this.writeMultipleRegisters;
1095
- this.handleFC17 = this.reportServerId;
1096
- this.handleFC22 = this.maskWriteRegister;
1097
- this.handleFC23 = this.readAndWriteMultipleRegisters;
1098
- this.handleFC43_14 = this.readDeviceIdentification;
1099
- physicalLayer.on('error', (error) => {
1100
- this.emit('error', error);
1101
- });
1102
- physicalLayer.on('close', () => {
1103
- this.emit('close');
1104
- });
1105
- }
1106
- waitResponse(request, response, timeout) {
1107
- return new Promise((resolve, reject) => {
1108
- this.physicalLayer
1109
- .write(request.data)
1110
- .then(() => {
1111
- if (request.broadcast) {
1112
- resolve();
1113
- }
1114
- else {
1115
- const tid = setTimeout(() => {
1116
- this.applicationLayer.stopWaitingResponse();
1117
- reject(new Error('Timeout'));
1118
- }, timeout);
1119
- this.applicationLayer.startWaitingResponse(response.preCheck, (error, frame) => {
1120
- clearTimeout(tid);
1121
- this.applicationLayer.stopWaitingResponse();
1122
- if (error) {
1123
- reject(error);
1124
- }
1125
- else {
1126
- resolve(frame);
1127
- }
1128
- });
1129
- }
1130
- })
1131
- .catch((error) => {
1132
- reject(error);
1133
- });
1134
- });
1135
- }
1136
- writeFC1Or2(unit, fc, address, length, timeout) {
1137
- const byteCount = Math.ceil(length / 8);
1138
- const bufferTx = Buffer.alloc(4);
1139
- bufferTx.writeUInt16BE(address, 0);
1140
- bufferTx.writeUInt16BE(length, 2);
1141
- return this.waitResponse({
1142
- data: this.applicationLayer.encode({
1143
- unit,
1144
- fc,
1145
- data: Array.from(bufferTx),
1146
- }),
1147
- broadcast: unit === 0,
1148
- }, {
1149
- preCheck: [(frame) => frame.unit === unit && frame.fc === fc, () => 1 + byteCount, (frame) => frame.data[0] === byteCount],
1150
- }, timeout).then((frame) => {
1151
- if (frame) {
1152
- return Object.assign(Object.assign({}, frame), { data: Array.from({ length }).map((_, index) => (frame.data[1 + ~~(index / 8)] & (1 << index % 8)) > 0) });
1153
- }
1154
- });
1155
- }
1156
- readCoils(unit, address, length, timeout = this.timeout) {
1157
- return this.writeFC1Or2(unit, 0x01, address, length, timeout);
1158
- }
1159
- readDiscreteInputs(unit, address, length, timeout = this.timeout) {
1160
- return this.writeFC1Or2(unit, 0x02, address, length, timeout);
1161
- }
1162
- writeFC3Or4(unit, fc, address, length, timeout) {
1163
- const byteCount = length * 2;
1164
- const bufferTx = Buffer.alloc(4);
1165
- bufferTx.writeUInt16BE(address, 0);
1166
- bufferTx.writeUInt16BE(length, 2);
1167
- return this.waitResponse({
1168
- data: this.applicationLayer.encode({
1169
- unit,
1170
- fc,
1171
- data: Array.from(bufferTx),
1172
- }),
1173
- broadcast: unit === 0,
1174
- }, {
1175
- preCheck: [(frame) => frame.unit === unit && frame.fc === fc, () => 1 + byteCount, (frame) => frame.data[0] === byteCount],
1176
- }, timeout).then((frame) => {
1177
- if (frame) {
1178
- const bufferRx = Buffer.from(frame.data.slice(1));
1179
- return Object.assign(Object.assign({}, frame), { data: Array.from({ length }).map((_, index) => bufferRx.readUInt16BE(index * 2)) });
1180
- }
1181
- });
1182
- }
1183
- readHoldingRegisters(unit, address, length, timeout = this.timeout) {
1184
- return this.writeFC3Or4(unit, 0x03, address, length, timeout);
1185
- }
1186
- readInputRegisters(unit, address, length, timeout = this.timeout) {
1187
- return this.writeFC3Or4(unit, 0x04, address, length, timeout);
1188
- }
1189
- writeSingleCoil(unit, address, value, timeout = this.timeout) {
1190
- const fc = 0x05;
1191
- const bufferTx = Buffer.alloc(4);
1192
- bufferTx.writeUInt16BE(address, 0);
1193
- bufferTx.writeUInt16BE(value ? 0xff00 : 0x0000, 2);
1194
- return this.waitResponse({
1195
- data: this.applicationLayer.encode({
1196
- unit,
1197
- fc,
1198
- data: Array.from(bufferTx),
1199
- }),
1200
- broadcast: unit === 0,
1201
- }, {
1202
- preCheck: [
1203
- (frame) => frame.unit === unit && frame.fc === fc,
1204
- () => bufferTx.length,
1205
- (frame) => frame.data.every((v, i) => v === bufferTx[i]),
1206
- ],
1207
- }, timeout).then((frame) => {
1208
- if (frame) {
1209
- return Object.assign(Object.assign({}, frame), { data: value });
1210
- }
1211
- });
1212
- }
1213
- writeSingleRegister(unit, address, value, timeout = this.timeout) {
1214
- const fc = 0x06;
1215
- const bufferTx = Buffer.alloc(4);
1216
- bufferTx.writeUInt16BE(address, 0);
1217
- bufferTx.writeUInt16BE(value, 2);
1218
- return this.waitResponse({
1219
- data: this.applicationLayer.encode({
1220
- unit,
1221
- fc,
1222
- data: Array.from(bufferTx),
1223
- }),
1224
- broadcast: unit === 0,
1225
- }, {
1226
- preCheck: [
1227
- (frame) => frame.unit === unit && frame.fc === fc,
1228
- () => bufferTx.length,
1229
- (frame) => frame.data.every((v, i) => v === bufferTx[i]),
1230
- ],
1231
- }, timeout).then((frame) => {
1232
- if (frame) {
1233
- return Object.assign(Object.assign({}, frame), { data: value });
1234
- }
1235
- });
1236
- }
1237
- writeMultipleCoils(unit, address, value, timeout = this.timeout) {
1238
- const fc = 0x0f;
1239
- const byteCount = Math.ceil(value.length / 8);
1240
- const bufferTx = Buffer.alloc(5 + byteCount);
1241
- bufferTx.writeUInt16BE(address, 0);
1242
- bufferTx.writeUInt16BE(value.length, 2);
1243
- bufferTx.writeUInt8(byteCount, 4);
1244
- value.forEach((v, i) => {
1245
- if (v) {
1246
- bufferTx[5 + ~~(i / 8)] |= 1 << i % 8;
1247
- }
1248
- });
1249
- return this.waitResponse({
1250
- data: this.applicationLayer.encode({
1251
- unit,
1252
- fc,
1253
- data: Array.from(bufferTx),
1254
- }),
1255
- broadcast: unit === 0,
1256
- }, {
1257
- preCheck: [(frame) => frame.unit === unit && frame.fc === fc, () => 4, (frame) => frame.data.every((v, i) => v === bufferTx[i])],
1258
- }, timeout).then((frame) => {
1259
- if (frame) {
1260
- return Object.assign(Object.assign({}, frame), { data: value });
1261
- }
1262
- });
1263
- }
1264
- writeMultipleRegisters(unit, address, value, timeout = this.timeout) {
1265
- const fc = 0x10;
1266
- const byteCount = value.length * 2;
1267
- const bufferTx = Buffer.alloc(5 + byteCount);
1268
- bufferTx.writeUInt16BE(address, 0);
1269
- bufferTx.writeUInt16BE(value.length, 2);
1270
- bufferTx.writeUInt8(byteCount, 4);
1271
- value.forEach((v, i) => {
1272
- bufferTx.writeUInt16BE(v, 5 + i * 2);
1273
- });
1274
- return this.waitResponse({
1275
- data: this.applicationLayer.encode({
1276
- unit,
1277
- fc,
1278
- data: Array.from(bufferTx),
1279
- }),
1280
- broadcast: unit === 0,
1281
- }, {
1282
- preCheck: [(frame) => frame.unit === unit && frame.fc === fc, () => 4, (frame) => frame.data.every((v, i) => v === bufferTx[i])],
1283
- }, timeout).then((frame) => {
1284
- if (frame) {
1285
- return Object.assign(Object.assign({}, frame), { data: value });
1286
- }
1287
- });
1288
- }
1289
- reportServerId(unit, timeout = this.timeout) {
1290
- const fc = 0x11;
1291
- return this.waitResponse({
1292
- data: this.applicationLayer.encode({
1293
- unit,
1294
- fc,
1295
- data: [],
1296
- }),
1297
- broadcast: unit === 0,
1298
- }, {
1299
- preCheck: [
1300
- (frame) => frame.unit === unit && frame.fc === fc,
1301
- (frame) => {
1302
- if (frame.data.length >= 3) {
1303
- return 1 + frame.data[0];
1304
- }
1305
- },
1306
- ],
1307
- }, timeout).then((frame) => {
1308
- if (frame) {
1309
- return Object.assign(Object.assign({}, frame), { data: {
1310
- serverId: frame.data[1],
1311
- runIndicatorStatus: frame.data[2] === 0xff,
1312
- additionalData: frame.data.slice(3),
1313
- } });
1314
- }
1315
- });
1316
- }
1317
- maskWriteRegister(unit, address, andMask, orMask, timeout = this.timeout) {
1318
- const fc = 0x16;
1319
- const bufferTx = Buffer.alloc(6);
1320
- bufferTx.writeUInt16BE(address, 0);
1321
- bufferTx.writeUInt16BE(andMask, 2);
1322
- bufferTx.writeUInt16BE(orMask, 4);
1323
- return this.waitResponse({
1324
- data: this.applicationLayer.encode({
1325
- unit,
1326
- fc,
1327
- data: Array.from(bufferTx),
1328
- }),
1329
- broadcast: unit === 0,
1330
- }, {
1331
- preCheck: [(frame) => frame.unit === unit && frame.fc === fc, () => 6, (frame) => frame.data.every((v, i) => v === bufferTx[i])],
1332
- }, timeout).then((frame) => {
1333
- if (frame) {
1334
- return Object.assign(Object.assign({}, frame), { data: { andMask, orMask } });
1335
- }
1336
- });
1337
- }
1338
- readAndWriteMultipleRegisters(unit, read, write, timeout = this.timeout) {
1339
- const fc = 0x17;
1340
- const byteCount = write.value.length * 2;
1341
- const bufferTx = Buffer.alloc(9 + byteCount);
1342
- bufferTx.writeUInt16BE(read.address, 0);
1343
- bufferTx.writeUInt16BE(read.length, 2);
1344
- bufferTx.writeUInt16BE(write.address, 4);
1345
- bufferTx.writeUInt16BE(write.value.length, 6);
1346
- bufferTx.writeUInt8(byteCount, 8);
1347
- write.value.forEach((v, i) => {
1348
- bufferTx.writeUInt16BE(v, 9 + i * 2);
1349
- });
1350
- return this.waitResponse({
1351
- data: this.applicationLayer.encode({
1352
- unit,
1353
- fc,
1354
- data: Array.from(bufferTx),
1355
- }),
1356
- broadcast: unit === 0,
1357
- }, {
1358
- preCheck: [(frame) => frame.unit === unit && frame.fc === fc, () => 1 + byteCount, (frame) => frame.data[0] === byteCount],
1359
- }, timeout).then((frame) => {
1360
- if (frame) {
1361
- const bufferRx = Buffer.from(frame.data.slice(1));
1362
- return Object.assign(Object.assign({}, frame), { data: Array.from({ length: read.length }).map((_, index) => bufferRx.readUInt16BE(index * 2)) });
1363
- }
1364
- });
1365
- }
1366
- readDeviceIdentification(unit, readDeviceIDCode, objectId, timeout = this.timeout) {
1367
- const fc = 0x2b;
1368
- return this.waitResponse({
1369
- data: this.applicationLayer.encode({
1370
- unit,
1371
- fc,
1372
- data: [0x0e, readDeviceIDCode, objectId],
1373
- }),
1374
- broadcast: unit === 0,
1375
- }, {
1376
- preCheck: [
1377
- (frame) => frame.unit === unit && frame.fc === fc,
1378
- (frame) => {
1379
- if (frame.data.length >= 6) {
1380
- if (frame.data[0] === 0x0e && frame.data[1] === readDeviceIDCode) {
1381
- const objects = [];
1382
- let object = [];
1383
- for (const v of frame.data.slice(6)) {
1384
- switch (object.length) {
1385
- case 0:
1386
- case 1: {
1387
- object.push(v);
1388
- break;
1389
- }
1390
- case 2: {
1391
- object.push([v]);
1392
- break;
1393
- }
1394
- case 3: {
1395
- object[2].push(v);
1396
- if (object[1] === object[2].length) {
1397
- objects.push(2 + object[1]);
1398
- object = [];
1399
- }
1400
- break;
1401
- }
1402
- }
1403
- }
1404
- if (objects.length === frame.data[5]) {
1405
- return 6 + objects.reduce((previous, current) => previous + current, 0);
1406
- }
1407
- }
1408
- else {
1409
- return false;
1410
- }
1411
- }
1412
- },
1413
- ],
1414
- }, timeout).then((frame) => {
1415
- if (frame) {
1416
- const objects = [];
1417
- let object = [];
1418
- for (const v of frame.data.slice(6)) {
1419
- switch (object.length) {
1420
- case 0:
1421
- case 1: {
1422
- object.push(v);
1423
- break;
1424
- }
1425
- case 2: {
1426
- object.push([v]);
1427
- break;
1428
- }
1429
- case 3: {
1430
- object[2].push(v);
1431
- if (object[1] === object[2].length) {
1432
- objects.push({ id: object[0], value: Buffer.from(object[2]).toString() });
1433
- object = [];
1434
- }
1435
- break;
1436
- }
1437
- }
1438
- }
1439
- return Object.assign(Object.assign({}, frame), { data: {
1440
- readDeviceIDCode,
1441
- conformityLevel: frame.data[2],
1442
- moreFollows: frame.data[3] === 0xff,
1443
- nextObjectId: frame.data[4],
1444
- objects,
1445
- } });
1446
- }
1447
- });
1448
- }
1449
- open(...args) {
1450
- return this.physicalLayer.open(...args);
1451
- }
1452
- close() {
1453
- return this.physicalLayer.close();
1454
- }
1455
- destroy() {
1456
- this.removeAllListeners();
1457
- this.applicationLayer.destroy();
1458
- return this.physicalLayer.destroy();
1459
- }
1460
- }
1461
-
1462
- /******************************************************************************
1463
- Copyright (c) Microsoft Corporation.
1464
-
1465
- Permission to use, copy, modify, and/or distribute this software for any
1466
- purpose with or without fee is hereby granted.
1467
-
1468
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
1469
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
1470
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
1471
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
1472
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
1473
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
1474
- PERFORMANCE OF THIS SOFTWARE.
1475
- ***************************************************************************** */
1476
- /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
1477
-
1478
-
1479
- function __awaiter(thisArg, _arguments, P, generator) {
1480
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
1481
- return new (P || (P = Promise))(function (resolve, reject) {
1482
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
1483
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
1484
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
1485
- step((generator = generator.apply(thisArg, _arguments || [])).next());
1486
- });
1487
- }
1488
-
1489
- typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
1490
- var e = new Error(message);
1491
- return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
1492
- };
1493
-
1494
- class ModbusSlave extends EventEmitter {
1495
- get isOpen() {
1496
- return this.physicalLayer.isOpen;
1497
- }
1498
- get destroyed() {
1499
- return this.physicalLayer.destroyed;
1500
- }
1501
- constructor(model, applicationLayer, physicalLayer) {
1502
- super();
1503
- Object.defineProperty(this, "model", {
1504
- enumerable: true,
1505
- configurable: true,
1506
- writable: true,
1507
- value: model
1508
- });
1509
- Object.defineProperty(this, "applicationLayer", {
1510
- enumerable: true,
1511
- configurable: true,
1512
- writable: true,
1513
- value: applicationLayer
1514
- });
1515
- Object.defineProperty(this, "physicalLayer", {
1516
- enumerable: true,
1517
- configurable: true,
1518
- writable: true,
1519
- value: physicalLayer
1520
- });
1521
- Object.defineProperty(this, "unit", {
1522
- enumerable: true,
1523
- configurable: true,
1524
- writable: true,
1525
- value: 1
1526
- });
1527
- if (typeof model.unit !== 'undefined') {
1528
- this.unit = model.unit;
1529
- }
1530
- applicationLayer.on('framing', (frame, _response) => __awaiter(this, void 0, void 0, function* () {
1531
- if (!(frame.unit === 0x00 || frame.unit === this.unit)) {
1532
- return;
1533
- }
1534
- const response = (data) => __awaiter(this, void 0, void 0, function* () {
1535
- if (frame.unit === 0x00) {
1536
- return;
1537
- }
1538
- try {
1539
- yield _response(data);
1540
- }
1541
- catch (error) { }
1542
- });
1543
- if (model.interceptor) {
1544
- try {
1545
- const data = yield model.interceptor(frame.fc, frame.data);
1546
- if (data) {
1547
- response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { data })));
1548
- return;
1549
- }
1550
- }
1551
- catch (error) {
1552
- this.responseError(frame, response, error);
1553
- return;
1554
- }
1555
- }
1556
- switch (frame.fc) {
1557
- case 0x01: {
1558
- this.handleFC1(frame, response);
1559
- break;
1560
- }
1561
- case 0x02: {
1562
- this.handleFC2(frame, response);
1563
- break;
1564
- }
1565
- case 0x03: {
1566
- this.handleFC3(frame, response);
1567
- break;
1568
- }
1569
- case 0x04: {
1570
- this.handleFC4(frame, response);
1571
- break;
1572
- }
1573
- case 0x05: {
1574
- this.handleFC5(frame, response);
1575
- break;
1576
- }
1577
- case 0x06: {
1578
- this.handleFC6(frame, response);
1579
- break;
1580
- }
1581
- case 0x0f: {
1582
- this.handleFC15(frame, response);
1583
- break;
1584
- }
1585
- case 0x10: {
1586
- this.handleFC16(frame, response);
1587
- break;
1588
- }
1589
- case 0x11: {
1590
- this.handleFC17(frame, response);
1591
- break;
1592
- }
1593
- case 0x16: {
1594
- this.handleFC22(frame, response);
1595
- break;
1596
- }
1597
- case 0x17: {
1598
- this.handleFC23(frame, response);
1599
- break;
1600
- }
1601
- case 0x2b: {
1602
- this.handleFC43_14(frame, response);
1603
- break;
1604
- }
1605
- default: {
1606
- this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
1607
- break;
1608
- }
1609
- }
1610
- }));
1611
- physicalLayer.on('error', (error) => {
1612
- this.emit('error', error);
1613
- });
1614
- physicalLayer.on('close', () => {
1615
- this.emit('close');
1616
- });
1617
- }
1618
- handleFC1(frame, response) {
1619
- var _a, _b;
1620
- if (frame.data.length === 4) {
1621
- if (this.model.readCoils) {
1622
- const bufferRx = Buffer.from(frame.data);
1623
- const address = bufferRx.readUInt16BE(0);
1624
- const length = bufferRx.readUInt16BE(2);
1625
- if (length >= 0x0001 && length <= 0x07d0) {
1626
- if (checkRange([address, address + length], (_b = (_a = this.model).getAddressRange) === null || _b === void 0 ? void 0 : _b.call(_a).coils)) {
1627
- Promise.resolve(this.model.readCoils(address, length))
1628
- .then((coils) => {
1629
- const bufferTx = Buffer.alloc(Math.ceil(length / 8));
1630
- coils.forEach((coil, index) => {
1631
- if (coil) {
1632
- bufferTx[~~(index / 8)] |= 1 << index % 8;
1633
- }
1634
- });
1635
- response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { data: [bufferTx.length].concat(Array.from(bufferTx)) })));
1636
- })
1637
- .catch((error) => {
1638
- this.responseError(frame, response, error);
1639
- });
1640
- }
1641
- else {
1642
- this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_ADDRESS));
1643
- }
1644
- }
1645
- else {
1646
- this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_VALUE));
1647
- }
1648
- }
1649
- else {
1650
- this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
1651
- }
1652
- }
1653
- }
1654
- handleFC2(frame, response) {
1655
- var _a, _b;
1656
- if (frame.data.length === 4) {
1657
- if (this.model.readDiscreteInputs) {
1658
- const bufferRx = Buffer.from(frame.data);
1659
- const address = bufferRx.readUInt16BE(0);
1660
- const length = bufferRx.readUInt16BE(2);
1661
- if (length >= 0x0001 && length <= 0x07d0) {
1662
- if (checkRange([address, address + length], (_b = (_a = this.model).getAddressRange) === null || _b === void 0 ? void 0 : _b.call(_a).discreteInputs)) {
1663
- Promise.resolve(this.model.readDiscreteInputs(address, length))
1664
- .then((discreteInputs) => {
1665
- const bufferTx = Buffer.alloc(Math.ceil(length / 8));
1666
- discreteInputs.forEach((discreteInput, index) => {
1667
- if (discreteInput) {
1668
- bufferTx[~~(index / 8)] |= 1 << index % 8;
1669
- }
1670
- });
1671
- response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { data: [bufferTx.length].concat(Array.from(bufferTx)) })));
1672
- })
1673
- .catch((error) => {
1674
- this.responseError(frame, response, error);
1675
- });
1676
- }
1677
- else {
1678
- this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_ADDRESS));
1679
- }
1680
- }
1681
- else {
1682
- this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_VALUE));
1683
- }
1684
- }
1685
- else {
1686
- this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
1687
- }
1688
- }
1689
- }
1690
- handleFC3(frame, response) {
1691
- var _a, _b;
1692
- if (frame.data.length === 4) {
1693
- if (this.model.readHoldingRegisters) {
1694
- const bufferRx = Buffer.from(frame.data);
1695
- const address = bufferRx.readUInt16BE(0);
1696
- const length = bufferRx.readUInt16BE(2);
1697
- if (length >= 0x0001 && length <= 0x007d) {
1698
- if (checkRange([address, address + length], (_b = (_a = this.model).getAddressRange) === null || _b === void 0 ? void 0 : _b.call(_a).holdingRegisters)) {
1699
- Promise.resolve(this.model.readHoldingRegisters(address, length))
1700
- .then((registers) => {
1701
- const bufferTx = Buffer.alloc(length * 2);
1702
- registers.forEach((register, index) => {
1703
- bufferTx.writeUInt16BE(register, index * 2);
1704
- });
1705
- response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { data: [bufferTx.length].concat(Array.from(bufferTx)) })));
1706
- })
1707
- .catch((error) => {
1708
- this.responseError(frame, response, error);
1709
- });
1710
- }
1711
- else {
1712
- this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_ADDRESS));
1713
- }
1714
- }
1715
- else {
1716
- this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_VALUE));
1717
- }
1718
- }
1719
- else {
1720
- this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
1721
- }
1722
- }
1723
- }
1724
- handleFC4(frame, response) {
1725
- var _a, _b;
1726
- if (frame.data.length === 4) {
1727
- if (this.model.readInputRegisters) {
1728
- const bufferRx = Buffer.from(frame.data);
1729
- const address = bufferRx.readUInt16BE(0);
1730
- const length = bufferRx.readUInt16BE(2);
1731
- if (length >= 0x0001 && length <= 0x007d) {
1732
- if (checkRange([address, address + length], (_b = (_a = this.model).getAddressRange) === null || _b === void 0 ? void 0 : _b.call(_a).inputRegisters)) {
1733
- Promise.resolve(this.model.readInputRegisters(address, length))
1734
- .then((registers) => {
1735
- const bufferTx = Buffer.alloc(length * 2);
1736
- registers.forEach((register, index) => {
1737
- bufferTx.writeUInt16BE(register, index * 2);
1738
- });
1739
- response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { data: [bufferTx.length].concat(Array.from(bufferTx)) })));
1740
- })
1741
- .catch((error) => {
1742
- this.responseError(frame, response, error);
1743
- });
1744
- }
1745
- else {
1746
- this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_ADDRESS));
1747
- }
1748
- }
1749
- else {
1750
- this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_VALUE));
1751
- }
1752
- }
1753
- else {
1754
- this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
1755
- }
1756
- }
1757
- }
1758
- handleFC5(frame, response) {
1759
- var _a, _b;
1760
- if (frame.data.length === 4) {
1761
- if (this.model.writeSingleCoil) {
1762
- const bufferRx = Buffer.from(frame.data);
1763
- const address = bufferRx.readUInt16BE(0);
1764
- const value = bufferRx.readUInt16BE(2);
1765
- if (value === 0x0000 || value === 0xff00) {
1766
- if (checkRange(address, (_b = (_a = this.model).getAddressRange) === null || _b === void 0 ? void 0 : _b.call(_a).coils)) {
1767
- Promise.resolve(this.model.writeSingleCoil(address, value === 0xff00))
1768
- .then(() => {
1769
- response(this.applicationLayer.encode(frame));
1770
- })
1771
- .catch((error) => {
1772
- this.responseError(frame, response, error);
1773
- });
1774
- }
1775
- else {
1776
- this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_ADDRESS));
1777
- }
1778
- }
1779
- else {
1780
- this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_VALUE));
1781
- }
1782
- }
1783
- else {
1784
- this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
1785
- }
1786
- }
1787
- }
1788
- handleFC6(frame, response) {
1789
- var _a, _b;
1790
- if (frame.data.length === 4) {
1791
- if (this.model.writeSingleRegister) {
1792
- const bufferRx = Buffer.from(frame.data);
1793
- const address = bufferRx.readUInt16BE(0);
1794
- const value = bufferRx.readUInt16BE(2);
1795
- if (value >= 0x0000 && value <= 0xffff) {
1796
- if (checkRange(address, (_b = (_a = this.model).getAddressRange) === null || _b === void 0 ? void 0 : _b.call(_a).holdingRegisters)) {
1797
- Promise.resolve(this.model.writeSingleRegister(address, value))
1798
- .then(() => {
1799
- response(this.applicationLayer.encode(frame));
1800
- })
1801
- .catch((error) => {
1802
- this.responseError(frame, response, error);
1803
- });
1804
- }
1805
- else {
1806
- this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_ADDRESS));
1807
- }
1808
- }
1809
- else {
1810
- this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_VALUE));
1811
- }
1812
- }
1813
- else {
1814
- this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
1815
- }
1816
- }
1817
- }
1818
- handleFC15(frame, response) {
1819
- var _a, _b;
1820
- if (frame.data.length > 5 && frame.data.length === 5 + frame.data[4]) {
1821
- if (this.model.writeMultipleCoils || this.model.writeSingleCoil) {
1822
- const bufferRx = Buffer.from(frame.data);
1823
- const address = bufferRx.readUInt16BE(0);
1824
- const length = bufferRx.readUInt16BE(2);
1825
- const byteCount = bufferRx[4];
1826
- if (length >= 0x0001 && length <= 0x07b0 && byteCount === Math.ceil(length / 8)) {
1827
- if (checkRange([address, address + length], (_b = (_a = this.model).getAddressRange) === null || _b === void 0 ? void 0 : _b.call(_a).coils)) {
1828
- const value = Array.from({ length }).map((_, index) => (bufferRx[5 + ~~(index / 8)] & (1 << index % 8)) > 0);
1829
- Promise.resolve(this.model.writeMultipleCoils
1830
- ? this.model.writeMultipleCoils(address, value)
1831
- : Promise.all(value.map((v, i) => this.model.writeSingleCoil(address + i, v))))
1832
- .then(() => {
1833
- response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { data: Array.from(bufferRx).slice(0, 4) })));
1834
- })
1835
- .catch((error) => {
1836
- this.responseError(frame, response, error);
1837
- });
1838
- }
1839
- else {
1840
- this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_ADDRESS));
1841
- }
1842
- }
1843
- else {
1844
- this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_VALUE));
1845
- }
1846
- }
1847
- else {
1848
- this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
1849
- }
1850
- }
1851
- }
1852
- handleFC16(frame, response) {
1853
- var _a, _b;
1854
- if (frame.data.length > 5 && frame.data.length === 5 + frame.data[4]) {
1855
- if (this.model.writeMultipleRegisters || this.model.writeSingleRegister) {
1856
- const bufferRx = Buffer.from(frame.data);
1857
- const address = bufferRx.readUInt16BE(0);
1858
- const length = bufferRx.readUInt16BE(2);
1859
- const byteCount = bufferRx[4];
1860
- if (length >= 0x0001 && length <= 0x007b && byteCount === length * 2) {
1861
- if (checkRange([address, address + length], (_b = (_a = this.model).getAddressRange) === null || _b === void 0 ? void 0 : _b.call(_a).holdingRegisters)) {
1862
- const value = Array.from({ length }).map((_, index) => bufferRx.readUInt16BE(5 + index * 2));
1863
- Promise.resolve(this.model.writeMultipleRegisters
1864
- ? this.model.writeMultipleRegisters(address, value)
1865
- : Promise.all(value.map((v, i) => this.model.writeSingleRegister(address + i, v))))
1866
- .then(() => {
1867
- response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { data: Array.from(bufferRx).slice(0, 4) })));
1868
- })
1869
- .catch((error) => {
1870
- this.responseError(frame, response, error);
1871
- });
1872
- }
1873
- else {
1874
- this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_ADDRESS));
1875
- }
1876
- }
1877
- else {
1878
- this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_VALUE));
1879
- }
1880
- }
1881
- else {
1882
- this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
1883
- }
1884
- }
1885
- }
1886
- handleFC17(frame, response) {
1887
- if (frame.data.length === 0) {
1888
- if (this.model.reportServerId) {
1889
- Promise.resolve(this.model.reportServerId())
1890
- .then(({ serverId = this.unit, runIndicatorStatus = true, additionalData = [] }) => {
1891
- response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { data: [2 + additionalData.length, serverId, runIndicatorStatus ? 0xff : 0x00].concat(additionalData) })));
1892
- })
1893
- .catch((error) => {
1894
- this.responseError(frame, response, error);
1895
- });
1896
- }
1897
- else {
1898
- this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
1899
- }
1900
- }
1901
- }
1902
- handleFC22(frame, response) {
1903
- var _a, _b;
1904
- if (frame.data.length === 6) {
1905
- if (this.model.maskWriteRegister || (this.model.readHoldingRegisters && this.model.writeSingleRegister)) {
1906
- const bufferRx = Buffer.from(frame.data);
1907
- const address = bufferRx.readUInt16BE(0);
1908
- const andMask = bufferRx.readUInt16BE(2);
1909
- const orMask = bufferRx.readUInt16BE(4);
1910
- if (checkRange(address, (_b = (_a = this.model).getAddressRange) === null || _b === void 0 ? void 0 : _b.call(_a).holdingRegisters)) {
1911
- Promise.resolve(this.model.maskWriteRegister
1912
- ? this.model.maskWriteRegister(address, andMask, orMask)
1913
- : Promise.resolve(this.model.readHoldingRegisters(address, 1)).then(([value]) => {
1914
- return Promise.resolve(this.model.writeSingleRegister(address, (value & andMask) | (orMask & (~andMask & 0xff))));
1915
- }))
1916
- .then(() => {
1917
- response(this.applicationLayer.encode(frame));
1918
- })
1919
- .catch((error) => {
1920
- this.responseError(frame, response, error);
1921
- });
1922
- }
1923
- else {
1924
- this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_ADDRESS));
1925
- }
1926
- }
1927
- else {
1928
- this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
1929
- }
1930
- }
1931
- }
1932
- handleFC23(frame, response) {
1933
- var _a, _b;
1934
- if (frame.data.length > 9 && frame.data.length === 9 + frame.data[8]) {
1935
- if (this.model.readHoldingRegisters && (this.model.writeMultipleRegisters || this.model.writeSingleRegister)) {
1936
- const bufferRx = Buffer.from(frame.data);
1937
- const address = {
1938
- read: bufferRx.readUInt16BE(0),
1939
- write: bufferRx.readUInt16BE(4),
1940
- };
1941
- const length = {
1942
- read: bufferRx.readUInt16BE(2),
1943
- write: bufferRx.readUInt16BE(6),
1944
- };
1945
- const byteCount = bufferRx[8];
1946
- if (length.read >= 0x0001 &&
1947
- length.read <= 0x007d &&
1948
- length.write >= 0x0001 &&
1949
- length.write <= 0x0079 &&
1950
- byteCount === length.write * 2) {
1951
- if (checkRange([address.read, address.read + length.read, address.write, address.write + length.write], (_b = (_a = this.model).getAddressRange) === null || _b === void 0 ? void 0 : _b.call(_a).holdingRegisters)) {
1952
- const value = Array.from({ length: length.write }).map((_, index) => bufferRx.readUInt16BE(9 + index * 2));
1953
- Promise.resolve(this.model.writeMultipleRegisters
1954
- ? this.model.writeMultipleRegisters(address.write, value)
1955
- : Promise.all(value.map((v, i) => this.model.writeSingleRegister(address.write + i, v))))
1956
- .then(() => Promise.resolve(this.model.readHoldingRegisters(address.read, length.read)))
1957
- .then((registers) => {
1958
- const bufferTx = Buffer.alloc(length.read * 2);
1959
- registers.forEach((register, index) => {
1960
- bufferTx.writeUInt16BE(register, index * 2);
1961
- });
1962
- response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { data: [bufferTx.length].concat(Array.from(bufferTx)) })));
1963
- })
1964
- .catch((error) => {
1965
- this.responseError(frame, response, error);
1966
- });
1967
- }
1968
- else {
1969
- this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_ADDRESS));
1970
- }
1971
- }
1972
- else {
1973
- this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_VALUE));
1974
- }
1975
- }
1976
- else {
1977
- this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
1978
- }
1979
- }
1980
- }
1981
- handleFC43_14(frame, response) {
1982
- if (frame.data.length === 3) {
1983
- if (frame.data[0] === 0x0e && this.model.readDeviceIdentification) {
1984
- const readDeviceIDCode = frame.data[1];
1985
- let objectID = frame.data[2];
1986
- switch (readDeviceIDCode) {
1987
- case 0x01: {
1988
- if (objectID > 0x02 || (objectID > 0x06 && objectID < 0x80)) {
1989
- objectID = 0x00;
1990
- }
1991
- break;
1992
- }
1993
- case 0x02: {
1994
- if (objectID >= 0x80 || (objectID > 0x06 && objectID < 0x80)) {
1995
- objectID = 0x00;
1996
- }
1997
- break;
1998
- }
1999
- case 0x03: {
2000
- if (objectID > 0x06 && objectID < 0x80) {
2001
- objectID = 0x00;
2002
- }
2003
- break;
2004
- }
2005
- case 0x04: {
2006
- if (objectID > 0x06 && objectID < 0x80) {
2007
- this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_ADDRESS));
2008
- return;
2009
- }
2010
- break;
2011
- }
2012
- default: {
2013
- this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_VALUE));
2014
- return;
2015
- }
2016
- }
2017
- Promise.resolve(this.model.readDeviceIdentification())
2018
- .then((identification) => {
2019
- const objects = new Map([
2020
- [0x00, 'null'],
2021
- [0x01, 'null'],
2022
- [0x02, 'null'],
2023
- ]);
2024
- for (const [key, value] of Object.entries(identification)) {
2025
- const id = parseInt(key);
2026
- if (!isNaN(id) && id >= 0 && id <= 255) {
2027
- objects.set(id, value);
2028
- }
2029
- }
2030
- if (!objects.has(objectID)) {
2031
- if (readDeviceIDCode === 0x04) {
2032
- this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_ADDRESS));
2033
- return;
2034
- }
2035
- objectID = 0x00;
2036
- }
2037
- const ids = [];
2038
- let totalLength = 10;
2039
- let lastID = 0;
2040
- let conformityLevel = 0x81;
2041
- for (const [id, value] of objects.entries()) {
2042
- if (id < 0x00 || (id >= 0x07 && id <= 0x7f) || id > 0xff) {
2043
- this.responseError(frame, response, getErrorByCode(ErrorCode.SERVER_DEVICE_FAILURE));
2044
- return;
2045
- }
2046
- if (id > 0x02) {
2047
- conformityLevel = 0x82;
2048
- }
2049
- if (id > 0x80) {
2050
- conformityLevel = 0x83;
2051
- }
2052
- if (objectID > id) {
2053
- continue;
2054
- }
2055
- if (value.length > 245) {
2056
- this.responseError(frame, response, getErrorByCode(ErrorCode.SERVER_DEVICE_FAILURE));
2057
- return;
2058
- }
2059
- if (lastID !== 0) {
2060
- continue;
2061
- }
2062
- if (value.length + 2 > 253 - totalLength) {
2063
- if (lastID === 0) {
2064
- lastID = id;
2065
- }
2066
- }
2067
- else {
2068
- totalLength += value.length + 2;
2069
- ids.push(id);
2070
- if (readDeviceIDCode === 0x04) {
2071
- break;
2072
- }
2073
- }
2074
- }
2075
- ids.sort((a, b) => a - b);
2076
- response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { data: [0x0e, readDeviceIDCode, conformityLevel, lastID === 0 ? 0x00 : 0xff, lastID, ids.length].concat(ids
2077
- .map((id) => {
2078
- const value = objects.get(id);
2079
- return [id, value.length].concat(Array.from(Buffer.from(value)));
2080
- })
2081
- .flat()) })));
2082
- })
2083
- .catch((error) => {
2084
- this.responseError(frame, response, error);
2085
- });
2086
- }
2087
- else {
2088
- this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
2089
- }
2090
- }
2091
- }
2092
- responseError(frame, response, error) {
2093
- response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { fc: frame.fc | 0x80, data: [getCodeByError(error)] })));
2094
- }
2095
- open(...args) {
2096
- return this.physicalLayer.open(...args);
2097
- }
2098
- close() {
2099
- return this.physicalLayer.close();
2100
- }
2101
- destroy() {
2102
- this.removeAllListeners();
2103
- this.applicationLayer.destroy();
2104
- return this.physicalLayer.destroy();
2105
- }
2106
- }
2107
-
2108
- export { AbstractApplicationLayer, AbstractPhysicalLayer, AsciiApplicationLayer, ErrorCode, ModbusMaster, ModbusSlave, RtuApplicationLayer, SerialPhysicalLayer, TcpApplicationLayer, TcpClientPhysicalLayer, TcpServerPhysicalLayer, UdpPhysicalLayer, getCodeByError, getErrorByCode };