Fix read line loop

This commit is contained in:
zaubentrucker 2025-02-18 22:48:28 +01:00
parent 60aea0a4f5
commit 0199799633
2 changed files with 46 additions and 14 deletions
red/src

View file

@ -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));
}
}

View file

@ -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);
}