Use generics instead of dyn

This commit is contained in:
Frederik Menke 2023-12-17 23:05:17 +01:00
parent b72c601a25
commit 4c7540b524
10 changed files with 40 additions and 30 deletions

View file

@ -34,7 +34,7 @@ pub type PrinterVec = Vector3D<f64, PrinterUnits>;
/// Jog the gantry by pumping loads of gcode into the printer board
pub async fn jog(gamepad: Arc<Gamepad>, mut printer: Printer) -> Never {
printer.send_gcode(Box::new(G91Command)).await.unwrap();
printer.send_gcode(G91Command).await.unwrap();
println!("Sent G91Command");
loop {
let (setpoint_x, setpoint_y, setpoint_z) = gamepad.speed_setpoint();
@ -57,7 +57,7 @@ pub async fn jog(gamepad: Arc<Gamepad>, mut printer: Printer) -> Never {
velocity: velocity.into(),
};
printer
.send_gcode(Box::new(command))
.send_gcode(command)
.await
.expect("Failed to send movement command!");

View file

@ -73,35 +73,32 @@ async fn write_to_spindle() -> Never {
async fn write_to_printer() -> Never {
let mut printer = Printer::connect(DEFAULT_TTY).await.unwrap();
printer.send_gcode(M114Command::new()).await.unwrap();
printer
.send_gcode(Box::new(M114Command::new()))
.await
.unwrap();
printer
.send_gcode(Box::new(G28Command::new(true, true, true)))
.send_gcode(G28Command::new(true, true, true))
.await
.unwrap();
loop {
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
printer
.send_gcode(Box::new(G0Command {
.send_gcode(G0Command {
x: Some(50.0),
y: Some(50.0),
z: Some(5.0),
e: None,
velocity: None,
}))
})
.await
.unwrap();
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
printer
.send_gcode(Box::new(G0Command {
.send_gcode(G0Command {
x: Some(25.0),
y: Some(25.0),
z: Some(5.0),
e: None,
velocity: None,
}))
})
.await
.unwrap();
}

View file

@ -11,6 +11,7 @@ pub struct G0Command {
}
impl GcodeCommand for G0Command {
type Reply = ();
fn command(&self) -> String {
fn unpack(letter: &str, o: Option<f64>) -> String {
o.map(|x| format!("{}{:.3}", letter, x)).unwrap_or_default()
@ -25,9 +26,9 @@ impl GcodeCommand for G0Command {
)
}
fn parse_reply(&self, reply: &str) -> Result<GcodeReply> {
fn parse_reply(&self, reply: &str) -> Result<Self::Reply> {
if reply.is_empty() {
Ok(GcodeReply::NoReply)
Ok(())
} else {
Err(GcodeReplyError {
sent_command: self.command(),

View file

@ -19,6 +19,7 @@ impl G28Command {
}
impl GcodeCommand for G28Command {
type Reply = ();
fn command(&self) -> String {
let x = if self.home_x { "X" } else { "" };
let y = if self.home_y { "Y" } else { "" };
@ -26,7 +27,7 @@ impl GcodeCommand for G28Command {
format!("G28 {} {} {}", x, y, z)
}
fn parse_reply(&self, reply: &str) -> Result<GcodeReply> {
fn parse_reply(&self, reply: &str) -> Result<Self::Reply> {
if !reply.is_empty() {
Err(GcodeReplyError {
sent_command: self.command(),
@ -34,7 +35,7 @@ impl GcodeCommand for G28Command {
problem: "Expected no reply".to_string(),
})
} else {
Ok(GcodeReply::NoReply)
Ok(())
}
}
}

View file

@ -5,11 +5,12 @@ use super::*;
pub struct G90Command;
impl GcodeCommand for G90Command {
type Reply = ();
fn command(&self) -> String {
"G90".into()
}
fn parse_reply(&self, reply: &str) -> Result<GcodeReply> {
fn parse_reply(&self, reply: &str) -> Result<()> {
if !reply.is_empty() {
Err(GcodeReplyError {
sent_command: self.command(),
@ -17,7 +18,7 @@ impl GcodeCommand for G90Command {
problem: "Expected no reply".to_string(),
})
} else {
Ok(GcodeReply::NoReply)
Ok(())
}
}
}

View file

@ -5,11 +5,12 @@ use super::*;
pub struct G91Command;
impl GcodeCommand for G91Command {
type Reply = ();
fn command(&self) -> String {
"G91".into()
}
fn parse_reply(&self, reply: &str) -> Result<GcodeReply> {
fn parse_reply(&self, reply: &str) -> Result<()> {
if !reply.is_empty() {
Err(GcodeReplyError {
sent_command: self.command(),
@ -17,7 +18,7 @@ impl GcodeCommand for G91Command {
problem: "Expected no reply".to_string(),
})
} else {
Ok(GcodeReply::NoReply)
Ok(())
}
}
}

View file

@ -1,3 +1,5 @@
use crate::printer::PrinterPosition;
use super::*;
use lazy_static::lazy_static;
use regex::Regex;
@ -13,12 +15,12 @@ impl M114Command {
}
impl GcodeCommand for M114Command {
type Reply = PrinterPosition;
fn command(&self) -> String {
"M114".into()
}
// TODO: This one doesn't seem to work and throws an error
fn parse_reply(&self, reply: &str) -> Result<GcodeReply> {
fn parse_reply(&self, reply: &str) -> Result<Self::Reply> {
lazy_static! {
static ref RE_SET: Vec<Regex> = vec![
Regex::new(r"X:(\d+(?:\.\d+))").unwrap(),
@ -42,11 +44,10 @@ impl GcodeCommand for M114Command {
})
.collect();
Ok(GcodeReply::M114Reply {
Ok(PrinterPosition {
x: fields[0].clone()?,
y: fields[1].clone()?,
z: fields[2].clone()?,
e: fields[3].clone()?,
})
}
}

View file

@ -5,11 +5,12 @@ use super::*;
pub struct M997Command;
impl GcodeCommand for M997Command {
type Reply = ();
fn command(&self) -> String {
"M997".into()
}
fn parse_reply(&self, reply: &str) -> Result<GcodeReply> {
fn parse_reply(&self, reply: &str) -> Result<Self::Reply> {
if !reply.is_empty() {
Err(GcodeReplyError {
sent_command: self.command(),
@ -17,7 +18,7 @@ impl GcodeCommand for M997Command {
problem: "Expected no reply".to_string(),
})
} else {
Ok(GcodeReply::NoReply)
Ok(())
}
}
}

View file

@ -49,6 +49,7 @@ impl std::fmt::Display for GcodeReplyError {
}
pub trait GcodeCommand: Debug + Send {
type Reply;
fn command(&self) -> String;
fn parse_reply(&self, reply: &str) -> Result<GcodeReply>;
fn parse_reply(&self, reply: &str) -> Result<Self::Reply>;
}

View file

@ -34,6 +34,12 @@ pub enum PrinterError {
NoResponseFromPrinter(String),
}
pub struct PrinterPosition {
x: f64,
y: f64,
z: f64,
}
pub struct State {
position: (f64, f64, f64, f64),
}
@ -48,10 +54,10 @@ pub struct Printer {
impl Printer {
/// Send gcode to the printer and parse its reply
pub async fn send_gcode(
pub async fn send_gcode<T: GcodeCommand>(
&mut self,
command: Box<dyn GcodeCommand>,
) -> Result<GcodeReply, PrinterError> {
command: T,
) -> Result<T::Reply, PrinterError> {
let command_text = format!("{}\n", command.command());
self.serial_tx.send(command_text.clone()).await.unwrap();
let mut reply = String::with_capacity(RECV_BUFFER_CAPACITY);
@ -127,7 +133,7 @@ impl Printer {
maximum_buffer_capacity: 0, // this is updated on the next call to `send_gcode()`
};
res.send_gcode(Box::new(G91Command))
res.send_gcode(G91Command)
.await
.expect("Could not ask for current position!");