use core::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum FunctionCode {
ReadCoils,
ReadDiscreteInputs,
ReadHoldingRegisters,
ReadInputRegisters,
WriteSingleCoil,
WriteSingleRegister,
WriteMultipleCoils,
WriteMultipleRegisters,
Other(u8),
}
impl From<u8> for FunctionCode {
fn from(v: u8) -> Self {
match v {
0x01 => Self::ReadCoils,
0x02 => Self::ReadDiscreteInputs,
0x03 => Self::ReadHoldingRegisters,
0x04 => Self::ReadInputRegisters,
0x05 => Self::WriteSingleCoil,
0x06 => Self::WriteSingleRegister,
0x0F => Self::WriteMultipleCoils,
0x10 => Self::WriteMultipleRegisters,
other => Self::Other(other),
}
}
}
impl fmt::Display for FunctionCode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::ReadCoils => write!(f, "ReadCoils"),
Self::ReadDiscreteInputs => write!(f, "ReadDiscreteInputs"),
Self::ReadHoldingRegisters => write!(f, "ReadHoldingRegisters"),
Self::ReadInputRegisters => write!(f, "ReadInputRegisters"),
Self::WriteSingleCoil => write!(f, "WriteSingleCoil"),
Self::WriteSingleRegister => write!(f, "WriteSingleRegister"),
Self::WriteMultipleCoils => write!(f, "WriteMultipleCoils"),
Self::WriteMultipleRegisters => write!(f, "WriteMultipleRegisters"),
Self::Other(n) => write!(f, "FC({:#04x})", n),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Transaction {
pub unit_id: u8,
pub function_code: FunctionCode,
pub start_address: u16,
pub register_count: u16,
}
impl fmt::Display for Transaction {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"unit={} fc={} addr={} count={}",
self.unit_id, self.function_code, self.start_address, self.register_count
)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Warning {
TransactionIdMismatch { expected: u16, got: u16 },
}
impl fmt::Display for Warning {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::TransactionIdMismatch { expected, got } => {
write!(f, "transaction ID mismatch: expected {expected}, got {got}")
}
}
}
}
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum BridgeEvent {
Transaction(Transaction),
Warning(Warning),
}
impl fmt::Display for BridgeEvent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Transaction(t) => fmt::Display::fmt(t, f),
Self::Warning(w) => fmt::Display::fmt(w, f),
}
}
}
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum BridgeError<SE, TE> {
TcpClosed,
RtuClosed,
TcpIo(TE),
RtuIo(SE),
RtuCrcMismatch,
BufferOverflow,
Timeout,
}
impl<SE: fmt::Debug, TE: fmt::Debug> fmt::Display for BridgeError<SE, TE> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::TcpClosed => write!(f, "TCP connection closed"),
Self::RtuClosed => write!(f, "RTU connection closed"),
Self::TcpIo(e) => write!(f, "TCP I/O error: {:?}", e),
Self::RtuIo(e) => write!(f, "RTU I/O error: {:?}", e),
Self::RtuCrcMismatch => write!(f, "RTU response CRC mismatch"),
Self::BufferOverflow => write!(f, "frame buffer overflow — increase BUF capacity"),
Self::Timeout => write!(f, "I/O timeout"),
}
}
}