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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -49,6 +49,7 @@ impl std::fmt::Display for GcodeReplyError {
} }
pub trait GcodeCommand: Debug + Send { pub trait GcodeCommand: Debug + Send {
type Reply;
fn command(&self) -> String; 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), NoResponseFromPrinter(String),
} }
pub struct PrinterPosition {
x: f64,
y: f64,
z: f64,
}
pub struct State { pub struct State {
position: (f64, f64, f64, f64), position: (f64, f64, f64, f64),
} }
@ -48,10 +54,10 @@ pub struct Printer {
impl Printer { impl Printer {
/// Send gcode to the printer and parse its reply /// Send gcode to the printer and parse its reply
pub async fn send_gcode( pub async fn send_gcode<T: GcodeCommand>(
&mut self, &mut self,
command: Box<dyn GcodeCommand>, command: T,
) -> Result<GcodeReply, PrinterError> { ) -> Result<T::Reply, PrinterError> {
let command_text = format!("{}\n", command.command()); let command_text = format!("{}\n", command.command());
self.serial_tx.send(command_text.clone()).await.unwrap(); self.serial_tx.send(command_text.clone()).await.unwrap();
let mut reply = String::with_capacity(RECV_BUFFER_CAPACITY); 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()` 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 .await
.expect("Could not ask for current position!"); .expect("Could not ask for current position!");