import { Logger } from 'pino'; import { EConnectionErrorType, ITransport, IWebSerialPort, IWebSerialTransportOptions, TDeviceStateHandler, TPortStateHandler, TRSMode } from '../../types/public.js'; import { TrafficSniffer } from '../trackers/traffic-sniffer.js'; /** * WebSerialTransport provides an implementation of the Modbus transport layer * using the Web Serial API, suitable for browser-based serial communication. */ export default class WebSerialTransport implements ITransport { isOpen: boolean; logger: Logger; private portFactory; private port; private options; private reader; private writer; private _sniffer; private _waitingForResponse; private _readBuffer; private _readBufferHead; private _readBufferTail; private _readBufferCount; private _connectedSlaveIds; private _isPortReady; private _reconnectAttempts; private _shouldReconnect; private _isConnecting; private _isDisconnecting; private _isFlushing; private _pendingFlushPromises; private _reconnectTimer; private _emptyReadCount; private _readLoopActive; private _readLoopAbortController; private _operationMutex; private _connectionPromise; private _resolveConnection; private _rejectConnection; private _portClosePromise; private _portCloseResolve; private _deviceStateHandler; private _portStateHandler; private _wasEverConnected; /** * Creates an instance of WebSerialTransport. * @param portFactory A function that returns a Promise for an IWebSerialPort instance. * @param options Configuration options for the serial port and transport behavior. */ constructor(portFactory: () => Promise, options?: IWebSerialTransportOptions); /** * Attaches a TrafficSniffer instance to monitor and analyze raw Web Serial traffic. * This allows for sub-millisecond latency tracking and real-time protocol inspection. * @param sniffer - The TrafficSniffer instance to use for monitoring. */ setSniffer(sniffer: TrafficSniffer): void; /** * Gets the current RS Mode (e.g., RS485 or RS232). * @returns The TRSMode value. */ getRSMode(): TRSMode; /** * Sets the callback handler for tracking device connection states. * @param handler A function to be called when a device connection status changes. */ setDeviceStateHandler(handler: TDeviceStateHandler): void; /** * Sets the callback handler for the serial port status changes. * @param handler A function to be called when the port is connected or disconnected. */ setPortStateHandler(handler: TPortStateHandler): void; /** * Disables tracking of connected Modbus slave devices. */ disableDeviceTracking(): Promise; /** * Enables tracking of connected Modbus slave devices. * @param handler Optional new handler for device state updates. */ enableDeviceTracking(handler?: TDeviceStateHandler): Promise; /** * Notifies the transport that a specific slave device is connected. * @param slaveId The ID of the Modbus slave device. */ notifyDeviceConnected(slaveId: number): void; /** * Notifies the transport that a specific slave device has disconnected. * @param slaveId The ID of the Modbus slave device. * @param errorType The category of the connection error. * @param errorMessage A descriptive error message. */ notifyDeviceDisconnected(slaveId: number, errorType: EConnectionErrorType, errorMessage: string): void; /** * Manually removes a device from the internal connected devices set. * @param slaveId The ID of the Modbus slave device to remove. */ removeConnectedDevice(slaveId: number): void; /** * Internal check to determine if the port is open and ready for I/O operations. * @returns True if the port is open and the writer is initialized. */ private isPortReady; /** * Internal helper to trigger the port connection notification handler. */ private _notifyPortConnected; /** * Internal helper to trigger the port disconnection notification handler. * @param errorType The reason for disconnection. * @param errorMessage Details regarding the disconnection. */ private _notifyPortDisconnected; /** * Handles the low-level physical closure of the serial port. */ private _handlerPortClose; /** * Monitors the closure promise to trigger cleanup when the port closes. */ private _watchForPortClose; /** * Releases all resources associated with the transport, such as readers, writers, and buffers. * @param hardClose If true, attempts to close the underlying physical port as well. */ private _releaseAllResources; /** * Establishes a connection to the serial port. * Performs port configuration and initializes reading/writing streams. */ connect(): Promise; /** * Starts the continuous reading loop from the serial port. * Appends incoming data to the internal read buffer. */ private _startReading; /** * Writes a buffer of data to the serial port. * @param buffer The Uint8Array to be sent. */ write(buffer: Uint8Array): Promise; /** * Reads a specified number of bytes from the internal buffer. * Waits for data to arrive if the buffer is currently insufficient. * @param length Number of bytes to read. * @param timeout Maximum time to wait for the data in milliseconds. * @returns A Promise that resolves to the requested Uint8Array. */ read(length: number, timeout?: number): Promise; /** * Disconnects the transport and stops all ongoing operations and reconnection attempts. */ disconnect(): Promise; /** * Clears the current read buffer and resets the empty read counter. */ flush(): Promise; /** * Maps generic serial errors to specific Modbus error types and logs them. * @param err The Error object caught during communication. */ private _onError; /** * Internal bridge to trigger connection loss handling upon a specific error. * @param err The error that occurred. */ private _handleError; /** * Manages state changes when the connection is lost and decides whether to trigger reconnection. * @param reason A string describing why the connection was lost. */ private _handleConnectionLoss; /** * Schedules a reconnection attempt after a failure. * @param err The error that triggered the reconnection requirement. */ private _scheduleReconnect; /** * Internal logic to perform a reconnection attempt by re-opening the port. */ private _attemptReconnect; /** * Destroys the transport instance, cleaning up all resources and preventing future connections. */ destroy(): void; }