From 3b5514e825c7315ae270b695c0956e5f28f45592 Mon Sep 17 00:00:00 2001 From: Ben Sherriff Date: Wed, 23 Apr 2025 19:20:30 -0400 Subject: [PATCH] Updated adsb stuff --- adsb/Cargo.toml | 4 +- adsb/adsb_lib/src/{adsb.rs => adsb_frame.rs} | 26 ++---- adsb/adsb_lib/src/lib.rs | 6 +- adsb/adsb_recv/src/main.rs | 52 ------------ adsb/adsb_sim/Cargo.toml | 8 -- adsb/{adsb_recv => squawk}/Cargo.toml | 6 +- adsb/squawk/src/main.rs | 79 +++++++++++++++++++ adsb/{adsb_recv => squawk}/src/rusb_device.rs | 0 adsb/{adsb_recv => squawk}/src/tcp_device.rs | 6 +- adsb/squawk_sim/Cargo.toml | 10 +++ adsb/{adsb_sim => squawk_sim}/src/main.rs | 29 ++++--- bruno/Airports/Import Airports.bru | 2 +- 12 files changed, 128 insertions(+), 100 deletions(-) rename adsb/adsb_lib/src/{adsb.rs => adsb_frame.rs} (95%) delete mode 100644 adsb/adsb_recv/src/main.rs delete mode 100644 adsb/adsb_sim/Cargo.toml rename adsb/{adsb_recv => squawk}/Cargo.toml (51%) create mode 100644 adsb/squawk/src/main.rs rename adsb/{adsb_recv => squawk}/src/rusb_device.rs (100%) rename adsb/{adsb_recv => squawk}/src/tcp_device.rs (97%) create mode 100644 adsb/squawk_sim/Cargo.toml rename adsb/{adsb_sim => squawk_sim}/src/main.rs (86%) diff --git a/adsb/Cargo.toml b/adsb/Cargo.toml index 0eb62b8..41b8578 100644 --- a/adsb/Cargo.toml +++ b/adsb/Cargo.toml @@ -1,8 +1,8 @@ [workspace] members = [ "adsb_lib", - "adsb_recv", - "adsb_sim" + "squawk", + "squawk_sim" ] resolver = "2" package.version = "0.1.0" diff --git a/adsb/adsb_lib/src/adsb.rs b/adsb/adsb_lib/src/adsb_frame.rs similarity index 95% rename from adsb/adsb_lib/src/adsb.rs rename to adsb/adsb_lib/src/adsb_frame.rs index 96d444a..f1974eb 100644 --- a/adsb/adsb_lib/src/adsb.rs +++ b/adsb/adsb_lib/src/adsb_frame.rs @@ -141,7 +141,7 @@ impl TryFrom for Capability { return Err(Error::new( ErrorKind::InvalidData, format!("invalid CA value: {}", value), - )) + )); } }; Ok(capability) @@ -164,9 +164,8 @@ impl TryFrom for Capability { pub enum ADSBMessage { AircraftIdentification(AircraftIdentification), SurfacePosition(SurfacePosition), - AirbornePositionBaro(AirbornePositionBaro), + AirbornePosition(AirbornePosition), AirborneVelocities(AirborneVelocities), - AirbornePositionGNSS(AirbornePositionGNSS), Reserved(u8), AircraftStatus(AircraftStatus), TargetState(TargetState), @@ -188,9 +187,9 @@ impl ADSBMessage { ADSBMessage::AircraftIdentification(AircraftIdentification::decode(type_code, data)?) } 5..=8 => ADSBMessage::SurfacePosition(SurfacePosition::decode(data)?), - 9..=18 => ADSBMessage::AirbornePositionBaro(AirbornePositionBaro::decode(data)?), + 9..=18 => ADSBMessage::AirbornePosition(AirbornePosition::decode(type_code, data)?), 19 => ADSBMessage::AirborneVelocities(AirborneVelocities::decode(data)?), - 20..=22 => ADSBMessage::AirbornePositionGNSS(AirbornePositionGNSS::decode(data)?), + 20..=22 => ADSBMessage::AirbornePosition(AirbornePosition::decode(type_code, data)?), 23..=27 => ADSBMessage::Reserved(type_code), 28 => ADSBMessage::AircraftStatus(AircraftStatus::decode(data)?), 29 => ADSBMessage::TargetState(TargetState::decode(data)?), @@ -199,7 +198,7 @@ impl ADSBMessage { return Err(Error::new( ErrorKind::InvalidData, format!("unsupported ADS-B type_code {}", type_code), - )) + )); } }; @@ -310,10 +309,10 @@ impl SurfacePosition { } #[derive(Debug, Clone, PartialEq, Eq)] -pub struct AirbornePositionBaro {} +pub struct AirbornePosition {} -impl AirbornePositionBaro { - pub fn decode(_data: &[u8]) -> Result { +impl AirbornePosition { + pub fn decode(_type_code: u8, _data: &[u8]) -> Result { Ok(Self {}) } } @@ -327,15 +326,6 @@ impl AirborneVelocities { } } -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct AirbornePositionGNSS {} - -impl AirbornePositionGNSS { - pub fn decode(_data: &[u8]) -> Result { - Ok(Self {}) - } -} - #[derive(Debug, Clone, PartialEq, Eq)] pub struct AircraftStatus {} diff --git a/adsb/adsb_lib/src/lib.rs b/adsb/adsb_lib/src/lib.rs index 1adc8dd..b958696 100644 --- a/adsb/adsb_lib/src/lib.rs +++ b/adsb/adsb_lib/src/lib.rs @@ -1,6 +1,6 @@ use std::io::{Error, ErrorKind, Result}; -pub mod adsb; +pub mod adsb_frame; pub mod device; pub fn hex_to_bytes(s: &str) -> Result> { @@ -20,7 +20,7 @@ pub fn hex_to_bytes(s: &str) -> Result> { return Err(Error::new( ErrorKind::InvalidInput, format!("invalid hex char '{}'", chunk[0] as char), - )) + )); } }; let lo = match hex_val(chunk[1]) { @@ -29,7 +29,7 @@ pub fn hex_to_bytes(s: &str) -> Result> { return Err(Error::new( ErrorKind::InvalidInput, format!("invalid hex char '{}'", chunk[1] as char), - )) + )); } }; out.push((hi << 4) | lo); diff --git a/adsb/adsb_recv/src/main.rs b/adsb/adsb_recv/src/main.rs deleted file mode 100644 index c822df2..0000000 --- a/adsb/adsb_recv/src/main.rs +++ /dev/null @@ -1,52 +0,0 @@ -mod rusb_device; -mod tcp_device; - -use crate::rusb_device::RusbDevice; -use crate::tcp_device::TcpDevice; -use adsb_lib::adsb::ADSBFrame; -use adsb_lib::{hex_to_bytes, device::run}; -use clap::Parser; -use std::io::Result; - -#[derive(Parser, Debug)] -#[command(author, version, about, long_about = None)] -struct ReceiverArgs { - #[arg(long)] - decode: Option, - - #[arg(long)] - net: bool, - #[arg(long, default_value = "127.0.0.1:9999", requires = "net")] - addr: String, - - #[arg(long)] - usb: bool, -} - -fn main() -> Result<()> { - let args = ReceiverArgs::parse(); - - if let Some(mut hex_string) = args.decode { - if let Some(stripped) = hex_string.strip_prefix("0x") { - hex_string = stripped.to_string(); - } - let buf = hex_to_bytes(&hex_string)?; - let frame = ADSBFrame::decode(&buf)?; - - println!("{}", frame); - return Ok(()); - } - - if args.net { - println!("Connecting to network {}", args.addr); - let mut device = TcpDevice::connect(&args.addr)?; - device.run() - } else if args.usb { - println!("Connecting to device"); - let mut device = RusbDevice::open()?; - run(&mut device) - } else { - println!("No connection specified"); - Ok(()) - } -} diff --git a/adsb/adsb_sim/Cargo.toml b/adsb/adsb_sim/Cargo.toml deleted file mode 100644 index 7ebf7c9..0000000 --- a/adsb/adsb_sim/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "adsb_sim" -version = "0.1.0" -edition = "2024" - -[dependencies] -adsb_lib = { path = "../adsb_lib" } -clap = { version = "4.5.37", features = ["derive"] } \ No newline at end of file diff --git a/adsb/adsb_recv/Cargo.toml b/adsb/squawk/Cargo.toml similarity index 51% rename from adsb/adsb_recv/Cargo.toml rename to adsb/squawk/Cargo.toml index 1f30ab6..3681de2 100644 --- a/adsb/adsb_recv/Cargo.toml +++ b/adsb/squawk/Cargo.toml @@ -1,9 +1,11 @@ [package] -name = "adsb_recv" +name = "squawk" version = "0.1.0" edition = "2024" [dependencies] adsb_lib = { path = "../adsb_lib" } rusb = "0.9.4" -clap = { version = "4.5.37", features = ["derive"] } \ No newline at end of file +clap = { version = "4.5.37", features = ["derive"] } +log = "0.4.27" +env_logger = "0.11.8" diff --git a/adsb/squawk/src/main.rs b/adsb/squawk/src/main.rs new file mode 100644 index 0000000..b8d8d20 --- /dev/null +++ b/adsb/squawk/src/main.rs @@ -0,0 +1,79 @@ +mod rusb_device; +mod tcp_device; + +use crate::rusb_device::RusbDevice; +use crate::tcp_device::TcpDevice; +use adsb_lib::adsb_frame::ADSBFrame; +use adsb_lib::{hex_to_bytes, device::run}; +use clap::Parser; +use std::io::Result; + +#[derive(Parser, Debug)] +#[command(author, version, about, long_about = "An ADS-B Receiver")] +struct ReceiverArgs { + /// Hex-string to decode + #[arg(long)] + decode: Option, + + /// Connect to the network + #[arg(long)] + net: bool, + /// Network listen address (requires --net) + #[arg(long, requires = "net", hide = true)] + addr: Option, + /// Network listen port (requires --net) + #[arg(long, requires = "net", hide = true)] + port: Option, + + /// Connect to the USB device + #[arg(long)] + usb: bool, + + /// Enable debug logging + #[arg(short, long, action)] + debug: bool, +} + +fn main() -> Result<()> { + let args = ReceiverArgs::parse(); + + let default_filter = if args.debug { + "warn,squawk=debug" + } else { + "warn,squawk=info" + }; + + env_logger::init_from_env(env_logger::Env::default().filter_or("RUST_LOG", default_filter)); + + // Handle decode mode + if let Some(mut hex_string) = args.decode { + if let Some(stripped) = hex_string.strip_prefix("0x") { + hex_string = stripped.to_string(); + } + let buf = hex_to_bytes(&hex_string)?; + let frame = ADSBFrame::decode(&buf)?; + + log::info!("{}", frame); + return Ok(()); + } + + // Handle net mode + if args.net { + let host = args.addr.unwrap_or_else(|| "127.0.0.1".into()); + let port = args.port.unwrap_or(9999); + let addr = format!("{host}:{port}"); + + log::info!("Connecting to network {}", addr); + let mut device = TcpDevice::connect(&addr)?; + device.run() + } + // Handle usb mode + else if args.usb { + log::info!("Connecting to device"); + let mut device = RusbDevice::open()?; + run(&mut device) + } else { + log::warn!("No connection specified"); + Ok(()) + } +} diff --git a/adsb/adsb_recv/src/rusb_device.rs b/adsb/squawk/src/rusb_device.rs similarity index 100% rename from adsb/adsb_recv/src/rusb_device.rs rename to adsb/squawk/src/rusb_device.rs diff --git a/adsb/adsb_recv/src/tcp_device.rs b/adsb/squawk/src/tcp_device.rs similarity index 97% rename from adsb/adsb_recv/src/tcp_device.rs rename to adsb/squawk/src/tcp_device.rs index 1297207..c46762d 100644 --- a/adsb/adsb_recv/src/tcp_device.rs +++ b/adsb/squawk/src/tcp_device.rs @@ -1,7 +1,7 @@ use adsb_lib::device::Device; use std::io::{Error, ErrorKind, Read, Result, Write}; use std::net::TcpStream; -use adsb_lib::adsb::ADSBFrame; +use adsb_lib::adsb_frame::ADSBFrame; // Tags for framing requests/responses over the TCP socket const TAG_CTRL_OUT: u8 = 0x10; @@ -34,7 +34,7 @@ impl TcpDevice { let mut status = [0u8; 1]; self.socket.read_exact(&mut status)?; if status[0] != 0 { - eprintln!("Remote reported error status {}", status[0]); + log::error!("Remote reported error status {}", status[0]); break; } @@ -54,7 +54,7 @@ impl TcpDevice { } let frame = ADSBFrame::decode(&adsb)?; - println!("{}", frame); + log::info!("{}", frame); } Ok(()) diff --git a/adsb/squawk_sim/Cargo.toml b/adsb/squawk_sim/Cargo.toml new file mode 100644 index 0000000..91a762a --- /dev/null +++ b/adsb/squawk_sim/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "squawk_sim" +version = "0.1.0" +edition = "2024" + +[dependencies] +adsb_lib = { path = "../adsb_lib" } +clap = { version = "4.5.37", features = ["derive"] } +log = "0.4.27" +env_logger = "0.11.8" diff --git a/adsb/adsb_sim/src/main.rs b/adsb/squawk_sim/src/main.rs similarity index 86% rename from adsb/adsb_sim/src/main.rs rename to adsb/squawk_sim/src/main.rs index 5b86e9c..b53035a 100644 --- a/adsb/adsb_sim/src/main.rs +++ b/adsb/squawk_sim/src/main.rs @@ -26,11 +26,14 @@ struct SimulationArgs { } fn main() { + env_logger::init_from_env( + env_logger::Env::default().filter_or("RUST_LOG", "warn,squawk_sim=info"), + ); let args = SimulationArgs::parse(); // Build the bind address, e.g. "127.0.0.1:9999" let bind_address = format!("{}:{}", args.host, args.port); - println!("Listening on {}", bind_address); + log::info!("Listening on {}", bind_address); // Start listening for incoming TCP connections let listener = TcpListener::bind(&bind_address) @@ -43,18 +46,18 @@ fn main() { // Spawn a thread per client thread::spawn(move || { if let Err(err) = handle_client_connection(client_stream) { - eprintln!("connection error: {}", err); + log::error!("connection error: {}", err); } }); } - Err(err) => eprintln!("error accepting connection: {}", err), + Err(err) => log::error!("error accepting connection: {}", err), } } } /// Handle a single client connection fn handle_client_connection(mut connection: TcpStream) -> Result<()> { - println!("Connection established"); + log::info!("Connection established"); loop { // Read the 4-byte header: [tag:1][bRequest:1][length:2 LE] let mut header_buffer = [0u8; 4]; @@ -67,13 +70,17 @@ fn handle_client_connection(mut connection: TcpStream) -> Result<()> { let _b_request = header_buffer[1]; let payload_length = u16::from_le_bytes([header_buffer[2], header_buffer[3]]) as usize; - // println!("Received message '{:02x}' with payload length {}", message_tag, payload_length); + log::trace!( + "Received message '{:02x}' with payload length {}", + message_tag, + payload_length + ); // Read the optional payload // let mut payload_buffer = vec![0u8; payload_length]; // if payload_length > 0 { // if connection.read(&mut payload_buffer).is_err() { - // eprintln!("error reading payload buffer"); + // log::error!("error reading payload buffer"); // break; // } // } @@ -81,19 +88,19 @@ fn handle_client_connection(mut connection: TcpStream) -> Result<()> { // Dispatch based on the framing tag match message_tag { TAG_CONTROL_OUT => { - // println!("Received control out"); + log::trace!("Received control out"); // Acknowledge with a status OK connection.write_all(&[0u8])?; } TAG_CONTROL_IN => { - // println!("Received control in"); + log::trace!("Received control in"); // STATUS(1) + LENGTH(2) + dummy payload connection.write_all(&[0x00])?; connection.write_all(&(payload_length as u16).to_le_bytes())?; connection.write_all(&vec![0x42; payload_length])?; } TAG_BULK => { - // println!("Received bulk message"); + log::trace!("Received bulk message"); let iq = generate_adsb_iq(); // STATUS(1) + LENGTH(4) + IQ data connection.write_all(&[0x00])?; @@ -104,13 +111,13 @@ fn handle_client_connection(mut connection: TcpStream) -> Result<()> { thread::sleep(Duration::from_millis(10)); } _unknown_tag => { - eprintln!("Unknown message tag {}", _unknown_tag); + log::warn!("Unknown message tag {}", _unknown_tag); break; } } } - println!("Connection closed"); + log::info!("Connection closed"); Ok(()) } diff --git a/bruno/Airports/Import Airports.bru b/bruno/Airports/Import Airports.bru index 34a3935..fd5ad96 100644 --- a/bruno/Airports/Import Airports.bru +++ b/bruno/Airports/Import Airports.bru @@ -11,5 +11,5 @@ post { } body:multipart-form { - : @file(/Users/bsherriff/git/private/aviation-weather/data/airports_2023-12-21.json) + : @file(/Users/bsherriff/git/private/aviation/data/airports_2023-12-21.json) }