Add gcode reply channel
This commit is contained in:
parent
6f92fae6c2
commit
a9dcb7e517
|
@ -7,22 +7,19 @@ const DEFAULT_TTY: &str = "/dev/ttyUSB0";
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> tokio_serial::Result<()> {
|
async fn main() -> tokio_serial::Result<()> {
|
||||||
let printer = Printer::connect(DEFAULT_TTY).await.unwrap();
|
let mut printer = Printer::connect(DEFAULT_TTY).await.unwrap();
|
||||||
printer
|
printer
|
||||||
.printer_in
|
.send_gcode(Box::new(M114Command::new()))
|
||||||
.send(Box::new(M114Command::new()))
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
printer
|
printer
|
||||||
.printer_in
|
.send_gcode(Box::new(G28Command::new(true, true, true)))
|
||||||
.send(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
|
||||||
.printer_in
|
.send_gcode(Box::new(G0Command {
|
||||||
.send(Box::new(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),
|
||||||
|
@ -33,8 +30,7 @@ async fn main() -> tokio_serial::Result<()> {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
|
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
|
||||||
printer
|
printer
|
||||||
.printer_in
|
.send_gcode(Box::new(G0Command {
|
||||||
.send(Box::new(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),
|
||||||
|
|
|
@ -5,15 +5,20 @@ use futures::sink::SinkExt;
|
||||||
use futures::stream::StreamExt;
|
use futures::stream::StreamExt;
|
||||||
use std::{fmt::Write, io, rc::Rc, str};
|
use std::{fmt::Write, io, rc::Rc, str};
|
||||||
use tokio;
|
use tokio;
|
||||||
use tokio::sync::mpsc::{channel, Sender};
|
use tokio::sync::mpsc::{channel, Receiver, Sender};
|
||||||
use tokio_serial::SerialPortBuilderExt;
|
use tokio_serial::SerialPortBuilderExt;
|
||||||
use tokio_util::codec::{Decoder, Encoder};
|
use tokio_util::codec::{Decoder, Encoder};
|
||||||
|
|
||||||
pub use gcode::{GcodeCommand, GcodeReply};
|
pub use gcode::{GcodeCommand, GcodeReply};
|
||||||
|
|
||||||
|
use self::gcode::GcodeReplyError;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum PrinterError {
|
pub enum PrinterError {
|
||||||
IO(std::io::Error),
|
IO(std::io::Error),
|
||||||
|
PrinterTaskDown,
|
||||||
|
OutputChannelDropped,
|
||||||
|
GcodeReply(GcodeReplyError),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct State {
|
pub struct State {
|
||||||
|
@ -21,11 +26,26 @@ pub struct State {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Printer {
|
pub struct Printer {
|
||||||
pub printer_in: Sender<Box<dyn GcodeCommand>>,
|
printer_in: Sender<Box<dyn GcodeCommand>>,
|
||||||
|
printer_out: Receiver<Result<GcodeReply, PrinterError>>,
|
||||||
pub state: Rc<State>,
|
pub state: Rc<State>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Printer {
|
impl Printer {
|
||||||
|
pub async fn send_gcode(
|
||||||
|
&mut self,
|
||||||
|
gcode: Box<dyn GcodeCommand>,
|
||||||
|
) -> Result<GcodeReply, PrinterError> {
|
||||||
|
self.printer_in
|
||||||
|
.send(gcode)
|
||||||
|
.await
|
||||||
|
.map_err(|_| PrinterError::PrinterTaskDown)?;
|
||||||
|
self.printer_out
|
||||||
|
.recv()
|
||||||
|
.await
|
||||||
|
.unwrap_or(Err(PrinterError::PrinterTaskDown))
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn connect(port_path: &str) -> Result<Self, PrinterError> {
|
pub async fn connect(port_path: &str) -> Result<Self, PrinterError> {
|
||||||
let mut port = tokio_serial::new(port_path, 115200)
|
let mut port = tokio_serial::new(port_path, 115200)
|
||||||
.open_native_async()
|
.open_native_async()
|
||||||
|
@ -35,35 +55,42 @@ impl Printer {
|
||||||
.expect("Unable to set serial port exclusive to false");
|
.expect("Unable to set serial port exclusive to false");
|
||||||
|
|
||||||
let connection = LineCodec.framed(port);
|
let connection = LineCodec.framed(port);
|
||||||
let (tx, mut rx) = channel::<Box<dyn GcodeCommand>>(32);
|
let (printer_in_tx, mut printer_in_rx) = channel::<Box<dyn GcodeCommand>>(32);
|
||||||
|
let (printer_out_tx, printer_out_rx) = channel::<Result<GcodeReply, PrinterError>>(32);
|
||||||
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let (mut printer_tx, mut printer_rx) = connection.split();
|
let (mut serial_tx, mut serial_rx) = connection.split();
|
||||||
|
|
||||||
// The printer will send some info after connecting. We need to wait for this
|
// The printer will send some info after connecting. We need to wait for this
|
||||||
// to be received as it will otherwise stop responding for some reason:
|
// to be received as it will otherwise stop responding for some reason:
|
||||||
while let Some(stuff) = printer_rx.next().await {
|
while let Some(stuff) = serial_rx.next().await {
|
||||||
if stuff.map(|s| s.contains("Loaded")).unwrap_or(false) {
|
if stuff.map(|s| s.contains("Loaded")).unwrap_or(false) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while let Some(command) = rx.recv().await {
|
while let Some(command) = printer_in_rx.recv().await {
|
||||||
let command_text = format!("{}\n", command.command());
|
let command_text = format!("{}\n", command.command());
|
||||||
printer_tx.send(command_text).await.unwrap();
|
serial_tx.send(command_text).await.unwrap();
|
||||||
while let Some(reply) = printer_rx.next().await {
|
while let Some(reply) = serial_rx.next().await {
|
||||||
let reply = reply.unwrap();
|
let reply = reply.unwrap();
|
||||||
if reply.contains("ok") {
|
if reply.contains("ok") {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
let reply = command.parse_reply(&reply);
|
let reply = command.parse_reply(&reply);
|
||||||
println!("got reply: {:?}", reply);
|
println!("got reply: {:?}", reply);
|
||||||
|
printer_out_tx
|
||||||
|
.send(reply.map_err(PrinterError::GcodeReply))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(Printer {
|
Ok(Printer {
|
||||||
printer_in: tx,
|
printer_in: printer_in_tx,
|
||||||
|
printer_out: printer_out_rx,
|
||||||
state: Rc::new(State {
|
state: Rc::new(State {
|
||||||
position: (0.0, 0.0, 0.0, 0.0),
|
position: (0.0, 0.0, 0.0, 0.0),
|
||||||
}),
|
}),
|
||||||
|
|
Loading…
Reference in a new issue