diff --git a/satrs-core/Cargo.toml b/satrs-core/Cargo.toml index 11aa619..da11060 100644 --- a/satrs-core/Cargo.toml +++ b/satrs-core/Cargo.toml @@ -32,6 +32,7 @@ default-features = false [dependencies.serde] version = "1.0" default-features = false +optional = true [dependencies.spacepackets] path = "../spacepackets" @@ -50,6 +51,7 @@ version = "1.0" default = ["std"] std = ["downcast-rs/std", "alloc", "bus", "postcard/use-std", "crossbeam-channel/std", "serde/std"] alloc = ["serde/alloc"] +serde = ["dep:serde"] heapless = [] doc-images = [] diff --git a/satrs-core/src/tmtc/mod.rs b/satrs-core/src/tmtc/mod.rs index b1d0b3d..0a31362 100644 --- a/satrs-core/src/tmtc/mod.rs +++ b/satrs-core/src/tmtc/mod.rs @@ -5,10 +5,11 @@ //! directly dispatch received packets to packet listeners based on packet fields like the CCSDS //! Application Process ID (APID) or the ECSS PUS service type. This allows for fast packet //! routing without the overhead and complication of using message queues. However, it also requires -use crate::error::{FsrcErrorRaw, FsrcGroupIds}; use downcast_rs::{impl_downcast, Downcast}; +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; use spacepackets::tc::PusTc; -use spacepackets::SpHeader; +use spacepackets::{ByteConversionError, SizeMissmatch, SpHeader}; #[cfg(feature = "alloc")] pub mod ccsds_distrib; @@ -19,24 +20,27 @@ pub mod tm_helper; 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"; +#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct AddressableId { + pub target_id: u32, + pub unique_id: u32, +} -// TODO: A macro for general and unknown errors would be nice -const _FROM_BYTES_SLICE_TOO_SMALL_ERROR: FsrcErrorRaw = FsrcErrorRaw::new( - FsrcGroupIds::Tmtc as u8, - 0, - _RAW_PACKET_ERROR, - "FROM_BYTES_SLICE_TOO_SMALL_ERROR", -); - -const _FROM_BYTES_ZEROCOPY_ERROR: FsrcErrorRaw = FsrcErrorRaw::new( - FsrcGroupIds::Tmtc as u8, - 1, - _RAW_PACKET_ERROR, - "FROM_BYTES_ZEROCOPY_ERROR", -); +impl AddressableId { + pub fn from_raw_be(buf: &[u8]) -> Result { + if buf.len() < 8 { + return Err(ByteConversionError::FromSliceTooSmall(SizeMissmatch { + found: buf.len(), + expected: 8, + })); + } + Ok(Self { + target_id: u32::from_be_bytes(buf[0..4].try_into().unwrap()), + unique_id: u32::from_be_bytes(buf[4..8].try_into().unwrap()), + }) + } +} /// Generic trait for object which can receive any telecommands in form of a raw bytestream, with /// no assumptions about the received protocol. diff --git a/satrs-example/src/hk.rs b/satrs-example/src/hk.rs index 01c4139..96cd37b 100644 --- a/satrs-example/src/hk.rs +++ b/satrs-example/src/hk.rs @@ -1,3 +1,4 @@ +#![allow(dead_code)] pub type CollectionIntervalFactor = u32; #[derive(Debug, Copy, Clone, PartialEq, Eq)] @@ -8,6 +9,7 @@ pub enum AcsHkIds { #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum HkRequest { OneShot(u32), - Enable(u32, CollectionIntervalFactor), - Disable(u32, CollectionIntervalFactor), + Enable(u32), + Disable(u32), + ModifyCollectionInterval(CollectionIntervalFactor), } diff --git a/satrs-example/src/main.rs b/satrs-example/src/main.rs index 6692363..3f069fd 100644 --- a/satrs-example/src/main.rs +++ b/satrs-example/src/main.rs @@ -31,6 +31,7 @@ use std::net::{IpAddr, SocketAddr}; use std::sync::mpsc::channel; use std::sync::{mpsc, Arc, RwLock}; use std::thread; +use std::time::Duration; struct TmFunnel { tm_funnel_rx: mpsc::Receiver, @@ -176,9 +177,19 @@ fn main() { } }); + println!("Starting AOCS thread"); + let jh3 = thread::spawn(move || loop { + match acs_thread_rx.try_recv() { + Ok(_) => {} + Err(_) => {} + } + thread::sleep(Duration::from_millis(500)); + }); + jh0.join().expect("Joining UDP TMTC server thread failed"); jh1.join().expect("Joining TM Funnel thread failed"); jh2.join().expect("Joining Event Manager thread failed"); + jh3.join().expect("Joining AOCS thread failed"); } pub fn update_time(time_provider: &mut TimeProvider, timestamp: &mut [u8]) { diff --git a/satrs-example/src/pus.rs b/satrs-example/src/pus.rs index 441be53..3adc309 100644 --- a/satrs-example/src/pus.rs +++ b/satrs-example/src/pus.rs @@ -1,15 +1,17 @@ +use crate::hk::HkRequest; use crate::requests::Request; use crate::tmtc::TmStore; use satrs_core::events::EventU32; use satrs_core::pool::StoreAddr; use satrs_core::pus::event::Subservices; use satrs_core::pus::event_man::{EventRequest, EventRequestWithToken}; +use satrs_core::pus::hk; use satrs_core::pus::verification::{ FailParams, StdVerifReporterWithSender, TcStateAccepted, VerificationToken, }; use satrs_core::res_code::ResultU16; use satrs_core::tmtc::tm_helper::PusTmWithCdsShortHelper; -use satrs_core::tmtc::PusServiceProvider; +use satrs_core::tmtc::{AddressableId, PusServiceProvider}; use satrs_example::{INVALID_PUS_SERVICE, INVALID_PUS_SUBSERVICE, NOT_ENOUGH_APP_DATA}; use spacepackets::ecss::PusPacket; use spacepackets::tc::PusTc; @@ -17,7 +19,6 @@ use spacepackets::time::cds::TimeProvider; use spacepackets::time::TimeWriter; use spacepackets::SpHeader; use std::collections::HashMap; -use std::sync::mpsc; use std::sync::mpsc::Sender; pub struct PusReceiver { @@ -89,7 +90,7 @@ impl PusServiceProvider for PusReceiver { impl PusReceiver { fn handle_test_service(&mut self, pus_tc: &PusTc, token: VerificationToken) { - if pus_tc.subservice() == 1 { + if PusPacket::subservice(pus_tc) == 1 { println!("Received PUS ping command TC[17,1]"); println!("Sending ping reply PUS TM[17,2]"); let ping_reply = self.tm_helper.create_pus_tm_timestamp_now(17, 2, None); @@ -124,7 +125,38 @@ impl PusReceiver { .expect("Writing timestamp failed"); } - fn handle_hk_request(&mut self, pus_tc: &PusTc, token: VerificationToken) {} + fn handle_hk_request(&mut self, pus_tc: &PusTc, token: VerificationToken) { + if pus_tc.user_data().is_none() { + self.update_time_stamp(); + self.verif_reporter + .start_failure( + token, + FailParams::new(&self.time_stamp, &NOT_ENOUGH_APP_DATA, None), + ) + .expect("Sending start failure TM failed"); + } + let user_data = pus_tc.user_data().unwrap(); + if PusPacket::subservice(pus_tc) == hk::Subservice::TcEnableGeneration as u8 { + if user_data.len() < 8 { + self.update_time_stamp(); + self.verif_reporter + .start_failure( + token, + FailParams::new(&self.time_stamp, &NOT_ENOUGH_APP_DATA, None), + ) + .expect("Sending start failure TM failed"); + } + let addressable_id = AddressableId::from_raw_be(&user_data).unwrap(); + if self.request_map.contains_key(&addressable_id.target_id) { + let sender = self.request_map.get(&addressable_id.target_id).unwrap(); + sender + .send(Request::HkRequest(HkRequest::Enable( + addressable_id.unique_id, + ))) + .expect("Sending HK request failed") + } + } + } fn handle_event_request(&mut self, pus_tc: &PusTc, token: VerificationToken) { let send_start_failure = |verif_reporter: &mut StdVerifReporterWithSender, timestamp: &[u8; 7], diff --git a/satrs-example/src/tmtc.rs b/satrs-example/src/tmtc.rs index 200df8f..5aab261 100644 --- a/satrs-example/src/tmtc.rs +++ b/satrs-example/src/tmtc.rs @@ -9,7 +9,6 @@ use std::thread; use std::time::Duration; use crate::ccsds::CcsdsReceiver; -use crate::hk::HkRequest; use crate::pus::PusReceiver; use crate::requests::Request; use crate::UdpTmtcServer;