njs-modbus 3.3.0 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +177 -131
- package/README.zh-CN.md +177 -130
- package/dist/index.cjs +715 -519
- package/dist/index.d.ts +86 -61
- package/dist/index.mjs +715 -519
- package/dist/utils.cjs +53 -25
- package/dist/utils.d.ts +15 -14
- package/dist/utils.mjs +49 -24
- package/package.json +3 -9
package/dist/utils.cjs
CHANGED
|
@@ -92,7 +92,7 @@ function checkRange(value, range) {
|
|
|
92
92
|
return false;
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
-
const
|
|
95
|
+
const CRC_TABLE = new Uint16Array([
|
|
96
96
|
0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241, 0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440, 0xcc01,
|
|
97
97
|
0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40, 0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841, 0xd801, 0x18c0,
|
|
98
98
|
0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40, 0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41, 0x1400, 0xd4c1, 0xd581,
|
|
@@ -110,23 +110,29 @@ const TABLE = new Uint16Array([
|
|
|
110
110
|
0x4c80, 0x8c41, 0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641, 0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081,
|
|
111
111
|
0x4040,
|
|
112
112
|
]);
|
|
113
|
-
|
|
113
|
+
/** CRC-16 (Modbus) over a single contiguous buffer. */
|
|
114
|
+
function crcFixed(data, start, end) {
|
|
114
115
|
let crc = 0xffff;
|
|
115
116
|
for (let index = start; index < end; index++) {
|
|
116
|
-
crc =
|
|
117
|
+
crc = CRC_TABLE[(crc ^ data[index]) & 0xff] ^ (crc >> 8);
|
|
117
118
|
}
|
|
118
119
|
return crc;
|
|
119
120
|
}
|
|
120
|
-
|
|
121
121
|
/**
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
* Used for byte-level Modbus payload validation (function-code values, raw
|
|
125
|
-
* byte arrays in FC17/FC43 responses) — rejects negative, fractional, NaN,
|
|
126
|
-
* Infinity, and out-of-range values uniformly.
|
|
122
|
+
* CRC-16 (Modbus) over two contiguous buffer segments.
|
|
123
|
+
* Computes CRC(head[headOff:headOff+headLen]) followed by CRC(tail[tailOff:tailOff+tailLen]).
|
|
127
124
|
*/
|
|
128
|
-
function
|
|
129
|
-
|
|
125
|
+
function crcDual(head, headOff, headLen, tail, tailOff, tailLen) {
|
|
126
|
+
let crc = 0xffff;
|
|
127
|
+
const headEnd = headOff + headLen;
|
|
128
|
+
for (let i = headOff; i < headEnd; i++) {
|
|
129
|
+
crc = CRC_TABLE[(crc ^ head[i]) & 0xff] ^ (crc >> 8);
|
|
130
|
+
}
|
|
131
|
+
const tailEnd = tailOff + tailLen;
|
|
132
|
+
for (let i = tailOff; i < tailEnd; i++) {
|
|
133
|
+
crc = CRC_TABLE[(crc ^ tail[i]) & 0xff] ^ (crc >> 8);
|
|
134
|
+
}
|
|
135
|
+
return crc;
|
|
130
136
|
}
|
|
131
137
|
|
|
132
138
|
function lrc(data, start, end) {
|
|
@@ -207,12 +213,12 @@ const RES_TABLE = new Int32Array(256);
|
|
|
207
213
|
RES_TABLE[FunctionCode.READ_WRITE_MULTIPLE_REGISTERS] = -517;
|
|
208
214
|
RES_TABLE[FunctionCode.READ_DEVICE_IDENTIFICATION] = -999;
|
|
209
215
|
})();
|
|
210
|
-
function predictRtuFrameLength(
|
|
216
|
+
function predictRtuFrameLength(residual, data, residualLen, start, end, isResponse) {
|
|
211
217
|
const len = end - start;
|
|
212
218
|
if (len < 2) {
|
|
213
219
|
return PREDICT_NEED_MORE;
|
|
214
220
|
}
|
|
215
|
-
const fc =
|
|
221
|
+
const fc = start + 1 < residualLen ? residual[start + 1] : data[start + 1 - residualLen];
|
|
216
222
|
if (isResponse) {
|
|
217
223
|
if ((fc & EXCEPTION_OFFSET) !== 0) {
|
|
218
224
|
return 5;
|
|
@@ -228,16 +234,16 @@ function predictRtuFrameLength(buffer, start, end, isResponse) {
|
|
|
228
234
|
if (end - start < 8) {
|
|
229
235
|
return PREDICT_NEED_MORE;
|
|
230
236
|
}
|
|
231
|
-
if (
|
|
237
|
+
if ((start + 2 < residualLen ? residual[start + 2] : data[start + 2 - residualLen]) !== MEI_READ_DEVICE_ID) {
|
|
232
238
|
return PREDICT_UNKNOWN;
|
|
233
239
|
}
|
|
234
|
-
const numObjs =
|
|
240
|
+
const numObjs = start + 7 < residualLen ? residual[start + 7] : data[start + 7 - residualLen];
|
|
235
241
|
let cursor = start + 8;
|
|
236
242
|
for (let i = 0; i < numObjs; i++) {
|
|
237
243
|
if (end < cursor + 2) {
|
|
238
244
|
return PREDICT_NEED_MORE;
|
|
239
245
|
}
|
|
240
|
-
cursor += 2 +
|
|
246
|
+
cursor += 2 + (cursor + 1 < residualLen ? residual[cursor + 1] : data[cursor + 1 - residualLen]);
|
|
241
247
|
}
|
|
242
248
|
return cursor - start + 2;
|
|
243
249
|
}
|
|
@@ -246,7 +252,7 @@ function predictRtuFrameLength(buffer, start, end, isResponse) {
|
|
|
246
252
|
if (len <= offset) {
|
|
247
253
|
return PREDICT_NEED_MORE;
|
|
248
254
|
}
|
|
249
|
-
return (decode & 0xff) +
|
|
255
|
+
return (decode & 0xff) + (start + offset < residualLen ? residual[start + offset] : data[start + offset - residualLen]);
|
|
250
256
|
}
|
|
251
257
|
}
|
|
252
258
|
else {
|
|
@@ -260,7 +266,7 @@ function predictRtuFrameLength(buffer, start, end, isResponse) {
|
|
|
260
266
|
if (len <= offset) {
|
|
261
267
|
return PREDICT_NEED_MORE;
|
|
262
268
|
}
|
|
263
|
-
return (decode & 0xff) +
|
|
269
|
+
return (decode & 0xff) + (start + offset < residualLen ? residual[start + offset] : data[start + offset - residualLen]);
|
|
264
270
|
}
|
|
265
271
|
}
|
|
266
272
|
return PREDICT_UNKNOWN;
|
|
@@ -303,7 +309,12 @@ function resolveOne(value, baudRate, fastBaudMs) {
|
|
|
303
309
|
if (baudRate === undefined) {
|
|
304
310
|
return undefined;
|
|
305
311
|
}
|
|
306
|
-
|
|
312
|
+
if (baudRate > 19200) {
|
|
313
|
+
return fastBaudMs;
|
|
314
|
+
}
|
|
315
|
+
const ms = bitsToMs(baudRate, value.value);
|
|
316
|
+
const trunc = ms | 0;
|
|
317
|
+
return trunc + (ms > trunc ? 1 : 0);
|
|
307
318
|
}
|
|
308
319
|
/**
|
|
309
320
|
* Resolve Modbus RTU timing parameters from user options into milliseconds.
|
|
@@ -320,7 +331,17 @@ function resolveRtuTiming(opts = {}, baudRate) {
|
|
|
320
331
|
if (intervalBetweenFrames === undefined) {
|
|
321
332
|
// Spec default: t3.5 derived from baudRate, or 0 when neither option nor
|
|
322
333
|
// baudRate were supplied.
|
|
323
|
-
|
|
334
|
+
if (baudRate === undefined) {
|
|
335
|
+
intervalBetweenFrames = 0;
|
|
336
|
+
}
|
|
337
|
+
else if (baudRate > 19200) {
|
|
338
|
+
intervalBetweenFrames = 1.75;
|
|
339
|
+
}
|
|
340
|
+
else {
|
|
341
|
+
const ms = bitsToMs(baudRate, 38.5);
|
|
342
|
+
const trunc = ms | 0;
|
|
343
|
+
intervalBetweenFrames = trunc + (ms > trunc ? 1 : 0);
|
|
344
|
+
}
|
|
324
345
|
}
|
|
325
346
|
let interCharTimeout = resolveOne(opts.interCharTimeout, baudRate, 0.75);
|
|
326
347
|
if (interCharTimeout === undefined) {
|
|
@@ -388,7 +409,9 @@ class TimerHeap {
|
|
|
388
409
|
this._mode = 'heap';
|
|
389
410
|
for (const [existingId, { handle, deadline }] of this._directTimers) {
|
|
390
411
|
clearTimeout(handle);
|
|
391
|
-
const
|
|
412
|
+
const diff = deadline - performance.now();
|
|
413
|
+
const trunc = diff | 0;
|
|
414
|
+
const remaining = diff > 0 ? trunc + (diff > trunc ? 1 : 0) : 0;
|
|
392
415
|
if (remaining === 0) {
|
|
393
416
|
this._onFire(existingId);
|
|
394
417
|
}
|
|
@@ -448,8 +471,10 @@ class TimerHeap {
|
|
|
448
471
|
if (this._deadlines.length === 0) {
|
|
449
472
|
return;
|
|
450
473
|
}
|
|
451
|
-
const
|
|
452
|
-
const
|
|
474
|
+
const diff = this._deadlines[0] - performance.now();
|
|
475
|
+
const trunc = diff | 0;
|
|
476
|
+
const delay = diff > 0 ? trunc + (diff > trunc ? 1 : 0) : 0;
|
|
477
|
+
const safeDelay = delay < 2147483647 ? delay : 2147483647;
|
|
453
478
|
this._timer = setTimeout(this._boundTick, safeDelay);
|
|
454
479
|
}
|
|
455
480
|
_onTick() {
|
|
@@ -521,14 +546,17 @@ function isWhitelisted(address, whitelist) {
|
|
|
521
546
|
return whitelist.includes(normalized);
|
|
522
547
|
}
|
|
523
548
|
|
|
549
|
+
exports.CRC_TABLE = CRC_TABLE;
|
|
524
550
|
exports.PREDICT_NEED_MORE = PREDICT_NEED_MORE;
|
|
525
551
|
exports.PREDICT_UNKNOWN = PREDICT_UNKNOWN;
|
|
552
|
+
exports.REQ_TABLE = REQ_TABLE;
|
|
553
|
+
exports.RES_TABLE = RES_TABLE;
|
|
526
554
|
exports.TimerHeap = TimerHeap;
|
|
527
555
|
exports.bitsToMs = bitsToMs;
|
|
528
556
|
exports.checkRange = checkRange;
|
|
529
|
-
exports.
|
|
557
|
+
exports.crcDual = crcDual;
|
|
558
|
+
exports.crcFixed = crcFixed;
|
|
530
559
|
exports.drainCbs = drainCbs;
|
|
531
|
-
exports.isUint8 = isUint8;
|
|
532
560
|
exports.isWhitelisted = isWhitelisted;
|
|
533
561
|
exports.lrc = lrc;
|
|
534
562
|
exports.predictRtuFrameLength = predictRtuFrameLength;
|
package/dist/utils.d.ts
CHANGED
|
@@ -39,11 +39,12 @@ interface RtuProtocolOptions {
|
|
|
39
39
|
*/
|
|
40
40
|
interCharTimeout?: RtuTimingValue;
|
|
41
41
|
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
42
|
+
* Enforces strict Modbus RTU timing. When true, any frame containing a t1.5
|
|
43
|
+
* inter-character timeout event will be discarded immediately, even if the
|
|
44
|
+
* CRC16 is valid.
|
|
45
|
+
* @default false
|
|
45
46
|
*/
|
|
46
|
-
|
|
47
|
+
strictTiming?: boolean;
|
|
47
48
|
}
|
|
48
49
|
/** Resolved RTU timing values in milliseconds. */
|
|
49
50
|
interface ResolvedRtuTiming {
|
|
@@ -87,22 +88,22 @@ declare function drainCbs(cbs: (((err?: Error | null) => void) | undefined)[] |
|
|
|
87
88
|
|
|
88
89
|
declare function checkRange(value: number | number[], range?: [number, number] | [number, number][]): boolean;
|
|
89
90
|
|
|
90
|
-
declare
|
|
91
|
-
|
|
91
|
+
declare const CRC_TABLE: Uint16Array<ArrayBuffer>;
|
|
92
|
+
/** CRC-16 (Modbus) over a single contiguous buffer. */
|
|
93
|
+
declare function crcFixed(data: Uint8Array, start: number, end: number): number;
|
|
92
94
|
/**
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
* Used for byte-level Modbus payload validation (function-code values, raw
|
|
96
|
-
* byte arrays in FC17/FC43 responses) — rejects negative, fractional, NaN,
|
|
97
|
-
* Infinity, and out-of-range values uniformly.
|
|
95
|
+
* CRC-16 (Modbus) over two contiguous buffer segments.
|
|
96
|
+
* Computes CRC(head[headOff:headOff+headLen]) followed by CRC(tail[tailOff:tailOff+tailLen]).
|
|
98
97
|
*/
|
|
99
|
-
declare function
|
|
98
|
+
declare function crcDual(head: Uint8Array, headOff: number, headLen: number, tail: Uint8Array, tailOff: number, tailLen: number): number;
|
|
100
99
|
|
|
101
100
|
declare function lrc(data: Uint8Array, start: number, end: number): number;
|
|
102
101
|
|
|
103
102
|
declare const PREDICT_NEED_MORE = 0;
|
|
104
103
|
declare const PREDICT_UNKNOWN = -1;
|
|
105
|
-
declare
|
|
104
|
+
declare const REQ_TABLE: Int32Array<ArrayBuffer>;
|
|
105
|
+
declare const RES_TABLE: Int32Array<ArrayBuffer>;
|
|
106
|
+
declare function predictRtuFrameLength(residual: Buffer, data: Buffer, residualLen: number, start: number, end: number, isResponse: boolean): number;
|
|
106
107
|
|
|
107
108
|
/**
|
|
108
109
|
* Convert a callback-style `(cb: (err?) => void) => void` call into a Promise.
|
|
@@ -159,5 +160,5 @@ declare class TimerHeap {
|
|
|
159
160
|
*/
|
|
160
161
|
declare function isWhitelisted(address: string | undefined, whitelist: string[] | undefined): boolean;
|
|
161
162
|
|
|
162
|
-
export { PREDICT_NEED_MORE, PREDICT_UNKNOWN, TimerHeap, bitsToMs, checkRange,
|
|
163
|
+
export { CRC_TABLE, PREDICT_NEED_MORE, PREDICT_UNKNOWN, REQ_TABLE, RES_TABLE, TimerHeap, bitsToMs, checkRange, crcDual, crcFixed, drainCbs, isWhitelisted, lrc, predictRtuFrameLength, promisifyCb, resolveRtuTiming };
|
|
163
164
|
export type { ResolvedRtuTiming, RtuProtocolOptions };
|
package/dist/utils.mjs
CHANGED
|
@@ -90,7 +90,7 @@ function checkRange(value, range) {
|
|
|
90
90
|
return false;
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
const
|
|
93
|
+
const CRC_TABLE = new Uint16Array([
|
|
94
94
|
0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241, 0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440, 0xcc01,
|
|
95
95
|
0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40, 0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841, 0xd801, 0x18c0,
|
|
96
96
|
0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40, 0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41, 0x1400, 0xd4c1, 0xd581,
|
|
@@ -108,23 +108,29 @@ const TABLE = new Uint16Array([
|
|
|
108
108
|
0x4c80, 0x8c41, 0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641, 0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081,
|
|
109
109
|
0x4040,
|
|
110
110
|
]);
|
|
111
|
-
|
|
111
|
+
/** CRC-16 (Modbus) over a single contiguous buffer. */
|
|
112
|
+
function crcFixed(data, start, end) {
|
|
112
113
|
let crc = 0xffff;
|
|
113
114
|
for (let index = start; index < end; index++) {
|
|
114
|
-
crc =
|
|
115
|
+
crc = CRC_TABLE[(crc ^ data[index]) & 0xff] ^ (crc >> 8);
|
|
115
116
|
}
|
|
116
117
|
return crc;
|
|
117
118
|
}
|
|
118
|
-
|
|
119
119
|
/**
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
* Used for byte-level Modbus payload validation (function-code values, raw
|
|
123
|
-
* byte arrays in FC17/FC43 responses) — rejects negative, fractional, NaN,
|
|
124
|
-
* Infinity, and out-of-range values uniformly.
|
|
120
|
+
* CRC-16 (Modbus) over two contiguous buffer segments.
|
|
121
|
+
* Computes CRC(head[headOff:headOff+headLen]) followed by CRC(tail[tailOff:tailOff+tailLen]).
|
|
125
122
|
*/
|
|
126
|
-
function
|
|
127
|
-
|
|
123
|
+
function crcDual(head, headOff, headLen, tail, tailOff, tailLen) {
|
|
124
|
+
let crc = 0xffff;
|
|
125
|
+
const headEnd = headOff + headLen;
|
|
126
|
+
for (let i = headOff; i < headEnd; i++) {
|
|
127
|
+
crc = CRC_TABLE[(crc ^ head[i]) & 0xff] ^ (crc >> 8);
|
|
128
|
+
}
|
|
129
|
+
const tailEnd = tailOff + tailLen;
|
|
130
|
+
for (let i = tailOff; i < tailEnd; i++) {
|
|
131
|
+
crc = CRC_TABLE[(crc ^ tail[i]) & 0xff] ^ (crc >> 8);
|
|
132
|
+
}
|
|
133
|
+
return crc;
|
|
128
134
|
}
|
|
129
135
|
|
|
130
136
|
function lrc(data, start, end) {
|
|
@@ -205,12 +211,12 @@ const RES_TABLE = new Int32Array(256);
|
|
|
205
211
|
RES_TABLE[FunctionCode.READ_WRITE_MULTIPLE_REGISTERS] = -517;
|
|
206
212
|
RES_TABLE[FunctionCode.READ_DEVICE_IDENTIFICATION] = -999;
|
|
207
213
|
})();
|
|
208
|
-
function predictRtuFrameLength(
|
|
214
|
+
function predictRtuFrameLength(residual, data, residualLen, start, end, isResponse) {
|
|
209
215
|
const len = end - start;
|
|
210
216
|
if (len < 2) {
|
|
211
217
|
return PREDICT_NEED_MORE;
|
|
212
218
|
}
|
|
213
|
-
const fc =
|
|
219
|
+
const fc = start + 1 < residualLen ? residual[start + 1] : data[start + 1 - residualLen];
|
|
214
220
|
if (isResponse) {
|
|
215
221
|
if ((fc & EXCEPTION_OFFSET) !== 0) {
|
|
216
222
|
return 5;
|
|
@@ -226,16 +232,16 @@ function predictRtuFrameLength(buffer, start, end, isResponse) {
|
|
|
226
232
|
if (end - start < 8) {
|
|
227
233
|
return PREDICT_NEED_MORE;
|
|
228
234
|
}
|
|
229
|
-
if (
|
|
235
|
+
if ((start + 2 < residualLen ? residual[start + 2] : data[start + 2 - residualLen]) !== MEI_READ_DEVICE_ID) {
|
|
230
236
|
return PREDICT_UNKNOWN;
|
|
231
237
|
}
|
|
232
|
-
const numObjs =
|
|
238
|
+
const numObjs = start + 7 < residualLen ? residual[start + 7] : data[start + 7 - residualLen];
|
|
233
239
|
let cursor = start + 8;
|
|
234
240
|
for (let i = 0; i < numObjs; i++) {
|
|
235
241
|
if (end < cursor + 2) {
|
|
236
242
|
return PREDICT_NEED_MORE;
|
|
237
243
|
}
|
|
238
|
-
cursor += 2 +
|
|
244
|
+
cursor += 2 + (cursor + 1 < residualLen ? residual[cursor + 1] : data[cursor + 1 - residualLen]);
|
|
239
245
|
}
|
|
240
246
|
return cursor - start + 2;
|
|
241
247
|
}
|
|
@@ -244,7 +250,7 @@ function predictRtuFrameLength(buffer, start, end, isResponse) {
|
|
|
244
250
|
if (len <= offset) {
|
|
245
251
|
return PREDICT_NEED_MORE;
|
|
246
252
|
}
|
|
247
|
-
return (decode & 0xff) +
|
|
253
|
+
return (decode & 0xff) + (start + offset < residualLen ? residual[start + offset] : data[start + offset - residualLen]);
|
|
248
254
|
}
|
|
249
255
|
}
|
|
250
256
|
else {
|
|
@@ -258,7 +264,7 @@ function predictRtuFrameLength(buffer, start, end, isResponse) {
|
|
|
258
264
|
if (len <= offset) {
|
|
259
265
|
return PREDICT_NEED_MORE;
|
|
260
266
|
}
|
|
261
|
-
return (decode & 0xff) +
|
|
267
|
+
return (decode & 0xff) + (start + offset < residualLen ? residual[start + offset] : data[start + offset - residualLen]);
|
|
262
268
|
}
|
|
263
269
|
}
|
|
264
270
|
return PREDICT_UNKNOWN;
|
|
@@ -301,7 +307,12 @@ function resolveOne(value, baudRate, fastBaudMs) {
|
|
|
301
307
|
if (baudRate === undefined) {
|
|
302
308
|
return undefined;
|
|
303
309
|
}
|
|
304
|
-
|
|
310
|
+
if (baudRate > 19200) {
|
|
311
|
+
return fastBaudMs;
|
|
312
|
+
}
|
|
313
|
+
const ms = bitsToMs(baudRate, value.value);
|
|
314
|
+
const trunc = ms | 0;
|
|
315
|
+
return trunc + (ms > trunc ? 1 : 0);
|
|
305
316
|
}
|
|
306
317
|
/**
|
|
307
318
|
* Resolve Modbus RTU timing parameters from user options into milliseconds.
|
|
@@ -318,7 +329,17 @@ function resolveRtuTiming(opts = {}, baudRate) {
|
|
|
318
329
|
if (intervalBetweenFrames === undefined) {
|
|
319
330
|
// Spec default: t3.5 derived from baudRate, or 0 when neither option nor
|
|
320
331
|
// baudRate were supplied.
|
|
321
|
-
|
|
332
|
+
if (baudRate === undefined) {
|
|
333
|
+
intervalBetweenFrames = 0;
|
|
334
|
+
}
|
|
335
|
+
else if (baudRate > 19200) {
|
|
336
|
+
intervalBetweenFrames = 1.75;
|
|
337
|
+
}
|
|
338
|
+
else {
|
|
339
|
+
const ms = bitsToMs(baudRate, 38.5);
|
|
340
|
+
const trunc = ms | 0;
|
|
341
|
+
intervalBetweenFrames = trunc + (ms > trunc ? 1 : 0);
|
|
342
|
+
}
|
|
322
343
|
}
|
|
323
344
|
let interCharTimeout = resolveOne(opts.interCharTimeout, baudRate, 0.75);
|
|
324
345
|
if (interCharTimeout === undefined) {
|
|
@@ -386,7 +407,9 @@ class TimerHeap {
|
|
|
386
407
|
this._mode = 'heap';
|
|
387
408
|
for (const [existingId, { handle, deadline }] of this._directTimers) {
|
|
388
409
|
clearTimeout(handle);
|
|
389
|
-
const
|
|
410
|
+
const diff = deadline - performance.now();
|
|
411
|
+
const trunc = diff | 0;
|
|
412
|
+
const remaining = diff > 0 ? trunc + (diff > trunc ? 1 : 0) : 0;
|
|
390
413
|
if (remaining === 0) {
|
|
391
414
|
this._onFire(existingId);
|
|
392
415
|
}
|
|
@@ -446,8 +469,10 @@ class TimerHeap {
|
|
|
446
469
|
if (this._deadlines.length === 0) {
|
|
447
470
|
return;
|
|
448
471
|
}
|
|
449
|
-
const
|
|
450
|
-
const
|
|
472
|
+
const diff = this._deadlines[0] - performance.now();
|
|
473
|
+
const trunc = diff | 0;
|
|
474
|
+
const delay = diff > 0 ? trunc + (diff > trunc ? 1 : 0) : 0;
|
|
475
|
+
const safeDelay = delay < 2147483647 ? delay : 2147483647;
|
|
451
476
|
this._timer = setTimeout(this._boundTick, safeDelay);
|
|
452
477
|
}
|
|
453
478
|
_onTick() {
|
|
@@ -519,4 +544,4 @@ function isWhitelisted(address, whitelist) {
|
|
|
519
544
|
return whitelist.includes(normalized);
|
|
520
545
|
}
|
|
521
546
|
|
|
522
|
-
export { PREDICT_NEED_MORE, PREDICT_UNKNOWN, TimerHeap, bitsToMs, checkRange,
|
|
547
|
+
export { CRC_TABLE, PREDICT_NEED_MORE, PREDICT_UNKNOWN, REQ_TABLE, RES_TABLE, TimerHeap, bitsToMs, checkRange, crcDual, crcFixed, drainCbs, isWhitelisted, lrc, predictRtuFrameLength, promisifyCb, resolveRtuTiming };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "njs-modbus",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.0",
|
|
4
4
|
"description": "A pure JavaScript implementation of Modbus for Node.js.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"modbus",
|
|
@@ -45,16 +45,10 @@
|
|
|
45
45
|
"scripts": {
|
|
46
46
|
"build": "node -e \"fs.rmSync('dist', {recursive: true, force: true})\" && rollup -c && node -e \"fs.rmSync('dist/src', {recursive: true, force: true})\"",
|
|
47
47
|
"test": "tsx --test test/**/*.test.ts",
|
|
48
|
-
"benchmark": "tsx benchmark/encode-decode.ts && echo && tsx benchmark/tcp-throughput.ts && echo && tsx benchmark/concurrent.ts",
|
|
49
|
-
"benchmark:encode-decode": "tsx benchmark/encode-decode.ts",
|
|
50
|
-
"benchmark:tcp": "tsx benchmark/tcp-throughput.ts",
|
|
51
|
-
"benchmark:concurrent": "tsx benchmark/concurrent.ts",
|
|
52
|
-
"benchmark:rtu": "tsx benchmark/rtu-throughput.ts",
|
|
53
|
-
"benchmark:all-fcs": "tsx benchmark/all-fcs.ts",
|
|
54
48
|
"benchmark:report": "tsx benchmark/generate-report.ts",
|
|
49
|
+
"benchmark:report:test": "tsx benchmark/test-report.ts",
|
|
55
50
|
"benchmark:report:quick": "tsx benchmark/generate-report.ts -- --duration 10s --runs 2",
|
|
56
|
-
"benchmark:report:full": "tsx benchmark/generate-report.ts -- --duration 120s --runs
|
|
57
|
-
"benchmark:profile": "tsx benchmark/all-fcs.ts -- --duration 30s --runs 1 --only fc03 --libs njs-modbus --profile",
|
|
51
|
+
"benchmark:report:full": "tsx benchmark/generate-report.ts -- --duration 120s --runs 5 --max-payload",
|
|
58
52
|
"util:sort-package-json": "sort-package-json"
|
|
59
53
|
},
|
|
60
54
|
"devDependencies": {
|