From e03dbe7165e9a3cb2a1e2fdc979e469aac700fac Mon Sep 17 00:00:00 2001 From: clerie Date: Wed, 25 Dec 2024 19:14:53 +0100 Subject: [PATCH] Read from serial device with timeouts --- src/serial.rs | 77 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 59 insertions(+), 18 deletions(-) diff --git a/src/serial.rs b/src/serial.rs index 9336f45..09054ac 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -18,7 +18,7 @@ use crate::utils::{ to_ascii_debug, }; -pub fn find_begin_of_improv_packet(buffer: &Vec) -> Result { +pub fn find_begin_of_improv_packet(buffer: &[u8]) -> Result { let mut improv_header_char: usize = 0; for (i, b) in buffer.iter().enumerate() { @@ -40,6 +40,31 @@ pub fn find_begin_of_improv_packet(buffer: &Vec) -> Result { bail!("Improv header not found"); } +pub struct PacketBounds { + begin: usize, + end: usize, +} + +pub fn find_packet(buffer: &[u8]) -> Result { + let improv_packet_offset = find_begin_of_improv_packet(buffer) + .context("Failed to find improv header in received bytes from serial device")?; + + let improv_packet_len_position = improv_packet_offset + 8; + if buffer.len() <= improv_packet_len_position { + bail!("Byte that contains length of improv packet not available in buffer"); + } + + let improv_packet_end = improv_packet_offset + 10 + >::into(buffer[improv_packet_len_position]); + if buffer.len() <= improv_packet_end { + bail!("Buffer stops before improv packet ends"); + } + + Ok(PacketBounds { + begin: improv_packet_offset, + end: improv_packet_end, + }) +} + pub struct SerialInterface { interface: Box, buffer: Vec, @@ -77,7 +102,7 @@ impl SerialInterface { Ok(()) } - pub fn recv_bytes(&mut self) -> Result> { + pub fn fill_buffer(&mut self) -> Result<()> { let available_bytes = self.interface.bytes_to_read() .context("Failed to figure out how many bytes are available to read")? .try_into()?; @@ -85,34 +110,50 @@ impl SerialInterface { debug!("Available bytes to read: {}", available_bytes); let mut buffer: Vec = vec![0; available_bytes]; - if buffer.len() > 0 { - self.interface.read(&mut buffer) - .context("Failed to read bytes from serial device")?; + if buffer.len() <= 0 { + debug!("No bytes available to read"); + return Ok(()); } + self.interface.read(&mut buffer) + .context("Failed to read bytes from serial device")?; + if log_enabled!(Level::Debug) { debug!("Received bytes: \n{}\n{}", hex::encode(&buffer), to_ascii_debug(&buffer)); } self.buffer.append(&mut buffer); - buffer = self.buffer.clone(); + Ok(()) + } - if log_enabled!(Level::Debug) { - debug!("Buffer: \n{}\n{}", hex::encode(&buffer), to_ascii_debug(&buffer)); + pub fn recv_bytes(&mut self) -> Result> { + let retry_counter = 0; + + let packet_bounds: PacketBounds; + let mut buffer: Vec; + + loop { + if retry_counter > 300 { + bail!("Failed to fetch more data, timed out"); + } + + self.fill_buffer() + .context("Failed to fill read buffer")?; + + buffer = self.buffer.clone(); + + if let Ok(pb) = find_packet(&buffer) { + packet_bounds = pb; + break; + } + + std::thread::sleep(std::time::Duration::from_millis(10)); } - let improv_packet_offset = find_begin_of_improv_packet(&buffer).context("Failed to find improv header in received bytes from serial device")?; + let packet_bytes = buffer[packet_bounds.begin..packet_bounds.end].to_vec(); - let improv_packet_end = improv_packet_offset + 10 + >::into(buffer[improv_packet_offset+8]); - - if buffer.len() <= improv_packet_end { - bail!("Incomplete packet, packet longer than available in buffer"); - } - - let packet_bytes = buffer[improv_packet_offset..improv_packet_end].to_vec(); - - self.buffer = buffer[improv_packet_end..].to_vec(); + self.buffer = buffer[packet_bounds.end..].to_vec(); if log_enabled!(Level::Debug) { debug!("Received packet: \n{}\n{}", hex::encode(&packet_bytes), to_ascii_debug(&packet_bytes));