Improve documentation

This commit is contained in:
zaubentrucker 2025-02-24 22:51:53 +01:00
parent 50e1bce54a
commit 79ddd63935

View file

@ -52,13 +52,19 @@ pub enum AutoReportSetting {
#[derive(Debug)]
pub enum PrinterError {
IO(io::Error),
PrinterTaskDown,
OutputChannelDropped,
/// The IO thread crashed. This can be recovered by dropping the `Printer`
/// struct and connecting a new one.
IoThreadDied,
/// The reply from the printer didn't match the GCODE that was sent
GcodeReply(GcodeReplyError),
// If the "ok" line can't be parsed
ConfirmationError { parsed_string: String },
/// The "ok" line can't be parsed. This can happen if the printer doesn't
/// have `#define ADVANCED_OK`.
ConfirmationError {
parsed_string: String,
},
/// The printer didn't reply to a GCODE command in time.
NoResponseFromPrinter(String),
// If the initial printer configuration fails
/// The initial printer configuration failed
InitializationError(String),
}
@ -69,6 +75,7 @@ impl std::fmt::Display for PrinterError {
}
impl std::error::Error for PrinterError {}
/// Position of the printer at a point in time in printer units (usually mm)
#[derive(Debug, Clone, Copy)]
pub struct PrinterPosition {
pub x: f64,
@ -82,6 +89,7 @@ pub enum MovementMode {
RelativeMovements,
}
/// State that a printer may have during operation
#[derive(Debug, Clone)]
pub struct State {
pub position: PrinterPosition,
@ -92,9 +100,10 @@ pub struct State {
pub struct Printer {
pub state: Arc<Mutex<State>>,
/// Queue a command to be sent to the IO thread
to_io_thread: std::sync::mpsc::Sender<String>,
to_io_thread: Sender<String>,
/// Used read replies as received from the printer. Should not be written to
from_io_thread: std::sync::mpsc::Receiver<Vec<u8>>,
from_io_thread: Receiver<Vec<u8>>,
/// Maximum
maximum_buffer_capacity: usize,
}
@ -114,13 +123,14 @@ impl Printer {
Err(RecvTimeoutError::Timeout) => {
Err(PrinterError::NoResponseFromPrinter(command_text))
}
Err(RecvTimeoutError::Disconnected) => Err(PrinterError::OutputChannelDropped),
Err(RecvTimeoutError::Disconnected) => Err(PrinterError::IoThreadDied),
}
}
pub fn connect(mut port: TTYPort) -> Result<Self, PrinterError> {
// The printer will send some info after connecting for the first time. We need to wait for this
// to be received as it will otherwise stop responding for some reason:
// The printer will send some info after connecting for the first time. We need to wait for
// this to be received before sending anything on our own as it will otherwise stop
// responding for some reason:
port.set_timeout(SERIALPORT_TIMEOUT)
.expect("Cannot set serial port timeout");
@ -164,7 +174,7 @@ impl Printer {
from_io_thread,
to_io_thread,
state: state.clone(),
maximum_buffer_capacity: 0, // this is updated on the next call to `send_gcode()`
maximum_buffer_capacity: 0, // this is updated below
};
// This implicitly sets `res.last_buffer_capacity`
@ -204,12 +214,13 @@ impl Printer {
}
/// Parse the "Ok" confirmation line that the printer sends after every successfully received
/// command.
/// command. The printers Marlin firmware must have `#define ADVANCED_OK`.
fn parse_ok(line: &str) -> Result<usize, PrinterError> {
let make_err = || PrinterError::ConfirmationError {
parsed_string: line.to_string(),
};
lazy_static! {
// P = planner buffer, B = unprocessed command buffer
static ref RE: Regex = Regex::new(r"ok P(\d+) B(\d+)").unwrap();
}
let captures = RE.captures(line).ok_or_else(make_err)?;
@ -377,15 +388,21 @@ impl Printer {
/// Background thread that handles direct communication with the printer serial port
///
/// Parameters
/// * `state` - State that is shared between background thread and the thread that owns the
/// according `Printer` struct
/// * `to_user_thread` - Replies from the printer to the last GCODE command on
/// `from_user_thread` will be sent here. Only whole lines are submitted
/// , and the `ok ...` lines will be filtered out.
/// * `from_user_thread` - GCODE commands may be sent here one at a time.
/// They should not end in `\n`.
/// * `port` - Serial port that the printer is connected to
/// * `state` - State that is shared between background thread and the
/// thread that owns the according `Printer` struct
fn io_thread_work(
to_user_thread: Sender<Vec<u8>>,
from_user_thread: Receiver<String>,
mut port: TTYPort,
state: Arc<Mutex<State>>,
) {
// Bytes that were read from the port that don't constitute a whole line
// Bytes that were read from the port that don't constitute a whole line yet
let mut partial_reads: Vec<u8> = Vec::new();
loop {
match from_user_thread.recv_timeout(Duration::from_millis(10)) {
@ -396,10 +413,10 @@ impl Printer {
&mut partial_reads,
to_user_thread.clone(),
),
Err(RecvTimeoutError::Disconnected) => break,
Err(RecvTimeoutError::Timeout) => {
handle_printer_autoreport(&mut port, &mut partial_reads, state.clone());
}
Err(RecvTimeoutError::Disconnected) => break,
}
}
}