Skip to main content

mbus_core/transport/
config.rs

1//! Transport configuration types: TCP and Serial.
2
3use core::str::FromStr;
4
5use crate::errors::MbusError;
6use heapless::String;
7
8use super::retry::{BackoffStrategy, JitterStrategy, RetryRandomFn};
9
10/// The default TCP port for Modbus communication.
11const MODBUS_TCP_DEFAULT_PORT: u16 = 502;
12
13/// Parity bit configuration for serial communication.
14#[derive(Debug, Clone, Copy, Default)]
15pub enum Parity {
16    /// No parity bit is used.
17    None,
18    /// Even parity: the number of 1-bits in the data plus parity bit is even.
19    #[default]
20    Even,
21    /// Odd parity: the number of 1-bits in the data plus parity bit is odd.
22    Odd,
23}
24
25/// Number of data bits per serial character.
26#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
27pub enum DataBits {
28    /// 5 data bits.
29    Five,
30    /// 6 data bits.
31    Six,
32    /// 7 data bits.
33    Seven,
34    /// 8 data bits.
35    #[default]
36    Eight,
37}
38
39/// Serial framing mode.
40#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
41pub enum SerialMode {
42    /// Modbus RTU mode, which uses binary encoding and CRC error checking.
43    #[default]
44    Rtu,
45    /// Modbus ASCII mode, which uses ASCII encoding and LRC error checking.
46    Ascii,
47}
48
49/// Baud rate configuration for serial communication.
50#[derive(Debug, Clone, Copy, Default)]
51pub enum BaudRate {
52    /// Standard baud rate of 9600 bits per second.
53    Baud9600,
54    /// Standard baud rate of 19200 bits per second.
55    #[default]
56    Baud19200,
57    /// Custom baud rate.
58    Custom(u32),
59}
60
61/// Configuration parameters for establishing a Modbus Serial connection.
62#[derive(Debug, Clone)]
63pub struct ModbusSerialConfig<const PORT_PATH_LEN: usize = 64> {
64    /// The path to the serial port (e.g., "/dev/ttyUSB0" or "COM1").
65    pub port_path: heapless::String<PORT_PATH_LEN>,
66    /// The serial mode to use (RTU or ASCII).
67    pub mode: SerialMode,
68    /// Communication speed in bits per second (e.g., 9600, 115200).
69    pub baud_rate: BaudRate,
70    /// Number of data bits per character (typically `DataBits::Eight` for RTU, `DataBits::Seven` for ASCII).
71    pub data_bits: DataBits,
72    /// Number of stop bits (This will be recalculated before calling the transport layer).
73    pub stop_bits: u8,
74    /// The parity checking mode.
75    pub parity: Parity,
76    /// Timeout for waiting for a response in milliseconds.
77    pub response_timeout_ms: u32,
78    /// Number of retries for failed operations.
79    pub retry_attempts: u8,
80    /// Backoff strategy used when scheduling retries.
81    pub retry_backoff_strategy: BackoffStrategy,
82    /// Optional jitter strategy applied on top of retry backoff delay.
83    pub retry_jitter_strategy: JitterStrategy,
84    /// Optional application-provided random callback used by jitter.
85    pub retry_random_fn: Option<RetryRandomFn>,
86}
87
88impl<const PORT_PATH_LEN: usize> Default for ModbusSerialConfig<PORT_PATH_LEN> {
89    fn default() -> Self {
90        Self {
91            port_path: heapless::String::new(),
92            mode: SerialMode::Rtu,
93            baud_rate: BaudRate::Baud19200,
94            data_bits: DataBits::Eight,
95            stop_bits: 1,
96            parity: Parity::Even,
97            response_timeout_ms: 1000,
98            retry_attempts: 3,
99            retry_backoff_strategy: BackoffStrategy::Immediate,
100            retry_jitter_strategy: JitterStrategy::None,
101            retry_random_fn: None,
102        }
103    }
104}
105
106/// Configuration parameters for establishing a Modbus TCP connection.
107#[derive(Debug, Clone)]
108pub struct ModbusTcpConfig {
109    /// The hostname or IP address of the Modbus TCP server to connect to.
110    pub host: heapless::String<64>,
111    /// The TCP port number on which the Modbus server is listening (default is typically 502).
112    pub port: u16,
113    /// Timeout for establishing a connection in milliseconds.
114    pub connection_timeout_ms: u32,
115    /// Timeout for waiting for a response in milliseconds.
116    pub response_timeout_ms: u32,
117    /// Number of retry attempts for failed operations.
118    pub retry_attempts: u8,
119    /// Backoff strategy used when scheduling retries.
120    pub retry_backoff_strategy: BackoffStrategy,
121    /// Optional jitter strategy applied on top of retry backoff delay.
122    pub retry_jitter_strategy: JitterStrategy,
123    /// Optional application-provided random callback used by jitter.
124    pub retry_random_fn: Option<RetryRandomFn>,
125}
126
127impl ModbusTcpConfig {
128    /// Creates a new `ModbusTcpConfig` using the default Modbus TCP port (502).
129    pub fn with_default_port(host: &str) -> Result<Self, MbusError> {
130        let host_string: String<64> =
131            String::from_str(host).map_err(|_| MbusError::BufferTooSmall)?;
132        Self::new(&host_string, MODBUS_TCP_DEFAULT_PORT)
133    }
134
135    /// Creates a new `ModbusTcpConfig` with the specified host and port.
136    pub fn new(host: &str, port: u16) -> Result<Self, MbusError> {
137        let host_string = String::from_str(host).map_err(|_| MbusError::BufferTooSmall)?;
138        Ok(Self {
139            host: host_string,
140            port,
141            connection_timeout_ms: 5000,
142            response_timeout_ms: 5000,
143            retry_attempts: 3,
144            retry_backoff_strategy: BackoffStrategy::Immediate,
145            retry_jitter_strategy: JitterStrategy::None,
146            retry_random_fn: None,
147        })
148    }
149}
150
151/// Top-level configuration for Modbus communication, supporting different transport layers.
152#[derive(Debug, Clone)]
153pub enum ModbusConfig {
154    /// Configuration for Modbus TCP/IP.
155    Tcp(ModbusTcpConfig),
156    /// Configuration for Modbus Serial (RTU or ASCII).
157    Serial(ModbusSerialConfig),
158}
159
160impl ModbusConfig {
161    /// Returns the number of retry attempts configured for the transport.
162    pub fn retry_attempts(&self) -> u8 {
163        match self {
164            ModbusConfig::Tcp(config) => config.retry_attempts,
165            ModbusConfig::Serial(config) => config.retry_attempts,
166        }
167    }
168
169    /// Returns the configured retry backoff strategy.
170    pub fn retry_backoff_strategy(&self) -> BackoffStrategy {
171        match self {
172            ModbusConfig::Tcp(config) => config.retry_backoff_strategy,
173            ModbusConfig::Serial(config) => config.retry_backoff_strategy,
174        }
175    }
176
177    /// Returns the configured retry jitter strategy.
178    pub fn retry_jitter_strategy(&self) -> JitterStrategy {
179        match self {
180            ModbusConfig::Tcp(config) => config.retry_jitter_strategy,
181            ModbusConfig::Serial(config) => config.retry_jitter_strategy,
182        }
183    }
184
185    /// Returns the optional application-provided random callback for jitter.
186    pub fn retry_random_fn(&self) -> Option<RetryRandomFn> {
187        match self {
188            ModbusConfig::Tcp(config) => config.retry_random_fn,
189            ModbusConfig::Serial(config) => config.retry_random_fn,
190        }
191    }
192}