blackboxer 0.1.4

A Rust library for capturing, logging, and replaying MAVLink messages
Documentation
use crate::types::{BbinHeader, LoggedMessage, LoggedMessageHeader};
use mavlink::ardupilotmega::MavMessage;
use mavlink::read_v2_msg;
use std::fs::File;
use std::io::{self, BufReader, Read};
use bincode::deserialize_from;

pub struct BbinReader {
    reader: BufReader<File>,
}

impl BbinReader {
    pub fn new(file_path: &str) -> io::Result<Self> {
        let file = File::open(file_path)?;
        let mut reader = BufReader::new(file);
        let header: BbinHeader = deserialize_from(&mut reader)
            .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
        if header.magic != *b"BBIN" {
            return Err(io::Error::new(io::ErrorKind::InvalidData, "Invalid BBIN file magic"));
        }
        Ok(BbinReader { reader })
    }

    pub fn read_messages(&mut self, filter_msg_type: Option<&str>, show: bool) -> io::Result<()> {
        loop {
            let header: LoggedMessageHeader = match deserialize_from(&mut self.reader) {
                Ok(h) => h,
                Err(e) => {
                    match *e {
                        bincode::ErrorKind::Io(ref io_err) if io_err.kind() == io::ErrorKind::UnexpectedEof => {
                            if show {
                                println!("Reached EOF or incomplete message, stopping.");
                            }
                            break;
                        }
                        _ => {
                            return Err(io::Error::new(io::ErrorKind::InvalidData, e));
                        }
                    }
                }
            };

            let mut msg_buf = vec![0u8; header.msg_len as usize];
            self.reader.read_exact(&mut msg_buf)?;

            let mut packet: &[u8] = &msg_buf;
            match read_v2_msg::<MavMessage, _>(&mut packet) {
                Ok((_hdr, msg)) => {
                    let msg_type_str = format!("{:?}", msg);
                    if show {
                        if let Some(filter) = filter_msg_type {
                            if msg_type_str.contains(filter) {
                                println!("{} message: {:?}\nTimestamp: {}", filter, msg, header.timestamp);
                            }
                        } else {
                            println!("Message: {:?}\nTimestamp: {}", msg, header.timestamp);
                        }
                    }
                }
                Err(e) => {
                    eprintln!("Failed to decode MAVLink message: {:?}", e);
                }
            }
        }
        Ok(())
    }

    pub fn read_and_collect(&mut self, filter_msg_type: Option<&str>) -> io::Result<Vec<LoggedMessage>> {
        let mut messages = Vec::new();

        loop {
            let header: LoggedMessageHeader = match deserialize_from(&mut self.reader) {
                Ok(h) => h,
                Err(e) => {
                    match *e {
                        bincode::ErrorKind::Io(ref io_err) if io_err.kind() == io::ErrorKind::UnexpectedEof => {
                            break;
                        }
                        _ => return Err(io::Error::new(io::ErrorKind::InvalidData, e)),
                    }
                }
            };

            let mut msg_buf = vec![0u8; header.msg_len as usize];
            self.reader.read_exact(&mut msg_buf)?;

            let mut packet: &[u8] = &msg_buf;
            match read_v2_msg::<MavMessage, _>(&mut packet) {
                Ok((_hdr, msg)) => {
                    let msg_type_str = format!("{:?}", msg);
                    if let Some(filter) = filter_msg_type {
                        if !msg_type_str.contains(filter) {
                            continue;
                        }
                    }
                    messages.push(LoggedMessage {
                        timestamp: header.timestamp,
                        message: msg,
                        is_armed: false,
                        message_type: msg_type_str,
                    });
                }
                Err(e) => {
                    eprintln!("Failed to decode MAVLink message: {:?}", e);
                }
            }
        }

        Ok(messages)
    }
}