ftswarm_serial/
serial.rs

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        // Read until the line is found
81        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}