diff --git a/satrs/src/pus/verification.rs b/satrs/src/pus/verification.rs index cd89905..aef9cdf 100644 --- a/satrs/src/pus/verification.rs +++ b/satrs/src/pus/verification.rs @@ -397,6 +397,12 @@ impl<'stamp, 'fargs> FailParamsWithStep<'stamp, 'fargs> { } } +/// This is a generic trait implemented by an object which can perform the ECSS PUS 1 verification +/// process according to PUS standard ECSS-E-ST-70-41C. +/// +/// This trait allows using different message queue backends for the verification reporting process +/// or to swap the actual reporter with a test reporter for unit tests. +/// For general purposes, the [VerificationReporter] should be sufficient. pub trait VerificationReportingProvider { fn set_apid(&mut self, apid: Apid); fn apid(&self) -> Apid; @@ -476,8 +482,8 @@ pub trait VerificationReportingProvider { ) -> Result<(), EcssTmtcError>; } -/// Primary verification handler. It provides an API to generate PUS 1 verification telemetry -/// packets and verify the various steps of telecommand handling as specified in the PUS standard. +/// Low level object which generates ECSS PUS 1 verification packets to verify the various steps +/// of telecommand handling as specified in the PUS standard. /// /// This is the core component which can be used without [`alloc`] support. Please note that /// the buffer passed to the API exposes by this struct will be used to serialize the source data. @@ -909,19 +915,36 @@ pub mod alloc_mod { } } - /// Primary verification handler. It provides an API to send PUS 1 verification telemetry packets - /// and verify the various steps of telecommand handling as specified in the PUS standard. + pub trait VerificationHookProvider { + fn modify_tm(&self, tm: &mut PusTmCreator); + } + + #[derive(Default)] + pub struct DummyVerificationHook {} + + impl VerificationHookProvider for DummyVerificationHook { + fn modify_tm(&self, _tm: &mut PusTmCreator) {} + } + + /// Primary verification reportewr object. It provides an API to send PUS 1 verification + /// telemetry packets and verify the various steps of telecommand handling as specified in the + /// PUS standard. + /// /// It is assumed that the sequence counter and message counters are updated in a central - /// TM funnel. This helper will always set those fields to 0. + /// TM funnel or TM inlet. This helper will always set those fields to 0. The APID and + /// destination fields are assumed to be constant for a given repoter instance. #[derive(Clone)] - pub struct VerificationReporter { + pub struct VerificationReporter< + VerificationHook: VerificationHookProvider = DummyVerificationHook, + > { // TODO: We could add a hook object which allows users to manipulate the verification // report TM before it is sent.. source_data_buf: RefCell>, pub reporter_creator: VerificationReportCreator, + pub tm_hook: VerificationHook, } - impl VerificationReporter { + impl VerificationReporter { pub fn new(cfg: &VerificationReporterCfg) -> Self { let reporter = VerificationReportCreator::new(cfg.apid).unwrap(); Self { @@ -932,9 +955,25 @@ pub mod alloc_mod { + cfg.fail_code_field_width + cfg.max_fail_data_len ]), - // seq_count_provider: None, - // msg_count_provider: None, reporter_creator: reporter, + tm_hook: DummyVerificationHook::default(), + } + } + } + + impl VerificationReporter { + pub fn new_with_hook(cfg: &VerificationReporterCfg, tm_hook: VerificationHook) -> Self { + let reporter = VerificationReportCreator::new(cfg.apid).unwrap(); + Self { + source_data_buf: RefCell::new(alloc::vec![ + 0; + RequestId::SIZE_AS_BYTES + + cfg.step_field_width + + cfg.fail_code_field_width + + cfg.max_fail_data_len + ]), + reporter_creator: reporter, + tm_hook, } } @@ -973,10 +1012,11 @@ pub mod alloc_mod { time_stamp: &[u8], ) -> Result, EcssTmtcError> { let mut source_data_buf = self.source_data_buf.borrow_mut(); - let (tm_creator, token) = self + let (mut tm_creator, token) = self .reporter_creator .acceptance_success(source_data_buf.as_mut_slice(), token, 0, 0, time_stamp) .map_err(PusError::ByteConversion)?; + self.tm_hook.modify_tm(&mut tm_creator); sender.send_tm(sender_id, PusTmVariant::Direct(tm_creator))?; Ok(token) } @@ -990,11 +1030,12 @@ pub mod alloc_mod { params: FailParams, ) -> Result<(), EcssTmtcError> { let mut buf = self.source_data_buf.borrow_mut(); - let sendable = self + let mut tm_creator = self .reporter_creator .acceptance_failure(buf.as_mut_slice(), token, 0, 0, params) .map_err(PusError::ByteConversion)?; - sender.send_tm(sender_id, PusTmVariant::Direct(sendable))?; + self.tm_hook.modify_tm(&mut tm_creator); + sender.send_tm(sender_id, PusTmVariant::Direct(tm_creator))?; Ok(()) } @@ -1009,10 +1050,11 @@ pub mod alloc_mod { time_stamp: &[u8], ) -> Result, EcssTmtcError> { let mut buf = self.source_data_buf.borrow_mut(); - let (tm_creator, started_token) = self + let (mut tm_creator, started_token) = self .reporter_creator .start_success(buf.as_mut_slice(), token, 0, 0, time_stamp) .map_err(PusError::ByteConversion)?; + self.tm_hook.modify_tm(&mut tm_creator); sender.send_tm(sender_id, PusTmVariant::Direct(tm_creator))?; Ok(started_token) } @@ -1029,11 +1071,12 @@ pub mod alloc_mod { params: FailParams, ) -> Result<(), EcssTmtcError> { let mut buf = self.source_data_buf.borrow_mut(); - let sendable = self + let mut tm_creator = self .reporter_creator .start_failure(buf.as_mut_slice(), token, 0, 0, params) .map_err(PusError::ByteConversion)?; - sender.send_tm(sender_id, PusTmVariant::Direct(sendable))?; + self.tm_hook.modify_tm(&mut tm_creator); + sender.send_tm(sender_id, PusTmVariant::Direct(tm_creator))?; Ok(()) } @@ -1049,11 +1092,12 @@ pub mod alloc_mod { step: impl EcssEnumeration, ) -> Result<(), EcssTmtcError> { let mut buf = self.source_data_buf.borrow_mut(); - let sendable = self + let mut tm_creator = self .reporter_creator .step_success(buf.as_mut_slice(), token, 0, 0, time_stamp, step) .map_err(PusError::ByteConversion)?; - sender.send_tm(sender_id, PusTmVariant::Direct(sendable))?; + self.tm_hook.modify_tm(&mut tm_creator); + sender.send_tm(sender_id, PusTmVariant::Direct(tm_creator))?; Ok(()) } @@ -1069,11 +1113,12 @@ pub mod alloc_mod { params: FailParamsWithStep, ) -> Result<(), EcssTmtcError> { let mut buf = self.source_data_buf.borrow_mut(); - let sendable = self + let mut tm_creator = self .reporter_creator .step_failure(buf.as_mut_slice(), token, 0, 0, params) .map_err(PusError::ByteConversion)?; - sender.send_tm(sender_id, PusTmVariant::Direct(sendable))?; + self.tm_hook.modify_tm(&mut tm_creator); + sender.send_tm(sender_id, PusTmVariant::Direct(tm_creator))?; Ok(()) } @@ -1089,11 +1134,12 @@ pub mod alloc_mod { time_stamp: &[u8], ) -> Result<(), EcssTmtcError> { let mut buf = self.source_data_buf.borrow_mut(); - let sendable = self + let mut tm_creator = self .reporter_creator .completion_success(buf.as_mut_slice(), token, 0, 0, time_stamp) .map_err(PusError::ByteConversion)?; - sender.send_tm(sender_id, PusTmVariant::Direct(sendable))?; + self.tm_hook.modify_tm(&mut tm_creator); + sender.send_tm(sender_id, PusTmVariant::Direct(tm_creator))?; Ok(()) } @@ -1109,11 +1155,12 @@ pub mod alloc_mod { params: FailParams, ) -> Result<(), EcssTmtcError> { let mut buf = self.source_data_buf.borrow_mut(); - let sendable = self + let mut tm_creator = self .reporter_creator .completion_failure(buf.as_mut_slice(), token, 0, 00, params) .map_err(PusError::ByteConversion)?; - sender.send_tm(sender_id, PusTmVariant::Direct(sendable))?; + self.tm_hook.modify_tm(&mut tm_creator); + sender.send_tm(sender_id, PusTmVariant::Direct(tm_creator))?; Ok(()) } }