From 6ab691e87c2b8896cfadc656008a3cb72c14661c Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 28 Aug 2022 00:28:29 +0200 Subject: [PATCH] basic TMTC infastructure for example --- .../Run_obsw_client_example.xml | 19 ++++ .idea/runConfigurations/Run_obsw_example.xml | 19 ++++ Cargo.lock | 1 + fsrc-core/src/hal/host/udp_server.rs | 14 ++- fsrc-core/src/hal/mod.rs | 2 +- fsrc-core/src/tmtc/ccsds_distrib.rs | 40 ++++--- fsrc-core/src/tmtc/mod.rs | 3 + fsrc-core/src/tmtc/pus_distrib.rs | 7 +- fsrc-core/tests/pool_test.rs | 3 +- fsrc-example/Cargo.toml | 3 + fsrc-example/src/bin/client.rs | 2 +- fsrc-example/src/bin/obsw.rs | 103 ++++++++++++++++-- spacepackets | 2 +- 13 files changed, 179 insertions(+), 39 deletions(-) create mode 100644 .idea/runConfigurations/Run_obsw_client_example.xml create mode 100644 .idea/runConfigurations/Run_obsw_example.xml diff --git a/.idea/runConfigurations/Run_obsw_client_example.xml b/.idea/runConfigurations/Run_obsw_client_example.xml new file mode 100644 index 0000000..dc85ad6 --- /dev/null +++ b/.idea/runConfigurations/Run_obsw_client_example.xml @@ -0,0 +1,19 @@ + + + + \ No newline at end of file diff --git a/.idea/runConfigurations/Run_obsw_example.xml b/.idea/runConfigurations/Run_obsw_example.xml new file mode 100644 index 0000000..ed323c9 --- /dev/null +++ b/.idea/runConfigurations/Run_obsw_example.xml @@ -0,0 +1,19 @@ + + + + \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 455bb58..af38bfb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -235,6 +235,7 @@ dependencies = [ name = "fsrc-example" version = "0.1.0" dependencies = [ + "fsrc-core", "spacepackets", ] diff --git a/fsrc-core/src/hal/host/udp_server.rs b/fsrc-core/src/hal/host/udp_server.rs index 53a67c5..b2c4b40 100644 --- a/fsrc-core/src/hal/host/udp_server.rs +++ b/fsrc-core/src/hal/host/udp_server.rs @@ -1,20 +1,24 @@ use crate::hal::host::udp_server::ReceiveResult::{IoError, ReceiverError}; use crate::tmtc::ReceivesTc; +use std::boxed::Box; use std::net::{SocketAddr, ToSocketAddrs, UdpSocket}; +use std::vec; use std::vec::Vec; -pub struct UdpTmtcServer { - socket: UdpSocket, +pub struct UdpTcServer { + pub socket: UdpSocket, recv_buf: Vec, + sender_addr: Option, tc_receiver: Box>, } +#[derive(Debug)] pub enum ReceiveResult { IoError(std::io::Error), ReceiverError(E), } -impl UdpTmtcServer { +impl UdpTcServer { pub fn new( addr: A, max_recv_size: usize, @@ -22,7 +26,8 @@ impl UdpTmtcServer { ) -> Result { Ok(Self { socket: UdpSocket::bind(addr)?, - recv_buf: Vec::with_capacity(max_recv_size), + recv_buf: vec![0; max_recv_size], + sender_addr: None, tc_receiver, }) } @@ -32,6 +37,7 @@ impl UdpTmtcServer { .socket .recv_from(&mut self.recv_buf) .map_err(|e| IoError(e))?; + self.sender_addr = Some(res.1); self.tc_receiver .pass_tc(&self.recv_buf[0..res.0]) .map_err(|e| ReceiverError(e))?; diff --git a/fsrc-core/src/hal/mod.rs b/fsrc-core/src/hal/mod.rs index 43769ba..0c9616d 100644 --- a/fsrc-core/src/hal/mod.rs +++ b/fsrc-core/src/hal/mod.rs @@ -1,2 +1,2 @@ -#[cfg(feature = "use_std")] +#[cfg(feature = "std")] pub mod host; diff --git a/fsrc-core/src/tmtc/ccsds_distrib.rs b/fsrc-core/src/tmtc/ccsds_distrib.rs index dfe1238..15bd1bb 100644 --- a/fsrc-core/src/tmtc/ccsds_distrib.rs +++ b/fsrc-core/src/tmtc/ccsds_distrib.rs @@ -2,7 +2,7 @@ //! //! The routing components consist of two core components: //! 1. [CcsdsDistributor] component which dispatches received packets to a user-provided handler -//! 2. [ApidPacketHandler] trait which should be implemented by the user-provided packet handler. +//! 2. [CcsdsPacketHandler] trait which should be implemented by the user-provided packet handler. //! //! The [CcsdsDistributor] implements the [ReceivesCcsdsTc] and [ReceivesTc] trait which allows to //! pass raw or CCSDS packets to it. Upon receiving a packet, it performs the following steps: @@ -11,14 +11,14 @@ //! respective CCSDS space packet header field. If that process fails, a [PacketError] is //! returned to the user //! 2. If a valid APID is found and matches one of the APIDs provided by -//! [ApidPacketHandler::valid_apids], it will pass the packet to the user provided -//! [ApidPacketHandler::handle_known_apid] function. If no valid APID is found, the packet -//! will be passed to the [ApidPacketHandler::handle_unknown_apid] function. +//! [CcsdsPacketHandler::valid_apids], it will pass the packet to the user provided +//! [CcsdsPacketHandler::handle_known_apid] function. If no valid APID is found, the packet +//! will be passed to the [CcsdsPacketHandler::handle_unknown_apid] function. //! //! # Example //! //! ```rust -//! use fsrc_core::tmtc::ccsds_distrib::{ApidPacketHandler, CcsdsDistributor}; +//! use fsrc_core::tmtc::ccsds_distrib::{CcsdsPacketHandler, CcsdsDistributor}; //! use fsrc_core::tmtc::ReceivesTc; //! use spacepackets::{CcsdsPacket, SpHeader}; //! use spacepackets::tc::PusTc; @@ -33,7 +33,7 @@ //! fn mutable_foo(&mut self) {} //! } //! -//! impl ApidPacketHandler for ConcreteApidHandler { +//! impl CcsdsPacketHandler for ConcreteApidHandler { //! type Error = (); //! fn valid_apids(&self) -> &'static [u16] { &[0x002] } //! fn handle_known_apid(&mut self, sp_header: &SpHeader, tc_raw: &[u8]) -> Result<(), Self::Error> { @@ -86,7 +86,7 @@ //! ``` use crate::tmtc::{ReceivesCcsdsTc, ReceivesTc}; use downcast_rs::Downcast; -use spacepackets::{CcsdsPacket, PacketError, SpHeader}; +use spacepackets::{CcsdsPacket, PacketError, SizeMissmatch, SpHeader}; /// Generic trait for a handler or dispatcher object handling CCSDS packets. /// @@ -98,7 +98,7 @@ use spacepackets::{CcsdsPacket, PacketError, SpHeader}; /// This trait automatically implements the [downcast_rs::Downcast] to allow a more convenient API /// to cast trait objects back to their concrete type after the handler was passed to the /// distributor. -pub trait ApidPacketHandler: Downcast { +pub trait CcsdsPacketHandler: Downcast { type Error; fn valid_apids(&self) -> &'static [u16]; @@ -111,14 +111,14 @@ pub trait ApidPacketHandler: Downcast { ) -> Result<(), Self::Error>; } -downcast_rs::impl_downcast!(ApidPacketHandler assoc Error); +downcast_rs::impl_downcast!(CcsdsPacketHandler assoc Error); /// The CCSDS distributor dispatches received CCSDS packets to a user provided packet handler. pub struct CcsdsDistributor { /// User provided APID handler stored as a generic trait object. /// It can be cast back to the original concrete type using the [Self::apid_handler_ref] or /// the [Self::apid_handler_mut] method. - pub apid_handler: Box>, + pub apid_handler: Box>, } #[derive(Debug, Copy, Clone, PartialEq, Eq)] @@ -139,26 +139,34 @@ impl ReceivesTc for CcsdsDistributor { type Error = CcsdsError; fn pass_tc(&mut self, tc_raw: &[u8]) -> Result<(), Self::Error> { + if tc_raw.len() < 7 { + return Err(CcsdsError::PacketError( + PacketError::FromBytesSliceTooSmall(SizeMissmatch { + found: tc_raw.len(), + expected: 7, + }), + )); + } let sp_header = SpHeader::from_raw_slice(tc_raw).map_err(|e| CcsdsError::PacketError(e))?; self.dispatch_ccsds(&sp_header, tc_raw) } } impl CcsdsDistributor { - pub fn new(apid_handler: Box>) -> Self { + pub fn new(apid_handler: Box>) -> Self { CcsdsDistributor { apid_handler } } /// This function can be used to retrieve a reference to the concrete instance of the APID /// handler after it was passed to the distributor. See the /// [module documentation][crate::tmtc::ccsds_distrib] for an fsrc-example. - pub fn apid_handler_ref>(&self) -> Option<&T> { + pub fn apid_handler_ref>(&self) -> Option<&T> { self.apid_handler.downcast_ref::() } /// This function can be used to retrieve a mutable reference to the concrete instance of the /// APID handler after it was passed to the distributor. - pub fn apid_handler_mut>(&mut self) -> Option<&mut T> { + pub fn apid_handler_mut>(&mut self) -> Option<&mut T> { self.apid_handler.downcast_mut::() } @@ -182,7 +190,7 @@ impl CcsdsDistributor { #[cfg(test)] pub(crate) mod tests { use super::*; - use crate::tmtc::ccsds_distrib::{ApidPacketHandler, CcsdsDistributor}; + use crate::tmtc::ccsds_distrib::{CcsdsDistributor, CcsdsPacketHandler}; use spacepackets::tc::PusTc; use spacepackets::CcsdsPacket; use std::collections::VecDeque; @@ -207,7 +215,7 @@ pub(crate) mod tests { pub unknown_packet_queue: VecDeque<(u16, Vec)>, } - impl ApidPacketHandler for BasicApidHandlerSharedQueue { + impl CcsdsPacketHandler for BasicApidHandlerSharedQueue { type Error = (); fn valid_apids(&self) -> &'static [u16] { &[0x000, 0x002] @@ -242,7 +250,7 @@ pub(crate) mod tests { } } - impl ApidPacketHandler for BasicApidHandlerOwnedQueue { + impl CcsdsPacketHandler for BasicApidHandlerOwnedQueue { type Error = (); fn valid_apids(&self) -> &'static [u16] { diff --git a/fsrc-core/src/tmtc/mod.rs b/fsrc-core/src/tmtc/mod.rs index 0c9c02c..7d52337 100644 --- a/fsrc-core/src/tmtc/mod.rs +++ b/fsrc-core/src/tmtc/mod.rs @@ -12,6 +12,9 @@ use spacepackets::SpHeader; pub mod ccsds_distrib; pub mod pus_distrib; +pub use ccsds_distrib::{CcsdsDistributor, CcsdsError, CcsdsPacketHandler}; +pub use pus_distrib::{PusDistributor, PusServiceProvider}; + const _RAW_PACKET_ERROR: &str = "raw-tmtc"; const _CCSDS_ERROR: &str = "ccsds-tmtc"; const _PUS_ERROR: &str = "pus-tmtc"; diff --git a/fsrc-core/src/tmtc/pus_distrib.rs b/fsrc-core/src/tmtc/pus_distrib.rs index 2928110..8a3dfa6 100644 --- a/fsrc-core/src/tmtc/pus_distrib.rs +++ b/fsrc-core/src/tmtc/pus_distrib.rs @@ -137,7 +137,8 @@ mod tests { use crate::tmtc::ccsds_distrib::tests::{ generate_ping_tc, BasicApidHandlerOwnedQueue, BasicApidHandlerSharedQueue, }; - use crate::tmtc::ccsds_distrib::{ApidPacketHandler, CcsdsDistributor}; + use crate::tmtc::ccsds_distrib::{CcsdsDistributor, CcsdsPacketHandler}; + use alloc::vec::Vec; use spacepackets::ecss::PusError; use spacepackets::tc::PusTc; use spacepackets::CcsdsPacket; @@ -235,11 +236,11 @@ mod tests { }; } - impl ApidPacketHandler for ApidHandlerOwned { + impl CcsdsPacketHandler for ApidHandlerOwned { apid_handler_impl!(); } - impl ApidPacketHandler for ApidHandlerShared { + impl CcsdsPacketHandler for ApidHandlerShared { apid_handler_impl!(); } diff --git a/fsrc-core/tests/pool_test.rs b/fsrc-core/tests/pool_test.rs index 54e10e9..aaa7910 100644 --- a/fsrc-core/tests/pool_test.rs +++ b/fsrc-core/tests/pool_test.rs @@ -1,7 +1,6 @@ +use fsrc_core::pool::{LocalPool, PoolCfg, StoreAddr, StoreError}; use std::sync::{Arc, RwLock}; use std::thread; -use fsrc_core::pool::{LocalPool, PoolCfg, StoreAddr, StoreError}; - struct PoolAccessDummy<'a> { pool: &'a mut LocalPool, diff --git a/fsrc-example/Cargo.toml b/fsrc-example/Cargo.toml index 1ddb71a..8f29e3b 100644 --- a/fsrc-example/Cargo.toml +++ b/fsrc-example/Cargo.toml @@ -6,3 +6,6 @@ authors = ["Robin Mueller "] [dependencies.spacepackets] path = "../spacepackets" + +[dependencies.fsrc-core] +path = "../fsrc-core" diff --git a/fsrc-example/src/bin/client.rs b/fsrc-example/src/bin/client.rs index 5956570..1a71a73 100644 --- a/fsrc-example/src/bin/client.rs +++ b/fsrc-example/src/bin/client.rs @@ -8,7 +8,7 @@ fn main() { let addr = SocketAddr::new(IpAddr::V4(OBSW_SERVER_ADDR), SERVER_PORT); let mut sph = SpHeader::tc(0x02, 0, 0).unwrap(); let pus_tc = PusTc::new_simple(&mut sph, 17, 1, None, true); - let client = UdpSocket::bind("127.0.0.1:7300").expect("Connecting to UDP server failed"); + let client = UdpSocket::bind("127.0.0.1:7302").expect("Connecting to UDP server failed"); let size = pus_tc.write_to(&mut buf).expect("Creating PUS TC failed"); client .send_to(&buf[0..size], &addr) diff --git a/fsrc-example/src/bin/obsw.rs b/fsrc-example/src/bin/obsw.rs index 690cd3e..f4ae995 100644 --- a/fsrc-example/src/bin/obsw.rs +++ b/fsrc-example/src/bin/obsw.rs @@ -1,15 +1,96 @@ +use fsrc_core::hal::host::udp_server::{ReceiveResult, UdpTcServer}; +use fsrc_core::tmtc::{ + CcsdsDistributor, CcsdsError, CcsdsPacketHandler, PusDistributor, PusServiceProvider, + ReceivesCcsdsTc, +}; use fsrc_example::{OBSW_SERVER_ADDR, SERVER_PORT}; -use std::net::{IpAddr, SocketAddr, UdpSocket}; +use spacepackets::tc::PusTc; +use spacepackets::{CcsdsPacket, SpHeader}; +use std::net::{IpAddr, SocketAddr}; -fn main() { - let mut recv_buf = [0; 1024]; - let addr = SocketAddr::new(IpAddr::V4(OBSW_SERVER_ADDR), SERVER_PORT); - let socket = UdpSocket::bind(&addr).expect("Error opening UDP socket"); - loop { - let (num_bytes, src) = socket.recv_from(&mut recv_buf).expect("UDP Receive error"); - println!( - "Received TM with len {num_bytes} from {src}: {:x?}", - &recv_buf[0..num_bytes] - ); +const PUS_APID: u16 = 0x02; + +struct PusReceiver {} + +struct CcsdsReceiver { + pus_handler: PusDistributor<()>, +} + +impl CcsdsPacketHandler for CcsdsReceiver { + type Error = (); + + fn valid_apids(&self) -> &'static [u16] { + &[PUS_APID] + } + + fn handle_known_apid( + &mut self, + sp_header: &SpHeader, + tc_raw: &[u8], + ) -> Result<(), Self::Error> { + if sp_header.apid() == PUS_APID { + self.pus_handler + .pass_ccsds(sp_header, tc_raw) + .expect("Handling PUS packet failed"); + } + Ok(()) + } + + fn handle_unknown_apid( + &mut self, + _sp_header: &SpHeader, + _tc_raw: &[u8], + ) -> Result<(), Self::Error> { + println!("Unknown APID detected"); + Ok(()) + } +} + +impl PusServiceProvider for PusReceiver { + type Error = (); + + fn handle_pus_tc_packet( + &mut self, + service: u8, + _header: &SpHeader, + pus_tc: &PusTc, + ) -> Result<(), Self::Error> { + if service == 17 { + println!("Received PUS ping command"); + let raw_data = pus_tc.raw().expect("Could not retrieve raw data"); + println!("Raw data: 0x{raw_data:x?}"); + } + Ok(()) + } +} + +fn main() { + let addr = SocketAddr::new(IpAddr::V4(OBSW_SERVER_ADDR), SERVER_PORT); + let pus_receiver = PusReceiver {}; + let pus_distributor = PusDistributor::new(Box::new(pus_receiver)); + let ccsds_receiver = CcsdsReceiver { + pus_handler: pus_distributor, + }; + let ccsds_distributor = CcsdsDistributor::new(Box::new(ccsds_receiver)); + let mut udp_tmtc_server = UdpTcServer::new(addr, 2048, Box::new(ccsds_distributor)) + .expect("Creating UDP TMTC server failed"); + loop { + let res = udp_tmtc_server.recv_tc(); + match res { + Ok(_) => (), + Err(e) => match e { + ReceiveResult::ReceiverError(e) => match e { + CcsdsError::PacketError(e) => { + println!("Got packet error: {e:?}"); + } + CcsdsError::CustomError(_) => { + println!("Unknown receiver error") + } + }, + ReceiveResult::IoError(e) => { + println!("IO error {e}"); + } + }, + } } } diff --git a/spacepackets b/spacepackets index 35073a4..42d3487 160000 --- a/spacepackets +++ b/spacepackets @@ -1 +1 @@ -Subproject commit 35073a45a536051e3852696c501d7afa1b36a808 +Subproject commit 42d3487c1934cfecf9b2d599c2f81fde52a61cc3