From d960c089fdf83d20c6124df1fd469876f6237a72 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 15 Feb 2023 00:33:33 +0100 Subject: [PATCH 1/5] add mode module with basic defintions --- satrs-core/src/lib.rs | 1 + satrs-core/src/mode.rs | 25 +++++++++++++++++++++++++ satrs-core/src/tmtc/mod.rs | 4 +++- 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/satrs-core/src/lib.rs b/satrs-core/src/lib.rs index d1b25d2..fd456c3 100644 --- a/satrs-core/src/lib.rs +++ b/satrs-core/src/lib.rs @@ -26,6 +26,7 @@ pub mod events; pub mod executable; pub mod hal; pub mod hk; +pub mod mode; pub mod objects; pub mod params; #[cfg(feature = "alloc")] diff --git a/satrs-core/src/mode.rs b/satrs-core/src/mode.rs index e69de29..00e534d 100644 --- a/satrs-core/src/mode.rs +++ b/satrs-core/src/mode.rs @@ -0,0 +1,25 @@ +use crate::tmtc::TargetId; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct ModePair { + mode: u32, + submode: u16, +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct ModeCommand { + address: TargetId, + mode: ModePair, +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub enum ModeRequest { + SetMode(ModeCommand), + ReadMode(TargetId), + AnnounceMode(TargetId), + AnnounceModeRecursive(TargetId), +} diff --git a/satrs-core/src/tmtc/mod.rs b/satrs-core/src/tmtc/mod.rs index f410eea..c2a0aa6 100644 --- a/satrs-core/src/tmtc/mod.rs +++ b/satrs-core/src/tmtc/mod.rs @@ -23,10 +23,12 @@ pub use ccsds_distrib::{CcsdsDistributor, CcsdsError, CcsdsPacketHandler}; #[cfg(feature = "alloc")] pub use pus_distrib::{PusDistributor, PusServiceProvider}; +pub type TargetId = u32; + #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct AddressableId { - pub target_id: u32, + pub target_id: TargetId, pub unique_id: u32, } From 802333cf3e8b0ec13a8e27002600587377c2082b Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 15 Feb 2023 02:12:00 +0100 Subject: [PATCH 2/5] started adding mode request handler in PUS handler --- satrs-core/src/pus/mod.rs | 6 + satrs-core/src/pus/verification.rs | 24 ++- satrs-example/Cargo.toml | 1 + satrs-example/src/lib.rs | 10 ++ satrs-example/src/pus.rs | 249 +++++++++++++++++------------ 5 files changed, 187 insertions(+), 103 deletions(-) diff --git a/satrs-core/src/pus/mod.rs b/satrs-core/src/pus/mod.rs index d0c1964..93a8469 100644 --- a/satrs-core/src/pus/mod.rs +++ b/satrs-core/src/pus/mod.rs @@ -88,6 +88,12 @@ mod alloc_mod { impl_downcast!(EcssTmSender assoc Error); } +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum GenericTcCheckError { + NotEnoughAppData, + InvalidSubservice, +} + pub(crate) fn source_buffer_large_enough(cap: usize, len: usize) -> Result<(), EcssTmError> { if len > cap { return Err(EcssTmError::ByteConversionError( diff --git a/satrs-core/src/pus/verification.rs b/satrs-core/src/pus/verification.rs index 834303b..dae6471 100644 --- a/satrs-core/src/pus/verification.rs +++ b/satrs-core/src/pus/verification.rs @@ -72,8 +72,11 @@ //! The [integration test](https://egit.irs.uni-stuttgart.de/rust/fsrc-launchpad/src/branch/main/fsrc-core/tests/verification_test.rs) //! for the verification module contains examples how this module could be used in a more complex //! context involving multiple threads -use crate::pus::{source_buffer_large_enough, EcssTmError, EcssTmErrorWithSend, EcssTmSenderCore}; -use core::fmt::{Display, Formatter}; +use crate::pus::{ + source_buffer_large_enough, EcssTmError, EcssTmErrorWithSend, EcssTmSenderCore, + GenericTcCheckError, +}; +use core::fmt::{Debug, Display, Formatter}; use core::hash::{Hash, Hasher}; use core::marker::PhantomData; use core::mem::size_of; @@ -81,7 +84,7 @@ use core::mem::size_of; use delegate::delegate; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; -use spacepackets::ecss::EcssEnumeration; +use spacepackets::ecss::{scheduling, EcssEnumeration, PusPacket}; use spacepackets::tc::PusTc; use spacepackets::tm::{PusTm, PusTmSecondaryHeader}; use spacepackets::{CcsdsPacket, PacketId, PacketSequenceCtrl}; @@ -1366,6 +1369,21 @@ mod stdmod { } } +pub fn pus_11_generic_tc_check( + pus_tc: &PusTc, +) -> Result { + if pus_tc.user_data().is_none() { + return Err(GenericTcCheckError::NotEnoughAppData); + } + let subservice: scheduling::Subservice = match pus_tc.subservice().try_into() { + Ok(subservice) => subservice, + Err(_) => { + return Err(GenericTcCheckError::InvalidSubservice); + } + }; + Ok(subservice) +} + #[cfg(test)] mod tests { use crate::pool::{LocalPool, PoolCfg, SharedPool}; diff --git a/satrs-example/Cargo.toml b/satrs-example/Cargo.toml index 66f7244..d542e87 100644 --- a/satrs-example/Cargo.toml +++ b/satrs-example/Cargo.toml @@ -10,6 +10,7 @@ crossbeam-channel = "0.5" delegate = "0.9" zerocopy = "0.6" csv = "1" +num_enum = "0.5" [dependencies.satrs-core] path = "../satrs-core" diff --git a/satrs-example/src/lib.rs b/satrs-example/src/lib.rs index e28ece5..91c9204 100644 --- a/satrs-example/src/lib.rs +++ b/satrs-example/src/lib.rs @@ -1,9 +1,17 @@ +use num_enum::{IntoPrimitive, TryFromPrimitive}; use satrs_core::events::{EventU32TypedSev, SeverityInfo}; use std::net::Ipv4Addr; use satrs_mib::res_code::{ResultU16, ResultU16Info}; use satrs_mib::resultcode; +#[derive(Copy, Clone, PartialEq, Eq, Debug, TryFromPrimitive, IntoPrimitive)] +#[repr(u8)] +pub enum CustomPusServiceId { + Mode = 200, + Health = 201, +} + #[derive(Copy, Clone, Eq, PartialEq, Debug)] pub enum RequestTargetId { AcsSubsystem = 1, @@ -28,6 +36,8 @@ pub mod tmtc_err { pub const INVALID_PUS_SERVICE: ResultU16 = ResultU16::const_new(GroupId::Tmtc as u8, 0); #[resultcode] pub const INVALID_PUS_SUBSERVICE: ResultU16 = ResultU16::const_new(GroupId::Tmtc as u8, 1); + #[resultcode] + pub const PUS_SERVICE_NOT_IMPLEMENTED: ResultU16 = ResultU16::const_new(GroupId::Tmtc as u8, 2); #[resultcode(info = "Not enough data inside the TC application data field")] pub const NOT_ENOUGH_APP_DATA: ResultU16 = ResultU16::const_new(GroupId::Tmtc as u8, 2); diff --git a/satrs-example/src/pus.rs b/satrs-example/src/pus.rs index 63daf27..1a9933c 100644 --- a/satrs-example/src/pus.rs +++ b/satrs-example/src/pus.rs @@ -4,24 +4,26 @@ use satrs_core::events::EventU32; use satrs_core::hk::{CollectionIntervalFactor, HkRequest}; use satrs_core::params::Params; use satrs_core::pool::StoreAddr; -use satrs_core::pus::event; use satrs_core::pus::event_man::{EventRequest, EventRequestWithToken}; use satrs_core::pus::hk; use satrs_core::pus::scheduling::PusScheduler; use satrs_core::pus::verification::{ - FailParams, StdVerifReporterWithSender, TcStateAccepted, VerificationToken, + pus_11_generic_tc_check, FailParams, StdVerifReporterWithSender, TcStateAccepted, + VerificationToken, }; +use satrs_core::pus::{event, GenericTcCheckError}; use satrs_core::res_code::ResultU16; -use satrs_core::spacepackets::ecss::scheduling; +use satrs_core::spacepackets::ecss::{scheduling, PusServiceId}; use satrs_core::tmtc::tm_helper::PusTmWithCdsShortHelper; use satrs_core::tmtc::{AddressableId, PusServiceProvider}; use satrs_core::{ spacepackets::ecss::PusPacket, spacepackets::tc::PusTc, spacepackets::time::cds::TimeProvider, spacepackets::time::TimeWriter, spacepackets::SpHeader, }; -use satrs_example::{hk_err, tmtc_err, TEST_EVENT}; +use satrs_example::{hk_err, tmtc_err, CustomPusServiceId, TEST_EVENT}; use std::cell::RefCell; use std::collections::HashMap; +use std::convert::TryFrom; use std::rc::Rc; use std::sync::mpsc::Sender; @@ -32,11 +34,10 @@ pub struct PusReceiver { pub verif_reporter: StdVerifReporterWithSender, #[allow(dead_code)] tc_source: PusTcSource, + stamp_helper: TimeStampHelper, event_request_tx: Sender, event_sender: Sender<(EventU32, Option)>, request_map: HashMap>, - stamper: TimeProvider, - time_stamp: [u8; 7], scheduler: Rc>, } @@ -59,6 +60,33 @@ pub struct PusTcArgs { pub scheduler: Rc>, } +struct TimeStampHelper { + stamper: TimeProvider, + time_stamp: [u8; 7], +} + +impl TimeStampHelper { + pub fn new() -> Self { + Self { + stamper: TimeProvider::new_with_u16_days(0, 0), + time_stamp: [0; 7], + } + } + + pub fn stamp(&self) -> &[u8] { + &self.time_stamp + } + + pub fn update_from_now(&mut self) { + self.stamper + .update_from_now() + .expect("Updating timestamp failed"); + self.stamper + .write_to_bytes(&mut self.time_stamp) + .expect("Writing timestamp failed"); + } +} + impl PusReceiver { pub fn new(apid: u16, tm_arguments: PusTmArgs, tc_arguments: PusTcArgs) -> Self { Self { @@ -70,8 +98,7 @@ impl PusReceiver { event_request_tx: tc_arguments.event_request_tx, event_sender: tc_arguments.event_sender, request_map: tc_arguments.request_map, - stamper: TimeProvider::new_with_u16_days(0, 0), - time_stamp: [0; 7], + stamp_helper: TimeStampHelper::new(), scheduler: tc_arguments.scheduler, } } @@ -87,27 +114,51 @@ impl PusServiceProvider for PusReceiver { pus_tc: &PusTc, ) -> Result<(), Self::Error> { let init_token = self.verif_reporter.add_tc(pus_tc); - self.update_time_stamp(); + self.stamp_helper.update_from_now(); let accepted_token = self .verif_reporter - .acceptance_success(init_token, Some(&self.time_stamp)) + .acceptance_success(init_token, Some(self.stamp_helper.stamp())) .expect("Acceptance success failure"); - if service == 17 { - self.handle_test_service(pus_tc, accepted_token); - } else if service == 5 { - self.handle_event_request(pus_tc, accepted_token); - } else if service == 3 { - self.handle_hk_request(pus_tc, accepted_token); - } else if service == 11 { - self.handle_scheduled_tc(pus_tc, accepted_token); - } else { - self.update_time_stamp(); - self.verif_reporter - .start_failure( - accepted_token, - FailParams::new(Some(&self.time_stamp), &tmtc_err::INVALID_PUS_SERVICE, None), - ) - .expect("Start failure verification failed") + let service = PusServiceId::try_from(service); + match service { + Ok(standard_service) => match standard_service { + PusServiceId::Test => self.handle_test_service(pus_tc, accepted_token), + PusServiceId::Housekeeping => self.handle_hk_request(pus_tc, accepted_token), + PusServiceId::Event => self.handle_event_request(pus_tc, accepted_token), + PusServiceId::Scheduling => self.handle_scheduled_tc(pus_tc, accepted_token), + _ => self + .verif_reporter + .start_failure( + accepted_token, + FailParams::new( + Some(self.stamp_helper.stamp()), + &tmtc_err::PUS_SERVICE_NOT_IMPLEMENTED, + Some(&[standard_service as u8]), + ), + ) + .expect("Start failure verification failed"), + }, + Err(e) => { + if let Ok(custom_service) = CustomPusServiceId::try_from(e.number) { + match custom_service { + CustomPusServiceId::Mode => { + self.handle_mode_service(pus_tc, accepted_token) + } + CustomPusServiceId::Health => {} + } + } else { + self.verif_reporter + .start_failure( + accepted_token, + FailParams::new( + Some(self.stamp_helper.stamp()), + &tmtc_err::INVALID_PUS_SUBSERVICE, + Some(&[e.number]), + ), + ) + .expect("Start failure verification failed") + } + } } Ok(()) } @@ -121,7 +172,7 @@ impl PusReceiver { println!("Sending ping reply PUS TM[17,2]"); let start_token = self .verif_reporter - .start_success(token, Some(&self.time_stamp)) + .start_success(token, Some(self.stamp_helper.stamp())) .expect("Error sending start success"); let ping_reply = self.tm_helper.create_pus_tm_timestamp_now(17, 2, None); let addr = self.tm_store.add_pus_tm(&ping_reply); @@ -129,29 +180,27 @@ impl PusReceiver { .send(addr) .expect("Sending TM to TM funnel failed"); self.verif_reporter - .completion_success(start_token, Some(&self.time_stamp)) + .completion_success(start_token, Some(self.stamp_helper.stamp())) .expect("Error sending completion success"); } 128 => { - self.update_time_stamp(); self.event_sender .send((TEST_EVENT.into(), None)) .expect("Sending test event failed"); let start_token = self .verif_reporter - .start_success(token, Some(&self.time_stamp)) + .start_success(token, Some(self.stamp_helper.stamp())) .expect("Error sending start success"); self.verif_reporter - .completion_success(start_token, Some(&self.time_stamp)) + .completion_success(start_token, Some(self.stamp_helper.stamp())) .expect("Error sending completion success"); } _ => { - self.update_time_stamp(); self.verif_reporter .start_failure( token, FailParams::new( - Some(&self.time_stamp), + Some(self.stamp_helper.stamp()), &tmtc_err::INVALID_PUS_SUBSERVICE, None, ), @@ -161,22 +210,16 @@ impl PusReceiver { } } - fn update_time_stamp(&mut self) { - self.stamper - .update_from_now() - .expect("Updating timestamp failed"); - self.stamper - .write_to_bytes(&mut self.time_stamp) - .expect("Writing timestamp failed"); - } - 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(Some(&self.time_stamp), &tmtc_err::NOT_ENOUGH_APP_DATA, None), + FailParams::new( + Some(self.stamp_helper.stamp()), + &tmtc_err::NOT_ENOUGH_APP_DATA, + None, + ), ) .expect("Sending start failure TM failed"); return; @@ -188,19 +231,24 @@ impl PusReceiver { } else { &hk_err::UNIQUE_ID_MISSING }; - self.update_time_stamp(); self.verif_reporter - .start_failure(token, FailParams::new(Some(&self.time_stamp), err, None)) + .start_failure( + token, + FailParams::new(Some(self.stamp_helper.stamp()), err, None), + ) .expect("Sending start failure TM failed"); return; } let addressable_id = AddressableId::from_raw_be(user_data).unwrap(); if !self.request_map.contains_key(&addressable_id.target_id) { - self.update_time_stamp(); self.verif_reporter .start_failure( token, - FailParams::new(Some(&self.time_stamp), &hk_err::UNKNOWN_TARGET_ID, None), + FailParams::new( + Some(self.stamp_helper.stamp()), + &hk_err::UNKNOWN_TARGET_ID, + None, + ), ) .expect("Sending start failure TM failed"); return; @@ -221,12 +269,11 @@ impl PusReceiver { == hk::Subservice::TcModifyHkCollectionInterval as u8 { if user_data.len() < 12 { - self.update_time_stamp(); self.verif_reporter .start_failure( token, FailParams::new( - Some(&self.time_stamp), + Some(self.stamp_helper.stamp()), &hk_err::COLLECTION_INTERVAL_MISSING, None, ), @@ -243,7 +290,7 @@ impl PusReceiver { fn handle_event_request(&mut self, pus_tc: &PusTc, token: VerificationToken) { let send_start_failure = |verif_reporter: &mut StdVerifReporterWithSender, - timestamp: &[u8; 7], + timestamp: &[u8], failure_code: &ResultU16, failure_data: Option<&[u8]>| { verif_reporter @@ -254,16 +301,15 @@ impl PusReceiver { .expect("Sending start failure TM failed"); }; let send_start_acceptance = |verif_reporter: &mut StdVerifReporterWithSender, - timestamp: &[u8; 7]| { + timestamp: &[u8]| { verif_reporter .start_success(token, Some(timestamp)) .expect("Sending start success TM failed") }; if pus_tc.user_data().is_none() { - self.update_time_stamp(); send_start_failure( &mut self.verif_reporter, - &self.time_stamp, + self.stamp_helper.stamp(), &tmtc_err::NOT_ENOUGH_APP_DATA, None, ); @@ -271,10 +317,9 @@ impl PusReceiver { } let app_data = pus_tc.user_data().unwrap(); if app_data.len() < 4 { - self.update_time_stamp(); send_start_failure( &mut self.verif_reporter, - &self.time_stamp, + self.stamp_helper.stamp(), &tmtc_err::NOT_ENOUGH_APP_DATA, None, ); @@ -283,8 +328,8 @@ impl PusReceiver { let event_id = EventU32::from(u32::from_be_bytes(app_data.try_into().unwrap())); match PusPacket::subservice(pus_tc).try_into() { Ok(event::Subservice::TcEnableEventGeneration) => { - self.update_time_stamp(); - let start_token = send_start_acceptance(&mut self.verif_reporter, &self.time_stamp); + let start_token = + send_start_acceptance(&mut self.verif_reporter, self.stamp_helper.stamp()); self.event_request_tx .send(EventRequestWithToken { request: EventRequest::Enable(event_id), @@ -293,8 +338,8 @@ impl PusReceiver { .expect("Sending event request failed"); } Ok(event::Subservice::TcDisableEventGeneration) => { - self.update_time_stamp(); - let start_token = send_start_acceptance(&mut self.verif_reporter, &self.time_stamp); + let start_token = + send_start_acceptance(&mut self.verif_reporter, self.stamp_helper.stamp()); self.event_request_tx .send(EventRequestWithToken { request: EventRequest::Disable(event_id), @@ -303,10 +348,9 @@ impl PusReceiver { .expect("Sending event request failed"); } _ => { - self.update_time_stamp(); send_start_failure( &mut self.verif_reporter, - &self.time_stamp, + self.stamp_helper.stamp(), &tmtc_err::INVALID_PUS_SUBSERVICE, None, ); @@ -315,75 +359,74 @@ impl PusReceiver { } fn handle_scheduled_tc(&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(Some(&self.time_stamp), &tmtc_err::NOT_ENOUGH_APP_DATA, None), - ) - .expect("Sending start failure TM failed"); - return; - } - - self.update_time_stamp(); - - let subservice: scheduling::Subservice = match pus_tc.subservice().try_into() { + let subservice = match pus_11_generic_tc_check(pus_tc) { Ok(subservice) => subservice, - Err(_) => { - self.verif_reporter - .start_failure( - token, - FailParams::new( - Some(&self.time_stamp), - &tmtc_err::NOT_ENOUGH_APP_DATA, - None, - ), - ) - .expect("Sending start failure TM failed"); - return; - } + Err(e) => match e { + GenericTcCheckError::NotEnoughAppData => { + self.verif_reporter + .start_failure( + token, + FailParams::new( + Some(self.stamp_helper.stamp()), + &tmtc_err::NOT_ENOUGH_APP_DATA, + None, + ), + ) + .expect("could not sent verification error"); + return; + } + GenericTcCheckError::InvalidSubservice => { + self.verif_reporter + .start_failure( + token, + FailParams::new( + Some(self.stamp_helper.stamp()), + &tmtc_err::INVALID_PUS_SUBSERVICE, + None, + ), + ) + .expect("could not sent verification error"); + return; + } + }, }; - match subservice { scheduling::Subservice::TcEnableScheduling => { let start_token = self .verif_reporter - .start_success(token, Some(&self.time_stamp)) + .start_success(token, Some(self.stamp_helper.stamp())) .expect("Error sending start success"); let mut scheduler = self.scheduler.borrow_mut(); scheduler.enable(); if scheduler.is_enabled() { self.verif_reporter - .completion_success(start_token, Some(&self.time_stamp)) + .completion_success(start_token, Some(self.stamp_helper.stamp())) .expect("Error sending completion success"); } else { panic!("Failed to enable scheduler"); } - drop(scheduler); } scheduling::Subservice::TcDisableScheduling => { let start_token = self .verif_reporter - .start_success(token, Some(&self.time_stamp)) + .start_success(token, Some(self.stamp_helper.stamp())) .expect("Error sending start success"); let mut scheduler = self.scheduler.borrow_mut(); scheduler.disable(); if !scheduler.is_enabled() { self.verif_reporter - .completion_success(start_token, Some(&self.time_stamp)) + .completion_success(start_token, Some(self.stamp_helper.stamp())) .expect("Error sending completion success"); } else { panic!("Failed to disable scheduler"); } - drop(scheduler); } scheduling::Subservice::TcResetScheduling => { let start_token = self .verif_reporter - .start_success(token, Some(&self.time_stamp)) + .start_success(token, Some(self.stamp_helper.stamp())) .expect("Error sending start success"); let mut pool = self @@ -400,13 +443,13 @@ impl PusReceiver { drop(scheduler); self.verif_reporter - .completion_success(start_token, Some(&self.time_stamp)) + .completion_success(start_token, Some(self.stamp_helper.stamp())) .expect("Error sending completion success"); } scheduling::Subservice::TcInsertActivity => { let start_token = self .verif_reporter - .start_success(token, Some(&self.time_stamp)) + .start_success(token, Some(self.stamp_helper.stamp())) .expect("Error sending start success"); let mut pool = self @@ -422,10 +465,16 @@ impl PusReceiver { drop(scheduler); self.verif_reporter - .completion_success(start_token, Some(&self.time_stamp)) + .completion_success(start_token, Some(self.stamp_helper.stamp())) .expect("Error sending completion success"); } _ => {} } } + + fn handle_mode_service(&mut self, _pus_tc: &PusTc, _token: VerificationToken) { + //match pus_tc.subservice() { + + //} + } } From 933f94f6879ef87035f841c5853b723cddc2687c Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 15 Feb 2023 11:05:32 +0100 Subject: [PATCH 3/5] stupid windows --- satrs-core/Cargo.toml | 7 +- satrs-core/src/mode.rs | 47 ++++++- satrs-core/src/pus/mod.rs | 1 + satrs-core/src/pus/mode.rs | 16 +++ satrs-example/src/lib.rs | 6 +- satrs-example/src/pus.rs | 236 +++++++++++++++++++++------------- satrs-example/src/requests.rs | 2 + 7 files changed, 221 insertions(+), 94 deletions(-) create mode 100644 satrs-core/src/pus/mode.rs diff --git a/satrs-core/Cargo.toml b/satrs-core/Cargo.toml index 5f728ee..a97872e 100644 --- a/satrs-core/Cargo.toml +++ b/satrs-core/Cargo.toml @@ -17,6 +17,10 @@ delegate = ">=0.8, <0.10" paste = "1" embed-doc-image = "0.1" +[dependencies.num_enum] +version = "0.5" +default-features = false + [dependencies.dyn-clone] version = "1" optional = true @@ -78,7 +82,8 @@ std = [ "postcard/use-std", "crossbeam-channel/std", "serde/std", - "spacepackets/std" + "spacepackets/std", + "num_enum/std" ] alloc = [ "serde/alloc", diff --git a/satrs-core/src/mode.rs b/satrs-core/src/mode.rs index 00e534d..2072d37 100644 --- a/satrs-core/src/mode.rs +++ b/satrs-core/src/mode.rs @@ -1,18 +1,61 @@ +use core::mem::size_of; use crate::tmtc::TargetId; use serde::{Deserialize, Serialize}; +use spacepackets::{ByteConversionError, SizeMissmatch}; #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub struct ModePair { +pub struct ModeAndSubmode { mode: u32, submode: u16, } +impl ModeAndSubmode { + pub const fn new_mode_only(mode: u32) -> Self { + Self { + mode, + submode: 0 + } + } + + pub const fn new(mode: u32, submode: u16) -> Self { + Self { + mode, + submode + } + } + + pub fn raw_len() -> usize { + size_of::() + size_of::() + } + + pub fn from_be_bytes(buf: &[u8]) -> Result { + if buf.len() < 6 { + return Err(ByteConversionError::FromSliceTooSmall(SizeMissmatch { + expected: 6, + found: buf.len() + })); + } + Ok(Self { + mode: u32::from_be_bytes(buf[0..4].try_into().unwrap()), + submode: u16::from_be_bytes(buf[4..6].try_into().unwrap()) + }) + } +} #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct ModeCommand { address: TargetId, - mode: ModePair, + mode_submode: ModeAndSubmode, +} + +impl ModeCommand { + pub const fn new(address: TargetId, mode_submode: ModeAndSubmode) -> Self { + Self { + address, + mode_submode + } + } } #[derive(Debug, Copy, Clone, PartialEq, Eq)] diff --git a/satrs-core/src/pus/mod.rs b/satrs-core/src/pus/mod.rs index 93a8469..1abcab6 100644 --- a/satrs-core/src/pus/mod.rs +++ b/satrs-core/src/pus/mod.rs @@ -11,6 +11,7 @@ use spacepackets::{ByteConversionError, SizeMissmatch}; pub mod event; pub mod event_man; pub mod hk; +pub mod mode; #[cfg(feature = "std")] pub mod scheduling; pub mod verification; diff --git a/satrs-core/src/pus/mode.rs b/satrs-core/src/pus/mode.rs new file mode 100644 index 0000000..1ab46ef --- /dev/null +++ b/satrs-core/src/pus/mode.rs @@ -0,0 +1,16 @@ +use num_enum::{IntoPrimitive, TryFromPrimitive}; +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Eq, PartialEq, Copy, Clone, IntoPrimitive, TryFromPrimitive)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[repr(u8)] +pub enum Subservice { + TcSetMode = 1, + TcReadMode = 3, + TcAnnounceMode = 4, + TcAnnounceModeRecursive = 5, + TmModeReply = 6, + TmCantReachMode = 7, + TmWrongModeReply = 8, +} diff --git a/satrs-example/src/lib.rs b/satrs-example/src/lib.rs index 91c9204..9429755 100644 --- a/satrs-example/src/lib.rs +++ b/satrs-example/src/lib.rs @@ -39,7 +39,11 @@ pub mod tmtc_err { #[resultcode] pub const PUS_SERVICE_NOT_IMPLEMENTED: ResultU16 = ResultU16::const_new(GroupId::Tmtc as u8, 2); - #[resultcode(info = "Not enough data inside the TC application data field")] + #[resultcode( + info = "Not enough data inside the TC application data field. Optionally includes: \ + 8 bytes of failure data containing 2 failure parameters, \ + P1 (u32 big endian): Expected data length, P2: Found data length" + )] pub const NOT_ENOUGH_APP_DATA: ResultU16 = ResultU16::const_new(GroupId::Tmtc as u8, 2); pub const TMTC_RESULTS: &[ResultU16Info] = &[ diff --git a/satrs-example/src/pus.rs b/satrs-example/src/pus.rs index 1a9933c..85ad91c 100644 --- a/satrs-example/src/pus.rs +++ b/satrs-example/src/pus.rs @@ -7,15 +7,13 @@ use satrs_core::pool::StoreAddr; use satrs_core::pus::event_man::{EventRequest, EventRequestWithToken}; use satrs_core::pus::hk; use satrs_core::pus::scheduling::PusScheduler; -use satrs_core::pus::verification::{ - pus_11_generic_tc_check, FailParams, StdVerifReporterWithSender, TcStateAccepted, - VerificationToken, -}; +use satrs_core::pus::mode; +use satrs_core::pus::verification::{pus_11_generic_tc_check, FailParams, StdVerifReporterWithSender, TcStateAccepted, VerificationToken, StdVerifSenderError}; use satrs_core::pus::{event, GenericTcCheckError}; use satrs_core::res_code::ResultU16; use satrs_core::spacepackets::ecss::{scheduling, PusServiceId}; use satrs_core::tmtc::tm_helper::PusTmWithCdsShortHelper; -use satrs_core::tmtc::{AddressableId, PusServiceProvider}; +use satrs_core::tmtc::{AddressableId, PusServiceProvider, TargetId}; use satrs_core::{ spacepackets::ecss::PusPacket, spacepackets::tc::PusTc, spacepackets::time::cds::TimeProvider, spacepackets::time::TimeWriter, spacepackets::SpHeader, @@ -26,12 +24,13 @@ use std::collections::HashMap; use std::convert::TryFrom; use std::rc::Rc; use std::sync::mpsc::Sender; +use satrs_core::mode::{ModeCommand, ModeAndSubmode, ModeRequest}; +use satrs_core::pus::mode::Subservice; +use satrs_core::spacepackets::tc::GenericPusTcSecondaryHeader; pub struct PusReceiver { pub tm_helper: PusTmWithCdsShortHelper, - pub tm_tx: Sender, - pub tm_store: TmStore, - pub verif_reporter: StdVerifReporterWithSender, + pub tm_args: PusTmArgs, #[allow(dead_code)] tc_source: PusTcSource, stamp_helper: TimeStampHelper, @@ -53,7 +52,7 @@ pub struct PusTmArgs { pub struct PusTcArgs { pub event_request_tx: Sender, /// Request routing helper. Maps targeted request to their recipient. - pub request_map: HashMap>, + pub request_map: HashMap>, /// Required for scheduling of telecommands. pub tc_source: PusTcSource, pub event_sender: Sender<(EventU32, Option)>, @@ -91,9 +90,7 @@ impl PusReceiver { pub fn new(apid: u16, tm_arguments: PusTmArgs, tc_arguments: PusTcArgs) -> Self { Self { tm_helper: PusTmWithCdsShortHelper::new(apid), - tm_tx: tm_arguments.tm_tx, - tm_store: tm_arguments.tm_store, - verif_reporter: tm_arguments.verif_reporter, + tm_args: tm_arguments, tc_source: tc_arguments.tc_source, event_request_tx: tc_arguments.event_request_tx, event_sender: tc_arguments.event_sender, @@ -102,6 +99,14 @@ impl PusReceiver { scheduler: tc_arguments.scheduler, } } + + fn vr_and_stamp(&mut self) -> (&mut StdVerifReporterWithSender, &[u8]) { + (&mut self.tm_args.verif_reporter, self.stamp()) + } + + fn stamp(&self) -> &[u8] { + self.stamp_helper.stamp() + } } impl PusServiceProvider for PusReceiver { @@ -113,11 +118,11 @@ impl PusServiceProvider for PusReceiver { _header: &SpHeader, pus_tc: &PusTc, ) -> Result<(), Self::Error> { - let init_token = self.verif_reporter.add_tc(pus_tc); + let init_token = self.tm_args.verif_reporter.add_tc(pus_tc); self.stamp_helper.update_from_now(); - let accepted_token = self - .verif_reporter - .acceptance_success(init_token, Some(self.stamp_helper.stamp())) + let (vr, stamp) = self.vr_and_stamp(); + let accepted_token = vr + .acceptance_success(init_token, Some(stamp)) .expect("Acceptance success failure"); let service = PusServiceId::try_from(service); match service { @@ -126,12 +131,11 @@ impl PusServiceProvider for PusReceiver { PusServiceId::Housekeeping => self.handle_hk_request(pus_tc, accepted_token), PusServiceId::Event => self.handle_event_request(pus_tc, accepted_token), PusServiceId::Scheduling => self.handle_scheduled_tc(pus_tc, accepted_token), - _ => self - .verif_reporter + _ => vr .start_failure( accepted_token, FailParams::new( - Some(self.stamp_helper.stamp()), + Some(stamp), &tmtc_err::PUS_SERVICE_NOT_IMPLEMENTED, Some(&[standard_service as u8]), ), @@ -147,7 +151,7 @@ impl PusServiceProvider for PusReceiver { CustomPusServiceId::Health => {} } } else { - self.verif_reporter + vr .start_failure( accepted_token, FailParams::new( @@ -166,41 +170,40 @@ impl PusServiceProvider for PusReceiver { impl PusReceiver { fn handle_test_service(&mut self, pus_tc: &PusTc, token: VerificationToken) { + let (vr, stamp) = self.vr_and_stamp(); match PusPacket::subservice(pus_tc) { 1 => { println!("Received PUS ping command TC[17,1]"); println!("Sending ping reply PUS TM[17,2]"); - let start_token = self - .verif_reporter - .start_success(token, Some(self.stamp_helper.stamp())) + let start_token = vr + .start_success(token, Some(stamp)) .expect("Error sending start success"); let ping_reply = self.tm_helper.create_pus_tm_timestamp_now(17, 2, None); - let addr = self.tm_store.add_pus_tm(&ping_reply); - self.tm_tx + let addr = self.tm_args.tm_store.add_pus_tm(&ping_reply); + self.tm_args.tm_tx .send(addr) .expect("Sending TM to TM funnel failed"); - self.verif_reporter - .completion_success(start_token, Some(self.stamp_helper.stamp())) + vr + .completion_success(start_token, Some(stamp)) .expect("Error sending completion success"); } 128 => { self.event_sender .send((TEST_EVENT.into(), None)) .expect("Sending test event failed"); - let start_token = self - .verif_reporter - .start_success(token, Some(self.stamp_helper.stamp())) + let start_token = vr + .start_success(token, Some(stamp)) .expect("Error sending start success"); - self.verif_reporter - .completion_success(start_token, Some(self.stamp_helper.stamp())) + vr + .completion_success(start_token, Some(stamp)) .expect("Error sending completion success"); } _ => { - self.verif_reporter + vr .start_failure( token, FailParams::new( - Some(self.stamp_helper.stamp()), + Some(stamp), &tmtc_err::INVALID_PUS_SUBSERVICE, None, ), @@ -211,12 +214,12 @@ impl PusReceiver { } fn handle_hk_request(&mut self, pus_tc: &PusTc, token: VerificationToken) { + let (vr, stamp) = self.vr_and_stamp(); if pus_tc.user_data().is_none() { - self.verif_reporter - .start_failure( + vr.start_failure( token, FailParams::new( - Some(self.stamp_helper.stamp()), + Some(stamp), &tmtc_err::NOT_ENOUGH_APP_DATA, None, ), @@ -231,21 +234,20 @@ impl PusReceiver { } else { &hk_err::UNIQUE_ID_MISSING }; - self.verif_reporter + vr .start_failure( token, - FailParams::new(Some(self.stamp_helper.stamp()), err, None), + FailParams::new(Some(stamp), err, None), ) .expect("Sending start failure TM failed"); return; } let addressable_id = AddressableId::from_raw_be(user_data).unwrap(); if !self.request_map.contains_key(&addressable_id.target_id) { - self.verif_reporter - .start_failure( + vr.start_failure( token, FailParams::new( - Some(self.stamp_helper.stamp()), + Some(stamp), &hk_err::UNKNOWN_TARGET_ID, None, ), @@ -269,11 +271,10 @@ impl PusReceiver { == hk::Subservice::TcModifyHkCollectionInterval as u8 { if user_data.len() < 12 { - self.verif_reporter - .start_failure( + vr.start_failure( token, FailParams::new( - Some(self.stamp_helper.stamp()), + Some(stamp), &hk_err::COLLECTION_INTERVAL_MISSING, None, ), @@ -289,27 +290,28 @@ impl PusReceiver { } fn handle_event_request(&mut self, pus_tc: &PusTc, token: VerificationToken) { - let send_start_failure = |verif_reporter: &mut StdVerifReporterWithSender, + let send_start_failure = |vr: &mut StdVerifReporterWithSender, timestamp: &[u8], failure_code: &ResultU16, failure_data: Option<&[u8]>| { - verif_reporter + vr .start_failure( token, FailParams::new(Some(timestamp), failure_code, failure_data), ) .expect("Sending start failure TM failed"); }; - let send_start_acceptance = |verif_reporter: &mut StdVerifReporterWithSender, + let send_start_acceptance = |vr: &mut StdVerifReporterWithSender, timestamp: &[u8]| { - verif_reporter + vr .start_success(token, Some(timestamp)) .expect("Sending start success TM failed") }; + let (vr, stamp) = self.vr_and_stamp(); if pus_tc.user_data().is_none() { send_start_failure( - &mut self.verif_reporter, - self.stamp_helper.stamp(), + vr, + stamp, &tmtc_err::NOT_ENOUGH_APP_DATA, None, ); @@ -318,8 +320,8 @@ impl PusReceiver { let app_data = pus_tc.user_data().unwrap(); if app_data.len() < 4 { send_start_failure( - &mut self.verif_reporter, - self.stamp_helper.stamp(), + vr, + stamp, &tmtc_err::NOT_ENOUGH_APP_DATA, None, ); @@ -329,7 +331,7 @@ impl PusReceiver { match PusPacket::subservice(pus_tc).try_into() { Ok(event::Subservice::TcEnableEventGeneration) => { let start_token = - send_start_acceptance(&mut self.verif_reporter, self.stamp_helper.stamp()); + send_start_acceptance(vr, stamp); self.event_request_tx .send(EventRequestWithToken { request: EventRequest::Enable(event_id), @@ -339,7 +341,7 @@ impl PusReceiver { } Ok(event::Subservice::TcDisableEventGeneration) => { let start_token = - send_start_acceptance(&mut self.verif_reporter, self.stamp_helper.stamp()); + send_start_acceptance(vr, stamp); self.event_request_tx .send(EventRequestWithToken { request: EventRequest::Disable(event_id), @@ -349,8 +351,8 @@ impl PusReceiver { } _ => { send_start_failure( - &mut self.verif_reporter, - self.stamp_helper.stamp(), + vr, + stamp, &tmtc_err::INVALID_PUS_SUBSERVICE, None, ); @@ -359,15 +361,16 @@ impl PusReceiver { } fn handle_scheduled_tc(&mut self, pus_tc: &PusTc, token: VerificationToken) { + let (vr, stamp) = self.vr_and_stamp(); let subservice = match pus_11_generic_tc_check(pus_tc) { Ok(subservice) => subservice, Err(e) => match e { GenericTcCheckError::NotEnoughAppData => { - self.verif_reporter + vr .start_failure( token, FailParams::new( - Some(self.stamp_helper.stamp()), + Some(stamp), &tmtc_err::NOT_ENOUGH_APP_DATA, None, ), @@ -376,11 +379,10 @@ impl PusReceiver { return; } GenericTcCheckError::InvalidSubservice => { - self.verif_reporter - .start_failure( + vr.start_failure( token, FailParams::new( - Some(self.stamp_helper.stamp()), + Some(stamp), &tmtc_err::INVALID_PUS_SUBSERVICE, None, ), @@ -392,41 +394,39 @@ impl PusReceiver { }; match subservice { scheduling::Subservice::TcEnableScheduling => { - let start_token = self - .verif_reporter - .start_success(token, Some(self.stamp_helper.stamp())) + let start_token = + vr + .start_success(token, Some(stamp)) .expect("Error sending start success"); let mut scheduler = self.scheduler.borrow_mut(); scheduler.enable(); if scheduler.is_enabled() { - self.verif_reporter - .completion_success(start_token, Some(self.stamp_helper.stamp())) + vr + .completion_success(start_token, Some(stamp)) .expect("Error sending completion success"); } else { panic!("Failed to enable scheduler"); } } scheduling::Subservice::TcDisableScheduling => { - let start_token = self - .verif_reporter - .start_success(token, Some(self.stamp_helper.stamp())) + let start_token =vr + .start_success(token, Some(stamp)) .expect("Error sending start success"); let mut scheduler = self.scheduler.borrow_mut(); scheduler.disable(); if !scheduler.is_enabled() { - self.verif_reporter - .completion_success(start_token, Some(self.stamp_helper.stamp())) + vr + .completion_success(start_token, Some(stamp)) .expect("Error sending completion success"); } else { panic!("Failed to disable scheduler"); } } scheduling::Subservice::TcResetScheduling => { - let start_token = self - .verif_reporter - .start_success(token, Some(self.stamp_helper.stamp())) + let start_token = vr + .start_success(token, Some(stamp)) .expect("Error sending start success"); let mut pool = self @@ -442,39 +442,95 @@ impl PusReceiver { .expect("Error resetting TC Pool"); drop(scheduler); - self.verif_reporter - .completion_success(start_token, Some(self.stamp_helper.stamp())) + vr.completion_success(start_token, Some(stamp)) .expect("Error sending completion success"); } scheduling::Subservice::TcInsertActivity => { - let start_token = self - .verif_reporter - .start_success(token, Some(self.stamp_helper.stamp())) - .expect("Error sending start success"); + let start_token = vr + .start_success(token, Some(stamp)) + .expect("error sending start success"); let mut pool = self .tc_source .tc_store .pool .write() - .expect("Locking pool failed"); + .expect("locking pool failed"); let mut scheduler = self.scheduler.borrow_mut(); scheduler .insert_wrapped_tc::(pus_tc, pool.as_mut()) - .expect("TODO: panic message"); + .expect("insertion of activity into pool failed"); drop(scheduler); - self.verif_reporter - .completion_success(start_token, Some(self.stamp_helper.stamp())) - .expect("Error sending completion success"); + vr + .completion_success(start_token, Some(stamp)) + .expect("sending completion success failed"); } _ => {} } } - fn handle_mode_service(&mut self, _pus_tc: &PusTc, _token: VerificationToken) { - //match pus_tc.subservice() { - - //} + fn handle_mode_service(&mut self, pus_tc: &PusTc, token: VerificationToken) { + let (vr, stamp) = self.vr_and_stamp(); + let mut app_data_len = 0; + let app_data = pus_tc.user_data(); + if app_data.is_some() { + app_data_len = pus_tc.user_data().unwrap().len(); + } + if app_data_len < 4 { + vr + .start_failure( + token, + FailParams::new( + Some(stamp), &tmtc_err::NOT_ENOUGH_APP_DATA, + Some(format!("expected {} bytes, found {}", 4, app_data_len).as_bytes()) + ), + ) + .expect("Sending start failure TM failed"); + } + let app_data = app_data.unwrap(); + let subservice = mode::Subservice::try_from(PusPacket::subservice(pus_tc)); + if let Ok(subservice) = subservice { + match subservice { + Subservice::TcSetMode => { + let target_id = u32::from_be_bytes(app_data[0..4].try_into().unwrap()); + let min_len = ModeAndSubmode::raw_len() + 4; + if app_data_len < min_len { + vr.start_failure( + token, + FailParams::new( + Some(stamp), &tmtc_err::NOT_ENOUGH_APP_DATA, + Some(format!("expected {} bytes, found {}", min_len, app_data_len).as_bytes()) + ), + ) + .expect("Sending start failure TM failed"); + } + // Should never fail after size check + let mode_submode = ModeAndSubmode::from_be_bytes(app_data[4..4 + ModeAndSubmode::raw_len()].try_into().unwrap()).unwrap(); + let mode_request = Request::ModeRequest(ModeRequest::SetMode(ModeCommand::new(target_id, mode_submode))); + match self.request_map.get(&target_id) { + None => {} + Some(sender_to_recipient) => { + sender_to_recipient.send(RequestWithToken(mode_request, token)).expect("sending mode request failed"); + } + } + } + Subservice::TcReadMode => {} + Subservice::TcAnnounceMode => {} + Subservice::TcAnnounceModeRecursive => {} + Subservice::TmModeReply => {} + Subservice::TmCantReachMode => {} + Subservice::TmWrongModeReply => {} + } + } else { + vr.start_failure( + token, + FailParams::new( + Some(stamp), &tmtc_err::INVALID_PUS_SUBSERVICE, + Some(&[PusPacket::subservice(pus_tc)]) + ), + ) + .expect("Sending start failure TM failed"); + } } } diff --git a/satrs-example/src/requests.rs b/satrs-example/src/requests.rs index efb5732..660d227 100644 --- a/satrs-example/src/requests.rs +++ b/satrs-example/src/requests.rs @@ -1,9 +1,11 @@ use satrs_core::hk::HkRequest; +use satrs_core::mode::ModeRequest; use satrs_core::pus::verification::{TcStateAccepted, VerificationToken}; #[derive(Copy, Clone, Eq, PartialEq, Debug)] pub enum Request { HkRequest(HkRequest), + ModeRequest(ModeRequest) } #[derive(Copy, Clone, Eq, PartialEq, Debug)] From 943ae821def8374860a700b5c2349dfcb06c4ea1 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 15 Feb 2023 11:19:23 +0100 Subject: [PATCH 4/5] add basic mode request handling --- satrs-core/src/mode.rs | 18 +-- satrs-core/src/power.rs | 13 -- satrs-example/src/main.rs | 3 + satrs-example/src/pus.rs | 237 ++++++++++++++++++++-------------- satrs-example/src/requests.rs | 3 +- 5 files changed, 153 insertions(+), 121 deletions(-) diff --git a/satrs-core/src/mode.rs b/satrs-core/src/mode.rs index 2072d37..c07a030 100644 --- a/satrs-core/src/mode.rs +++ b/satrs-core/src/mode.rs @@ -1,5 +1,5 @@ -use core::mem::size_of; use crate::tmtc::TargetId; +use core::mem::size_of; use serde::{Deserialize, Serialize}; use spacepackets::{ByteConversionError, SizeMissmatch}; @@ -12,17 +12,11 @@ pub struct ModeAndSubmode { impl ModeAndSubmode { pub const fn new_mode_only(mode: u32) -> Self { - Self { - mode, - submode: 0 - } + Self { mode, submode: 0 } } pub const fn new(mode: u32, submode: u16) -> Self { - Self { - mode, - submode - } + Self { mode, submode } } pub fn raw_len() -> usize { @@ -33,12 +27,12 @@ impl ModeAndSubmode { if buf.len() < 6 { return Err(ByteConversionError::FromSliceTooSmall(SizeMissmatch { expected: 6, - found: buf.len() + found: buf.len(), })); } Ok(Self { mode: u32::from_be_bytes(buf[0..4].try_into().unwrap()), - submode: u16::from_be_bytes(buf[4..6].try_into().unwrap()) + submode: u16::from_be_bytes(buf[4..6].try_into().unwrap()), }) } } @@ -53,7 +47,7 @@ impl ModeCommand { pub const fn new(address: TargetId, mode_submode: ModeAndSubmode) -> Self { Self { address, - mode_submode + mode_submode, } } } diff --git a/satrs-core/src/power.rs b/satrs-core/src/power.rs index 82063a3..810ed72 100644 --- a/satrs-core/src/power.rs +++ b/satrs-core/src/power.rs @@ -32,19 +32,6 @@ pub trait PowerSwitcherCommandSender { fn send_switch_on_cmd(&mut self, switch_id: SwitchId) -> Result<(), Self::Error>; fn send_switch_off_cmd(&mut self, switch_id: SwitchId) -> Result<(), Self::Error>; - - fn switch_on( - &mut self, - switch: &mut T, - ) -> Result<(), ::Error> { - switch.switch_on() - } - fn switch_off( - &mut self, - switch: &mut T, - ) -> Result<(), ::Error> { - switch.switch_off() - } } pub trait PowerSwitchInfo { diff --git a/satrs-example/src/main.rs b/satrs-example/src/main.rs index a070109..1d6b2c1 100644 --- a/satrs-example/src/main.rs +++ b/satrs-example/src/main.rs @@ -245,6 +245,9 @@ fn main() { HkRequest::Disable(_) => {} HkRequest::ModifyCollectionInterval(_, _) => {} }, + Request::ModeRequest(_mode_req) => { + println!("mode request handling not implemented yet") + } } let started_token = reporter_aocs .start_success(request.1, Some(×tamp)) diff --git a/satrs-example/src/pus.rs b/satrs-example/src/pus.rs index 85ad91c..905efff 100644 --- a/satrs-example/src/pus.rs +++ b/satrs-example/src/pus.rs @@ -2,13 +2,18 @@ use crate::requests::{Request, RequestWithToken}; use crate::tmtc::{PusTcSource, TmStore}; use satrs_core::events::EventU32; use satrs_core::hk::{CollectionIntervalFactor, HkRequest}; +use satrs_core::mode::{ModeAndSubmode, ModeCommand, ModeRequest}; use satrs_core::params::Params; use satrs_core::pool::StoreAddr; use satrs_core::pus::event_man::{EventRequest, EventRequestWithToken}; use satrs_core::pus::hk; -use satrs_core::pus::scheduling::PusScheduler; use satrs_core::pus::mode; -use satrs_core::pus::verification::{pus_11_generic_tc_check, FailParams, StdVerifReporterWithSender, TcStateAccepted, VerificationToken, StdVerifSenderError}; +use satrs_core::pus::mode::Subservice; +use satrs_core::pus::scheduling::PusScheduler; +use satrs_core::pus::verification::{ + pus_11_generic_tc_check, FailParams, StdVerifReporterWithSender, TcStateAccepted, + VerificationToken, +}; use satrs_core::pus::{event, GenericTcCheckError}; use satrs_core::res_code::ResultU16; use satrs_core::spacepackets::ecss::{scheduling, PusServiceId}; @@ -24,9 +29,6 @@ use std::collections::HashMap; use std::convert::TryFrom; use std::rc::Rc; use std::sync::mpsc::Sender; -use satrs_core::mode::{ModeCommand, ModeAndSubmode, ModeRequest}; -use satrs_core::pus::mode::Subservice; -use satrs_core::spacepackets::tc::GenericPusTcSecondaryHeader; pub struct PusReceiver { pub tm_helper: PusTmWithCdsShortHelper, @@ -99,14 +101,6 @@ impl PusReceiver { scheduler: tc_arguments.scheduler, } } - - fn vr_and_stamp(&mut self) -> (&mut StdVerifReporterWithSender, &[u8]) { - (&mut self.tm_args.verif_reporter, self.stamp()) - } - - fn stamp(&self) -> &[u8] { - self.stamp_helper.stamp() - } } impl PusServiceProvider for PusReceiver { @@ -120,9 +114,10 @@ impl PusServiceProvider for PusReceiver { ) -> Result<(), Self::Error> { let init_token = self.tm_args.verif_reporter.add_tc(pus_tc); self.stamp_helper.update_from_now(); - let (vr, stamp) = self.vr_and_stamp(); - let accepted_token = vr - .acceptance_success(init_token, Some(stamp)) + let accepted_token = self + .tm_args + .verif_reporter + .acceptance_success(init_token, Some(self.stamp_helper.stamp())) .expect("Acceptance success failure"); let service = PusServiceId::try_from(service); match service { @@ -131,11 +126,13 @@ impl PusServiceProvider for PusReceiver { PusServiceId::Housekeeping => self.handle_hk_request(pus_tc, accepted_token), PusServiceId::Event => self.handle_event_request(pus_tc, accepted_token), PusServiceId::Scheduling => self.handle_scheduled_tc(pus_tc, accepted_token), - _ => vr + _ => self + .tm_args + .verif_reporter .start_failure( accepted_token, FailParams::new( - Some(stamp), + Some(self.stamp_helper.stamp()), &tmtc_err::PUS_SERVICE_NOT_IMPLEMENTED, Some(&[standard_service as u8]), ), @@ -151,7 +148,8 @@ impl PusServiceProvider for PusReceiver { CustomPusServiceId::Health => {} } } else { - vr + self.tm_args + .verif_reporter .start_failure( accepted_token, FailParams::new( @@ -170,40 +168,47 @@ impl PusServiceProvider for PusReceiver { impl PusReceiver { fn handle_test_service(&mut self, pus_tc: &PusTc, token: VerificationToken) { - let (vr, stamp) = self.vr_and_stamp(); match PusPacket::subservice(pus_tc) { 1 => { println!("Received PUS ping command TC[17,1]"); println!("Sending ping reply PUS TM[17,2]"); - let start_token = vr - .start_success(token, Some(stamp)) + let start_token = self + .tm_args + .verif_reporter + .start_success(token, Some(self.stamp_helper.stamp())) .expect("Error sending start success"); let ping_reply = self.tm_helper.create_pus_tm_timestamp_now(17, 2, None); let addr = self.tm_args.tm_store.add_pus_tm(&ping_reply); - self.tm_args.tm_tx + self.tm_args + .tm_tx .send(addr) .expect("Sending TM to TM funnel failed"); - vr - .completion_success(start_token, Some(stamp)) + self.tm_args + .verif_reporter + .completion_success(start_token, Some(self.stamp_helper.stamp())) .expect("Error sending completion success"); } 128 => { self.event_sender .send((TEST_EVENT.into(), None)) .expect("Sending test event failed"); - let start_token = vr - .start_success(token, Some(stamp)) + let start_token = self + .tm_args + .verif_reporter + .start_success(token, Some(self.stamp_helper.stamp())) .expect("Error sending start success"); - vr - .completion_success(start_token, Some(stamp)) + self.tm_args + .verif_reporter + .completion_success(start_token, Some(self.stamp_helper.stamp())) .expect("Error sending completion success"); } _ => { - vr + self.tm_args + .verif_reporter .start_failure( token, FailParams::new( - Some(stamp), + Some(self.stamp_helper.stamp()), &tmtc_err::INVALID_PUS_SUBSERVICE, None, ), @@ -214,12 +219,13 @@ impl PusReceiver { } fn handle_hk_request(&mut self, pus_tc: &PusTc, token: VerificationToken) { - let (vr, stamp) = self.vr_and_stamp(); if pus_tc.user_data().is_none() { - vr.start_failure( + self.tm_args + .verif_reporter + .start_failure( token, FailParams::new( - Some(stamp), + Some(self.stamp_helper.stamp()), &tmtc_err::NOT_ENOUGH_APP_DATA, None, ), @@ -234,20 +240,23 @@ impl PusReceiver { } else { &hk_err::UNIQUE_ID_MISSING }; - vr + self.tm_args + .verif_reporter .start_failure( token, - FailParams::new(Some(stamp), err, None), + FailParams::new(Some(self.stamp_helper.stamp()), err, None), ) .expect("Sending start failure TM failed"); return; } let addressable_id = AddressableId::from_raw_be(user_data).unwrap(); if !self.request_map.contains_key(&addressable_id.target_id) { - vr.start_failure( + self.tm_args + .verif_reporter + .start_failure( token, FailParams::new( - Some(stamp), + Some(self.stamp_helper.stamp()), &hk_err::UNKNOWN_TARGET_ID, None, ), @@ -271,10 +280,12 @@ impl PusReceiver { == hk::Subservice::TcModifyHkCollectionInterval as u8 { if user_data.len() < 12 { - vr.start_failure( + self.tm_args + .verif_reporter + .start_failure( token, FailParams::new( - Some(stamp), + Some(self.stamp_helper.stamp()), &hk_err::COLLECTION_INTERVAL_MISSING, None, ), @@ -294,24 +305,20 @@ impl PusReceiver { timestamp: &[u8], failure_code: &ResultU16, failure_data: Option<&[u8]>| { - vr - .start_failure( - token, - FailParams::new(Some(timestamp), failure_code, failure_data), - ) - .expect("Sending start failure TM failed"); + vr.start_failure( + token, + FailParams::new(Some(timestamp), failure_code, failure_data), + ) + .expect("Sending start failure TM failed"); }; - let send_start_acceptance = |vr: &mut StdVerifReporterWithSender, - timestamp: &[u8]| { - vr - .start_success(token, Some(timestamp)) + let send_start_acceptance = |vr: &mut StdVerifReporterWithSender, timestamp: &[u8]| { + vr.start_success(token, Some(timestamp)) .expect("Sending start success TM failed") }; - let (vr, stamp) = self.vr_and_stamp(); if pus_tc.user_data().is_none() { send_start_failure( - vr, - stamp, + &mut self.tm_args.verif_reporter, + self.stamp_helper.stamp(), &tmtc_err::NOT_ENOUGH_APP_DATA, None, ); @@ -320,8 +327,8 @@ impl PusReceiver { let app_data = pus_tc.user_data().unwrap(); if app_data.len() < 4 { send_start_failure( - vr, - stamp, + &mut self.tm_args.verif_reporter, + self.stamp_helper.stamp(), &tmtc_err::NOT_ENOUGH_APP_DATA, None, ); @@ -330,8 +337,10 @@ impl PusReceiver { let event_id = EventU32::from(u32::from_be_bytes(app_data.try_into().unwrap())); match PusPacket::subservice(pus_tc).try_into() { Ok(event::Subservice::TcEnableEventGeneration) => { - let start_token = - send_start_acceptance(vr, stamp); + let start_token = send_start_acceptance( + &mut self.tm_args.verif_reporter, + self.stamp_helper.stamp(), + ); self.event_request_tx .send(EventRequestWithToken { request: EventRequest::Enable(event_id), @@ -340,8 +349,10 @@ impl PusReceiver { .expect("Sending event request failed"); } Ok(event::Subservice::TcDisableEventGeneration) => { - let start_token = - send_start_acceptance(vr, stamp); + let start_token = send_start_acceptance( + &mut self.tm_args.verif_reporter, + self.stamp_helper.stamp(), + ); self.event_request_tx .send(EventRequestWithToken { request: EventRequest::Disable(event_id), @@ -351,8 +362,8 @@ impl PusReceiver { } _ => { send_start_failure( - vr, - stamp, + &mut self.tm_args.verif_reporter, + self.stamp_helper.stamp(), &tmtc_err::INVALID_PUS_SUBSERVICE, None, ); @@ -361,16 +372,16 @@ impl PusReceiver { } fn handle_scheduled_tc(&mut self, pus_tc: &PusTc, token: VerificationToken) { - let (vr, stamp) = self.vr_and_stamp(); let subservice = match pus_11_generic_tc_check(pus_tc) { Ok(subservice) => subservice, Err(e) => match e { GenericTcCheckError::NotEnoughAppData => { - vr + self.tm_args + .verif_reporter .start_failure( token, FailParams::new( - Some(stamp), + Some(self.stamp_helper.stamp()), &tmtc_err::NOT_ENOUGH_APP_DATA, None, ), @@ -379,10 +390,12 @@ impl PusReceiver { return; } GenericTcCheckError::InvalidSubservice => { - vr.start_failure( + self.tm_args + .verif_reporter + .start_failure( token, FailParams::new( - Some(stamp), + Some(self.stamp_helper.stamp()), &tmtc_err::INVALID_PUS_SUBSERVICE, None, ), @@ -394,39 +407,46 @@ impl PusReceiver { }; match subservice { scheduling::Subservice::TcEnableScheduling => { - let start_token = - vr - .start_success(token, Some(stamp)) + let start_token = self + .tm_args + .verif_reporter + .start_success(token, Some(self.stamp_helper.stamp())) .expect("Error sending start success"); let mut scheduler = self.scheduler.borrow_mut(); scheduler.enable(); if scheduler.is_enabled() { - vr - .completion_success(start_token, Some(stamp)) + self.tm_args + .verif_reporter + .completion_success(start_token, Some(self.stamp_helper.stamp())) .expect("Error sending completion success"); } else { panic!("Failed to enable scheduler"); } } scheduling::Subservice::TcDisableScheduling => { - let start_token =vr - .start_success(token, Some(stamp)) + let start_token = self + .tm_args + .verif_reporter + .start_success(token, Some(self.stamp_helper.stamp())) .expect("Error sending start success"); let mut scheduler = self.scheduler.borrow_mut(); scheduler.disable(); if !scheduler.is_enabled() { - vr - .completion_success(start_token, Some(stamp)) + self.tm_args + .verif_reporter + .completion_success(start_token, Some(self.stamp_helper.stamp())) .expect("Error sending completion success"); } else { panic!("Failed to disable scheduler"); } } scheduling::Subservice::TcResetScheduling => { - let start_token = vr - .start_success(token, Some(stamp)) + let start_token = self + .tm_args + .verif_reporter + .start_success(token, Some(self.stamp_helper.stamp())) .expect("Error sending start success"); let mut pool = self @@ -442,12 +462,16 @@ impl PusReceiver { .expect("Error resetting TC Pool"); drop(scheduler); - vr.completion_success(start_token, Some(stamp)) + self.tm_args + .verif_reporter + .completion_success(start_token, Some(self.stamp_helper.stamp())) .expect("Error sending completion success"); } scheduling::Subservice::TcInsertActivity => { - let start_token = vr - .start_success(token, Some(stamp)) + let start_token = self + .tm_args + .verif_reporter + .start_success(token, Some(self.stamp_helper.stamp())) .expect("error sending start success"); let mut pool = self @@ -462,8 +486,9 @@ impl PusReceiver { .expect("insertion of activity into pool failed"); drop(scheduler); - vr - .completion_success(start_token, Some(stamp)) + self.tm_args + .verif_reporter + .completion_success(start_token, Some(self.stamp_helper.stamp())) .expect("sending completion success failed"); } _ => {} @@ -471,19 +496,20 @@ impl PusReceiver { } fn handle_mode_service(&mut self, pus_tc: &PusTc, token: VerificationToken) { - let (vr, stamp) = self.vr_and_stamp(); let mut app_data_len = 0; let app_data = pus_tc.user_data(); if app_data.is_some() { app_data_len = pus_tc.user_data().unwrap().len(); } if app_data_len < 4 { - vr + self.tm_args + .verif_reporter .start_failure( token, FailParams::new( - Some(stamp), &tmtc_err::NOT_ENOUGH_APP_DATA, - Some(format!("expected {} bytes, found {}", 4, app_data_len).as_bytes()) + Some(self.stamp_helper.stamp()), + &tmtc_err::NOT_ENOUGH_APP_DATA, + Some(format!("expected {} bytes, found {}", 4, app_data_len).as_bytes()), ), ) .expect("Sending start failure TM failed"); @@ -496,22 +522,40 @@ impl PusReceiver { let target_id = u32::from_be_bytes(app_data[0..4].try_into().unwrap()); let min_len = ModeAndSubmode::raw_len() + 4; if app_data_len < min_len { - vr.start_failure( + self.tm_args + .verif_reporter + .start_failure( token, FailParams::new( - Some(stamp), &tmtc_err::NOT_ENOUGH_APP_DATA, - Some(format!("expected {} bytes, found {}", min_len, app_data_len).as_bytes()) + Some(self.stamp_helper.stamp()), + &tmtc_err::NOT_ENOUGH_APP_DATA, + Some( + format!( + "expected {} bytes, found {}", + min_len, app_data_len + ) + .as_bytes(), + ), ), ) .expect("Sending start failure TM failed"); } // Should never fail after size check - let mode_submode = ModeAndSubmode::from_be_bytes(app_data[4..4 + ModeAndSubmode::raw_len()].try_into().unwrap()).unwrap(); - let mode_request = Request::ModeRequest(ModeRequest::SetMode(ModeCommand::new(target_id, mode_submode))); + let mode_submode = ModeAndSubmode::from_be_bytes( + app_data[4..4 + ModeAndSubmode::raw_len()] + .try_into() + .unwrap(), + ) + .unwrap(); + let mode_request = Request::ModeRequest(ModeRequest::SetMode( + ModeCommand::new(target_id, mode_submode), + )); match self.request_map.get(&target_id) { None => {} Some(sender_to_recipient) => { - sender_to_recipient.send(RequestWithToken(mode_request, token)).expect("sending mode request failed"); + sender_to_recipient + .send(RequestWithToken(mode_request, token)) + .expect("sending mode request failed"); } } } @@ -523,11 +567,14 @@ impl PusReceiver { Subservice::TmWrongModeReply => {} } } else { - vr.start_failure( + self.tm_args + .verif_reporter + .start_failure( token, FailParams::new( - Some(stamp), &tmtc_err::INVALID_PUS_SUBSERVICE, - Some(&[PusPacket::subservice(pus_tc)]) + Some(self.stamp_helper.stamp()), + &tmtc_err::INVALID_PUS_SUBSERVICE, + Some(&[PusPacket::subservice(pus_tc)]), ), ) .expect("Sending start failure TM failed"); diff --git a/satrs-example/src/requests.rs b/satrs-example/src/requests.rs index 660d227..68f59a4 100644 --- a/satrs-example/src/requests.rs +++ b/satrs-example/src/requests.rs @@ -3,9 +3,10 @@ use satrs_core::mode::ModeRequest; use satrs_core::pus::verification::{TcStateAccepted, VerificationToken}; #[derive(Copy, Clone, Eq, PartialEq, Debug)] +#[non_exhaustive] pub enum Request { HkRequest(HkRequest), - ModeRequest(ModeRequest) + ModeRequest(ModeRequest), } #[derive(Copy, Clone, Eq, PartialEq, Debug)] From 3f862b18c7d1a0d409bb5d92ec7a810ef816d583 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 15 Feb 2023 11:26:19 +0100 Subject: [PATCH 5/5] simplified struct further --- satrs-example/src/pus.rs | 43 ++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/satrs-example/src/pus.rs b/satrs-example/src/pus.rs index 905efff..cad999c 100644 --- a/satrs-example/src/pus.rs +++ b/satrs-example/src/pus.rs @@ -33,13 +33,8 @@ use std::sync::mpsc::Sender; pub struct PusReceiver { pub tm_helper: PusTmWithCdsShortHelper, pub tm_args: PusTmArgs, - #[allow(dead_code)] - tc_source: PusTcSource, + pub tc_args: PusTcArgs, stamp_helper: TimeStampHelper, - event_request_tx: Sender, - event_sender: Sender<(EventU32, Option)>, - request_map: HashMap>, - scheduler: Rc>, } pub struct PusTmArgs { @@ -51,6 +46,12 @@ pub struct PusTmArgs { pub verif_reporter: StdVerifReporterWithSender, } +impl PusTmArgs { + fn vr(&mut self) -> &mut StdVerifReporterWithSender { + &mut self.verif_reporter + } +} + pub struct PusTcArgs { pub event_request_tx: Sender, /// Request routing helper. Maps targeted request to their recipient. @@ -93,12 +94,8 @@ impl PusReceiver { Self { tm_helper: PusTmWithCdsShortHelper::new(apid), tm_args: tm_arguments, - tc_source: tc_arguments.tc_source, - event_request_tx: tc_arguments.event_request_tx, - event_sender: tc_arguments.event_sender, - request_map: tc_arguments.request_map, + tc_args: tc_arguments, stamp_helper: TimeStampHelper::new(), - scheduler: tc_arguments.scheduler, } } } @@ -116,7 +113,7 @@ impl PusServiceProvider for PusReceiver { self.stamp_helper.update_from_now(); let accepted_token = self .tm_args - .verif_reporter + .vr() .acceptance_success(init_token, Some(self.stamp_helper.stamp())) .expect("Acceptance success failure"); let service = PusServiceId::try_from(service); @@ -189,7 +186,7 @@ impl PusReceiver { .expect("Error sending completion success"); } 128 => { - self.event_sender + self.tc_args.event_sender .send((TEST_EVENT.into(), None)) .expect("Sending test event failed"); let start_token = self @@ -250,7 +247,7 @@ impl PusReceiver { return; } let addressable_id = AddressableId::from_raw_be(user_data).unwrap(); - if !self.request_map.contains_key(&addressable_id.target_id) { + if !self.tc_args.request_map.contains_key(&addressable_id.target_id) { self.tm_args .verif_reporter .start_failure( @@ -265,7 +262,7 @@ impl PusReceiver { return; } let send_request = |request: HkRequest| { - let sender = self.request_map.get(&addressable_id.target_id).unwrap(); + let sender = self.tc_args.request_map.get(&addressable_id.target_id).unwrap(); sender .send(RequestWithToken(Request::HkRequest(request), token)) .unwrap_or_else(|_| panic!("Sending HK request {request:?} failed")); @@ -341,7 +338,7 @@ impl PusReceiver { &mut self.tm_args.verif_reporter, self.stamp_helper.stamp(), ); - self.event_request_tx + self.tc_args.event_request_tx .send(EventRequestWithToken { request: EventRequest::Enable(event_id), token: start_token, @@ -353,7 +350,7 @@ impl PusReceiver { &mut self.tm_args.verif_reporter, self.stamp_helper.stamp(), ); - self.event_request_tx + self.tc_args.event_request_tx .send(EventRequestWithToken { request: EventRequest::Disable(event_id), token: start_token, @@ -413,7 +410,7 @@ impl PusReceiver { .start_success(token, Some(self.stamp_helper.stamp())) .expect("Error sending start success"); - let mut scheduler = self.scheduler.borrow_mut(); + let mut scheduler = self.tc_args.scheduler.borrow_mut(); scheduler.enable(); if scheduler.is_enabled() { self.tm_args @@ -431,7 +428,7 @@ impl PusReceiver { .start_success(token, Some(self.stamp_helper.stamp())) .expect("Error sending start success"); - let mut scheduler = self.scheduler.borrow_mut(); + let mut scheduler = self.tc_args.scheduler.borrow_mut(); scheduler.disable(); if !scheduler.is_enabled() { self.tm_args @@ -450,13 +447,14 @@ impl PusReceiver { .expect("Error sending start success"); let mut pool = self + .tc_args .tc_source .tc_store .pool .write() .expect("Locking pool failed"); - let mut scheduler = self.scheduler.borrow_mut(); + let mut scheduler = self.tc_args.scheduler.borrow_mut(); scheduler .reset(pool.as_mut()) .expect("Error resetting TC Pool"); @@ -475,12 +473,13 @@ impl PusReceiver { .expect("error sending start success"); let mut pool = self + .tc_args .tc_source .tc_store .pool .write() .expect("locking pool failed"); - let mut scheduler = self.scheduler.borrow_mut(); + let mut scheduler = self.tc_args.scheduler.borrow_mut(); scheduler .insert_wrapped_tc::(pus_tc, pool.as_mut()) .expect("insertion of activity into pool failed"); @@ -550,7 +549,7 @@ impl PusReceiver { let mode_request = Request::ModeRequest(ModeRequest::SetMode( ModeCommand::new(target_id, mode_submode), )); - match self.request_map.get(&target_id) { + match self.tc_args.request_map.get(&target_id) { None => {} Some(sender_to_recipient) => { sender_to_recipient