rusty-telemetry/src/main.rs
Jan-Peter v. Hunnius 30543fd0ba feat: initial rusty-telemetry UDP listener
- Async UDP listener on configurable bind address (default 127.0.0.1:5005)
- RUSTY_TELEMETRY_BIND env var for cross-machine deployment
- Deserializes JSON telemetry frames with serde
- deny_unknown_fields for schema drift detection
- ReceiveStats tracker with packet rate and data rate
- Locked stdout writes for efficient output
- .gitignore for /target/ and .idea/
2026-06-01 15:13:13 +02:00

78 lines
2.3 KiB
Rust

mod stats;
mod telemetry;
use stats::ReceiveStats;
use telemetry::TelemetryFrame;
use std::io::Write;
const DEFAULT_BIND_ADDR: &str = "127.0.0.1:5005";
const BUFFER_SIZE: usize = 65535;
fn print_banner(bind_addr: &str) {
println!("========================================");
println!(" rusty-telemetry listener");
println!(" Phase 1 - UDP JSON receiver");
println!("========================================");
println!(" Bind: {}", bind_addr);
println!("========================================");
println!();
}
#[tokio::main]
async fn main() {
let bind_addr =
std::env::var("RUSTY_TELEMETRY_BIND").unwrap_or_else(|_| DEFAULT_BIND_ADDR.to_string());
print_banner(&bind_addr);
let socket = match tokio::net::UdpSocket::bind(&bind_addr).await {
Ok(s) => {
let local_addr = s.local_addr().unwrap();
println!("[INFO] Listening on {}", local_addr);
s
}
Err(e) => {
eprintln!("[ERROR] Failed to bind UDP socket: {}", e);
std::process::exit(1);
}
};
let mut buf = vec![0u8; BUFFER_SIZE];
let mut stats = ReceiveStats::new();
let stdout = std::io::stdout();
loop {
match socket.recv_from(&mut buf).await {
Ok((len, src)) => {
stats.record(len);
let text = match std::str::from_utf8(&buf[..len]) {
Ok(s) => s,
Err(e) => {
eprintln!("[WARN] Invalid UTF-8 from {}: {}", src, e);
continue;
}
};
let frame: TelemetryFrame = match serde_json::from_str(text) {
Ok(f) => f,
Err(e) => {
eprintln!("[WARN] JSON parse error from {}: {}", src, e);
continue;
}
};
{
let mut handle = stdout.lock();
let _ = writeln!(handle, "{}", frame);
let _ = writeln!(handle, " [{}] {}", src, stats);
let _ = writeln!(handle);
}
}
Err(e) => {
eprintln!("[ERROR] Receive error: {}", e);
}
}
}
}