modbus-connect
Version:
Modbus RTU over Web Serial and Node.js SerialPort
655 lines (577 loc) • 16.6 kB
text/typescript
// src/errors.ts
import { ModbusExceptionCode, MODBUS_EXCEPTION_MESSAGES } from './constants/constants.js';
/**
* Base class for all Modbus errors
*/
export class ModbusError extends Error {
constructor(message: string) {
super(message);
this.name = 'ModbusError';
}
}
/**
* Error class for Modbus timeout
*/
export class ModbusTimeoutError extends ModbusError {
constructor(message: string = 'Modbus request timed out') {
super(message);
this.name = 'ModbusTimeoutError';
}
}
/**
* Error class for Modbus CRC check failure
*/
export class ModbusCRCError extends ModbusError {
constructor(message: string = 'Modbus CRC check failed') {
super(message);
this.name = 'ModbusCRCError';
}
}
/**
* Error class for Modbus response errors
*/
export class ModbusResponseError extends ModbusError {
constructor(message: string = 'Invalid Modbus response') {
super(message);
this.name = 'ModbusResponseError';
}
}
/**
* Error class for Modbus too many empty reads
*/
export class ModbusTooManyEmptyReadsError extends ModbusError {
constructor(message: string = 'Too many empty reads from transport') {
super(message);
this.name = 'ModbusTooManyEmptyReadsError';
}
}
/**
* Error class for Modbus exception
*/
export class ModbusExceptionError extends ModbusError {
functionCode: number;
exceptionCode: number;
constructor(functionCode: number, exceptionCode: number) {
const exceptionMessage =
MODBUS_EXCEPTION_MESSAGES[exceptionCode as ModbusExceptionCode] ||
`Unknown exception code: ${exceptionCode}`;
super(
`Modbus exception: function 0x${functionCode.toString(16)}, code 0x${exceptionCode.toString(16)} (${exceptionMessage})`
);
this.name = 'ModbusExceptionError';
this.functionCode = functionCode;
this.exceptionCode = exceptionCode;
}
}
/**
* Error class for Modbus flush error
*/
export class ModbusFlushError extends ModbusError {
constructor(message: string = 'Modbus operation interrupted by transport flush') {
super(message);
this.name = 'ModbusFlushError';
}
}
// --- Errors for Data Validation ---
/**
* Error class for invalid Modbus address
*/
export class ModbusInvalidAddressError extends ModbusError {
constructor(address: number) {
super(`Invalid Modbus address: ${address}. Address must be between 1-255 for RTU/TCP.`);
this.name = 'ModbusInvalidAddressError';
}
}
/**
* Error class for invalid function code
*/
export class ModbusInvalidFunctionCodeError extends ModbusError {
constructor(functionCode: number) {
super(`Invalid Modbus function code: 0x${functionCode.toString(16)}`);
this.name = 'ModbusInvalidFunctionCodeError';
}
}
/**
* Error class for invalid quantity (register/coil count)
*/
export class ModbusInvalidQuantityError extends ModbusError {
constructor(quantity: number, min: number, max: number) {
super(`Invalid quantity: ${quantity}. Must be between ${min}-${max}.`);
this.name = 'ModbusInvalidQuantityError';
}
}
/**
* Error class for illegal data address exception
*/
export class ModbusIllegalDataAddressError extends ModbusError {
constructor(address: number, quantity: number) {
super(`Illegal data address: start=${address}, quantity=${quantity}`);
this.name = 'ModbusIllegalDataAddressError';
}
}
/**
* Error class for illegal data value exception
*/
export class ModbusIllegalDataValueError extends ModbusError {
constructor(value: number | string, expected: string) {
super(`Illegal data value: ${value}, expected ${expected}`);
this.name = 'ModbusIllegalDataValueError';
}
}
/**
* Error class for slave device busy exception
*/
export class ModbusSlaveBusyError extends ModbusError {
constructor() {
super('Slave device is busy');
this.name = 'ModbusSlaveBusyError';
}
}
/**
* Error class for acknowledge exception
*/
export class ModbusAcknowledgeError extends ModbusError {
constructor() {
super('Acknowledge received - device needs continued polling');
this.name = 'ModbusAcknowledgeError';
}
}
/**
* Error class for slave device failure exception
*/
export class ModbusSlaveDeviceFailureError extends ModbusError {
constructor() {
super('Slave device failure');
this.name = 'ModbusSlaveDeviceFailureError';
}
}
// --- Errors for Message Format ---
/**
* Error class for malformed Modbus frame
*/
export class ModbusMalformedFrameError extends ModbusResponseError {
constructor(rawData: Buffer | Uint8Array) {
super(`Malformed Modbus frame received: ${Buffer.from(rawData).toString('hex')}`);
this.name = 'ModbusMalformedFrameError';
}
}
/**
* Error class for invalid frame length
*/
export class ModbusInvalidFrameLengthError extends ModbusResponseError {
constructor(received: number, expected: number) {
super(`Invalid frame length: received ${received}, expected ${expected}`);
this.name = 'ModbusInvalidFrameLengthError';
}
}
/**
* Error class for invalid Modbus transaction ID
*/
export class ModbusInvalidTransactionIdError extends ModbusResponseError {
constructor(received: number, expected: number) {
super(`Invalid transaction ID: received ${received}, expected ${expected}`);
this.name = 'ModbusInvalidTransactionIdError';
}
}
/**
* Error class for unexpected function code in response
*/
export class ModbusUnexpectedFunctionCodeError extends ModbusResponseError {
constructor(sent: number, received: number) {
super(
`Unexpected function code: sent 0x${sent.toString(16)}, received 0x${received.toString(16)}`
);
this.name = 'ModbusUnexpectedFunctionCodeError';
}
}
// --- Errors for Connection and Transport ---
/**
* Error class for connection refused
*/
export class ModbusConnectionRefusedError extends ModbusError {
constructor(host: string, port: number) {
super(`Connection refused to ${host}:${port}`);
this.name = 'ModbusConnectionRefusedError';
}
}
/**
* Error class for connection timeout
*/
export class ModbusConnectionTimeoutError extends ModbusError {
constructor(host: string, port: number, timeout: number) {
super(`Connection timeout to ${host}:${port} after ${timeout}ms`);
this.name = 'ModbusConnectionTimeoutError';
}
}
/**
* Error class for not connected
*/
export class ModbusNotConnectedError extends ModbusError {
constructor() {
super('Not connected to Modbus device');
this.name = 'ModbusNotConnectedError';
}
}
/**
* Error class for already connected
*/
export class ModbusAlreadyConnectedError extends ModbusError {
constructor() {
super('Already connected to Modbus device');
this.name = 'ModbusAlreadyConnectedError';
}
}
// --- Errors for Buffer and Data ---
/**
* Error class for buffer overflow
*/
export class ModbusBufferOverflowError extends ModbusError {
constructor(size: number, max: number) {
super(`Buffer overflow: ${size} bytes exceeds maximum ${max} bytes`);
this.name = 'ModbusBufferOverflowError';
}
}
/**
* Error class for insufficient data
*/
export class ModbusInsufficientDataError extends ModbusResponseError {
constructor(received: number, required: number) {
super(`Insufficient data: received ${received} bytes, required ${required} bytes`);
this.name = 'ModbusInsufficientDataError';
}
}
/**
* Error class for data type conversion errors
*/
export class ModbusDataConversionError extends ModbusError {
constructor(data: unknown, expectedType: string) {
super(`Cannot convert data "${data}" to ${expectedType}`);
this.name = 'ModbusDataConversionError';
}
}
// --- Errors for Security and Access ---
/**
* Error class for gateway path unavailable
*/
export class ModbusGatewayPathUnavailableError extends ModbusError {
constructor() {
super('Gateway path unavailable');
this.name = 'ModbusGatewayPathUnavailableError';
}
}
/**
* Error class for gateway target device failed to respond
*/
export class ModbusGatewayTargetDeviceError extends ModbusError {
constructor() {
super('Gateway target device failed to respond');
this.name = 'ModbusGatewayTargetDeviceError';
}
}
// --- Errors for Specific Functions ---
/**
* Error class for invalid starting address in read operations
*/
export class ModbusInvalidStartingAddressError extends ModbusError {
constructor(address: number) {
super(`Invalid starting address: ${address}`);
this.name = 'ModbusInvalidStartingAddressError';
}
}
/**
* Error class for memory parity error (function code 8)
*/
export class ModbusMemoryParityError extends ModbusError {
constructor() {
super('Memory parity error');
this.name = 'ModbusMemoryParityError';
}
}
// --- Additional Integrity and Checksum Errors ---
/**
* Error class for Modbus LRC (Longitudinal Redundancy Check) failure
*/
export class ModbusLRCError extends ModbusError {
constructor(message: string = 'Modbus LRC check failed') {
super(message);
this.name = 'ModbusLRCError';
}
}
/**
* Error class for Modbus checksum validation failure
*/
export class ModbusChecksumError extends ModbusError {
constructor(message: string = 'Modbus checksum validation failed') {
super(message);
this.name = 'ModbusChecksumError';
}
}
/**
* Error class for Modbus parity bit error
*/
export class ModbusParityError extends ModbusError {
constructor(message: string = 'Modbus parity check failed') {
super(message);
this.name = 'ModbusParityError';
}
}
/**
* Error class for Modbus frame synchronization error
*/
export class ModbusSyncError extends ModbusError {
constructor(message: string = 'Modbus frame synchronization error') {
super(message);
this.name = 'ModbusSyncError';
}
}
/**
* Error class for Modbus frame boundary detection error
*/
export class ModbusFrameBoundaryError extends ModbusError {
constructor(message: string = 'Modbus frame boundary detection error') {
super(message);
this.name = 'ModbusFrameBoundaryError';
}
}
// --- Additional Transport and Communication Errors ---
/**
* Error class for Modbus buffer underrun
*/
export class ModbusBufferUnderrunError extends ModbusError {
constructor(size: number, required: number) {
super(`Buffer underrun: ${size} bytes available, ${required} bytes needed`);
this.name = 'ModbusBufferUnderrunError';
}
}
/**
* Error class for Modbus communication collision
*/
export class ModbusCollisionError extends ModbusError {
constructor(message: string = 'Modbus communication collision detected') {
super(message);
this.name = 'ModbusCollisionError';
}
}
/**
* Error class for Modbus noise error
*/
export class ModbusNoiseError extends ModbusError {
constructor(message: string = 'Modbus communication affected by noise') {
super(message);
this.name = 'ModbusNoiseError';
}
}
/**
* Error class for Modbus overrun error
*/
export class ModbusOverrunError extends ModbusError {
constructor(message: string = 'Modbus receiver overrun error') {
super(message);
this.name = 'ModbusOverrunError';
}
}
/**
* Error class for Modbus framing error
*/
export class ModbusFramingError extends ModbusError {
constructor(message: string = 'Modbus framing error') {
super(message);
this.name = 'ModbusFramingError';
}
}
// --- Additional Timing and Synchronization Errors ---
/**
* Error class for Modbus inter-frame timeout
*/
export class ModbusInterFrameTimeoutError extends ModbusError {
constructor(message: string = 'Modbus inter-frame timeout') {
super(message);
this.name = 'ModbusInterFrameTimeoutError';
}
}
/**
* Error class for Modbus silent interval violation
*/
export class ModbusSilentIntervalError extends ModbusError {
constructor(message: string = 'Modbus silent interval violation') {
super(message);
this.name = 'ModbusSilentIntervalError';
}
}
/**
* Error class for Modbus baud rate configuration error
*/
export class ModbusBaudRateError extends ModbusError {
constructor(expected: number, actual: number) {
super(`Baud rate mismatch: expected ${expected}, actual ${actual}`);
this.name = 'ModbusBaudRateError';
}
}
// --- Additional Protocol-Specific Errors ---
/**
* Error class for Modbus broadcast operation error
*/
export class ModbusBroadcastError extends ModbusError {
constructor(message: string = 'Modbus broadcast operation failed') {
super(message);
this.name = 'ModbusBroadcastError';
}
}
/**
* Error class for Modbus gateway busy error
*/
export class ModbusGatewayBusyError extends ModbusError {
constructor() {
super('Modbus gateway is busy');
this.name = 'ModbusGatewayBusyError';
}
}
/**
* Error class for Modbus data overrun error
*/
export class ModbusDataOverrunError extends ModbusError {
constructor() {
super('Modbus data overrun error');
this.name = 'ModbusDataOverrunError';
}
}
/**
* Error class for Modbus configuration error
*/
export class ModbusConfigError extends ModbusError {
constructor(message: string = 'Modbus configuration error') {
super(message);
this.name = 'ModbusConfigError';
}
}
// --- Additional Memory and Buffer Errors ---
/**
* Error class for Modbus memory error
*/
export class ModbusMemoryError extends ModbusError {
constructor(message: string = 'Modbus memory access error') {
super(message);
this.name = 'ModbusMemoryError';
}
}
/**
* Error class for Modbus stack overflow error
*/
export class ModbusStackOverflowError extends ModbusError {
constructor(message: string = 'Modbus stack overflow error') {
super(message);
this.name = 'ModbusStackOverflowError';
}
}
// --- Errors for Transports ---
/**
* Base class for all Transport errors
*/
export class TransportError extends ModbusError {
constructor(message: string) {
super(message);
this.name = 'TransportError';
}
}
/**
* Error class for Web Serial transport errors
*/
export class WebSerialTransportError extends TransportError {
constructor(message: string) {
super(message);
this.name = 'WebSerialTransportError';
}
}
/**
* Error class for Web Serial connection errors
*/
export class WebSerialConnectionError extends WebSerialTransportError {
constructor(message: string) {
super(message);
this.name = 'WebSerialConnectionError';
}
}
/**
* Error class for Web Serial read errors
*/
export class WebSerialReadError extends WebSerialTransportError {
constructor(message: string) {
super(message);
this.name = 'WebSerialReadError';
}
}
/**
* Error class for Web Serial write errors
*/
export class WebSerialWriteError extends WebSerialTransportError {
constructor(message: string) {
super(message);
this.name = 'WebSerialWriteError';
}
}
/**
* Error class for Node Serial transport errors
*/
export class NodeSerialTransportError extends TransportError {
constructor(message: string) {
super(message);
this.name = 'NodeSerialTransportError';
}
}
/**
* Error class for Node Serial connection errors
*/
export class NodeSerialConnectionError extends NodeSerialTransportError {
constructor(message: string) {
super(message);
this.name = 'NodeSerialConnectionError';
}
}
/**
* Error class for Node Serial read errors
*/
export class NodeSerialReadError extends NodeSerialTransportError {
constructor(message: string) {
super(message);
this.name = 'NodeSerialReadError';
}
}
/**
* Error class for Node Serial write errors
*/
export class NodeSerialWriteError extends NodeSerialTransportError {
constructor(message: string) {
super(message);
this.name = 'NodeSerialWriteError';
}
}
export class PollingManagerError extends ModbusError {
constructor(message: string) {
super(message);
this.name = 'PollingManagerError';
}
}
export class PollingTaskAlreadyExistsError extends PollingManagerError {
constructor(id: string) {
super(`Polling task with id "${id}" already exists.`);
this.name = 'PollingTaskAlreadyExistsError';
}
}
export class PollingTaskNotFoundError extends PollingManagerError {
constructor(id: string) {
super(`Polling task with id "${id}" does not exist.`);
this.name = 'PollingTaskNotFoundError';
}
}
export class PollingTaskValidationError extends PollingManagerError {
constructor(message: string) {
super(message);
this.name = 'PollingTaskValidationError';
}
}
export class RSModeConstraintError extends ModbusError {
constructor(message: string) {
super(message);
this.name = 'RSModeConstraintError';
}
}