Crate blackbox_log

source ·
Expand description

Ergonomic parser for Betaflight blackbox logs.

For details about the format of blackbox logs, see the Blackbox Internals development documentation from INAV, Betaflight, or EmuFlight.

Examples

The simplest way to extract a few fields of interest:

use blackbox_log::frame::FieldDef;
use blackbox_log::prelude::*;

let file = b"...";
for mut reader in blackbox_log::File::new(file).iter() {
    let mut headers = Headers::parse(&mut reader).unwrap();

    // This restricts the included fields to `loopIteration`, `time` and
    // `rcCommand[0]` through `rcCommand[3]` for main frames
    headers.main_frame_def.apply_filter(&["rcCommand"].into());

    // ... and only `flightModeFlags` for slow frames
    let filter = FieldFilter::from(["flightModeFlags"]);
    headers.slow_frame_def.apply_filter(&filter);

    let mut parser = DataParser::new(reader, &headers);
    while let Some(event) = parser.next() {
        match event {
            ParserEvent::Main(main) => {
                for (value, FieldDef { name, .. }) in
                    main.iter().zip(headers.main_frame_def.iter())
                {
                    println!("{name}: {value:?}");
                }
            }
            ParserEvent::Slow(slow) => {
                for (value, FieldDef { name, .. }) in
                    slow.iter().zip(headers.slow_frame_def.iter())
                {
                    println!("{name}: {value:?}");
                }
            }
            ParserEvent::Event(_) | ParserEvent::Gps(_) => {}
        }
    }
}

Get only the GPS data without parsing logs that cannot contain GPS frames:

use blackbox_log::frame::FieldDef;
use blackbox_log::prelude::*;

let file = b"...";
let file = blackbox_log::File::new(file);

for mut reader in file.iter() {
    let headers = Headers::parse(&mut reader).unwrap();

    if let Some(gps_def) = &headers.gps_frame_def {
        let mut parser = DataParser::new(reader, &headers);

        while let Some(event) = parser.next() {
            if let ParserEvent::Gps(gps) = event {
                for (value, FieldDef { name, .. }) in gps.iter().zip(gps_def.iter()) {
                    println!("{name}: {value:?}");
                }
            }
        }
    }
}

Features

  • std: Enabled by default. Currently, this only implements std::error::Error for headers::ParseError.
  • serde: Disabled by default. This allows serializing parsed logs using serde. Note: This is only used for internal snapshot testing and is not yet intended for public use.

Re-exports

pub use self::data::DataParser;
pub use self::data::ParserEvent;
pub use self::event::Event;
pub use self::frame::Unit;
pub use self::frame::Value;
pub use self::headers::Headers;

Modules

Types for the data section of blackbox logs.
Types for blackbox log events.
Types for blackbox log data frames.
Types for the header section of blackbox logs.
Minimal set of imports for convenience.

Structs

A filter for the fields to be included in one kind of frame.
A complete blackbox log file containing zero or more logs.
A wrapper around a byte slice to efficiently read data from a blackbox log.