njs-modbus 2.1.0 → 3.1.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 +324 -147
- package/README.zh-CN.md +380 -0
- package/dist/index.cjs +2552 -2288
- package/dist/index.d.ts +400 -233
- package/dist/index.mjs +2548 -2287
- package/dist/src/error-code.d.ts +2 -24
- package/dist/src/layers/application/abstract-application-layer.d.ts +13 -8
- package/dist/src/layers/application/ascii-application-layer.d.ts +9 -11
- package/dist/src/layers/application/rtu-application-layer.d.ts +20 -47
- package/dist/src/layers/application/tcp-application-layer.d.ts +9 -8
- package/dist/src/layers/physical/abstract-physical-layer.d.ts +43 -14
- package/dist/src/layers/physical/index.d.ts +9 -3
- package/dist/src/layers/physical/serial-physical-layer.d.ts +43 -15
- package/dist/src/layers/physical/tcp-client-physical-layer.d.ts +13 -12
- package/dist/src/layers/physical/tcp-physical-connection.d.ts +16 -0
- package/dist/src/layers/physical/tcp-server-physical-layer.d.ts +24 -14
- package/dist/src/layers/physical/udp-client-physical-layer.d.ts +33 -0
- package/dist/src/layers/physical/udp-server-physical-layer.d.ts +50 -0
- package/dist/src/layers/physical/utils.d.ts +39 -0
- package/dist/src/layers/physical/vars.d.ts +11 -0
- package/dist/src/master/master-session.d.ts +3 -3
- package/dist/src/master/master.d.ts +55 -19
- package/dist/src/slave/slave.d.ts +58 -33
- package/dist/src/types.d.ts +2 -2
- package/dist/src/utils/callback.d.ts +8 -0
- package/dist/src/utils/crc.d.ts +1 -1
- package/dist/src/utils/index.d.ts +7 -4
- package/dist/src/utils/predictRtuFrameLength.d.ts +13 -16
- package/dist/src/utils/promisify-cb.d.ts +4 -0
- package/dist/src/utils/rtu-timing.d.ts +63 -0
- package/dist/src/utils/whitelist.d.ts +11 -0
- package/dist/src/vars.d.ts +2 -0
- package/package.json +15 -8
- package/dist/src/layers/physical/udp-physical-layer.d.ts +0 -42
- package/dist/src/utils/genConnectionId.d.ts +0 -2
- package/dist/test/adu-buffer.test.d.ts +0 -1
- package/dist/test/ascii-hex-sentry.test.d.ts +0 -1
- package/dist/test/ascii-hex-validation.test.d.ts +0 -1
- package/dist/test/ascii-tcp-fragmentation.test.d.ts +0 -1
- package/dist/test/check-range.test.d.ts +0 -1
- package/dist/test/fallback-atomic.test.d.ts +0 -1
- package/dist/test/fallback-serial.test.d.ts +0 -1
- package/dist/test/fc17-serverid-validation.test.d.ts +0 -1
- package/dist/test/fc43-conformity.test.d.ts +0 -1
- package/dist/test/fc43-utf8-objects.test.d.ts +0 -1
- package/dist/test/gen-connection-id.test.d.ts +0 -1
- package/dist/test/helpers/raw-tcp.d.ts +0 -38
- package/dist/test/master-concurrent.test.d.ts +0 -1
- package/dist/test/modbus-error.test.d.ts +0 -1
- package/dist/test/physical-lifecycle.test.d.ts +0 -1
- package/dist/test/predict-rtu.test.d.ts +0 -1
- package/dist/test/rtu-custom-fc.test.d.ts +0 -1
- package/dist/test/rtu-pool-overflow.test.d.ts +0 -1
- package/dist/test/rtu-t15-timing.test.d.ts +0 -1
- package/dist/test/rtu-t35-default.test.d.ts +0 -1
- package/dist/test/rtu-t35-strict.test.d.ts +0 -1
- package/dist/test/rtu-tcp-fragmentation.test.d.ts +0 -1
- package/dist/test/serial-e2e.test.d.ts +0 -1
- package/dist/test/slave-multi-connection.test.d.ts +0 -1
- package/dist/test/slave.test.d.ts +0 -1
- package/dist/test/tcp-fragmentation.test.d.ts +0 -1
- package/dist/test/udp-multi-client.test.d.ts +0 -1
package/dist/src/error-code.d.ts
CHANGED
|
@@ -9,31 +9,9 @@ export declare enum ErrorCode {
|
|
|
9
9
|
GATEWAY_PATH_UNAVAILABLE = 10,
|
|
10
10
|
GATEWAY_TARGET_DEVICE_FAILED_TO_RESPOND = 11
|
|
11
11
|
}
|
|
12
|
-
/** Internal error codes for programmatic error handling. */
|
|
13
|
-
export declare const ModbusErrorCode: {
|
|
14
|
-
readonly TIMEOUT: "ETIMEOUT";
|
|
15
|
-
readonly INVALID_RESPONSE: "EINVALID_RESPONSE";
|
|
16
|
-
readonly INSUFFICIENT_DATA: "EINSUFFICIENT_DATA";
|
|
17
|
-
readonly MASTER_CLOSED: "EMASTER_CLOSED";
|
|
18
|
-
readonly MASTER_DESTROYED: "EMASTER_DESTROYED";
|
|
19
|
-
readonly CONCURRENT_NOT_TCP: "ECONCURRENT_NOT_TCP";
|
|
20
|
-
readonly PORT_DESTROYED: "EPORT_DESTROYED";
|
|
21
|
-
readonly PORT_ALREADY_OPEN: "EPORT_ALREADY_OPEN";
|
|
22
|
-
readonly PORT_NOT_OPEN: "EPORT_NOT_OPEN";
|
|
23
|
-
readonly NOT_SUPPORTED: "ENOT_SUPPORTED";
|
|
24
|
-
readonly INVALID_DATA: "EINVALID_DATA";
|
|
25
|
-
readonly INVALID_HEX: "EINVALID_HEX";
|
|
26
|
-
readonly CRC_MISMATCH: "ECRC_MISMATCH";
|
|
27
|
-
readonly LRC_MISMATCH: "ELRC_MISMATCH";
|
|
28
|
-
readonly INCOMPLETE_FRAME: "EINCOMPLETE_FRAME";
|
|
29
|
-
readonly T1_5_EXCEEDED: "ET1_5_EXCEEDED";
|
|
30
|
-
readonly UNKNOWN_FC: "EUNKNOWN_FC";
|
|
31
|
-
readonly INVALID_ROLE: "EINVALID_ROLE";
|
|
32
|
-
readonly RANGE: "ERANGE";
|
|
33
|
-
};
|
|
34
12
|
export declare class ModbusError extends Error {
|
|
35
|
-
readonly code:
|
|
36
|
-
constructor(code:
|
|
13
|
+
readonly code: ErrorCode;
|
|
14
|
+
constructor(code: ErrorCode, message?: string);
|
|
37
15
|
}
|
|
38
16
|
export declare function getErrorByCode(code: ErrorCode): ModbusError;
|
|
39
17
|
export declare function getCodeByError(err: Error): ErrorCode;
|
|
@@ -1,21 +1,26 @@
|
|
|
1
1
|
import type { ApplicationDataUnit, CustomFunctionCode } from '../../types';
|
|
2
|
-
import type {
|
|
2
|
+
import type { AbstractPhysicalConnection } from '../physical';
|
|
3
3
|
import EventEmitter from 'node:events';
|
|
4
4
|
interface AbstractApplicationLayerEvents {
|
|
5
5
|
framing: [frame: ApplicationDataUnit & {
|
|
6
6
|
buffer: Buffer;
|
|
7
|
-
}
|
|
7
|
+
}];
|
|
8
8
|
'framing-error': [error: Error];
|
|
9
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* Application-layer protocol handler bound to a single physical connection.
|
|
12
|
+
*
|
|
13
|
+
* Its lifetime follows the channel: created when the underlying connection is
|
|
14
|
+
* established and discarded when the connection closes. Subclasses implement
|
|
15
|
+
* ASCII, RTU, or TCP framing rules.
|
|
16
|
+
*/
|
|
10
17
|
export declare abstract class AbstractApplicationLayer extends EventEmitter<AbstractApplicationLayerEvents> {
|
|
11
|
-
abstract readonly PROTOCOL: '
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
set role(value: 'MASTER' | 'SLAVE');
|
|
18
|
+
abstract readonly PROTOCOL: 'ASCII' | 'RTU' | 'TCP';
|
|
19
|
+
abstract ROLE: 'MASTER' | 'SLAVE';
|
|
20
|
+
abstract readonly connection: AbstractPhysicalConnection;
|
|
15
21
|
flush(): void;
|
|
16
22
|
addCustomFunctionCode(cfc: CustomFunctionCode): void;
|
|
17
23
|
removeCustomFunctionCode(fc: number): void;
|
|
18
|
-
abstract encode(data:
|
|
19
|
-
abstract destroy(): void;
|
|
24
|
+
abstract encode(unit: number, fc: number, data: Buffer, transaction?: number): Buffer;
|
|
20
25
|
}
|
|
21
26
|
export {};
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { TcpClientPhysicalLayer, TcpServerPhysicalLayer, UdpPhysicalLayer } from '../physical';
|
|
3
|
-
import type { SerialPhysicalLayer } from '../physical';
|
|
1
|
+
import type { AbstractPhysicalConnection } from '../physical';
|
|
4
2
|
import { AbstractApplicationLayer } from './abstract-application-layer';
|
|
5
3
|
export interface AsciiApplicationLayerOptions {
|
|
6
4
|
/**
|
|
@@ -12,14 +10,14 @@ export interface AsciiApplicationLayerOptions {
|
|
|
12
10
|
}
|
|
13
11
|
export declare class AsciiApplicationLayer extends AbstractApplicationLayer {
|
|
14
12
|
readonly PROTOCOL: "ASCII";
|
|
13
|
+
readonly ROLE: 'MASTER' | 'SLAVE';
|
|
15
14
|
readonly lenientHex: boolean;
|
|
16
|
-
private
|
|
17
|
-
private
|
|
18
|
-
private
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
flush(): void;
|
|
15
|
+
private _connection;
|
|
16
|
+
private _state;
|
|
17
|
+
private _cleanupFns;
|
|
18
|
+
get connection(): AbstractPhysicalConnection;
|
|
19
|
+
constructor(role: 'MASTER' | 'SLAVE', connection: AbstractPhysicalConnection, options?: AsciiApplicationLayerOptions);
|
|
22
20
|
private framing;
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
flush(): void;
|
|
22
|
+
encode(unit: number, fc: number, data: Buffer, transaction?: number): Buffer;
|
|
25
23
|
}
|
|
@@ -1,61 +1,34 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
3
|
-
import type { SerialPhysicalLayer } from '../physical';
|
|
1
|
+
import type { CustomFunctionCode } from '../../types';
|
|
2
|
+
import type { AbstractPhysicalConnection } from '../physical';
|
|
4
3
|
import { AbstractApplicationLayer } from './abstract-application-layer';
|
|
5
4
|
export interface RtuApplicationLayerOptions {
|
|
5
|
+
/** Inter-frame silence in milliseconds (Modbus RTU t3.5). 0 = disabled (immediate parse). */
|
|
6
|
+
intervalBetweenFrames?: number;
|
|
7
|
+
/** Inter-character timeout in milliseconds (Modbus RTU t1.5). Opt-in. */
|
|
8
|
+
interCharTimeout?: number;
|
|
6
9
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* - `{ unit: 'bit', value: 38.5 }` — spec bit-time approximation
|
|
11
|
-
* - `{ unit: 'ms', value: 20 }` — explicit milliseconds
|
|
12
|
-
*
|
|
13
|
-
* Per Modbus V1.02 §2.5.1.1, at baud rates > 19200 the spec uses a fixed
|
|
14
|
-
* 1.75 ms regardless of the bit value supplied.
|
|
10
|
+
* Buffer pool size per connection (bytes). Defaults to `MAX_FRAME_LENGTH * 2`
|
|
11
|
+
* (512 bytes). Increase this if you expect frames larger than 256 bytes or
|
|
12
|
+
* heavy pipelining on a single connection.
|
|
15
13
|
*/
|
|
16
|
-
|
|
17
|
-
unit: 'bit' | 'ms';
|
|
18
|
-
value: number;
|
|
19
|
-
};
|
|
20
|
-
/**
|
|
21
|
-
* Inter-character timeout (Modbus RTU t1.5). Opt-in; **disabled** by default
|
|
22
|
-
* because Node.js `setTimeout` precision (~1 ms minimum, ~15.6 ms on Windows)
|
|
23
|
-
* is too coarse to reliably honor t1.5 at common baud rates without
|
|
24
|
-
* false-positive frame discards. When set, a mid-frame gap exceeding this
|
|
25
|
-
* duration discards the in-progress buffer and emits `framing-error`.
|
|
26
|
-
* Only takes effect on serial transports.
|
|
27
|
-
*
|
|
28
|
-
* - `{ unit: 'bit', value: 21 }` — bit-time approximation (~1.5 char times)
|
|
29
|
-
* - `{ unit: 'ms', value: 1 }` — explicit milliseconds
|
|
30
|
-
*
|
|
31
|
-
* Per Modbus V1.02 §2.5.1.1, at baud rates > 19200 the spec uses a fixed
|
|
32
|
-
* 0.75 ms regardless of the bit value supplied.
|
|
33
|
-
*/
|
|
34
|
-
interCharTimeout?: {
|
|
35
|
-
unit: 'bit' | 'ms';
|
|
36
|
-
value: number;
|
|
37
|
-
};
|
|
14
|
+
poolSize?: number;
|
|
38
15
|
}
|
|
39
16
|
export declare class RtuApplicationLayer extends AbstractApplicationLayer {
|
|
40
17
|
readonly PROTOCOL: "RTU";
|
|
41
|
-
|
|
42
|
-
private
|
|
43
|
-
private
|
|
18
|
+
readonly ROLE: 'MASTER' | 'SLAVE';
|
|
19
|
+
private _connection;
|
|
20
|
+
private _state;
|
|
21
|
+
private _poolSize;
|
|
44
22
|
private _threePointFiveT;
|
|
45
23
|
private _onePointFiveT;
|
|
46
|
-
private
|
|
47
|
-
|
|
48
|
-
|
|
24
|
+
private _customFunctionCodes;
|
|
25
|
+
private _cleanupFns;
|
|
26
|
+
get connection(): AbstractPhysicalConnection;
|
|
27
|
+
constructor(role: 'MASTER' | 'SLAVE', connection: AbstractPhysicalConnection, options?: RtuApplicationLayerOptions);
|
|
49
28
|
private clearStateTimers;
|
|
50
|
-
private
|
|
29
|
+
private flushBuffer;
|
|
51
30
|
flush(): void;
|
|
52
31
|
addCustomFunctionCode(cfc: CustomFunctionCode): void;
|
|
53
32
|
removeCustomFunctionCode(fc: number): void;
|
|
54
|
-
|
|
55
|
-
private tryExtract;
|
|
56
|
-
private checkExpected;
|
|
57
|
-
private crcMatches;
|
|
58
|
-
private deliverFrame;
|
|
59
|
-
encode(data: ApplicationDataUnit): Buffer;
|
|
60
|
-
destroy(): void;
|
|
33
|
+
encode(unit: number, fc: number, data: Buffer, transaction?: number): Buffer;
|
|
61
34
|
}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { TcpClientPhysicalLayer, TcpServerPhysicalLayer, UdpPhysicalLayer } from '../physical';
|
|
1
|
+
import type { AbstractPhysicalConnection } from '../physical';
|
|
3
2
|
import { AbstractApplicationLayer } from './abstract-application-layer';
|
|
4
3
|
export declare class TcpApplicationLayer extends AbstractApplicationLayer {
|
|
5
4
|
readonly PROTOCOL: "TCP";
|
|
5
|
+
readonly ROLE: 'MASTER' | 'SLAVE';
|
|
6
|
+
private _connection;
|
|
6
7
|
private _transactionId;
|
|
7
|
-
private
|
|
8
|
-
private
|
|
9
|
-
|
|
10
|
-
constructor(
|
|
8
|
+
private _buffer;
|
|
9
|
+
private _cleanupFns;
|
|
10
|
+
get connection(): AbstractPhysicalConnection;
|
|
11
|
+
constructor(role: 'MASTER' | 'SLAVE', connection: AbstractPhysicalConnection);
|
|
11
12
|
private tryExtract;
|
|
12
13
|
private processFrame;
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
flush(): void;
|
|
15
|
+
encode(unit: number, fc: number, data: Buffer, transaction?: number): Buffer;
|
|
15
16
|
}
|
|
@@ -1,21 +1,50 @@
|
|
|
1
|
+
import type { SerialPhysicalLayer } from './serial-physical-layer';
|
|
2
|
+
import type { TcpClientPhysicalLayer } from './tcp-client-physical-layer';
|
|
3
|
+
import type { TcpServerPhysicalLayer } from './tcp-server-physical-layer';
|
|
4
|
+
import type { UdpClientPhysicalLayer } from './udp-client-physical-layer';
|
|
5
|
+
import type { UdpServerPhysicalLayer } from './udp-server-physical-layer';
|
|
6
|
+
import type { PhysicalConnectionState, PhysicalState } from './vars';
|
|
1
7
|
import EventEmitter from 'node:events';
|
|
2
|
-
|
|
3
|
-
|
|
8
|
+
interface AbstractPhysicalConnectionEvents {
|
|
9
|
+
data: [data: Buffer];
|
|
10
|
+
close: [];
|
|
4
11
|
}
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
12
|
+
/**
|
|
13
|
+
* A one-way data transmission channel.
|
|
14
|
+
*
|
|
15
|
+
* State transitions are unidirectional: CONNECTED → DESTROYING → DESTROYED.
|
|
16
|
+
* Once closed, the instance cannot be reused; create a new connection instead.
|
|
17
|
+
*/
|
|
18
|
+
export declare abstract class AbstractPhysicalConnection extends EventEmitter<AbstractPhysicalConnectionEvents> {
|
|
19
|
+
abstract readonly state: PhysicalConnectionState;
|
|
20
|
+
abstract readonly physicalLayer: AbstractPhysicalLayer;
|
|
21
|
+
abstract write(data: Buffer, cb?: (err?: Error | null) => void): void;
|
|
22
|
+
abstract destroy(cb?: (err?: Error | null) => void): void;
|
|
23
|
+
}
|
|
24
|
+
export interface AbstractPhysicalLayerEvents {
|
|
25
|
+
open: [];
|
|
26
|
+
connect: [connection: AbstractPhysicalConnection];
|
|
10
27
|
close: [];
|
|
28
|
+
error: [error: Error];
|
|
11
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* An abstraction over local hardware or network resources.
|
|
32
|
+
*
|
|
33
|
+
* `open()` acquires the resource (serial port, TCP socket, UDP socket, etc.).
|
|
34
|
+
* Once ready, it emits `connect` with an {@link AbstractPhysicalConnection},
|
|
35
|
+
* unifying serial, TCP client, TCP server, and UDP under a single
|
|
36
|
+
* "connection-oriented" model similar to a TCP server accepting sockets.
|
|
37
|
+
*/
|
|
12
38
|
export declare abstract class AbstractPhysicalLayer extends EventEmitter<AbstractPhysicalLayerEvents> {
|
|
13
|
-
abstract readonly TYPE: 'SERIAL' | '
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
abstract
|
|
39
|
+
abstract readonly TYPE: 'SERIAL' | 'TCP_CLIENT' | 'TCP_SERVER' | 'UDP_CLIENT' | 'UDP_SERVER';
|
|
40
|
+
is(type: 'SERIAL'): this is SerialPhysicalLayer;
|
|
41
|
+
is(type: 'TCP_CLIENT'): this is TcpClientPhysicalLayer;
|
|
42
|
+
is(type: 'TCP_SERVER'): this is TcpServerPhysicalLayer;
|
|
43
|
+
is(type: 'UDP_CLIENT'): this is UdpClientPhysicalLayer;
|
|
44
|
+
is(type: 'UDP_SERVER'): this is UdpServerPhysicalLayer;
|
|
45
|
+
abstract readonly state: PhysicalState;
|
|
46
|
+
/** Last argument is the callback: `(err?: Error | null) => void`. Callback is optional. */
|
|
47
|
+
abstract open(...args: any[]): void;
|
|
48
|
+
abstract close(cb?: (err?: Error | null) => void): void;
|
|
20
49
|
}
|
|
21
50
|
export {};
|
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
export type {
|
|
2
|
-
export {
|
|
1
|
+
export type { AbstractPhysicalLayerEvents } from './abstract-physical-layer';
|
|
2
|
+
export type { PhysicalConfig, OpenArgs } from './utils';
|
|
3
|
+
export type { TcpServerPhysicalLayerOptions } from './tcp-server-physical-layer';
|
|
4
|
+
export type { UdpServerPhysicalLayerOptions } from './udp-server-physical-layer';
|
|
5
|
+
export { AbstractPhysicalConnection, AbstractPhysicalLayer } from './abstract-physical-layer';
|
|
3
6
|
export { SerialPhysicalLayer } from './serial-physical-layer';
|
|
4
7
|
export { TcpClientPhysicalLayer } from './tcp-client-physical-layer';
|
|
5
8
|
export { TcpServerPhysicalLayer } from './tcp-server-physical-layer';
|
|
6
|
-
export {
|
|
9
|
+
export { UdpClientPhysicalLayer } from './udp-client-physical-layer';
|
|
10
|
+
export { UdpServerPhysicalLayer } from './udp-server-physical-layer';
|
|
11
|
+
export { PhysicalState, PhysicalConnectionState } from './vars';
|
|
12
|
+
export { createPhysicalLayer } from './utils';
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SerialPort } from 'serialport';
|
|
2
|
+
import { AbstractPhysicalConnection, AbstractPhysicalLayer } from './abstract-physical-layer';
|
|
3
|
+
import { PhysicalConnectionState, PhysicalState } from './vars';
|
|
2
4
|
export interface SerialPhysicalLayerOptions {
|
|
3
5
|
/** The system path of the serial port you want to open. For example, `/dev/tty.XXX` on Mac/Linux, or `COM1` on Windows */
|
|
4
6
|
path: string;
|
|
@@ -6,37 +8,63 @@ export interface SerialPhysicalLayerOptions {
|
|
|
6
8
|
* The baud rate of the port to be opened. This should match one of the commonly available baud rates, such as 110, 300, 1200, 2400, 4800, 9600, 14400, 19200, 38400, 57600, or 115200. Custom rates are supported best effort per platform. The device connected to the serial port is not guaranteed to support the requested baud rate, even if the port itself supports that baud rate.
|
|
7
9
|
*/
|
|
8
10
|
baudRate: number;
|
|
9
|
-
/** Must be one of these: 5, 6, 7, or 8
|
|
11
|
+
/** Must be one of these: 5, 6, 7, or 8. Defaults to 8 */
|
|
10
12
|
dataBits?: 5 | 6 | 7 | 8;
|
|
11
13
|
/** Prevent other processes from opening the port. Windows does not currently support `false`. Defaults to true */
|
|
12
14
|
lock?: boolean;
|
|
13
|
-
/** Must be 1, 1.5 or 2
|
|
15
|
+
/** Must be 1, 1.5 or 2. Defaults to 1 */
|
|
14
16
|
stopBits?: 1 | 1.5 | 2;
|
|
15
|
-
parity
|
|
17
|
+
/** Device parity. Defaults to none */
|
|
18
|
+
parity?: 'none' | 'even' | 'odd' | 'mark' | 'space';
|
|
16
19
|
/** Flow control Setting. Defaults to false */
|
|
17
20
|
rtscts?: boolean;
|
|
18
21
|
/** Flow control Setting. Defaults to false */
|
|
19
22
|
xon?: boolean;
|
|
20
23
|
/** Flow control Setting. Defaults to false */
|
|
21
24
|
xoff?: boolean;
|
|
22
|
-
/** Flow control Setting
|
|
25
|
+
/** Flow control Setting. Defaults to false */
|
|
23
26
|
xany?: boolean;
|
|
24
27
|
/** drop DTR on close. Defaults to true */
|
|
25
28
|
hupcl?: boolean;
|
|
29
|
+
/** The size of the read and write buffers. Defaults to 64k */
|
|
30
|
+
highWaterMark?: number;
|
|
31
|
+
/** Emit 'end' on port close. Defaults to false */
|
|
32
|
+
endOnClose?: boolean;
|
|
33
|
+
/** see `man termios`. Defaults to 1 (Darwin/Linux only) */
|
|
34
|
+
vmin?: number;
|
|
35
|
+
/** see `man termios`. Defaults to 0 (Darwin/Linux only) */
|
|
36
|
+
vtime?: number;
|
|
37
|
+
/** RTS mode. Defaults to handshake (Windows only) */
|
|
38
|
+
rtsMode?: 'handshake' | 'enable' | 'toggle';
|
|
39
|
+
}
|
|
40
|
+
export declare class SerialPhysicalConnection extends AbstractPhysicalConnection {
|
|
41
|
+
private _state;
|
|
42
|
+
private _physicalLayer;
|
|
43
|
+
private _serialport;
|
|
44
|
+
private _pendingDestroyCbs;
|
|
45
|
+
private _cleanupFns;
|
|
46
|
+
get state(): PhysicalConnectionState;
|
|
47
|
+
get physicalLayer(): AbstractPhysicalLayer;
|
|
48
|
+
constructor(physicalLayer: SerialPhysicalLayer, serialport: SerialPort);
|
|
49
|
+
write(data: Buffer, cb?: (err?: Error | null) => void): void;
|
|
50
|
+
destroy(cb?: (err?: Error | null) => void): void;
|
|
26
51
|
}
|
|
27
52
|
export declare class SerialPhysicalLayer extends AbstractPhysicalLayer {
|
|
28
|
-
TYPE:
|
|
53
|
+
readonly TYPE: "SERIAL";
|
|
54
|
+
private _state;
|
|
55
|
+
private _connections;
|
|
29
56
|
private _serialport;
|
|
30
|
-
private
|
|
31
|
-
private
|
|
32
|
-
private _destroyed;
|
|
57
|
+
private _serialportOpts;
|
|
58
|
+
private _path;
|
|
33
59
|
private _baudRate;
|
|
34
|
-
|
|
35
|
-
|
|
60
|
+
private _pendingOpenCbs;
|
|
61
|
+
private _pendingCloseCbs;
|
|
62
|
+
private _cleanupFns;
|
|
63
|
+
get state(): PhysicalState;
|
|
64
|
+
get serialport(): SerialPort | null;
|
|
65
|
+
get path(): string;
|
|
36
66
|
get baudRate(): number;
|
|
37
67
|
constructor(options: SerialPhysicalLayerOptions);
|
|
38
|
-
open():
|
|
39
|
-
|
|
40
|
-
close(): Promise<void>;
|
|
41
|
-
destroy(): Promise<void>;
|
|
68
|
+
open(cb?: (err?: Error | null) => void): void;
|
|
69
|
+
close(cb?: (err?: Error | null) => void): void;
|
|
42
70
|
}
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import type { SocketConstructorOpts, SocketConnectOpts } from 'node:net';
|
|
2
|
+
import { Socket } from 'node:net';
|
|
2
3
|
import { AbstractPhysicalLayer } from './abstract-physical-layer';
|
|
4
|
+
import { PhysicalState } from './vars';
|
|
3
5
|
export declare class TcpClientPhysicalLayer extends AbstractPhysicalLayer {
|
|
4
|
-
TYPE:
|
|
6
|
+
readonly TYPE: "TCP_CLIENT";
|
|
7
|
+
private _state;
|
|
8
|
+
private _connections;
|
|
5
9
|
private _socket;
|
|
6
|
-
private
|
|
7
|
-
private
|
|
8
|
-
private
|
|
9
|
-
private
|
|
10
|
-
|
|
11
|
-
get
|
|
12
|
-
get destroyed(): boolean;
|
|
10
|
+
private _socketOpts?;
|
|
11
|
+
private _pendingOpenCbs;
|
|
12
|
+
private _pendingCloseCbs;
|
|
13
|
+
private _cleanupFns;
|
|
14
|
+
get state(): PhysicalState;
|
|
15
|
+
get socket(): Socket | null;
|
|
13
16
|
constructor(options?: SocketConstructorOpts);
|
|
14
|
-
open(options?: SocketConnectOpts):
|
|
15
|
-
|
|
16
|
-
close(): Promise<void>;
|
|
17
|
-
destroy(): Promise<void>;
|
|
17
|
+
open(options?: SocketConnectOpts | ((err?: Error | null) => void), cb?: (err?: Error | null) => void): void;
|
|
18
|
+
close(cb?: (err?: Error | null) => void): void;
|
|
18
19
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { AbstractPhysicalLayer } from './abstract-physical-layer';
|
|
2
|
+
import type { Socket } from 'node:net';
|
|
3
|
+
import { AbstractPhysicalConnection } from './abstract-physical-layer';
|
|
4
|
+
import { PhysicalConnectionState } from './vars';
|
|
5
|
+
export declare class TcpPhysicalConnection extends AbstractPhysicalConnection {
|
|
6
|
+
private _state;
|
|
7
|
+
private _physicalLayer;
|
|
8
|
+
private _socket;
|
|
9
|
+
private _pendingDestroyCbs;
|
|
10
|
+
private _cleanupFns;
|
|
11
|
+
get state(): PhysicalConnectionState;
|
|
12
|
+
get physicalLayer(): AbstractPhysicalLayer;
|
|
13
|
+
constructor(physicalLayer: AbstractPhysicalLayer, socket: Socket);
|
|
14
|
+
write(data: Buffer, cb?: (err?: Error | null) => void): void;
|
|
15
|
+
destroy(cb?: (err?: Error | null) => void): void;
|
|
16
|
+
}
|
|
@@ -1,18 +1,28 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Server, ListenOptions, ServerOpts } from 'node:net';
|
|
2
2
|
import { AbstractPhysicalLayer } from './abstract-physical-layer';
|
|
3
|
+
import { PhysicalState } from './vars';
|
|
4
|
+
export interface TcpServerPhysicalLayerOptions {
|
|
5
|
+
/** Allowed client IP addresses. IPv4-mapped IPv6 addresses (e.g., ::ffff:192.168.1.1) are normalized before checking. */
|
|
6
|
+
whitelist?: string[];
|
|
7
|
+
/** Maximum number of concurrent connections. When exceeded, new connections are silently dropped by Node.js. */
|
|
8
|
+
maxConnections?: number;
|
|
9
|
+
/** Idle timeout in ms. Connection is destroyed if no data is received within this time. 0 = disabled. */
|
|
10
|
+
idleTimeout?: number;
|
|
11
|
+
/** Forwarded to `net.createServer()`. */
|
|
12
|
+
serverOpts?: ServerOpts;
|
|
13
|
+
}
|
|
3
14
|
export declare class TcpServerPhysicalLayer extends AbstractPhysicalLayer {
|
|
4
|
-
TYPE:
|
|
5
|
-
private
|
|
6
|
-
private _isOpen;
|
|
7
|
-
private _isOpening;
|
|
8
|
-
private _destroyed;
|
|
15
|
+
readonly TYPE: "TCP_SERVER";
|
|
16
|
+
private _state;
|
|
9
17
|
private _connections;
|
|
10
|
-
private
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
private _server;
|
|
19
|
+
private _opts;
|
|
20
|
+
private _pendingOpenCbs;
|
|
21
|
+
private _pendingCloseCbs;
|
|
22
|
+
private _cleanupFns;
|
|
23
|
+
get state(): PhysicalState;
|
|
24
|
+
get server(): Server | null;
|
|
25
|
+
constructor(options?: TcpServerPhysicalLayerOptions);
|
|
26
|
+
open(options?: ListenOptions | ((err?: Error | null) => void), cb?: (err?: Error | null) => void): void;
|
|
27
|
+
close(cb?: (err?: Error | null) => void): void;
|
|
18
28
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Socket, SocketOptions } from 'node:dgram';
|
|
2
|
+
import { AbstractPhysicalConnection, AbstractPhysicalLayer } from './abstract-physical-layer';
|
|
3
|
+
import { PhysicalConnectionState, PhysicalState } from './vars';
|
|
4
|
+
export declare class UdpClientPhysicalConnection extends AbstractPhysicalConnection {
|
|
5
|
+
private _state;
|
|
6
|
+
private _physicalLayer;
|
|
7
|
+
private _socket;
|
|
8
|
+
private _pendingDestroyCbs;
|
|
9
|
+
private _cleanupFns;
|
|
10
|
+
get state(): PhysicalConnectionState;
|
|
11
|
+
get physicalLayer(): AbstractPhysicalLayer;
|
|
12
|
+
constructor(physicalLayer: UdpClientPhysicalLayer, socket: Socket);
|
|
13
|
+
write(data: Buffer, cb?: (err?: Error | null) => void): void;
|
|
14
|
+
destroy(cb?: (err?: Error | null) => void): void;
|
|
15
|
+
}
|
|
16
|
+
export declare class UdpClientPhysicalLayer extends AbstractPhysicalLayer {
|
|
17
|
+
readonly TYPE: "UDP_CLIENT";
|
|
18
|
+
private _state;
|
|
19
|
+
private _connections;
|
|
20
|
+
private _socket;
|
|
21
|
+
private _socketOpts;
|
|
22
|
+
private _pendingOpenCbs;
|
|
23
|
+
private _pendingCloseCbs;
|
|
24
|
+
private _cleanupFns;
|
|
25
|
+
get state(): PhysicalState;
|
|
26
|
+
get socket(): Socket | null;
|
|
27
|
+
constructor(options?: Partial<SocketOptions>);
|
|
28
|
+
open(remote?: {
|
|
29
|
+
port?: number;
|
|
30
|
+
address?: string;
|
|
31
|
+
} | ((err?: Error | null) => void), cb?: (err?: Error | null) => void): void;
|
|
32
|
+
close(cb?: (err?: Error | null) => void): void;
|
|
33
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { BindOptions, RemoteInfo, Socket, SocketOptions } from 'node:dgram';
|
|
2
|
+
import { AbstractPhysicalConnection, AbstractPhysicalLayer } from './abstract-physical-layer';
|
|
3
|
+
import { PhysicalConnectionState, PhysicalState } from './vars';
|
|
4
|
+
export interface UdpServerPhysicalLayerOptions {
|
|
5
|
+
/** Allowed client IP addresses. IPv4-mapped IPv6 addresses (e.g., ::ffff:192.168.1.1) are normalized before checking. */
|
|
6
|
+
whitelist?: string[];
|
|
7
|
+
/** Maximum number of concurrent virtual client connections. When exceeded, datagrams from new clients are silently ignored. */
|
|
8
|
+
maxConnections?: number;
|
|
9
|
+
/** Connection idle timeout in ms. Pass `0` to disable eviction. Defaults to 30000. */
|
|
10
|
+
idleTimeout?: number;
|
|
11
|
+
/** Forwarded to `dgram.createSocket()`. */
|
|
12
|
+
socketOpts?: Partial<SocketOptions>;
|
|
13
|
+
}
|
|
14
|
+
export declare class UdpServerPhysicalConnection extends AbstractPhysicalConnection {
|
|
15
|
+
private _state;
|
|
16
|
+
private _physicalLayer;
|
|
17
|
+
private _socket;
|
|
18
|
+
private _remote;
|
|
19
|
+
private _idleTid;
|
|
20
|
+
private _cleanupFns;
|
|
21
|
+
get state(): PhysicalConnectionState;
|
|
22
|
+
get physicalLayer(): AbstractPhysicalLayer;
|
|
23
|
+
constructor(physicalLayer: UdpServerPhysicalLayer, socket: Socket, remote: RemoteInfo, idleTimeout: number, messageEventDelegation: {
|
|
24
|
+
add: (listener: (msg: Buffer, rinfo: RemoteInfo) => void) => void;
|
|
25
|
+
remove: (listener: (...args: any[]) => void) => void;
|
|
26
|
+
});
|
|
27
|
+
write(data: Buffer, cb?: (err?: Error | null) => void): void;
|
|
28
|
+
destroy(cb?: (err?: Error | null) => void): void;
|
|
29
|
+
}
|
|
30
|
+
export declare class UdpServerPhysicalLayer extends AbstractPhysicalLayer {
|
|
31
|
+
readonly TYPE: "UDP_SERVER";
|
|
32
|
+
private _state;
|
|
33
|
+
private _connections;
|
|
34
|
+
private _socket;
|
|
35
|
+
private _opts;
|
|
36
|
+
private _pendingOpenCbs;
|
|
37
|
+
private _pendingCloseCbs;
|
|
38
|
+
private _cleanupFns;
|
|
39
|
+
get state(): PhysicalState;
|
|
40
|
+
get socket(): Socket | null;
|
|
41
|
+
constructor(options?: UdpServerPhysicalLayerOptions);
|
|
42
|
+
/**
|
|
43
|
+
* Bind the UDP socket and start accepting datagrams.
|
|
44
|
+
*
|
|
45
|
+
* @param options Bind options (port, address, etc.). Defaults to port 502.
|
|
46
|
+
* @param cb Callback invoked when binding completes or fails.
|
|
47
|
+
*/
|
|
48
|
+
open(options?: BindOptions | ((err?: Error | null) => void), cb?: (err?: Error | null) => void): void;
|
|
49
|
+
close(cb?: (err?: Error | null) => void): void;
|
|
50
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { AbstractPhysicalLayer } from './abstract-physical-layer';
|
|
2
|
+
import type { SocketOptions } from 'node:dgram';
|
|
3
|
+
import type { SocketConstructorOpts } from 'node:net';
|
|
4
|
+
import { SerialPhysicalLayer, type SerialPhysicalLayerOptions } from './serial-physical-layer';
|
|
5
|
+
import { TcpClientPhysicalLayer } from './tcp-client-physical-layer';
|
|
6
|
+
import { TcpServerPhysicalLayer, type TcpServerPhysicalLayerOptions } from './tcp-server-physical-layer';
|
|
7
|
+
import { UdpClientPhysicalLayer } from './udp-client-physical-layer';
|
|
8
|
+
import { UdpServerPhysicalLayer, type UdpServerPhysicalLayerOptions } from './udp-server-physical-layer';
|
|
9
|
+
export type PhysicalConfig = {
|
|
10
|
+
type: 'SERIAL';
|
|
11
|
+
opts: SerialPhysicalLayerOptions;
|
|
12
|
+
} | {
|
|
13
|
+
type: 'TCP_CLIENT';
|
|
14
|
+
socketOpts?: SocketConstructorOpts;
|
|
15
|
+
} | {
|
|
16
|
+
type: 'TCP_SERVER';
|
|
17
|
+
opts?: TcpServerPhysicalLayerOptions;
|
|
18
|
+
} | {
|
|
19
|
+
type: 'UDP_CLIENT';
|
|
20
|
+
socketOpts?: Partial<SocketOptions>;
|
|
21
|
+
} | {
|
|
22
|
+
type: 'UDP_SERVER';
|
|
23
|
+
opts?: UdpServerPhysicalLayerOptions;
|
|
24
|
+
} | {
|
|
25
|
+
type: 'CUSTOM';
|
|
26
|
+
layer: AbstractPhysicalLayer;
|
|
27
|
+
};
|
|
28
|
+
export type OpenArgs<T extends PhysicalConfig> = T extends {
|
|
29
|
+
type: 'SERIAL';
|
|
30
|
+
} ? Parameters<SerialPhysicalLayer['open']> : T extends {
|
|
31
|
+
type: 'TCP_CLIENT';
|
|
32
|
+
} ? Parameters<TcpClientPhysicalLayer['open']> : T extends {
|
|
33
|
+
type: 'TCP_SERVER';
|
|
34
|
+
} ? Parameters<TcpServerPhysicalLayer['open']> : T extends {
|
|
35
|
+
type: 'UDP_CLIENT';
|
|
36
|
+
} ? Parameters<UdpClientPhysicalLayer['open']> : T extends {
|
|
37
|
+
type: 'UDP_SERVER';
|
|
38
|
+
} ? Parameters<UdpServerPhysicalLayer['open']> : never;
|
|
39
|
+
export declare function createPhysicalLayer(config: PhysicalConfig): AbstractPhysicalLayer;
|
|
@@ -2,17 +2,17 @@ import type { ApplicationDataUnit } from '../types';
|
|
|
2
2
|
type Frame = ApplicationDataUnit & {
|
|
3
3
|
buffer: Buffer;
|
|
4
4
|
};
|
|
5
|
-
type PreCheck = (frame: Frame) => boolean | number | undefined;
|
|
6
5
|
type Callback = (error: Error | null, frame?: Frame) => void;
|
|
7
6
|
export declare const FIFO_KEY: "fifo";
|
|
8
7
|
export declare class MasterSession {
|
|
9
8
|
private _waiters;
|
|
10
|
-
|
|
9
|
+
/** Register a callback for `key`. No timer — timeout is managed by the caller. */
|
|
10
|
+
start(key: string | number, callback: Callback): void;
|
|
11
|
+
/** Cancel a pending waiter without firing its callback. */
|
|
11
12
|
stop(key: string | number): void;
|
|
12
13
|
stopAll(error: Error): void;
|
|
13
14
|
has(key: string | number): boolean;
|
|
14
15
|
handleFrame(frame: Frame): void;
|
|
15
16
|
handleError(error: Error): void;
|
|
16
|
-
private runPreChecks;
|
|
17
17
|
}
|
|
18
18
|
export {};
|