njs-modbus 3.1.1 → 3.3.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 +84 -35
- package/README.zh-CN.md +84 -35
- package/dist/index.cjs +1291 -497
- package/dist/index.d.ts +99 -31
- package/dist/index.mjs +1291 -498
- package/dist/utils.cjs +536 -0
- package/dist/utils.d.ts +163 -0
- package/dist/utils.mjs +522 -0
- package/package.json +22 -2
- 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 -20
- package/dist/src/layers/physical/tcp-physical-connection.d.ts +0 -16
- package/dist/src/layers/physical/tcp-server-physical-layer.d.ts +0 -29
- package/dist/src/layers/physical/udp-client-physical-layer.d.ts +0 -34
- package/dist/src/layers/physical/udp-server-physical-layer.d.ts +0 -51
- 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
|
@@ -12,7 +12,7 @@ interface ApplicationDataUnit {
|
|
|
12
12
|
data: Buffer;
|
|
13
13
|
}
|
|
14
14
|
interface ServerId {
|
|
15
|
-
/** Server ID
|
|
15
|
+
/** Server ID as a byte array (e.g. single-byte IDs use `[id]`). */
|
|
16
16
|
serverId?: number[];
|
|
17
17
|
runIndicatorStatus?: boolean;
|
|
18
18
|
additionalData?: number[];
|
|
@@ -44,10 +44,32 @@ 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
|
+
* @param end — Byte offset one past the last valid byte. Bounds checks must use
|
|
56
|
+
* `end - start` as available bytes, NOT `buffer.length` (pool capacity).
|
|
57
|
+
* @returns Total frame length (>= 4, <= 256), or `null` if more bytes are needed.
|
|
58
|
+
*/
|
|
59
|
+
predictRequestLength: (buffer: Buffer, start: number, end: number) => number | null;
|
|
60
|
+
/**
|
|
61
|
+
* Predict total RTU frame length for an incoming response (master-side framing).
|
|
62
|
+
*
|
|
63
|
+
* @param buffer — The raw frame buffer (a shared pool or incoming chunk). Do NOT
|
|
64
|
+
* modify it; the framing layer owns the memory.
|
|
65
|
+
* @param start — Byte offset in `buffer` where the current candidate frame begins
|
|
66
|
+
* (the unit ID byte). Read the function code at `buffer[start + 1]` and derive
|
|
67
|
+
* the total frame length from the trailing bytes.
|
|
68
|
+
* @param end — Byte offset one past the last valid byte. Bounds checks must use
|
|
69
|
+
* `end - start` as available bytes, NOT `buffer.length` (pool capacity).
|
|
70
|
+
* @returns Total frame length (>= 4, <= 256), or `null` if more bytes are needed.
|
|
71
|
+
*/
|
|
72
|
+
predictResponseLength: (buffer: Buffer, start: number, end: number) => number | null;
|
|
51
73
|
/**
|
|
52
74
|
* Slave-side handler. Receives PDU payload (bytes after `fc`, before CRC) and
|
|
53
75
|
* the unit ID being addressed; must return the PDU payload of the response.
|
|
@@ -115,6 +137,8 @@ declare enum ConformityLevel {
|
|
|
115
137
|
}
|
|
116
138
|
/** Shared empty Buffer to avoid repeated allocations. */
|
|
117
139
|
declare const EMPTY_BUFFER: Buffer<ArrayBuffer>;
|
|
140
|
+
/** Shared no-op function to avoid repeated allocations. */
|
|
141
|
+
declare const NOOP: () => void;
|
|
118
142
|
/** Modbus V1.1b3 PDU quantity limits. */
|
|
119
143
|
declare const LIMITS: {
|
|
120
144
|
readonly READ_COILS_MIN: 1;
|
|
@@ -353,25 +377,37 @@ type PhysicalConfig = {
|
|
|
353
377
|
type: 'CUSTOM';
|
|
354
378
|
layer: AbstractPhysicalLayer;
|
|
355
379
|
};
|
|
380
|
+
/**
|
|
381
|
+
* User-facing arguments for `Master.open()` / `Slave.open()`.
|
|
382
|
+
*
|
|
383
|
+
* These match the physical layer's `open()` signatures **without** the trailing
|
|
384
|
+
* callback — `promisifyCb` appends it internally so the user gets a `Promise`.
|
|
385
|
+
*
|
|
386
|
+
* | Config | User-facing args |
|
|
387
|
+
* |---------------|--------------------------------------|
|
|
388
|
+
* | SERIAL | `()` — configured at construction |
|
|
389
|
+
* | TCP_CLIENT | `(opts?)` — `SocketConnectOpts` |
|
|
390
|
+
* | TCP_SERVER | `(opts?)` — `ListenOptions` |
|
|
391
|
+
* | UDP_CLIENT | `(remote?)` — `{ port?, address? }` |
|
|
392
|
+
* | UDP_SERVER | `(opts?)` — `BindOptions` |
|
|
393
|
+
* | CUSTOM | `never` — call `layer.open()` directly |
|
|
394
|
+
*/
|
|
356
395
|
type OpenArgs<T extends PhysicalConfig> = T extends {
|
|
357
396
|
type: 'SERIAL';
|
|
358
|
-
} ?
|
|
397
|
+
} ? [] : T extends {
|
|
359
398
|
type: 'TCP_CLIENT';
|
|
360
|
-
} ?
|
|
399
|
+
} ? [options?: SocketConnectOpts] : T extends {
|
|
361
400
|
type: 'TCP_SERVER';
|
|
362
|
-
} ?
|
|
401
|
+
} ? [options?: ListenOptions] : T extends {
|
|
363
402
|
type: 'UDP_CLIENT';
|
|
364
|
-
} ?
|
|
403
|
+
} ? [remote?: {
|
|
404
|
+
port?: number;
|
|
405
|
+
address?: string;
|
|
406
|
+
}] : T extends {
|
|
365
407
|
type: 'UDP_SERVER';
|
|
366
|
-
} ?
|
|
408
|
+
} ? [options?: BindOptions] : never;
|
|
367
409
|
declare function createPhysicalLayer(config: PhysicalConfig): AbstractPhysicalLayer;
|
|
368
410
|
|
|
369
|
-
interface AbstractApplicationLayerEvents {
|
|
370
|
-
framing: [frame: ApplicationDataUnit & {
|
|
371
|
-
buffer: Buffer;
|
|
372
|
-
}];
|
|
373
|
-
'framing-error': [error: Error];
|
|
374
|
-
}
|
|
375
411
|
/**
|
|
376
412
|
* Application-layer protocol handler bound to a single physical connection.
|
|
377
413
|
*
|
|
@@ -379,10 +415,16 @@ interface AbstractApplicationLayerEvents {
|
|
|
379
415
|
* established and discarded when the connection closes. Subclasses implement
|
|
380
416
|
* ASCII, RTU, or TCP framing rules.
|
|
381
417
|
*/
|
|
382
|
-
declare abstract class AbstractApplicationLayer
|
|
418
|
+
declare abstract class AbstractApplicationLayer {
|
|
383
419
|
abstract readonly PROTOCOL: 'ASCII' | 'RTU' | 'TCP';
|
|
384
420
|
abstract ROLE: 'MASTER' | 'SLAVE';
|
|
385
421
|
abstract readonly connection: AbstractPhysicalConnection;
|
|
422
|
+
/** Called when a complete frame is decoded. Defaults to no-op. */
|
|
423
|
+
onFraming: (frame: ApplicationDataUnit & {
|
|
424
|
+
buffer: Buffer;
|
|
425
|
+
}) => void;
|
|
426
|
+
/** Called when a framing error is detected. Defaults to no-op. */
|
|
427
|
+
onFramingError: (error: Error) => void;
|
|
386
428
|
flush(): void;
|
|
387
429
|
addCustomFunctionCode(cfc: CustomFunctionCode): void;
|
|
388
430
|
removeCustomFunctionCode(fc: number): void;
|
|
@@ -403,7 +445,7 @@ declare class AsciiApplicationLayer extends AbstractApplicationLayer {
|
|
|
403
445
|
readonly lenientHex: boolean;
|
|
404
446
|
private _connection;
|
|
405
447
|
private _state;
|
|
406
|
-
private
|
|
448
|
+
private _cleanupCbs;
|
|
407
449
|
get connection(): AbstractPhysicalConnection;
|
|
408
450
|
constructor(role: 'MASTER' | 'SLAVE', connection: AbstractPhysicalConnection, options?: AsciiApplicationLayerOptions);
|
|
409
451
|
private framing;
|
|
@@ -432,10 +474,18 @@ declare class RtuApplicationLayer extends AbstractApplicationLayer {
|
|
|
432
474
|
private _threePointFiveT;
|
|
433
475
|
private _onePointFiveT;
|
|
434
476
|
private _customFunctionCodes;
|
|
435
|
-
private
|
|
477
|
+
private _cleanupCbs;
|
|
436
478
|
get connection(): AbstractPhysicalConnection;
|
|
437
479
|
constructor(role: 'MASTER' | 'SLAVE', connection: AbstractPhysicalConnection, options?: RtuApplicationLayerOptions);
|
|
438
480
|
private clearStateTimers;
|
|
481
|
+
/**
|
|
482
|
+
* Shared handler for every "frame is not yet complete" exit in `flushBuffer`.
|
|
483
|
+
* Returns `true` when the caller should `return` (strict reset), `false` to
|
|
484
|
+
* `break` the parse loop. Hot path never reaches here — only error/incomplete
|
|
485
|
+
* edges. Extracted as a method so it is not recreated on every `flushBuffer`
|
|
486
|
+
* call.
|
|
487
|
+
*/
|
|
488
|
+
private _handleIncomplete;
|
|
439
489
|
private flushBuffer;
|
|
440
490
|
flush(): void;
|
|
441
491
|
addCustomFunctionCode(cfc: CustomFunctionCode): void;
|
|
@@ -449,7 +499,7 @@ declare class TcpApplicationLayer extends AbstractApplicationLayer {
|
|
|
449
499
|
private _connection;
|
|
450
500
|
private _transactionId;
|
|
451
501
|
private _buffer;
|
|
452
|
-
private
|
|
502
|
+
private _cleanupCbs;
|
|
453
503
|
get connection(): AbstractPhysicalConnection;
|
|
454
504
|
constructor(role: 'MASTER' | 'SLAVE', connection: AbstractPhysicalConnection);
|
|
455
505
|
private tryExtract;
|
|
@@ -546,19 +596,21 @@ declare class ModbusMaster<T extends ModbusMasterOptions = ModbusMasterOptions>
|
|
|
546
596
|
private _queueDatas;
|
|
547
597
|
private _queueTimeouts;
|
|
548
598
|
private _queueBroadcasts;
|
|
549
|
-
private
|
|
550
|
-
private _queueRejects;
|
|
599
|
+
private _queueCallbacks;
|
|
551
600
|
private _queueHead;
|
|
552
601
|
private _queueLen;
|
|
553
602
|
private _draining;
|
|
554
603
|
private _nextTid;
|
|
555
604
|
private _cleanupFns;
|
|
556
605
|
private _closePromise;
|
|
606
|
+
private _nextExchangeId;
|
|
607
|
+
private _pendingExchanges;
|
|
608
|
+
private _timerHeap;
|
|
557
609
|
get state(): PhysicalState;
|
|
558
610
|
get physicalLayer(): AbstractPhysicalLayer;
|
|
559
611
|
constructor(options: T);
|
|
560
612
|
private _createAppLayer;
|
|
561
|
-
private
|
|
613
|
+
private _send;
|
|
562
614
|
private _drain;
|
|
563
615
|
private _processNext;
|
|
564
616
|
private _exchange;
|
|
@@ -620,7 +672,7 @@ declare class ModbusMaster<T extends ModbusMasterOptions = ModbusMasterOptions>
|
|
|
620
672
|
sendCustomFC(unit: 0, fc: number, data: Buffer | number[], timeout?: number): Promise<void>;
|
|
621
673
|
sendCustomFC(unit: number, fc: number, data: Buffer | number[], timeout?: number): Promise<Buffer>;
|
|
622
674
|
/**
|
|
623
|
-
* Open the underlying physical layer and
|
|
675
|
+
* Open the underlying physical layer and establish a connection.
|
|
624
676
|
*
|
|
625
677
|
* A `ModbusMaster` instance can only be opened once. Once {@link close}
|
|
626
678
|
* is called — explicitly or because the physical layer disconnected —
|
|
@@ -665,15 +717,19 @@ interface ModbusSlaveModel {
|
|
|
665
717
|
* Otherwise keep the default read and write behavior.
|
|
666
718
|
*/
|
|
667
719
|
interceptor?: MaybeAsyncFunction<(fc: number, data: Buffer) => Buffer | undefined>;
|
|
668
|
-
|
|
669
|
-
|
|
720
|
+
/** Return `Uint8Array` to avoid the `Array.from` allocation overhead. */
|
|
721
|
+
readDiscreteInputs?: MaybeAsyncFunction<(address: number, length: number) => boolean[] | Uint8Array>;
|
|
722
|
+
/** Return `Uint8Array` to avoid the `Array.from` allocation overhead. */
|
|
723
|
+
readCoils?: MaybeAsyncFunction<(address: number, length: number) => boolean[] | Uint8Array>;
|
|
670
724
|
writeSingleCoil?: MaybeAsyncFunction<(address: number, value: boolean) => void>;
|
|
671
725
|
/**
|
|
672
726
|
* If omitted, defaults to loop and call `writeSingleCoil`.
|
|
673
727
|
*/
|
|
674
728
|
writeMultipleCoils?: MaybeAsyncFunction<(address: number, value: boolean[]) => void>;
|
|
675
|
-
|
|
676
|
-
|
|
729
|
+
/** Return `Uint16Array` to avoid the `Array.from` allocation overhead. */
|
|
730
|
+
readInputRegisters?: MaybeAsyncFunction<(address: number, length: number) => number[] | Uint16Array>;
|
|
731
|
+
/** Return `Uint16Array` to avoid the `Array.from` allocation overhead. */
|
|
732
|
+
readHoldingRegisters?: MaybeAsyncFunction<(address: number, length: number) => number[] | Uint16Array>;
|
|
677
733
|
writeSingleRegister?: MaybeAsyncFunction<(address: number, value: number) => void>;
|
|
678
734
|
/**
|
|
679
735
|
* If omitted, defaults to loop and call `writeSingleRegister`.
|
|
@@ -719,7 +775,7 @@ declare class ModbusSlave<T extends ModbusSlaveOptions = ModbusSlaveOptions> ext
|
|
|
719
775
|
private _protocol;
|
|
720
776
|
private _appLayers;
|
|
721
777
|
private _customFunctionCodes;
|
|
722
|
-
private
|
|
778
|
+
private _intervalLocks;
|
|
723
779
|
private _cleanupFns;
|
|
724
780
|
private _closePromise;
|
|
725
781
|
get state(): PhysicalState;
|
|
@@ -742,7 +798,19 @@ declare class ModbusSlave<T extends ModbusSlaveOptions = ModbusSlaveOptions> ext
|
|
|
742
798
|
private _drain;
|
|
743
799
|
private _processFrame;
|
|
744
800
|
private _intercept;
|
|
745
|
-
|
|
801
|
+
/**
|
|
802
|
+
* Serialize a code block over the half-open address interval `[lo, hi)`.
|
|
803
|
+
* The block runs after all previously-installed locks whose intervals
|
|
804
|
+
* overlap with this one have completed. Two non-overlapping intervals
|
|
805
|
+
* execute in parallel.
|
|
806
|
+
*
|
|
807
|
+
* Locks are tracked in a flat array (`_intervalLocks`); the typical depth
|
|
808
|
+
* is 0-2 entries, so the linear overlap scan is sub-µs. Compare with the
|
|
809
|
+
* old per-address Map design, where FC23 writing 121 registers allocated
|
|
810
|
+
* ~125 objects per request (one Promise.resolve / address + Set + sort +
|
|
811
|
+
* Promise.all); this version allocates 1-3.
|
|
812
|
+
*/
|
|
813
|
+
private _withIntervalLock;
|
|
746
814
|
private _handleFC;
|
|
747
815
|
private _handleCustomFC;
|
|
748
816
|
add(model: ModbusSlaveModel): void;
|
|
@@ -770,5 +838,5 @@ declare class ModbusSlave<T extends ModbusSlaveOptions = ModbusSlaveOptions> ext
|
|
|
770
838
|
close(): Promise<void>;
|
|
771
839
|
}
|
|
772
840
|
|
|
773
|
-
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 };
|
|
841
|
+
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 };
|
|
774
842
|
export type { AbstractPhysicalLayerEvents, ApplicationDataUnit, AsciiApplicationLayerOptions, Callback$1 as Callback, CustomFunctionCode, DeviceIdentification, MaybeAsyncFunction, ModbusMasterOptions, ModbusSlaveModel, ModbusSlaveOptions, OpenArgs, PhysicalConfig, RtuApplicationLayerOptions, ServerId, TcpServerPhysicalLayerOptions, UdpServerPhysicalLayerOptions };
|