#![warn(clippy::all, clippy::pedantic)] use anyhow::Result; use chrono::{TimeDelta, Utc}; use log::{error, info}; use nautilus_common::add_ctrlc_handler; use nautilus_common::command::{SetPin, ValidPriorityCommand}; use nautilus_common::telemetry::Telemetry; use nautilus_common::udp::{UdpRecvPostcardError, UdpSocketExt}; use std::net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket}; use std::sync::Arc; use std::sync::atomic::{AtomicBool, Ordering}; use std::time::Duration; /// Run the Ground Software /// /// # Errors /// If any unhandled error occurred in the Ground Software pub fn run() -> Result<()> { info!( "Project Nautilus Ground Software {}", env!("CARGO_PKG_VERSION") ); let running = Arc::new(AtomicBool::new(true)); add_ctrlc_handler(running.clone())?; let mut flight_addr = None; let bind_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 14000); let udp = UdpSocket::bind(bind_addr)?; udp.set_read_timeout(Some(Duration::from_millis(100)))?; let mut buffer = [0u8; 512]; let mut do_once = true; while running.load(Ordering::Relaxed) { match udp.recv_postcard::(&mut buffer) { Ok((tlm, addr)) => { flight_addr = Some(addr); info!("{tlm:?}"); if do_once { do_once = false; udp.send_command( "/mcp23017a/set", &ValidPriorityCommand { inner: SetPin { pin: 0, value: true, }, valid_until: Utc::now() + TimeDelta::seconds(5), priority: 0, }, addr, )?; } } Err(UdpRecvPostcardError::NoData) => { // NoOp } Err(err) => { error!("Rx error: {err}"); } } } if let Some(flight_addr) = flight_addr { udp.send_command("/shutdown", &(), flight_addr)?; // let cmd_data = CommandData::Shutdown; // udp.send_postcard(&cmd_data, &mut buffer, flight_addr)?; // let cmd_data = SetPin { // pin: 4, // value: true, // valid_until: Utc::now(), // priority: 120, // }; // let cmd_data = postcard::to_allocvec(&cmd_data)?; // // let cmd = CommandHeader { // name: "/shutdown", // data: &cmd_data, // }; // // let encoded = postcard::to_allocvec(&cmd)?; // println!("{}", hex::encode(&encoded)); // // let decoded = postcard::from_bytes::(&encoded)?; // println!("{decoded:?}"); // // let (decoded, remainder) = postcard::take_from_bytes::(decoded.data)?; // ensure!(remainder.is_empty(), "Not all command bytes consumed"); // println!("{decoded:?}"); // let mut another_buffer = Cursor::new([0u8; 512]); // // ciborium::into_writer(&cmd, &mut another_buffer)?; // let _ = Serializer::writer(&cmd, &mut another_buffer)?; // let size_encoded = usize::try_from(another_buffer.position())?; // let _ = test(&another_buffer.get_ref()[0..size_encoded])?; } Ok(()) }