mbus_async/runtime/
serial_client.rs1use super::*;
14use std::ops::Deref;
15
16pub struct AsyncSerialClient {
22 core: AsyncClientCore,
23}
24
25impl Deref for AsyncSerialClient {
26 type Target = AsyncClientCore;
27
28 fn deref(&self) -> &Self::Target {
29 &self.core
30 }
31}
32
33impl AsyncSerialClient {
36 #[cfg(feature = "serial-rtu")]
40 #[deprecated(note = "use AsyncSerialClient::new_rtu(...) and then client.connect().await")]
41 pub fn connect_rtu(serial_config: ModbusSerialConfig) -> Result<Self, AsyncError> {
42 Self::new_rtu(serial_config)
43 }
44
45 #[cfg(feature = "serial-rtu")]
50 #[deprecated(
51 note = "use AsyncSerialClient::new_rtu_with_poll_interval(...) and then client.connect().await"
52 )]
53 pub fn connect_rtu_with_poll_interval(
54 serial_config: ModbusSerialConfig,
55 poll_interval: Duration,
56 ) -> Result<Self, AsyncError> {
57 Self::new_rtu_with_poll_interval(serial_config, poll_interval)
58 }
59
60 #[cfg(feature = "serial-ascii")]
65 #[deprecated(note = "use AsyncSerialClient::new_ascii(...) and then client.connect().await")]
66 pub fn connect_ascii(serial_config: ModbusSerialConfig) -> Result<Self, AsyncError> {
67 Self::new_ascii(serial_config)
68 }
69
70 #[cfg(feature = "serial-ascii")]
75 #[deprecated(
76 note = "use AsyncSerialClient::new_ascii_with_poll_interval(...) and then client.connect().await"
77 )]
78 pub fn connect_ascii_with_poll_interval(
79 serial_config: ModbusSerialConfig,
80 poll_interval: Duration,
81 ) -> Result<Self, AsyncError> {
82 Self::new_ascii_with_poll_interval(serial_config, poll_interval)
83 }
84
85 #[deprecated(
90 note = "use AsyncSerialClient::new_with_transport(...) and then client.connect().await"
91 )]
92 pub fn connect_with_transport<TRANSPORT>(
93 transport: TRANSPORT,
94 config: ModbusConfig,
95 poll_interval: Duration,
96 ) -> Result<Self, AsyncError>
97 where
98 TRANSPORT: Transport + Send + 'static,
99 {
100 Self::new_with_transport(transport, config, poll_interval)
101 }
102
103 #[cfg(feature = "serial-rtu")]
109 pub fn new_rtu(serial_config: ModbusSerialConfig) -> Result<Self, AsyncError> {
110 if serial_config.mode != SerialMode::Rtu {
111 return Err(AsyncError::Mbus(MbusError::InvalidConfiguration));
112 }
113
114 let transport = StdRtuTransport::new();
115 let config = ModbusConfig::Serial(serial_config);
116 Self::from_transport_config(transport, config, Duration::from_millis(20))
117 }
118
119 #[cfg(feature = "serial-rtu")]
125 pub fn new_rtu_with_poll_interval(
126 serial_config: ModbusSerialConfig,
127 poll_interval: Duration,
128 ) -> Result<Self, AsyncError> {
129 if serial_config.mode != SerialMode::Rtu {
130 return Err(AsyncError::Mbus(MbusError::InvalidConfiguration));
131 }
132
133 let transport = StdRtuTransport::new();
134 let config = ModbusConfig::Serial(serial_config);
135 Self::from_transport_config(transport, config, poll_interval)
136 }
137
138 #[cfg(feature = "serial-ascii")]
144 pub fn new_ascii(serial_config: ModbusSerialConfig) -> Result<Self, AsyncError> {
145 if serial_config.mode != SerialMode::Ascii {
146 return Err(AsyncError::Mbus(MbusError::InvalidConfiguration));
147 }
148
149 let transport = StdAsciiTransport::new();
150 let config = ModbusConfig::Serial(serial_config);
151 Self::from_transport_config(transport, config, Duration::from_millis(20))
152 }
153
154 #[cfg(feature = "serial-ascii")]
160 pub fn new_ascii_with_poll_interval(
161 serial_config: ModbusSerialConfig,
162 poll_interval: Duration,
163 ) -> Result<Self, AsyncError> {
164 if serial_config.mode != SerialMode::Ascii {
165 return Err(AsyncError::Mbus(MbusError::InvalidConfiguration));
166 }
167
168 let transport = StdAsciiTransport::new();
169 let config = ModbusConfig::Serial(serial_config);
170 Self::from_transport_config(transport, config, poll_interval)
171 }
172
173 pub fn new_with_transport<TRANSPORT>(
183 transport: TRANSPORT,
184 config: ModbusConfig,
185 poll_interval: Duration,
186 ) -> Result<Self, AsyncError>
187 where
188 TRANSPORT: Transport + Send + 'static,
189 {
190 if !matches!(config, ModbusConfig::Serial(_)) {
191 return Err(AsyncError::Mbus(MbusError::InvalidTransport));
192 }
193
194 let pending = Arc::new(Mutex::new(HashMap::new()));
195 #[cfg(feature = "traffic")]
196 let traffic_handler = Arc::new(Mutex::new(None));
197 #[cfg(feature = "traffic")]
198 let (traffic_sender, traffic_receiver) = mpsc::channel();
199 let app = AsyncApp {
200 pending: pending.clone(),
201 #[cfg(feature = "traffic")]
202 traffic_sender,
203 };
204
205 let client = ClientServices::<_, _, 1>::new(transport, app, config)?;
207 let (sender, receiver) = mpsc::channel();
208
209 thread::spawn(move || run_worker(client, pending, receiver, poll_interval));
210 #[cfg(feature = "traffic")]
211 {
212 let dispatcher_handler = traffic_handler.clone();
213 thread::spawn(move || run_traffic_dispatcher(traffic_receiver, dispatcher_handler));
214 }
215
216 #[cfg(feature = "traffic")]
217 {
218 Ok(Self {
219 core: AsyncClientCore::new(sender, traffic_handler),
220 })
221 }
222
223 #[cfg(not(feature = "traffic"))]
224 {
225 Ok(Self {
226 core: AsyncClientCore::new(sender),
227 })
228 }
229 }
230
231 #[cfg(any(feature = "serial-rtu", feature = "serial-ascii"))]
233 fn from_transport_config<const ASCII: bool>(
234 transport: StdSerialTransport<ASCII>,
235 config: ModbusConfig,
236 poll_interval: Duration,
237 ) -> Result<Self, AsyncError> {
238 Self::new_with_transport(transport, config, poll_interval)
239 }
240}