Improve documentation
This commit is contained in:
parent
50e1bce54a
commit
79ddd63935
1 changed files with 33 additions and 16 deletions
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue