Read from serial device with timeouts

This commit is contained in:
clerie 2024-12-25 19:14:53 +01:00
parent b7b01d8600
commit e03dbe7165

View File

@ -18,7 +18,7 @@ use crate::utils::{
to_ascii_debug, to_ascii_debug,
}; };
pub fn find_begin_of_improv_packet(buffer: &Vec<u8>) -> Result<usize> { pub fn find_begin_of_improv_packet(buffer: &[u8]) -> Result<usize> {
let mut improv_header_char: usize = 0; let mut improv_header_char: usize = 0;
for (i, b) in buffer.iter().enumerate() { for (i, b) in buffer.iter().enumerate() {
@ -40,6 +40,31 @@ pub fn find_begin_of_improv_packet(buffer: &Vec<u8>) -> Result<usize> {
bail!("Improv header not found"); bail!("Improv header not found");
} }
pub struct PacketBounds {
begin: usize,
end: usize,
}
pub fn find_packet(buffer: &[u8]) -> Result<PacketBounds> {
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 + <u8 as Into<usize>>::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 { pub struct SerialInterface {
interface: Box<dyn tokio_serial::SerialPort>, interface: Box<dyn tokio_serial::SerialPort>,
buffer: Vec<u8>, buffer: Vec<u8>,
@ -77,7 +102,7 @@ impl SerialInterface {
Ok(()) Ok(())
} }
pub fn recv_bytes(&mut self) -> Result<Vec<u8>> { pub fn fill_buffer(&mut self) -> Result<()> {
let available_bytes = self.interface.bytes_to_read() let available_bytes = self.interface.bytes_to_read()
.context("Failed to figure out how many bytes are available to read")? .context("Failed to figure out how many bytes are available to read")?
.try_into()?; .try_into()?;
@ -85,10 +110,13 @@ impl SerialInterface {
debug!("Available bytes to read: {}", available_bytes); debug!("Available bytes to read: {}", available_bytes);
let mut buffer: Vec<u8> = vec![0; available_bytes]; let mut buffer: Vec<u8> = vec![0; available_bytes];
if buffer.len() > 0 { if buffer.len() <= 0 {
debug!("No bytes available to read");
return Ok(());
}
self.interface.read(&mut buffer) self.interface.read(&mut buffer)
.context("Failed to read bytes from serial device")?; .context("Failed to read bytes from serial device")?;
}
if log_enabled!(Level::Debug) { if log_enabled!(Level::Debug) {
debug!("Received bytes: \n{}\n{}", hex::encode(&buffer), to_ascii_debug(&buffer)); debug!("Received bytes: \n{}\n{}", hex::encode(&buffer), to_ascii_debug(&buffer));
@ -96,23 +124,36 @@ impl SerialInterface {
self.buffer.append(&mut buffer); self.buffer.append(&mut buffer);
Ok(())
}
pub fn recv_bytes(&mut self) -> Result<Vec<u8>> {
let retry_counter = 0;
let packet_bounds: PacketBounds;
let mut buffer: Vec<u8>;
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(); buffer = self.buffer.clone();
if log_enabled!(Level::Debug) { if let Ok(pb) = find_packet(&buffer) {
debug!("Buffer: \n{}\n{}", hex::encode(&buffer), to_ascii_debug(&buffer)); packet_bounds = pb;
break;
} }
let improv_packet_offset = find_begin_of_improv_packet(&buffer).context("Failed to find improv header in received bytes from serial device")?; std::thread::sleep(std::time::Duration::from_millis(10));
let improv_packet_end = improv_packet_offset + 10 + <u8 as Into<usize>>::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(); let packet_bytes = buffer[packet_bounds.begin..packet_bounds.end].to_vec();
self.buffer = buffer[improv_packet_end..].to_vec(); self.buffer = buffer[packet_bounds.end..].to_vec();
if log_enabled!(Level::Debug) { if log_enabled!(Level::Debug) {
debug!("Received packet: \n{}\n{}", hex::encode(&packet_bytes), to_ascii_debug(&packet_bytes)); debug!("Received packet: \n{}\n{}", hex::encode(&packet_bytes), to_ascii_debug(&packet_bytes));