use crate::error::Error;
use crate::transport::serial::{TIMEOUT, helpers::drain_until_str};
use crate::{error::Result, logging::debug};
use crate::logging::trace;
use serialport::SerialPort;
use crate::transport::{Transport, serial::FLIPPER_BAUD};
use super::{
helpers::{drain_until, read_to_string_no_eof},
rpc::SerialRpcTransport,
};
#[derive(Debug)]
pub struct SerialCliTransport {
port: Box<dyn SerialPort>,
}
impl SerialCliTransport {
#[cfg_attr(feature = "tracing", tracing::instrument)]
pub fn new<S: AsRef<str> + std::fmt::Debug>(port: S) -> Result<Self> {
let mut port = serialport::new(port.as_ref(), FLIPPER_BAUD)
.timeout(TIMEOUT)
.open()?;
debug!("Draining port until prompt");
drain_until_str(&mut port, ">: ", TIMEOUT)?;
Ok(Self { port })
}
#[cfg_attr(feature = "tracing", tracing::instrument)]
pub fn into_rpc(mut self) -> Result<SerialRpcTransport> {
self.send("start_rpc_session".to_string())?;
drain_until(&mut self.port, b'\n', TIMEOUT)?;
SerialRpcTransport::from_port(self.port)
}
}
impl Transport<String> for SerialCliTransport {
type Err = Error;
#[cfg_attr(feature = "tracing", tracing::instrument)]
fn send(&mut self, cmd: String) -> std::result::Result<(), Self::Err> {
trace!("running: {}", cmd);
self.port.write_all(cmd.as_bytes())?;
self.port.write_all(b"\r")?;
self.port.flush()?;
Ok(())
}
#[cfg_attr(feature = "tracing", tracing::instrument)]
fn receive(&mut self) -> std::result::Result<String, Self::Err> {
let string = read_to_string_no_eof(&mut self.port)?;
Ok(string)
}
}