use mabi_core::Error as CoreError;
use thiserror::Error;
pub type ModbusResult<T> = Result<T, ModbusError>;
#[derive(Debug, Error)]
pub enum ModbusError {
#[error("Invalid function code: {0}")]
InvalidFunction(u8),
#[error("Invalid address: {address} (range: 0-{max})")]
InvalidAddress { address: u16, max: u16 },
#[error("Invalid quantity: {quantity} (range: 1-{max})")]
InvalidQuantity { quantity: u16, max: u16 },
#[error("Invalid data: {0}")]
InvalidData(String),
#[error("Device not found: unit {unit_id}")]
DeviceNotFound { unit_id: u8 },
#[error("Server error: {0}")]
Server(String),
#[error("Connection error: {0}")]
Connection(String),
#[error("I/O error: {0}")]
Io(#[from] std::io::Error),
#[error("Core error: {0}")]
Core(#[from] CoreError),
#[error("Internal error: {0}")]
Internal(String),
#[error("Invalid unit ID {unit_id}: {reason}")]
InvalidUnitId { unit_id: u8, reason: String },
#[error("Unit not found: {unit_id}")]
UnitNotFound { unit_id: u8 },
#[error("Unit already exists: {unit_id}")]
UnitAlreadyExists { unit_id: u8 },
#[error("Unit limit reached: maximum {max} units allowed")]
UnitLimitReached { max: usize },
#[error("Unit {unit_id} is disabled")]
UnitDisabled { unit_id: u8 },
#[error("Configuration error: {0}")]
Config(String),
}
impl ModbusError {
pub fn to_exception_code(&self) -> u8 {
match self {
Self::InvalidFunction(_) => 0x01, Self::InvalidAddress { .. } => 0x02, Self::InvalidQuantity { .. } => 0x03, Self::InvalidData(_) => 0x03, Self::DeviceNotFound { .. } => 0x0B, Self::Server(_) => 0x04, Self::Connection(_) => 0x0A, Self::Io(_) => 0x04, Self::Core(_) => 0x04, Self::Internal(_) => 0x04, Self::InvalidUnitId { .. } => 0x0B, Self::UnitNotFound { .. } => 0x0B, Self::UnitAlreadyExists { .. } => 0x04, Self::UnitLimitReached { .. } => 0x04, Self::UnitDisabled { .. } => 0x0B, Self::Config(_) => 0x04, }
}
pub fn invalid_address(address: u16, max: u16) -> Self {
Self::InvalidAddress { address, max }
}
pub fn invalid_quantity(quantity: u16, max: u16) -> Self {
Self::InvalidQuantity { quantity, max }
}
}
impl From<ModbusError> for CoreError {
fn from(err: ModbusError) -> Self {
CoreError::Protocol(err.to_string())
}
}