use crate::connection::ConnectionPort;
use crate::error::{Error, Result};
use serialport::{ClearBuffer, DataBits, FlowControl, Parity, StopBits};
use std::io::{Read, Write};
use std::time::Duration;
pub struct SerialPort {
port: Box<dyn serialport::SerialPort>,
name: String,
timeout: Duration,
baud_rate: u32,
}
impl SerialPort {
pub const DEFAULT_TIMEOUT: Duration = Duration::from_millis(1000);
pub fn open(port_name: &str, baud_rate: u32) -> Result<Self> {
Self::open_with_timeout(port_name, baud_rate, Self::DEFAULT_TIMEOUT)
}
pub fn open_with_timeout(port_name: &str, baud_rate: u32, timeout: Duration) -> Result<Self> {
let port = serialport::new(port_name, baud_rate)
.timeout(timeout)
.data_bits(DataBits::Eight)
.parity(Parity::None)
.stop_bits(StopBits::One)
.flow_control(FlowControl::None)
.open()?;
Ok(Self {
port,
name: port_name.to_string(),
timeout,
baud_rate,
})
}
pub fn list_ports() -> Result<Vec<serialport::SerialPortInfo>> {
serialport::available_ports().map_err(Error::Serial)
}
pub fn inner(&self) -> &dyn serialport::SerialPort {
self.port.as_ref()
}
pub fn inner_mut(&mut self) -> &mut dyn serialport::SerialPort {
self.port.as_mut()
}
pub fn set_dtr(&mut self, level: bool) -> Result<()> {
self.port.write_data_terminal_ready(level)?;
Ok(())
}
pub fn set_rts(&mut self, level: bool) -> Result<()> {
self.port.write_request_to_send(level)?;
Ok(())
}
pub fn dtr(&self) -> Result<bool> {
Ok(false)
}
pub fn cts(&mut self) -> Result<bool> {
Ok(self.port.read_clear_to_send()?)
}
pub fn dsr(&mut self) -> Result<bool> {
Ok(self.port.read_data_set_ready()?)
}
}
impl ConnectionPort for SerialPort {
fn set_timeout(&mut self, timeout: Duration) -> Result<()> {
self.port.set_timeout(timeout)?;
self.timeout = timeout;
Ok(())
}
fn timeout(&self) -> Duration {
self.timeout
}
fn set_baud_rate(&mut self, baud_rate: u32) -> Result<()> {
self.port.set_baud_rate(baud_rate)?;
self.baud_rate = baud_rate;
Ok(())
}
fn baud_rate(&self) -> u32 {
self.baud_rate
}
fn clear(&mut self) -> Result<()> {
self.port.clear(ClearBuffer::All)?;
Ok(())
}
fn name(&self) -> &str {
&self.name
}
}
impl Read for SerialPort {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
self.port.read(buf)
}
}
impl Write for SerialPort {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.port.write(buf)
}
fn flush(&mut self) -> std::io::Result<()> {
self.port.flush()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_list_ports() {
let _ = SerialPort::list_ports();
}
}