1use serde::{Deserialize, Serialize};
2use serde_json::json;
3use tokio_tungstenite::tungstenite::protocol::Message;
4
5use crate::error::{ObnizError, ObnizResult};
6use crate::obniz::Obniz;
7
8#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
10#[serde(rename_all = "lowercase")]
11pub enum Parity {
12 Off,
13 Odd,
14 Even,
15}
16
17#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
19#[serde(rename_all = "lowercase")]
20pub enum FlowControl {
21 Off,
22 Rts,
23 Cts,
24 #[serde(rename = "rts-cts")]
25 RtsCts,
26}
27
28#[derive(Debug, Clone)]
30pub struct UartConfig {
31 pub rx_pin: u8,
32 pub tx_pin: u8,
33 pub baud_rate: u32,
34 pub stop_bits: f32,
35 pub data_bits: u8,
36 pub parity: Parity,
37 pub flow_control: FlowControl,
38 pub rts_pin: Option<u8>,
39 pub cts_pin: Option<u8>,
40}
41
42impl Default for UartConfig {
43 fn default() -> Self {
44 Self {
45 rx_pin: 0,
46 tx_pin: 1,
47 baud_rate: 115200,
48 stop_bits: 1.0,
49 data_bits: 8,
50 parity: Parity::Off,
51 flow_control: FlowControl::Off,
52 rts_pin: None,
53 cts_pin: None,
54 }
55 }
56}
57
58#[derive(Debug)]
60pub struct UartChannel {
61 channel: u8,
62 obniz: Obniz,
63}
64
65impl UartChannel {
66 pub fn new(channel: u8, obniz: Obniz) -> Self {
67 Self { channel, obniz }
68 }
69
70 pub fn channel_key(&self) -> String {
71 format!("uart{}", self.channel)
72 }
73
74 pub async fn init(&self, config: UartConfig) -> ObnizResult<()> {
76 if config.rx_pin > 11 || config.tx_pin > 11 {
78 return Err(ObnizError::Generic("UART pins must be 0-11".to_string()));
79 }
80
81 if let Some(rts_pin) = config.rts_pin {
82 if rts_pin > 11 {
83 return Err(ObnizError::InvalidPin(rts_pin));
84 }
85 }
86
87 if let Some(cts_pin) = config.cts_pin {
88 if cts_pin > 11 {
89 return Err(ObnizError::InvalidPin(cts_pin));
90 }
91 }
92
93 if config.baud_rate == 0 || config.baud_rate > 5_000_000 {
95 return Err(ObnizError::Generic(
96 "Baud rate must be between 1 and 5,000,000".to_string(),
97 ));
98 }
99
100 if config.data_bits < 5 || config.data_bits > 8 {
102 return Err(ObnizError::Generic(
103 "Data bits must be 5, 6, 7, or 8".to_string(),
104 ));
105 }
106
107 if config.stop_bits != 1.0 && config.stop_bits != 1.5 && config.stop_bits != 2.0 {
109 return Err(ObnizError::Generic(
110 "Stop bits must be 1, 1.5, or 2".to_string(),
111 ));
112 }
113
114 let channel_key = self.channel_key();
115 let mut uart_config = json!({
116 "rx": config.rx_pin,
117 "tx": config.tx_pin,
118 "baud": config.baud_rate,
119 "stop": config.stop_bits,
120 "bits": config.data_bits,
121 "parity": config.parity
122 });
123
124 if let Some(rts_pin) = config.rts_pin {
126 uart_config["rts"] = json!(rts_pin);
127 }
128 if let Some(cts_pin) = config.cts_pin {
129 uart_config["cts"] = json!(cts_pin);
130 }
131
132 let request = json!([{&channel_key: uart_config}]);
133 let message = Message::from(request.to_string());
134
135 self.obniz
136 .send_message(message)
137 .map_err(|e| ObnizError::Connection(e.to_string()))
138 }
139
140 pub async fn send(&self, data: Vec<u8>) -> ObnizResult<()> {
142 if data.is_empty() {
143 return Err(ObnizError::Generic("Data cannot be empty".to_string()));
144 }
145
146 let channel_key = self.channel_key();
149 let request = json!([{&channel_key: {"data": data}}]);
150 let message = Message::from(request.to_string());
151
152 self.obniz
153 .send_message(message)
154 .map_err(|e| ObnizError::Connection(e.to_string()))
155 }
156
157 pub async fn send_string(&self, text: &str) -> ObnizResult<()> {
159 let data = text.as_bytes().to_vec();
160 self.send(data).await
161 }
162
163 pub async fn on_receive<F>(&self, callback: F) -> ObnizResult<()>
165 where
166 F: Fn(Vec<u8>) + Send + Sync + 'static,
167 {
168 let channel_key = self.channel_key();
169 let channel_key_clone = channel_key.clone();
170
171 self.obniz
172 .register_callback(channel_key, move |response| {
173 if let Some(uart_data) = response.get(&channel_key_clone) {
174 if let Some(data_array) = uart_data.get("data") {
175 if let Some(data_vec) = data_array.as_array() {
176 let bytes: Vec<u8> = data_vec
177 .iter()
178 .filter_map(|v| v.as_u64())
179 .map(|v| v as u8)
180 .collect();
181 callback(bytes);
182 }
183 }
184 }
185 })
186 .map_err(|e| ObnizError::CallbackError(e.to_string()))?;
187
188 Ok(())
189 }
190
191 pub async fn on_receive_string<F>(&self, callback: F) -> ObnizResult<()>
193 where
194 F: Fn(String) + Send + Sync + 'static,
195 {
196 self.on_receive(move |data| {
197 if let Ok(text) = String::from_utf8(data) {
198 callback(text);
199 }
200 })
201 .await
202 }
203
204 pub fn remove_callback(&self) -> ObnizResult<()> {
206 let channel_key = self.channel_key();
207 self.obniz
208 .unregister_callback(channel_key)
209 .map_err(|e| ObnizError::CallbackError(e.to_string()))
210 }
211
212 pub async fn deinit(&self) -> ObnizResult<()> {
214 let channel_key = self.channel_key();
215 let request = json!([{&channel_key: null}]);
216 let message = Message::from(request.to_string());
217
218 self.obniz
219 .send_message(message)
220 .map_err(|e| ObnizError::Connection(e.to_string()))
221 }
222}
223
224#[derive(Debug, Clone)]
226pub struct UartManager {
227 obniz: Obniz,
228}
229
230impl UartManager {
231 pub fn new(obniz: Obniz) -> Self {
232 Self { obniz }
233 }
234
235 pub fn channel(&self, channel: u8) -> ObnizResult<UartChannel> {
237 if channel > 2 {
239 return Err(ObnizError::Generic("UART channel must be 0-2".to_string()));
240 }
241 Ok(UartChannel::new(channel, self.obniz.clone()))
242 }
243
244 pub fn uart0(&self) -> UartChannel {
246 UartChannel::new(0, self.obniz.clone())
247 }
248
249 pub async fn init_channel(&self, channel: u8, config: UartConfig) -> ObnizResult<()> {
251 self.channel(channel)?.init(config).await
252 }
253
254 pub async fn send_data(&self, channel: u8, data: Vec<u8>) -> ObnizResult<()> {
256 self.channel(channel)?.send(data).await
257 }
258
259 pub async fn send_string(&self, channel: u8, text: &str) -> ObnizResult<()> {
261 self.channel(channel)?.send_string(text).await
262 }
263
264 pub async fn set_receive_callback<F>(&self, channel: u8, callback: F) -> ObnizResult<()>
266 where
267 F: Fn(Vec<u8>) + Send + Sync + 'static,
268 {
269 self.channel(channel)?.on_receive(callback).await
270 }
271
272 pub async fn set_string_callback<F>(&self, channel: u8, callback: F) -> ObnizResult<()>
274 where
275 F: Fn(String) + Send + Sync + 'static,
276 {
277 self.channel(channel)?.on_receive_string(callback).await
278 }
279
280 pub fn remove_channel_callback(&self, channel: u8) -> ObnizResult<()> {
282 self.channel(channel)?.remove_callback()
283 }
284
285 pub async fn deinit_channel(&self, channel: u8) -> ObnizResult<()> {
287 self.channel(channel)?.deinit().await
288 }
289
290 pub fn simple_config(rx_pin: u8, tx_pin: u8, baud_rate: u32) -> UartConfig {
292 UartConfig {
293 rx_pin,
294 tx_pin,
295 baud_rate,
296 ..Default::default()
297 }
298 }
299
300 pub fn flow_control_config(
302 rx_pin: u8,
303 tx_pin: u8,
304 rts_pin: u8,
305 cts_pin: u8,
306 baud_rate: u32,
307 ) -> UartConfig {
308 UartConfig {
309 rx_pin,
310 tx_pin,
311 baud_rate,
312 flow_control: FlowControl::RtsCts,
313 rts_pin: Some(rts_pin),
314 cts_pin: Some(cts_pin),
315 ..Default::default()
316 }
317 }
318}
319
320#[cfg(test)]
321mod tests {
322 use super::*;
323
324 #[test]
325 fn test_uart_config_default() {
326 let config = UartConfig::default();
327
328 assert_eq!(config.rx_pin, 0);
329 assert_eq!(config.tx_pin, 1);
330 assert_eq!(config.baud_rate, 115200);
331 assert_eq!(config.stop_bits, 1.0);
332 assert_eq!(config.data_bits, 8);
333 assert_eq!(config.parity, Parity::Off);
334 assert_eq!(config.flow_control, FlowControl::Off);
335 }
336
337 #[test]
338 fn test_uart_config_custom() {
339 let config = UartConfig {
340 rx_pin: 2,
341 tx_pin: 3,
342 baud_rate: 9600,
343 stop_bits: 2.0,
344 data_bits: 7,
345 parity: Parity::Even,
346 flow_control: FlowControl::RtsCts,
347 rts_pin: Some(4),
348 cts_pin: Some(5),
349 };
350
351 assert_eq!(config.rx_pin, 2);
352 assert_eq!(config.tx_pin, 3);
353 assert_eq!(config.baud_rate, 9600);
354 assert_eq!(config.parity, Parity::Even);
355 assert_eq!(config.flow_control, FlowControl::RtsCts);
356 }
357
358 #[test]
359 fn test_parity_serialization() {
360 use serde_json;
361
362 assert_eq!(serde_json::to_string(&Parity::Off).unwrap(), "\"off\"");
363 assert_eq!(serde_json::to_string(&Parity::Odd).unwrap(), "\"odd\"");
364 assert_eq!(serde_json::to_string(&Parity::Even).unwrap(), "\"even\"");
365 }
366
367 #[test]
368 fn test_flow_control_serialization() {
369 use serde_json;
370
371 assert_eq!(serde_json::to_string(&FlowControl::Off).unwrap(), "\"off\"");
372 assert_eq!(serde_json::to_string(&FlowControl::Rts).unwrap(), "\"rts\"");
373 assert_eq!(serde_json::to_string(&FlowControl::Cts).unwrap(), "\"cts\"");
374 assert_eq!(
375 serde_json::to_string(&FlowControl::RtsCts).unwrap(),
376 "\"rts-cts\""
377 );
378 }
379
380 #[test]
381 fn test_simple_config_creation() {
382 let config = UartManager::simple_config(2, 3, 9600);
383
384 assert_eq!(config.rx_pin, 2);
385 assert_eq!(config.tx_pin, 3);
386 assert_eq!(config.baud_rate, 9600);
387 assert_eq!(config.parity, Parity::Off);
388 }
389
390 #[test]
391 fn test_flow_control_config_creation() {
392 let config = UartManager::flow_control_config(0, 1, 2, 3, 115200);
393
394 assert_eq!(config.rx_pin, 0);
395 assert_eq!(config.tx_pin, 1);
396 assert_eq!(config.rts_pin, Some(2));
397 assert_eq!(config.cts_pin, Some(3));
398 assert_eq!(config.flow_control, FlowControl::RtsCts);
399 }
400
401 #[test]
402 fn test_channel_key_generation() {
403 assert_eq!(format!("uart{}", 0), "uart0");
404 assert_eq!(format!("uart{}", 1), "uart1");
405 }
406}