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)]
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
88/// Configuration parameters for establishing a Modbus TCP connection.
89#[derive(Debug, Clone)]
90pub struct ModbusTcpConfig {
91 /// The hostname or IP address of the Modbus TCP server to connect to.
92 pub host: heapless::String<64>,
93 /// The TCP port number on which the Modbus server is listening (default is typically 502).
94 pub port: u16,
95 /// Timeout for establishing a connection in milliseconds.
96 pub connection_timeout_ms: u32,
97 /// Timeout for waiting for a response in milliseconds.
98 pub response_timeout_ms: u32,
99 /// Number of retry attempts for failed operations.
100 pub retry_attempts: u8,
101 /// Backoff strategy used when scheduling retries.
102 pub retry_backoff_strategy: BackoffStrategy,
103 /// Optional jitter strategy applied on top of retry backoff delay.
104 pub retry_jitter_strategy: JitterStrategy,
105 /// Optional application-provided random callback used by jitter.
106 pub retry_random_fn: Option<RetryRandomFn>,
107}
108
109impl ModbusTcpConfig {
110 /// Creates a new `ModbusTcpConfig` using the default Modbus TCP port (502).
111 pub fn with_default_port(host: &str) -> Result<Self, MbusError> {
112 let host_string: String<64> =
113 String::from_str(host).map_err(|_| MbusError::BufferTooSmall)?;
114 Self::new(&host_string, MODBUS_TCP_DEFAULT_PORT)
115 }
116
117 /// Creates a new `ModbusTcpConfig` with the specified host and port.
118 pub fn new(host: &str, port: u16) -> Result<Self, MbusError> {
119 let host_string = String::from_str(host).map_err(|_| MbusError::BufferTooSmall)?;
120 Ok(Self {
121 host: host_string,
122 port,
123 connection_timeout_ms: 5000,
124 response_timeout_ms: 5000,
125 retry_attempts: 3,
126 retry_backoff_strategy: BackoffStrategy::Immediate,
127 retry_jitter_strategy: JitterStrategy::None,
128 retry_random_fn: None,
129 })
130 }
131}
132
133/// Top-level configuration for Modbus communication, supporting different transport layers.
134#[derive(Debug)]
135pub enum ModbusConfig {
136 /// Configuration for Modbus TCP/IP.
137 Tcp(ModbusTcpConfig),
138 /// Configuration for Modbus Serial (RTU or ASCII).
139 Serial(ModbusSerialConfig),
140}
141
142impl ModbusConfig {
143 /// Returns the number of retry attempts configured for the transport.
144 pub fn retry_attempts(&self) -> u8 {
145 match self {
146 ModbusConfig::Tcp(config) => config.retry_attempts,
147 ModbusConfig::Serial(config) => config.retry_attempts,
148 }
149 }
150
151 /// Returns the configured retry backoff strategy.
152 pub fn retry_backoff_strategy(&self) -> BackoffStrategy {
153 match self {
154 ModbusConfig::Tcp(config) => config.retry_backoff_strategy,
155 ModbusConfig::Serial(config) => config.retry_backoff_strategy,
156 }
157 }
158
159 /// Returns the configured retry jitter strategy.
160 pub fn retry_jitter_strategy(&self) -> JitterStrategy {
161 match self {
162 ModbusConfig::Tcp(config) => config.retry_jitter_strategy,
163 ModbusConfig::Serial(config) => config.retry_jitter_strategy,
164 }
165 }
166
167 /// Returns the optional application-provided random callback for jitter.
168 pub fn retry_random_fn(&self) -> Option<RetryRandomFn> {
169 match self {
170 ModbusConfig::Tcp(config) => config.retry_random_fn,
171 ModbusConfig::Serial(config) => config.retry_random_fn,
172 }
173 }
174}