1use serialport::SerialPort;
2use std::thread::sleep;
3use std::io::{Read, Write};
4use log::trace;
5use crate::{SerialError, SwarmSerialPort};
6
7pub struct SerialCommunication {
8 port: Box<dyn SerialPort>,
9}
10
11impl SerialCommunication {
12 pub fn new(port: Box<dyn SerialPort>) -> Self {
13 SerialCommunication {
14 port
15 }
16 }
17
18 pub fn connect(tty: &str) -> Self {
19 let port = serialport::new(tty, 115200)
20 .timeout(std::time::Duration::from_millis(10))
21 .open()
22 .unwrap_or_else(|_| panic!("Failed to open serial port at {}", tty));
23
24 SerialCommunication {
25 port
26 }
27 }
28
29 pub fn get_first_available() -> Result<String, String> {
30 let ports = serialport::available_ports()
31 .map_err(|_| "No serial ports found")?;
32
33 if ports.is_empty() {
34 return Err("No serial ports found".to_string());
35 }
36
37 trace!("Found serial ports: {:?}", ports);
38
39 Ok(ports[0].port_name.clone())
40 }
41}
42
43impl Default for SerialCommunication {
44 fn default() -> Self {
45 let tty = SerialCommunication::get_first_available().expect("No serial ports found");
46 SerialCommunication::connect(&tty)
47 }
48}
49
50impl SwarmSerialPort for SerialCommunication {
51 fn available(&self) -> Result<bool, SerialError> {
52 Ok(self.port.bytes_to_read().map_err(|_| SerialError::IoError)? > 0)
53 }
54
55 fn read_line(&mut self) -> Result<String, SerialError> {
56 let mut buffer = Vec::new();
57 loop {
58 let mut byte = [0];
59 self.port.read_exact(&mut byte).map_err(|_| SerialError::IoError)?;
60 if byte[0] == b'\n' {
61 break;
62 }
63 buffer.push(byte[0]);
64 }
65 let str = String::from_utf8(buffer).map_err(|_| SerialError::EncodingError)?;
66 trace!("S > R: {}", str);
67 Ok(str)
68 }
69
70 fn write_line(&mut self, line: String) -> Result<(), SerialError> {
71 trace!("R > S: {}", line);
72 self.port.write_all(line.as_bytes()).map_err(|_| SerialError::IoError)?;
73 self.port.write_all(b"\r\n").map_err(|_| SerialError::IoError)?;
74
75 Ok(())
76 }
77
78 fn block_until(&mut self, line: String) -> Result<(), SerialError> {
79 trace!("Blocking until: {}", line);
80 let mut line_pos = 0;
82 loop {
83 if !self.available()? {
84 sleep(std::time::Duration::from_millis(10));
85 continue;
86 }
87 let mut byte = [0];
88 self.port.read_exact(&mut byte).map_err(|_| SerialError::IoError)?;
89
90 if byte[0] == line.as_bytes()[line_pos] {
91 line_pos += 1;
92 if line_pos == line.len() {
93 break;
94 }
95 } else {
96 line_pos = 0;
97 }
98 }
99
100 sleep(std::time::Duration::from_millis(10));
101
102 if let Ok(t) = self.port.bytes_to_read() {
103 if t > 0 {
104 let mut buf = vec![0; t as usize];
105 self.port.read_exact(&mut buf).map_err(|_| SerialError::IoError)?;
106 }
107 }
108
109 trace!("Blocking until: {} - Done", line);
110 Ok(())
111 }
112}