Use Error type for reply parsing

This commit is contained in:
Frederik Menke 2022-10-22 20:57:57 +02:00
parent c6c0f65f7a
commit 65bab91e8b
3 changed files with 39 additions and 17 deletions

View file

@ -7,7 +7,10 @@ const DEFAULT_TTY: &str = "/dev/ttyUSB0";
#[tokio::main]
async fn main() -> tokio_serial::Result<()> {
let printer = Printer::connect(DEFAULT_TTY).await.unwrap();
printer.printer_in.send(Box::new(red::printer::M114Command::new())).await;
printer
.printer_in
.send(Box::new(red::printer::M114Command::new()))
.await;
tokio::time::sleep(std::time::Duration::from_secs(15)).await;
Ok(())
}

View file

@ -3,9 +3,28 @@ use std::fmt::Debug;
use lazy_static::lazy_static;
use regex::Regex;
type Result<T> = std::result::Result<T, GcodeReplyError>;
#[derive(Debug, Clone)]
pub struct GcodeReplyError {
sent_command: String,
parsed_input: String,
problem: String,
}
impl std::fmt::Display for GcodeReplyError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"Failed to parse response `{}` to command {}: {}",
self.parsed_input, self.sent_command, self.problem
)
}
}
pub trait GcodeCommand: Debug + Send {
fn command(&self) -> &str;
fn parse_reply(&self, reply: &str) -> GcodeReply;
fn parse_reply(&self, reply: &str) -> Result<GcodeReply>;
}
#[derive(Debug)]
@ -13,12 +32,7 @@ pub struct M114Command;
#[derive(Debug)]
pub enum GcodeReply {
M114Reply {
x: Option<f64>,
y: Option<f64>,
z: Option<f64>,
e: Option<f64>,
},
M114Reply { x: f64, y: f64, z: f64, e: f64 },
}
impl M114Command {
@ -31,7 +45,7 @@ impl GcodeCommand for M114Command {
fn command(&self) -> &'static str {
"M114"
}
fn parse_reply(&self, reply: &str) -> GcodeReply {
fn parse_reply(&self, reply: &str) -> Result<GcodeReply> {
lazy_static! {
static ref RE_SET: Vec<Regex> = vec![
Regex::new(r"X:(\d+(?:\.\d+))").unwrap(),
@ -41,20 +55,25 @@ impl GcodeCommand for M114Command {
];
}
let fields: Vec<Option<f64>> = RE_SET
let fields: Vec<Result<f64>> = RE_SET
.iter()
.map(|re| {
re.captures(reply)
.and_then(|cpt| cpt.get(1).map(|mtch| mtch.as_str().to_string()))
.and_then(|s| s.parse().ok())
.ok_or(GcodeReplyError {
parsed_input: reply.to_string(),
problem: format!("Failed to match to regex {}", re.as_str()),
sent_command: self.command().to_string(),
})
})
.collect();
GcodeReply::M114Reply {
x: fields[0],
y: fields[1],
z: fields[2],
e: fields[3],
}
Ok(GcodeReply::M114Reply {
x: fields[0].clone()?,
y: fields[1].clone()?,
z: fields[2].clone()?,
e: fields[3].clone()?,
})
}
}

View file

@ -5,8 +5,8 @@ use futures::sink::SinkExt;
use futures::stream::StreamExt;
use std::{fmt::Write, io, rc::Rc, str};
use tokio;
use tokio::sync::mpsc::{channel, Sender};
use tokio_serial::SerialPortBuilderExt;
use tokio::sync::mpsc::{Sender, channel};
use tokio_util::codec::{Decoder, Encoder};
pub use gcode::{GcodeCommand, GcodeReply, M114Command};