njs-modbus 3.0.2 → 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/dist/index.d.ts CHANGED
@@ -113,6 +113,8 @@ declare enum ConformityLevel {
113
113
  REGULAR = 130,
114
114
  EXTENDED = 131
115
115
  }
116
+ /** Shared empty Buffer to avoid repeated allocations. */
117
+ declare const EMPTY_BUFFER: Buffer<ArrayBuffer>;
116
118
  /** Modbus V1.1b3 PDU quantity limits. */
117
119
  declare const LIMITS: {
118
120
  readonly READ_COILS_MIN: 1;
@@ -180,17 +182,16 @@ declare class SerialPhysicalLayer extends AbstractPhysicalLayer {
180
182
  private _serialportOpts;
181
183
  private _path;
182
184
  private _baudRate;
183
- private _openPromise;
184
- private _closePromise;
185
- private _resolveClose;
185
+ private _pendingOpenCbs;
186
+ private _pendingCloseCbs;
186
187
  private _cleanupFns;
187
188
  get state(): PhysicalState;
188
189
  get serialport(): SerialPort | null;
189
190
  get path(): string;
190
191
  get baudRate(): number;
191
192
  constructor(options: SerialPhysicalLayerOptions);
192
- open(): Promise<void>;
193
- close(): Promise<void>;
193
+ open(cb?: (err?: Error | null) => void): void;
194
+ close(cb?: (err?: Error | null) => void): void;
194
195
  }
195
196
 
196
197
  declare class TcpClientPhysicalLayer extends AbstractPhysicalLayer {
@@ -199,15 +200,14 @@ declare class TcpClientPhysicalLayer extends AbstractPhysicalLayer {
199
200
  private _connections;
200
201
  private _socket;
201
202
  private _socketOpts?;
202
- private _openPromise;
203
- private _closePromise;
204
- private _resolveClose;
203
+ private _pendingOpenCbs;
204
+ private _pendingCloseCbs;
205
205
  private _cleanupFns;
206
206
  get state(): PhysicalState;
207
207
  get socket(): Socket | null;
208
208
  constructor(options?: SocketConstructorOpts);
209
- open(options?: SocketConnectOpts): Promise<void>;
210
- close(): Promise<void>;
209
+ open(options?: SocketConnectOpts | ((err?: Error | null) => void), cb?: (err?: Error | null) => void): void;
210
+ close(cb?: (err?: Error | null) => void): void;
211
211
  }
212
212
 
213
213
  interface TcpServerPhysicalLayerOptions {
@@ -226,15 +226,14 @@ declare class TcpServerPhysicalLayer extends AbstractPhysicalLayer {
226
226
  private _connections;
227
227
  private _server;
228
228
  private _opts;
229
- private _openPromise;
230
- private _closePromise;
231
- private _resolveClose;
229
+ private _pendingOpenCbs;
230
+ private _pendingCloseCbs;
232
231
  private _cleanupFns;
233
232
  get state(): PhysicalState;
234
233
  get server(): Server | null;
235
234
  constructor(options?: TcpServerPhysicalLayerOptions);
236
- open(options?: ListenOptions): Promise<void>;
237
- close(): Promise<void>;
235
+ open(options?: ListenOptions | ((err?: Error | null) => void), cb?: (err?: Error | null) => void): void;
236
+ close(cb?: (err?: Error | null) => void): void;
238
237
  }
239
238
 
240
239
  declare class UdpClientPhysicalLayer extends AbstractPhysicalLayer {
@@ -243,9 +242,8 @@ declare class UdpClientPhysicalLayer extends AbstractPhysicalLayer {
243
242
  private _connections;
244
243
  private _socket;
245
244
  private _socketOpts;
246
- private _openPromise;
247
- private _closePromise;
248
- private _resolveClose;
245
+ private _pendingOpenCbs;
246
+ private _pendingCloseCbs;
249
247
  private _cleanupFns;
250
248
  get state(): PhysicalState;
251
249
  get socket(): Socket$1 | null;
@@ -253,8 +251,8 @@ declare class UdpClientPhysicalLayer extends AbstractPhysicalLayer {
253
251
  open(remote?: {
254
252
  port?: number;
255
253
  address?: string;
256
- }): Promise<void>;
257
- close(): Promise<void>;
254
+ } | ((err?: Error | null) => void), cb?: (err?: Error | null) => void): void;
255
+ close(cb?: (err?: Error | null) => void): void;
258
256
  }
259
257
 
260
258
  interface UdpServerPhysicalLayerOptions {
@@ -273,9 +271,8 @@ declare class UdpServerPhysicalLayer extends AbstractPhysicalLayer {
273
271
  private _connections;
274
272
  private _socket;
275
273
  private _opts;
276
- private _openPromise;
277
- private _closePromise;
278
- private _resolveClose;
274
+ private _pendingOpenCbs;
275
+ private _pendingCloseCbs;
279
276
  private _cleanupFns;
280
277
  get state(): PhysicalState;
281
278
  get socket(): Socket$1 | null;
@@ -284,13 +281,10 @@ declare class UdpServerPhysicalLayer extends AbstractPhysicalLayer {
284
281
  * Bind the UDP socket and start accepting datagrams.
285
282
  *
286
283
  * @param options Bind options (port, address, etc.). Defaults to port 502.
287
- * @param [idleTimeout=30000] Maximum idle time in milliseconds before an
288
- * inactive client connection is evicted. Pass `0` to disable eviction
289
- * (connections never time out). Disabling eviction may cause unbounded
290
- * memory growth if the server sees many unique clients.
284
+ * @param cb Callback invoked when binding completes or fails.
291
285
  */
292
- open(options?: BindOptions): Promise<void>;
293
- close(): Promise<void>;
286
+ open(options?: BindOptions | ((err?: Error | null) => void), cb?: (err?: Error | null) => void): void;
287
+ close(cb?: (err?: Error | null) => void): void;
294
288
  }
295
289
 
296
290
  interface AbstractPhysicalConnectionEvents {
@@ -306,8 +300,8 @@ interface AbstractPhysicalConnectionEvents {
306
300
  declare abstract class AbstractPhysicalConnection extends EventEmitter<AbstractPhysicalConnectionEvents> {
307
301
  abstract readonly state: PhysicalConnectionState;
308
302
  abstract readonly physicalLayer: AbstractPhysicalLayer;
309
- abstract write(data: Buffer): Promise<void>;
310
- abstract destroy(): Promise<void>;
303
+ abstract write(data: Buffer, cb?: (err?: Error | null) => void): void;
304
+ abstract destroy(cb?: (err?: Error | null) => void): void;
311
305
  }
312
306
  interface AbstractPhysicalLayerEvents {
313
307
  open: [];
@@ -331,8 +325,9 @@ declare abstract class AbstractPhysicalLayer extends EventEmitter<AbstractPhysic
331
325
  is(type: 'UDP_CLIENT'): this is UdpClientPhysicalLayer;
332
326
  is(type: 'UDP_SERVER'): this is UdpServerPhysicalLayer;
333
327
  abstract readonly state: PhysicalState;
334
- abstract open(...args: any[]): Promise<void>;
335
- abstract close(): Promise<void>;
328
+ /** Last argument is the callback: `(err?: Error | null) => void`. Callback is optional. */
329
+ abstract open(...args: any[]): void;
330
+ abstract close(cb?: (err?: Error | null) => void): void;
336
331
  }
337
332
 
338
333
  type PhysicalConfig = {
@@ -387,7 +382,7 @@ declare abstract class AbstractApplicationLayer extends EventEmitter<AbstractApp
387
382
  flush(): void;
388
383
  addCustomFunctionCode(cfc: CustomFunctionCode): void;
389
384
  removeCustomFunctionCode(fc: number): void;
390
- abstract encode(data: ApplicationDataUnit): Buffer;
385
+ abstract encode(unit: number, fc: number, data: Buffer, transaction?: number): Buffer;
391
386
  }
392
387
 
393
388
  interface AsciiApplicationLayerOptions {
@@ -409,7 +404,7 @@ declare class AsciiApplicationLayer extends AbstractApplicationLayer {
409
404
  constructor(role: 'MASTER' | 'SLAVE', connection: AbstractPhysicalConnection, options?: AsciiApplicationLayerOptions);
410
405
  private framing;
411
406
  flush(): void;
412
- encode(data: ApplicationDataUnit): Buffer;
407
+ encode(unit: number, fc: number, data: Buffer, transaction?: number): Buffer;
413
408
  }
414
409
 
415
410
  interface RtuApplicationLayerOptions {
@@ -438,14 +433,10 @@ declare class RtuApplicationLayer extends AbstractApplicationLayer {
438
433
  constructor(role: 'MASTER' | 'SLAVE', connection: AbstractPhysicalConnection, options?: RtuApplicationLayerOptions);
439
434
  private clearStateTimers;
440
435
  private flushBuffer;
441
- private deliverFrame;
442
- private tryExtract;
443
- private checkExpected;
444
- private crcMatches;
445
436
  flush(): void;
446
437
  addCustomFunctionCode(cfc: CustomFunctionCode): void;
447
438
  removeCustomFunctionCode(fc: number): void;
448
- encode(data: ApplicationDataUnit): Buffer;
439
+ encode(unit: number, fc: number, data: Buffer, transaction?: number): Buffer;
449
440
  }
450
441
 
451
442
  declare class TcpApplicationLayer extends AbstractApplicationLayer {
@@ -460,35 +451,49 @@ declare class TcpApplicationLayer extends AbstractApplicationLayer {
460
451
  private tryExtract;
461
452
  private processFrame;
462
453
  flush(): void;
463
- encode(data: ApplicationDataUnit): Buffer;
454
+ encode(unit: number, fc: number, data: Buffer, transaction?: number): Buffer;
464
455
  }
465
456
 
457
+ /**
458
+ * RTU timing parameter — accepts either:
459
+ * - a bare `number` in milliseconds (`0` to disable the timer entirely)
460
+ * - `{ unit: 'ms', value: N }` — explicit milliseconds (equivalent to bare `N`)
461
+ * - `{ unit: 'bit', value: N }` — bit-time approximation, derived from `baudRate`
462
+ *
463
+ * The bare-number form is the recommended default; the object form exists for
464
+ * specs that quote bit-time. Pass `0` (or `{ unit: 'ms', value: 0 }`) to disable
465
+ * the timer; either form short-circuits the baudRate-derived fallback.
466
+ */
467
+ type RtuTimingValue = number | {
468
+ unit: 'bit' | 'ms';
469
+ value: number;
470
+ };
466
471
  /** User-facing RTU protocol options (supports both bit and ms units). */
467
472
  interface RtuProtocolOptions {
468
473
  /**
469
474
  * Inter-frame silence (Modbus RTU t3.5).
475
+ *
476
+ * - `20` or `{ unit: 'ms', value: 20 }` — 20 ms
470
477
  * - `{ unit: 'bit', value: 38.5 }` — spec bit-time approximation (default when `baudRate` is provided)
471
- * - `{ unit: 'ms', value: 20 }` explicit milliseconds
478
+ * - `0` disable t3.5 timing (immediate parse on every chunk; useful for
479
+ * lossless transports such as RTU-over-TCP or PTY-based tests where the
480
+ * wire's silence semantics do not apply)
472
481
  *
473
482
  * Per Modbus V1.02 §2.5.1.1, at baud rates > 19200 a fixed 1.75 ms is used
474
483
  * regardless of the bit value.
475
484
  */
476
- intervalBetweenFrames?: {
477
- unit: 'bit' | 'ms';
478
- value: number;
479
- };
485
+ intervalBetweenFrames?: RtuTimingValue;
480
486
  /**
481
487
  * Inter-character timeout (Modbus RTU t1.5). Opt-in; **disabled** by default.
488
+ *
489
+ * - `1` or `{ unit: 'ms', value: 1 }` — 1 ms
482
490
  * - `{ unit: 'bit', value: 21 }` — bit-time approximation (~1.5 char times)
483
- * - `{ unit: 'ms', value: 1 }` — explicit milliseconds
491
+ * - `0` — disable explicitly
484
492
  *
485
493
  * Per Modbus V1.02 §2.5.1.1, at baud rates > 19200 a fixed 0.75 ms is used
486
494
  * regardless of the bit value.
487
495
  */
488
- interCharTimeout?: {
489
- unit: 'bit' | 'ms';
490
- value: number;
491
- };
496
+ interCharTimeout?: RtuTimingValue;
492
497
  /**
493
498
  * Buffer pool size per connection (bytes). Defaults to `MAX_FRAME_LENGTH * 2`
494
499
  * (512 bytes). Increase this if you expect frames larger than 256 bytes or
@@ -532,7 +537,15 @@ declare class ModbusMaster<T extends ModbusMasterOptions = ModbusMasterOptions>
532
537
  private _protocol;
533
538
  private _appLayer?;
534
539
  private _customFunctionCodes;
535
- private _queue;
540
+ private _queueUnits;
541
+ private _queueFcs;
542
+ private _queueDatas;
543
+ private _queueTimeouts;
544
+ private _queueBroadcasts;
545
+ private _queueResolves;
546
+ private _queueRejects;
547
+ private _queueHead;
548
+ private _queueLen;
536
549
  private _draining;
537
550
  private _nextTid;
538
551
  private _cleanupFns;
@@ -543,6 +556,7 @@ declare class ModbusMaster<T extends ModbusMasterOptions = ModbusMasterOptions>
543
556
  private _createAppLayer;
544
557
  private send;
545
558
  private _drain;
559
+ private _processNext;
546
560
  private _exchange;
547
561
  private writeFC1Or2;
548
562
  writeFC1: this['readCoils'];
@@ -601,7 +615,6 @@ declare class ModbusMaster<T extends ModbusMasterOptions = ModbusMasterOptions>
601
615
  removeCustomFunctionCode(fc: number): void;
602
616
  sendCustomFC(unit: 0, fc: number, data: Buffer | number[], timeout?: number): Promise<void>;
603
617
  sendCustomFC(unit: number, fc: number, data: Buffer | number[], timeout?: number): Promise<Buffer>;
604
- private _clean;
605
618
  /**
606
619
  * Open the underlying physical layer and begin accepting connections.
607
620
  *
@@ -626,17 +639,17 @@ declare class ModbusMaster<T extends ModbusMasterOptions = ModbusMasterOptions>
626
639
  type Frame = ApplicationDataUnit & {
627
640
  buffer: Buffer;
628
641
  };
629
- type PreCheck = (frame: Frame) => boolean | number | undefined;
630
642
  type Callback = (error: Error | null, frame?: Frame) => void;
631
643
  declare class MasterSession {
632
644
  private _waiters;
633
- start(key: string | number, preCheck: PreCheck[], callback: Callback): void;
645
+ /** Register a callback for `key`. No timer timeout is managed by the caller. */
646
+ start(key: string | number, callback: Callback): void;
647
+ /** Cancel a pending waiter without firing its callback. */
634
648
  stop(key: string | number): void;
635
649
  stopAll(error: Error): void;
636
650
  has(key: string | number): boolean;
637
651
  handleFrame(frame: Frame): void;
638
652
  handleError(error: Error): void;
639
- private runPreChecks;
640
653
  }
641
654
 
642
655
  interface ModbusSlaveModel {
@@ -727,6 +740,7 @@ declare class ModbusSlave<T extends ModbusSlaveOptions = ModbusSlaveOptions> ext
727
740
  private _intercept;
728
741
  private _withAddressLock;
729
742
  private _handleFC;
743
+ private _handleCustomFC;
730
744
  add(model: ModbusSlaveModel): void;
731
745
  remove(unit: number): void;
732
746
  addCustomFunctionCode(cfc: CustomFunctionCode): void;
@@ -752,5 +766,5 @@ declare class ModbusSlave<T extends ModbusSlaveOptions = ModbusSlaveOptions> ext
752
766
  close(): Promise<void>;
753
767
  }
754
768
 
755
- export { AbstractApplicationLayer, AbstractPhysicalConnection, AbstractPhysicalLayer, AsciiApplicationLayer, COIL_OFF, COIL_ON, ConformityLevel, 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 };
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 };
756
770
  export type { AbstractPhysicalLayerEvents, ApplicationDataUnit, AsciiApplicationLayerOptions, Callback$1 as Callback, CustomFunctionCode, DeviceIdentification, MaybeAsyncFunction, ModbusMasterOptions, ModbusSlaveModel, ModbusSlaveOptions, OpenArgs, PhysicalConfig, RtuApplicationLayerOptions, ServerId, TcpServerPhysicalLayerOptions, UdpServerPhysicalLayerOptions };