use anyhow::Result;
use clap::Parser;
use libexail::{Message, NavigationBlock, reader::ExailReader};
use std::{collections::HashMap, fs::File};
#[derive(Parser)]
#[command(about = "Parse Exail frames from a binary file")]
struct Args {
file: String,
#[arg(short, long)]
verbose: bool,
}
fn main() -> Result<()> {
let args = Args::parse();
eprintln!("Reading from file: {}", args.file);
let file = File::open(&args.file)?;
let reader = ExailReader::new(file);
let mut stats: HashMap<String, usize> = HashMap::new();
for result in reader {
let msg = result?;
if args.verbose {
println!("{msg:?}");
}
let label = match &msg {
Message::NavigationData(frame) => {
if !args.verbose {
for block in &frame.navigation {
match block {
NavigationBlock::Position(p) => {
println!(
"Position: lat={:.6} lon={:.6} alt={:.2}m",
p.latitude, p.longitude, p.altitude,
);
}
NavigationBlock::AttitudeHeading(a) => {
println!(
"Attitude: hdg={:.1} roll={:.1} pitch={:.1}",
a.heading, a.roll, a.pitch,
);
}
NavigationBlock::SpeedGeographic(s) => {
println!(
"Speed: N={:.2} E={:.2} U={:.2} m/s",
s.north, s.east, s.up,
);
}
_ => {}
}
}
}
"NavigationData"
}
Message::InputData(_) => "InputData",
Message::Command(_) => "Command",
Message::Answer(_) => "Answer",
};
*stats.entry(label.to_string()).or_insert(0) += 1;
}
eprintln!("\n=== Message Statistics ===");
let total: usize = stats.values().sum();
let mut sorted: Vec<_> = stats.iter().collect();
sorted.sort_by(|a, b| b.1.cmp(a.1));
for (msg_type, count) in &sorted {
eprintln!("{msg_type}: {count}");
}
eprintln!("Total messages: {total}");
Ok(())
}