import { Logger } from 'pino'; import { ITransport, INodeTcpTransportOptions, EConnectionErrorType, TDeviceStateHandler, TPortStateHandler, TRSMode } from '../../types/public.js'; import { TrafficSniffer } from '../trackers/traffic-sniffer.js'; /** * NodeTcpTransport implements the ITransportTcp interface using Node.js native 'net' module. * It manages TCP/IP socket connections to Modbus devices or gateways, providing: * - Automatic reconnection logic. * - Mutex-protected write operations. * - Buffered reading with timeout support. * - Real-time tracking of connected/disconnected slave devices. */ export default class NodeTcpTransport implements ITransport { isOpen: boolean; logger: Logger; private host; private port; private options; private socket; private _sniffer; private _waitingForResponse; private _readBuffer; private _readBufferHead; private _readBufferTail; private _readBufferCount; private _reconnectAttempts; private _shouldReconnect; private _reconnectTimeout; private _isConnecting; private _isDisconnecting; private _operationMutex; private _connectedSlaveIds; private _deviceStateHandler; private _portStateHandler; private _wasEverConnected; /** * Creates an instance of NodeTcpTransport. * @param host - The IP address or hostname of the Modbus device/gateway. * @param port - The TCP port (defaults to 502). * @param options - Configuration for timeouts, buffer sizes, and reconnection. */ constructor(host: string, port?: number, options?: INodeTcpTransportOptions); /** * Attaches a TrafficSniffer instance to monitor and analyze raw TCP traffic. * This allows for sub-millisecond latency tracking and real-time MBAP/PDU inspection. * @param sniffer - The TrafficSniffer instance to use for monitoring. */ setSniffer(sniffer: TrafficSniffer): void; /** * Returns the transport protocol mode. * @returns Always returns 'TCP/IP'. */ getRSMode(): TRSMode; /** * Sets the callback for device (slave) state changes. * @param handler - Function to call when a device connects or disconnects. */ setDeviceStateHandler(handler: TDeviceStateHandler): void; /** * Sets the callback for port (socket) state changes. * @param handler - Function to call when the TCP connection state changes. */ setPortStateHandler(handler: TPortStateHandler): void; /** * Removes the device state handler and stops device tracking. */ disableDeviceTracking(): Promise; /** * Enables device tracking and optionally sets a new handler. * @param handler - Optional device state handler. */ enableDeviceTracking(handler?: TDeviceStateHandler): Promise; /** * Flags a specific Slave ID as connected and notifies the handler. * Typically called by the Client after a successful response. * @param slaveId - The Modbus unit identifier. */ notifyDeviceConnected(slaveId: number): void; /** * Flags a specific Slave ID as disconnected and notifies the handler. * @param slaveId - The Modbus unit identifier. * @param errorType - The reason for disconnection. * @param errorMessage - Detailed error description. */ notifyDeviceDisconnected(slaveId: number, errorType: EConnectionErrorType, errorMessage: string): void; /** * Establishes the TCP connection to the host and port. * Sets up event listeners for socket data, errors, and closure. * @returns A promise that resolves when the connection is established. */ connect(): Promise; /** * Internal handler for incoming socket data. * Implements filtering for non-Modbus text noise and manages the read buffer. * @param data - Raw buffer received from the socket. */ private _onData; /** * Internal handler for socket errors. * Triggers connection loss logic if the socket was previously open. * @param err - The Error object from the socket. */ private _onError; /** * Internal handler for the socket 'close' event. * Updates state, notifies handlers, and schedules reconnection if applicable. */ private _onClose; /** * Schedules a reconnection attempt based on the configured interval. */ private _scheduleReconnect; /** * Notifies the port state handler that a connection has been established. */ private _notifyPortConnected; /** * Notifies the port state handler about a disconnection. * @param errorType - The category of the connection error. * @param errorMessage - Descriptive text of the error. * @param slaveIds - List of slave IDs that are now unreachable. */ private _notifyPortDisconnected; /** * Logic for handling unexpected connection loss. * @param reason - Text description of why the connection was lost. */ private _handleConnectionLoss; /** * Writes a byte buffer to the TCP socket. * Operation is protected by a mutex to ensure sequential access. * @param buffer - Data to be sent. * @throws NodeSerialWriteError if the socket is closed or writing fails. */ write(buffer: Uint8Array): Promise; /** * Reads a specific number of bytes from the internal buffer. * Polls the buffer until the required length is met or the timeout expires. * @param length - Number of bytes to read. * @param timeout - Maximum time to wait for data (defaults to transport options). * @returns A promise resolving to the Uint8Array data. * @throws ModbusTimeoutError if data is not received within the specified time. */ read(length: number, timeout?: number): Promise; /** * Gracefully closes the TCP connection and stops reconnection attempts. */ disconnect(): Promise; /** * Clears the current read buffer. */ flush(): Promise; /** * Forcefully destroys the transport, closing sockets and clearing all timeouts. */ destroy(): void; }