njs-modbus 3.1.0 → 3.2.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 +20 -0
- package/README.zh-CN.md +20 -0
- package/dist/index.cjs +878 -390
- package/dist/index.d.ts +96 -30
- package/dist/index.mjs +878 -391
- package/dist/utils.cjs +439 -0
- package/dist/utils.d.ts +161 -0
- package/dist/utils.mjs +425 -0
- package/package.json +16 -3
- package/dist/src/error-code.d.ts +0 -17
- package/dist/src/index.d.ts +0 -7
- package/dist/src/layers/application/abstract-application-layer.d.ts +0 -26
- package/dist/src/layers/application/ascii-application-layer.d.ts +0 -23
- package/dist/src/layers/application/index.d.ts +0 -6
- package/dist/src/layers/application/rtu-application-layer.d.ts +0 -34
- package/dist/src/layers/application/tcp-application-layer.d.ts +0 -16
- package/dist/src/layers/physical/abstract-physical-layer.d.ts +0 -50
- package/dist/src/layers/physical/index.d.ts +0 -12
- package/dist/src/layers/physical/serial-physical-layer.d.ts +0 -70
- package/dist/src/layers/physical/tcp-client-physical-layer.d.ts +0 -19
- package/dist/src/layers/physical/tcp-physical-connection.d.ts +0 -16
- package/dist/src/layers/physical/tcp-server-physical-layer.d.ts +0 -28
- package/dist/src/layers/physical/udp-client-physical-layer.d.ts +0 -33
- package/dist/src/layers/physical/udp-server-physical-layer.d.ts +0 -50
- package/dist/src/layers/physical/utils.d.ts +0 -39
- package/dist/src/layers/physical/vars.d.ts +0 -11
- package/dist/src/master/index.d.ts +0 -3
- package/dist/src/master/master-session.d.ts +0 -18
- package/dist/src/master/master.d.ts +0 -140
- package/dist/src/slave/index.d.ts +0 -2
- package/dist/src/slave/slave.d.ts +0 -119
- package/dist/src/types.d.ts +0 -54
- package/dist/src/utils/bitsToMs.d.ts +0 -13
- package/dist/src/utils/callback.d.ts +0 -8
- package/dist/src/utils/checkRange.d.ts +0 -1
- package/dist/src/utils/crc.d.ts +0 -1
- package/dist/src/utils/index.d.ts +0 -11
- package/dist/src/utils/isUint8.d.ts +0 -8
- package/dist/src/utils/lrc.d.ts +0 -1
- package/dist/src/utils/predictRtuFrameLength.d.ts +0 -17
- package/dist/src/utils/promisify-cb.d.ts +0 -4
- package/dist/src/utils/rtu-timing.d.ts +0 -63
- package/dist/src/utils/whitelist.d.ts +0 -11
- package/dist/src/vars.d.ts +0 -49
package/dist/index.d.ts
CHANGED
|
@@ -44,10 +44,30 @@ interface DeviceIdentification {
|
|
|
44
44
|
*/
|
|
45
45
|
interface CustomFunctionCode {
|
|
46
46
|
fc: number;
|
|
47
|
-
/**
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
/**
|
|
48
|
+
* Predict total RTU frame length for an incoming request (slave-side framing).
|
|
49
|
+
*
|
|
50
|
+
* @param buffer — The raw frame buffer (a shared pool or incoming chunk). Do NOT
|
|
51
|
+
* modify it; the framing layer owns the memory.
|
|
52
|
+
* @param start — Byte offset in `buffer` where the current candidate frame begins
|
|
53
|
+
* (the unit ID byte). Read the function code at `buffer[start + 1]` and derive
|
|
54
|
+
* the total frame length from the trailing bytes.
|
|
55
|
+
* @returns Total frame length (>= 4, <= 256), or `null` if more bytes are needed.
|
|
56
|
+
*/
|
|
57
|
+
predictRequestLength: (buffer: Buffer, start: number, end: number) => number | null;
|
|
58
|
+
/**
|
|
59
|
+
* Predict total RTU frame length for an incoming response (master-side framing).
|
|
60
|
+
*
|
|
61
|
+
* @param buffer — The raw frame buffer (a shared pool or incoming chunk). Do NOT
|
|
62
|
+
* modify it; the framing layer owns the memory.
|
|
63
|
+
* @param start — Byte offset in `buffer` where the current candidate frame begins
|
|
64
|
+
* (the unit ID byte). Read the function code at `buffer[start + 1]` and derive
|
|
65
|
+
* the total frame length from the trailing bytes.
|
|
66
|
+
* @param end — Byte offset one past the last valid byte. Bounds checks must use
|
|
67
|
+
* `end - start` as available bytes, NOT `buffer.length` (pool capacity).
|
|
68
|
+
* @returns Total frame length (>= 4, <= 256), or `null` if more bytes are needed.
|
|
69
|
+
*/
|
|
70
|
+
predictResponseLength: (buffer: Buffer, start: number, end: number) => number | null;
|
|
51
71
|
/**
|
|
52
72
|
* Slave-side handler. Receives PDU payload (bytes after `fc`, before CRC) and
|
|
53
73
|
* the unit ID being addressed; must return the PDU payload of the response.
|
|
@@ -115,6 +135,8 @@ declare enum ConformityLevel {
|
|
|
115
135
|
}
|
|
116
136
|
/** Shared empty Buffer to avoid repeated allocations. */
|
|
117
137
|
declare const EMPTY_BUFFER: Buffer<ArrayBuffer>;
|
|
138
|
+
/** Shared no-op function to avoid repeated allocations. */
|
|
139
|
+
declare const NOOP: () => void;
|
|
118
140
|
/** Modbus V1.1b3 PDU quantity limits. */
|
|
119
141
|
declare const LIMITS: {
|
|
120
142
|
readonly READ_COILS_MIN: 1;
|
|
@@ -206,7 +228,8 @@ declare class TcpClientPhysicalLayer extends AbstractPhysicalLayer {
|
|
|
206
228
|
get state(): PhysicalState;
|
|
207
229
|
get socket(): Socket | null;
|
|
208
230
|
constructor(options?: SocketConstructorOpts);
|
|
209
|
-
open(
|
|
231
|
+
open(cb?: (err?: Error | null) => void): void;
|
|
232
|
+
open(options: SocketConnectOpts, cb?: (err?: Error | null) => void): void;
|
|
210
233
|
close(cb?: (err?: Error | null) => void): void;
|
|
211
234
|
}
|
|
212
235
|
|
|
@@ -232,7 +255,8 @@ declare class TcpServerPhysicalLayer extends AbstractPhysicalLayer {
|
|
|
232
255
|
get state(): PhysicalState;
|
|
233
256
|
get server(): Server | null;
|
|
234
257
|
constructor(options?: TcpServerPhysicalLayerOptions);
|
|
235
|
-
open(
|
|
258
|
+
open(cb?: (err?: Error | null) => void): void;
|
|
259
|
+
open(options: ListenOptions, cb?: (err?: Error | null) => void): void;
|
|
236
260
|
close(cb?: (err?: Error | null) => void): void;
|
|
237
261
|
}
|
|
238
262
|
|
|
@@ -248,10 +272,11 @@ declare class UdpClientPhysicalLayer extends AbstractPhysicalLayer {
|
|
|
248
272
|
get state(): PhysicalState;
|
|
249
273
|
get socket(): Socket$1 | null;
|
|
250
274
|
constructor(options?: Partial<SocketOptions>);
|
|
251
|
-
open(
|
|
275
|
+
open(cb?: (err?: Error | null) => void): void;
|
|
276
|
+
open(remote: {
|
|
252
277
|
port?: number;
|
|
253
278
|
address?: string;
|
|
254
|
-
}
|
|
279
|
+
}, cb?: (err?: Error | null) => void): void;
|
|
255
280
|
close(cb?: (err?: Error | null) => void): void;
|
|
256
281
|
}
|
|
257
282
|
|
|
@@ -283,7 +308,8 @@ declare class UdpServerPhysicalLayer extends AbstractPhysicalLayer {
|
|
|
283
308
|
* @param options Bind options (port, address, etc.). Defaults to port 502.
|
|
284
309
|
* @param cb Callback invoked when binding completes or fails.
|
|
285
310
|
*/
|
|
286
|
-
open(
|
|
311
|
+
open(cb?: (err?: Error | null) => void): void;
|
|
312
|
+
open(options: BindOptions, cb?: (err?: Error | null) => void): void;
|
|
287
313
|
close(cb?: (err?: Error | null) => void): void;
|
|
288
314
|
}
|
|
289
315
|
|
|
@@ -349,25 +375,37 @@ type PhysicalConfig = {
|
|
|
349
375
|
type: 'CUSTOM';
|
|
350
376
|
layer: AbstractPhysicalLayer;
|
|
351
377
|
};
|
|
378
|
+
/**
|
|
379
|
+
* User-facing arguments for `Master.open()` / `Slave.open()`.
|
|
380
|
+
*
|
|
381
|
+
* These match the physical layer's `open()` signatures **without** the trailing
|
|
382
|
+
* callback — `promisifyCb` appends it internally so the user gets a `Promise`.
|
|
383
|
+
*
|
|
384
|
+
* | Config | User-facing args |
|
|
385
|
+
* |---------------|--------------------------------------|
|
|
386
|
+
* | SERIAL | `()` — configured at construction |
|
|
387
|
+
* | TCP_CLIENT | `(opts?)` — `SocketConnectOpts` |
|
|
388
|
+
* | TCP_SERVER | `(opts?)` — `ListenOptions` |
|
|
389
|
+
* | UDP_CLIENT | `(remote?)` — `{ port?, address? }` |
|
|
390
|
+
* | UDP_SERVER | `(opts?)` — `BindOptions` |
|
|
391
|
+
* | CUSTOM | `never` — call `layer.open()` directly |
|
|
392
|
+
*/
|
|
352
393
|
type OpenArgs<T extends PhysicalConfig> = T extends {
|
|
353
394
|
type: 'SERIAL';
|
|
354
|
-
} ?
|
|
395
|
+
} ? [] : T extends {
|
|
355
396
|
type: 'TCP_CLIENT';
|
|
356
|
-
} ?
|
|
397
|
+
} ? [options?: SocketConnectOpts] : T extends {
|
|
357
398
|
type: 'TCP_SERVER';
|
|
358
|
-
} ?
|
|
399
|
+
} ? [options?: ListenOptions] : T extends {
|
|
359
400
|
type: 'UDP_CLIENT';
|
|
360
|
-
} ?
|
|
401
|
+
} ? [remote?: {
|
|
402
|
+
port?: number;
|
|
403
|
+
address?: string;
|
|
404
|
+
}] : T extends {
|
|
361
405
|
type: 'UDP_SERVER';
|
|
362
|
-
} ?
|
|
406
|
+
} ? [options?: BindOptions] : never;
|
|
363
407
|
declare function createPhysicalLayer(config: PhysicalConfig): AbstractPhysicalLayer;
|
|
364
408
|
|
|
365
|
-
interface AbstractApplicationLayerEvents {
|
|
366
|
-
framing: [frame: ApplicationDataUnit & {
|
|
367
|
-
buffer: Buffer;
|
|
368
|
-
}];
|
|
369
|
-
'framing-error': [error: Error];
|
|
370
|
-
}
|
|
371
409
|
/**
|
|
372
410
|
* Application-layer protocol handler bound to a single physical connection.
|
|
373
411
|
*
|
|
@@ -375,10 +413,16 @@ interface AbstractApplicationLayerEvents {
|
|
|
375
413
|
* established and discarded when the connection closes. Subclasses implement
|
|
376
414
|
* ASCII, RTU, or TCP framing rules.
|
|
377
415
|
*/
|
|
378
|
-
declare abstract class AbstractApplicationLayer
|
|
416
|
+
declare abstract class AbstractApplicationLayer {
|
|
379
417
|
abstract readonly PROTOCOL: 'ASCII' | 'RTU' | 'TCP';
|
|
380
418
|
abstract ROLE: 'MASTER' | 'SLAVE';
|
|
381
419
|
abstract readonly connection: AbstractPhysicalConnection;
|
|
420
|
+
/** Called when a complete frame is decoded. Defaults to no-op. */
|
|
421
|
+
onFraming: (frame: ApplicationDataUnit & {
|
|
422
|
+
buffer: Buffer;
|
|
423
|
+
}) => void;
|
|
424
|
+
/** Called when a framing error is detected. Defaults to no-op. */
|
|
425
|
+
onFramingError: (error: Error) => void;
|
|
382
426
|
flush(): void;
|
|
383
427
|
addCustomFunctionCode(cfc: CustomFunctionCode): void;
|
|
384
428
|
removeCustomFunctionCode(fc: number): void;
|
|
@@ -399,7 +443,7 @@ declare class AsciiApplicationLayer extends AbstractApplicationLayer {
|
|
|
399
443
|
readonly lenientHex: boolean;
|
|
400
444
|
private _connection;
|
|
401
445
|
private _state;
|
|
402
|
-
private
|
|
446
|
+
private _cleanupCbs;
|
|
403
447
|
get connection(): AbstractPhysicalConnection;
|
|
404
448
|
constructor(role: 'MASTER' | 'SLAVE', connection: AbstractPhysicalConnection, options?: AsciiApplicationLayerOptions);
|
|
405
449
|
private framing;
|
|
@@ -428,10 +472,18 @@ declare class RtuApplicationLayer extends AbstractApplicationLayer {
|
|
|
428
472
|
private _threePointFiveT;
|
|
429
473
|
private _onePointFiveT;
|
|
430
474
|
private _customFunctionCodes;
|
|
431
|
-
private
|
|
475
|
+
private _cleanupCbs;
|
|
432
476
|
get connection(): AbstractPhysicalConnection;
|
|
433
477
|
constructor(role: 'MASTER' | 'SLAVE', connection: AbstractPhysicalConnection, options?: RtuApplicationLayerOptions);
|
|
434
478
|
private clearStateTimers;
|
|
479
|
+
/**
|
|
480
|
+
* Shared handler for every "frame is not yet complete" exit in `flushBuffer`.
|
|
481
|
+
* Returns `true` when the caller should `return` (strict reset), `false` to
|
|
482
|
+
* `break` the parse loop. Hot path never reaches here — only error/incomplete
|
|
483
|
+
* edges. Extracted as a method so it is not recreated on every `flushBuffer`
|
|
484
|
+
* call.
|
|
485
|
+
*/
|
|
486
|
+
private _handleIncomplete;
|
|
435
487
|
private flushBuffer;
|
|
436
488
|
flush(): void;
|
|
437
489
|
addCustomFunctionCode(cfc: CustomFunctionCode): void;
|
|
@@ -445,7 +497,7 @@ declare class TcpApplicationLayer extends AbstractApplicationLayer {
|
|
|
445
497
|
private _connection;
|
|
446
498
|
private _transactionId;
|
|
447
499
|
private _buffer;
|
|
448
|
-
private
|
|
500
|
+
private _cleanupCbs;
|
|
449
501
|
get connection(): AbstractPhysicalConnection;
|
|
450
502
|
constructor(role: 'MASTER' | 'SLAVE', connection: AbstractPhysicalConnection);
|
|
451
503
|
private tryExtract;
|
|
@@ -542,19 +594,21 @@ declare class ModbusMaster<T extends ModbusMasterOptions = ModbusMasterOptions>
|
|
|
542
594
|
private _queueDatas;
|
|
543
595
|
private _queueTimeouts;
|
|
544
596
|
private _queueBroadcasts;
|
|
545
|
-
private
|
|
546
|
-
private _queueRejects;
|
|
597
|
+
private _queueCallbacks;
|
|
547
598
|
private _queueHead;
|
|
548
599
|
private _queueLen;
|
|
549
600
|
private _draining;
|
|
550
601
|
private _nextTid;
|
|
551
602
|
private _cleanupFns;
|
|
552
603
|
private _closePromise;
|
|
604
|
+
private _nextExchangeId;
|
|
605
|
+
private _pendingExchanges;
|
|
606
|
+
private _timerHeap;
|
|
553
607
|
get state(): PhysicalState;
|
|
554
608
|
get physicalLayer(): AbstractPhysicalLayer;
|
|
555
609
|
constructor(options: T);
|
|
556
610
|
private _createAppLayer;
|
|
557
|
-
private
|
|
611
|
+
private _send;
|
|
558
612
|
private _drain;
|
|
559
613
|
private _processNext;
|
|
560
614
|
private _exchange;
|
|
@@ -715,7 +769,7 @@ declare class ModbusSlave<T extends ModbusSlaveOptions = ModbusSlaveOptions> ext
|
|
|
715
769
|
private _protocol;
|
|
716
770
|
private _appLayers;
|
|
717
771
|
private _customFunctionCodes;
|
|
718
|
-
private
|
|
772
|
+
private _intervalLocks;
|
|
719
773
|
private _cleanupFns;
|
|
720
774
|
private _closePromise;
|
|
721
775
|
get state(): PhysicalState;
|
|
@@ -738,7 +792,19 @@ declare class ModbusSlave<T extends ModbusSlaveOptions = ModbusSlaveOptions> ext
|
|
|
738
792
|
private _drain;
|
|
739
793
|
private _processFrame;
|
|
740
794
|
private _intercept;
|
|
741
|
-
|
|
795
|
+
/**
|
|
796
|
+
* Serialize a code block over the half-open address interval `[lo, hi)`.
|
|
797
|
+
* The block runs after all previously-installed locks whose intervals
|
|
798
|
+
* overlap with this one have completed. Two non-overlapping intervals
|
|
799
|
+
* execute in parallel.
|
|
800
|
+
*
|
|
801
|
+
* Locks are tracked in a flat array (`_intervalLocks`); the typical depth
|
|
802
|
+
* is 0-2 entries, so the linear overlap scan is sub-µs. Compare with the
|
|
803
|
+
* old per-address Map design, where FC23 writing 121 registers allocated
|
|
804
|
+
* ~125 objects per request (one Promise.resolve / address + Set + sort +
|
|
805
|
+
* Promise.all); this version allocates 1-3.
|
|
806
|
+
*/
|
|
807
|
+
private _withIntervalLock;
|
|
742
808
|
private _handleFC;
|
|
743
809
|
private _handleCustomFC;
|
|
744
810
|
add(model: ModbusSlaveModel): void;
|
|
@@ -766,5 +832,5 @@ declare class ModbusSlave<T extends ModbusSlaveOptions = ModbusSlaveOptions> ext
|
|
|
766
832
|
close(): Promise<void>;
|
|
767
833
|
}
|
|
768
834
|
|
|
769
|
-
export { AbstractApplicationLayer, AbstractPhysicalConnection, AbstractPhysicalLayer, AsciiApplicationLayer, COIL_OFF, COIL_ON, ConformityLevel, EMPTY_BUFFER, EXCEPTION_OFFSET, ErrorCode, FunctionCode, LIMITS, MEI_READ_DEVICE_ID, MasterSession, ModbusError, ModbusMaster, ModbusSlave, PhysicalConnectionState, PhysicalState, ReadDeviceIDCode, RtuApplicationLayer, SerialPhysicalLayer, TcpApplicationLayer, TcpClientPhysicalLayer, TcpServerPhysicalLayer, UdpClientPhysicalLayer, UdpServerPhysicalLayer, createPhysicalLayer, getCodeByError, getErrorByCode };
|
|
835
|
+
export { AbstractApplicationLayer, AbstractPhysicalConnection, AbstractPhysicalLayer, AsciiApplicationLayer, COIL_OFF, COIL_ON, ConformityLevel, EMPTY_BUFFER, EXCEPTION_OFFSET, ErrorCode, FunctionCode, LIMITS, MEI_READ_DEVICE_ID, MasterSession, ModbusError, ModbusMaster, ModbusSlave, NOOP, PhysicalConnectionState, PhysicalState, ReadDeviceIDCode, RtuApplicationLayer, SerialPhysicalLayer, TcpApplicationLayer, TcpClientPhysicalLayer, TcpServerPhysicalLayer, UdpClientPhysicalLayer, UdpServerPhysicalLayer, createPhysicalLayer, getCodeByError, getErrorByCode };
|
|
770
836
|
export type { AbstractPhysicalLayerEvents, ApplicationDataUnit, AsciiApplicationLayerOptions, Callback$1 as Callback, CustomFunctionCode, DeviceIdentification, MaybeAsyncFunction, ModbusMasterOptions, ModbusSlaveModel, ModbusSlaveOptions, OpenArgs, PhysicalConfig, RtuApplicationLayerOptions, ServerId, TcpServerPhysicalLayerOptions, UdpServerPhysicalLayerOptions };
|