libexail 0.1.0

A rust library for communicating with Exail devices through their binary protocol
Documentation
use anyhow::Result;
use clap::Parser;
use libexail::{Message, NavigationBlock, parse_datagram};
use std::net::UdpSocket;

#[derive(Parser)]
#[command(about = "Listen for Exail datagrams on UDP")]
struct Args {
    /// UDP port to listen on
    #[arg(default_value_t = 8080)]
    port: u16,

    /// Print full message debug output
    #[arg(short, long)]
    verbose: bool,
}

fn main() -> Result<()> {
    let args = Args::parse();

    let addr = format!("0.0.0.0:{}", args.port);
    let socket = UdpSocket::bind(&addr)?;
    eprintln!("Listening on {addr}...");

    let mut buf = [0u8; 65536];
    let mut count: usize = 0;

    loop {
        let (n, src) = socket.recv_from(&mut buf)?;

        match parse_datagram(&buf[..n]) {
            Ok(msg) => {
                count += 1;
                if args.verbose {
                    println!("#{count} [{src}] {msg:?}");
                    continue;
                }

                match &msg {
                    Message::NavigationData(frame) => {
                        print!("#{count} [{src}] NavigationData:");
                        for block in &frame.navigation {
                            match block {
                                NavigationBlock::Position(p) => {
                                    print!(
                                        " lat={:.6} lon={:.6} alt={:.2}m",
                                        p.latitude, p.longitude, p.altitude,
                                    );
                                }
                                NavigationBlock::AttitudeHeading(a) => {
                                    print!(
                                        " hdg={:.1} roll={:.1} pitch={:.1}",
                                        a.heading, a.roll, a.pitch,
                                    );
                                }
                                _ => {}
                            }
                        }
                        println!();
                    }
                    Message::InputData(_) => println!("#{count} [{src}] InputData"),
                    Message::Command(_) => println!("#{count} [{src}] Command"),
                    Message::Answer(_) => println!("#{count} [{src}] Answer"),
                }
            }
            Err(e) => {
                eprintln!("[{src}] Parse error: {e:?}");
            }
        }
    }
}