105 lines
2.4 KiB
Rust
105 lines
2.4 KiB
Rust
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
|
|
use tokio_serial::SerialStream;
|
|
use tracing_error::SpanTrace;
|
|
|
|
#[derive(Debug)]
|
|
pub struct Error {
|
|
kind: ErrorKind,
|
|
context: SpanTrace,
|
|
}
|
|
|
|
#[derive(Debug, thiserror::Error)]
|
|
pub enum ErrorKind {
|
|
#[error(transparent)]
|
|
Serial(#[from] tokio_serial::Error),
|
|
|
|
#[error(transparent)]
|
|
Io(#[from] std::io::Error),
|
|
|
|
#[error(transparent)]
|
|
Utf8(#[from] std::string::FromUtf8Error),
|
|
}
|
|
|
|
pub async fn identity(port: &mut SerialStream) -> Result<Vec<u8>, Error> {
|
|
get_prop(port, b"ident").await
|
|
}
|
|
|
|
pub async fn name(port: &mut SerialStream) -> Result<String, Error> {
|
|
get_string_prop(port, b"name").await
|
|
}
|
|
|
|
pub async fn author(port: &mut SerialStream) -> Result<String, Error> {
|
|
get_string_prop(port, b"author").await
|
|
}
|
|
|
|
pub async fn repo(port: &mut SerialStream) -> Result<String, Error> {
|
|
get_string_prop(port, b"repo").await
|
|
}
|
|
|
|
pub async fn version(port: &mut SerialStream) -> Result<String, Error> {
|
|
get_string_prop(port, b"version").await
|
|
}
|
|
|
|
pub async fn reset(port: &mut SerialStream) -> Result<(), Error> {
|
|
send_command(port, b"reset").await
|
|
}
|
|
|
|
async fn send_command<Port>(port: &mut Port, command: &[u8]) -> Result<(), Error>
|
|
where
|
|
Port: AsyncWrite + Unpin,
|
|
{
|
|
port.write_all(command).await?;
|
|
port.flush().await?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
async fn get_string_prop<Port>(port: &mut Port, prop: &[u8]) -> Result<String, Error>
|
|
where
|
|
Port: AsyncRead + AsyncWrite + Unpin,
|
|
{
|
|
Ok(String::from_utf8(get_prop(port, prop).await?)?)
|
|
}
|
|
|
|
async fn get_prop<Port>(port: &mut Port, prop: &[u8]) -> Result<Vec<u8>, Error>
|
|
where
|
|
Port: AsyncRead + AsyncWrite + Unpin,
|
|
{
|
|
send_command::<Port>(port, prop).await?;
|
|
|
|
let mut len_buf = [0u8; 1];
|
|
|
|
port.read_exact(&mut len_buf).await?;
|
|
let input_len = len_buf[0];
|
|
|
|
let mut input = vec![0u8; input_len as usize];
|
|
port.read_exact(&mut input).await?;
|
|
|
|
Ok(input)
|
|
}
|
|
|
|
impl std::fmt::Display for Error {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
writeln!(f, "{}", self.kind)?;
|
|
std::fmt::Display::fmt(&self.context, f)
|
|
}
|
|
}
|
|
|
|
impl std::error::Error for Error {
|
|
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
|
self.kind.source()
|
|
}
|
|
}
|
|
|
|
impl<T> From<T> for Error
|
|
where
|
|
ErrorKind: From<T>,
|
|
{
|
|
fn from(error: T) -> Self {
|
|
Error {
|
|
kind: error.into(),
|
|
context: SpanTrace::capture(),
|
|
}
|
|
}
|
|
}
|