Fix read line loop
This commit is contained in:
parent
60aea0a4f5
commit
0199799633
2 changed files with 46 additions and 14 deletions
|
@ -25,6 +25,7 @@ fn look_for_printer() -> Never {
|
|||
println!("Found serial port: {:?}", &port_path);
|
||||
let printer = Printer::connect_to_path(&port_path.as_os_str().to_string_lossy()).unwrap();
|
||||
loop {
|
||||
println!("{}", printer.printer_state());
|
||||
println!("{:?}", printer.printer_state());
|
||||
std::thread::sleep(std::time::Duration::from_millis(1000));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ pub mod gcode;
|
|||
use lazy_static::lazy_static;
|
||||
|
||||
use core::panic;
|
||||
pub use gcode::{GcodeCommand};
|
||||
use regex::Regex;
|
||||
use serialport::SerialPort;
|
||||
use serialport::TTYPort;
|
||||
|
@ -18,8 +19,6 @@ use std::sync::Mutex;
|
|||
use std::time::{Duration, Instant};
|
||||
use std::{io, str};
|
||||
|
||||
pub use gcode::{GcodeCommand, GcodeReply};
|
||||
|
||||
use crate::printer::gcode::{G91Command, M114Command};
|
||||
|
||||
use self::gcode::{G0Command, G28Command, G90Command, GcodeReplyError};
|
||||
|
@ -112,7 +111,7 @@ impl Printer {
|
|||
.expect("Cannot set serial port timeout");
|
||||
|
||||
let mut buf = [0; 1024];
|
||||
let deadline = Instant::now() + Duration::from_millis(200);
|
||||
let deadline = Instant::now() + Duration::from_millis(2000);
|
||||
let mut initial_msg = Vec::new();
|
||||
while Instant::now() < deadline {
|
||||
if let Ok(message) = port.read(&mut buf) {
|
||||
|
@ -359,15 +358,42 @@ impl Printer {
|
|||
|
||||
/// Check for auto-report messages coming in from the printer and update the `state` accordingly
|
||||
fn handle_printer_autoreport(port: &mut TTYPort, state: Arc<Mutex<State>>) {
|
||||
todo!()
|
||||
if port
|
||||
.bytes_to_read()
|
||||
.expect("`handle_printer_autoreport`: Failed to check for available data")
|
||||
> 0
|
||||
{
|
||||
let mut buf = [0; BUF_SIZE_READ_LINE];
|
||||
let bytes_read = port
|
||||
.read(&mut buf)
|
||||
.expect("`handle_printer_autoreport`: Failed to read data");
|
||||
assert!(
|
||||
bytes_read > 0,
|
||||
"The port returned 0 bytes after a read. Is the port closed?"
|
||||
);
|
||||
match String::from_utf8(buf[..bytes_read].to_vec()) {
|
||||
Ok(s) => {
|
||||
println!("Received autoreport:");
|
||||
println!("<< {}", s);
|
||||
}
|
||||
Err(e) => {
|
||||
panic!(
|
||||
"`handle_printer_autoreport` Failed to parse received bytes `{}` as UTF8: {}",
|
||||
bytes_read, e
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Read a line from `port` unless it timeouts
|
||||
///
|
||||
/// Parameters
|
||||
/// * `port` - The port to read from
|
||||
/// * `already_read` - Read bytes from a previous call. May not contain `\n`.
|
||||
/// On a successful read, the buffer will be cleared and then filled with the new residual bytes
|
||||
/// * `already_read` - Read bytes from a previous call.
|
||||
/// On a successful read, the buffer will be cleared until the end of the returned line and then
|
||||
/// filled with the new residual bytes. It might contain an entire line if the port returns
|
||||
/// multiple lines in one read. It is fine to then call this function again to retrieve the line.
|
||||
/// * `timeout` - Time to wait for new bytes from the `port` before raising a timeout error
|
||||
///
|
||||
/// Returns
|
||||
|
@ -383,6 +409,11 @@ fn read_line(
|
|||
let deadline = Instant::now() + timeout;
|
||||
let mut buf = [0; BUF_SIZE_READ_LINE];
|
||||
while Instant::now() < deadline {
|
||||
if let Some(line_break_idx) = already_read.iter().position(|x| *x == b'\n') {
|
||||
let res = Ok(already_read[..line_break_idx].into());
|
||||
*already_read = already_read[line_break_idx+1..].into();
|
||||
return res;
|
||||
}
|
||||
match port.read(&mut buf) {
|
||||
Err(e) => {
|
||||
if let io::ErrorKind::TimedOut = e.kind() {
|
||||
|
@ -394,13 +425,6 @@ fn read_line(
|
|||
Ok(0) => panic!("TTYPort returned 0 bytes!"),
|
||||
Ok(n) => {
|
||||
already_read.extend_from_slice(&buf[..n]);
|
||||
if let Some(line_break_idx) = already_read[..n].iter().position(|x| *x == b'\n') {
|
||||
let res = Ok(already_read[..line_break_idx].into());
|
||||
*already_read = already_read[line_break_idx..].into();
|
||||
return res;
|
||||
}
|
||||
|
||||
std::thread::sleep(Duration::from_millis(5));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -417,17 +441,23 @@ fn handle_user_command(
|
|||
to_user_thread: Sender<Vec<u8>>,
|
||||
) {
|
||||
// TODO: Add timeout?
|
||||
println!(">> {}", user_command);
|
||||
port.write_all(user_command.as_bytes())
|
||||
.expect("Failed to write to printer serial port");
|
||||
port.flush().unwrap();
|
||||
|
||||
let mut already_read_lines = Vec::new();
|
||||
let mut rest = Vec::new();
|
||||
let start_time = Instant::now();
|
||||
loop {
|
||||
if start_time.elapsed() > DEFAULT_COMMAND_TIMEOUT {
|
||||
panic!("No reply from printer within timeout");
|
||||
}
|
||||
let line = read_line(port, &mut rest, DEFAULT_COMMAND_TIMEOUT)
|
||||
.expect("Failed to read from printer");
|
||||
|
||||
let str_line = String::from_utf8(line.clone()).expect("Read line was no valid utf8");
|
||||
println!("<< {:?}", str_line);
|
||||
|
||||
if str_line.starts_with("ok") {
|
||||
state.lock().unwrap().last_buffer_capacity =
|
||||
|
@ -435,6 +465,7 @@ fn handle_user_command(
|
|||
to_user_thread
|
||||
.send(already_read_lines.join(&b'\n'))
|
||||
.expect("Failed to send read bytes to user thread");
|
||||
break;
|
||||
} else {
|
||||
already_read_lines.push(line);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue