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