use crate::errors::MbusError;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[repr(u8)]
pub enum FunctionCode {
#[default]
Default = 0x00,
#[cfg(feature = "coils")]
ReadCoils = 0x01,
#[cfg(feature = "discrete-inputs")]
ReadDiscreteInputs = 0x02,
#[cfg(feature = "coils")]
WriteSingleCoil = 0x05,
#[cfg(feature = "coils")]
WriteMultipleCoils = 0x0F,
#[cfg(feature = "registers")]
ReadHoldingRegisters = 0x03,
#[cfg(feature = "registers")]
ReadInputRegisters = 0x04,
#[cfg(feature = "registers")]
WriteSingleRegister = 0x06,
#[cfg(feature = "registers")]
WriteMultipleRegisters = 0x10,
#[cfg(feature = "registers")]
MaskWriteRegister = 0x16,
#[cfg(feature = "registers")]
ReadWriteMultipleRegisters = 0x17,
#[cfg(feature = "fifo")]
ReadFifoQueue = 0x18,
#[cfg(feature = "file-record")]
ReadFileRecord = 0x14,
#[cfg(feature = "file-record")]
WriteFileRecord = 0x15,
#[cfg(feature = "diagnostics")]
ReadExceptionStatus = 0x07,
#[cfg(feature = "diagnostics")]
Diagnostics = 0x08,
#[cfg(feature = "diagnostics")]
GetCommEventCounter = 0x0B,
#[cfg(feature = "diagnostics")]
GetCommEventLog = 0x0C,
#[cfg(feature = "diagnostics")]
ReportServerId = 0x11,
#[cfg(feature = "diagnostics")]
EncapsulatedInterfaceTransport = 0x2B,
}
impl TryFrom<u8> for FunctionCode {
type Error = MbusError;
fn try_from(value: u8) -> Result<Self, Self::Error> {
use FunctionCode::*;
match value {
#[cfg(feature = "coils")]
0x01 => Ok(ReadCoils),
#[cfg(feature = "discrete-inputs")]
0x02 => Ok(ReadDiscreteInputs),
#[cfg(feature = "registers")]
0x03 => Ok(ReadHoldingRegisters),
#[cfg(feature = "registers")]
0x04 => Ok(ReadInputRegisters),
#[cfg(feature = "coils")]
0x05 => Ok(WriteSingleCoil),
#[cfg(feature = "registers")]
0x06 => Ok(WriteSingleRegister),
#[cfg(feature = "diagnostics")]
0x07 => Ok(ReadExceptionStatus),
#[cfg(feature = "diagnostics")]
0x08 => Ok(Diagnostics),
#[cfg(feature = "diagnostics")]
0x0B => Ok(GetCommEventCounter),
#[cfg(feature = "diagnostics")]
0x0C => Ok(GetCommEventLog),
#[cfg(feature = "coils")]
0x0F => Ok(WriteMultipleCoils),
#[cfg(feature = "registers")]
0x10 => Ok(WriteMultipleRegisters),
#[cfg(feature = "diagnostics")]
0x11 => Ok(ReportServerId),
#[cfg(feature = "file-record")]
0x14 => Ok(ReadFileRecord),
#[cfg(feature = "file-record")]
0x15 => Ok(WriteFileRecord),
#[cfg(feature = "registers")]
0x16 => Ok(MaskWriteRegister),
#[cfg(feature = "registers")]
0x17 => Ok(ReadWriteMultipleRegisters),
#[cfg(feature = "fifo")]
0x18 => Ok(ReadFifoQueue),
#[cfg(feature = "diagnostics")]
0x2B => Ok(EncapsulatedInterfaceTransport),
_ => Err(MbusError::UnsupportedFunction(value)),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u16)]
pub enum DiagnosticSubFunction {
ReturnQueryData = 0x0000,
RestartCommunicationsOption = 0x0001,
ReturnDiagnosticRegister = 0x0002,
ChangeAsciiInputDelimiter = 0x0003,
ForceListenOnlyMode = 0x0004,
ClearCountersAndDiagnosticRegister = 0x000A,
ReturnBusMessageCount = 0x000B,
ReturnBusCommunicationErrorCount = 0x000C,
ReturnBusExceptionErrorCount = 0x000D,
ReturnServerMessageCount = 0x000E,
ReturnServerNoResponseCount = 0x000F,
ReturnServerNakCount = 0x0010,
ReturnServerBusyCount = 0x0011,
ReturnBusCharacterOverrunCount = 0x0012,
ClearOverrunCounterAndFlag = 0x0014,
}
impl DiagnosticSubFunction {
pub fn to_be_bytes(self) -> [u8; 2] {
(self as u16).to_be_bytes()
}
}
impl From<DiagnosticSubFunction> for u16 {
fn from(sub_func: DiagnosticSubFunction) -> Self {
sub_func as u16
}
}
impl TryFrom<u16> for DiagnosticSubFunction {
type Error = MbusError;
fn try_from(value: u16) -> Result<Self, Self::Error> {
use DiagnosticSubFunction::*;
match value {
0x0000 => Ok(ReturnQueryData),
0x0001 => Ok(RestartCommunicationsOption),
0x0002 => Ok(ReturnDiagnosticRegister),
0x0003 => Ok(ChangeAsciiInputDelimiter),
0x0004 => Ok(ForceListenOnlyMode),
0x000A => Ok(ClearCountersAndDiagnosticRegister),
0x000B => Ok(ReturnBusMessageCount),
0x000C => Ok(ReturnBusCommunicationErrorCount),
0x000D => Ok(ReturnBusExceptionErrorCount),
0x000E => Ok(ReturnServerMessageCount),
0x000F => Ok(ReturnServerNoResponseCount),
0x0010 => Ok(ReturnServerNakCount),
0x0011 => Ok(ReturnServerBusyCount),
0x0012 => Ok(ReturnBusCharacterOverrunCount),
0x0014 => Ok(ClearOverrunCounterAndFlag),
_ => Err(MbusError::ReservedSubFunction(value)),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[repr(u8)]
pub enum EncapsulatedInterfaceType {
#[default]
Err,
CanopenGeneralReference = 0x0D,
ReadDeviceIdentification = 0x0E,
}
impl From<EncapsulatedInterfaceType> for u8 {
fn from(val: EncapsulatedInterfaceType) -> Self {
val as u8
}
}
impl TryFrom<u8> for EncapsulatedInterfaceType {
type Error = MbusError;
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0x0D => Ok(Self::CanopenGeneralReference),
0x0E => Ok(Self::ReadDeviceIdentification),
_ => Err(MbusError::ReservedSubFunction(value as u16)),
}
}
}