use std::io::Write;
use crate::frame::{DEFAULT_MAX_FRAME_SIZE, expected_frame_count, read_frames};
use crate::{PrintError, Printer, PrinterConfig, StatusQuery};
const DEFAULT_BAUD: u32 = 9600;
pub struct SerialPrinter {
port: Box<dyn serialport::SerialPort>,
config: PrinterConfig,
}
impl SerialPrinter {
pub fn open(path: &str, baud: u32, config: PrinterConfig) -> Result<Self, PrintError> {
let timeout = config.timeouts.read.max(config.timeouts.write);
let port = serialport::new(path, baud)
.timeout(timeout)
.open()
.map_err(|e| PrintError::SerialError(e.to_string()))?;
Ok(Self { port, config })
}
pub fn open_default(path: &str, config: PrinterConfig) -> Result<Self, PrintError> {
Self::open(path, DEFAULT_BAUD, config)
}
pub fn list_ports() -> Vec<String> {
serialport::available_ports()
.unwrap_or_default()
.into_iter()
.map(|p| p.port_name)
.collect()
}
}
impl Printer for SerialPrinter {
fn send_raw(&mut self, data: &[u8]) -> Result<(), PrintError> {
self.port.write_all(data).map_err(PrintError::WriteFailed)?;
self.port.flush().map_err(PrintError::WriteFailed)?;
Ok(())
}
}
impl StatusQuery for SerialPrinter {
fn query_raw(&mut self, cmd: &[u8]) -> Result<Vec<Vec<u8>>, PrintError> {
self.send_raw(cmd)?;
let expected_frames = expected_frame_count(cmd);
let timeout = self.config.timeouts.read;
read_frames(
&mut self.port,
expected_frames,
timeout,
DEFAULT_MAX_FRAME_SIZE,
)
}
}