From 08e3242f84f02eaf7ac134cc4cc435d804f90b67 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 11 Sep 2022 20:51:14 +0200 Subject: [PATCH 01/13] pus modules now no_std compatible --- fsrc-core/src/hal/host/udp_server.rs | 4 +- fsrc-core/src/pus/event.rs | 115 +++++ fsrc-core/src/pus/mod.rs | 49 +- fsrc-core/src/pus/verification.rs | 695 +++++++++++++++++---------- fsrc-core/src/tmtc/ccsds_distrib.rs | 10 +- fsrc-core/src/tmtc/pus_distrib.rs | 2 +- fsrc-core/tests/verification_test.rs | 6 +- fsrc-example/src/bin/client.rs | 4 +- fsrc-example/src/bin/obsw/main.rs | 2 +- fsrc-example/src/bin/obsw/tmtc.rs | 2 +- spacepackets | 2 +- 11 files changed, 620 insertions(+), 271 deletions(-) create mode 100644 fsrc-core/src/pus/event.rs diff --git a/fsrc-core/src/hal/host/udp_server.rs b/fsrc-core/src/hal/host/udp_server.rs index 2c7cd37..dd7ca67 100644 --- a/fsrc-core/src/hal/host/udp_server.rs +++ b/fsrc-core/src/hal/host/udp_server.rs @@ -41,7 +41,7 @@ use std::vec::Vec; /// let mut sph = SpHeader::tc(0x02, 0, 0).unwrap(); /// let pus_tc = PusTc::new_simple(&mut sph, 17, 1, None, true); /// let len = pus_tc -/// .write_to(&mut buf) +/// .write_to_bytes(&mut buf) /// .expect("Error writing PUS TC packet"); /// assert_eq!(len, 13); /// let client = UdpSocket::bind("127.0.0.1:7778").expect("Connecting to UDP server failed"); @@ -166,7 +166,7 @@ mod tests { let mut sph = SpHeader::tc(0x02, 0, 0).unwrap(); let pus_tc = PusTc::new_simple(&mut sph, 17, 1, None, true); let len = pus_tc - .write_to(&mut buf) + .write_to_bytes(&mut buf) .expect("Error writing PUS TC packet"); let client = UdpSocket::bind("127.0.0.1:7778").expect("Connecting to UDP server failed"); client diff --git a/fsrc-core/src/pus/event.rs b/fsrc-core/src/pus/event.rs new file mode 100644 index 0000000..394b15e --- /dev/null +++ b/fsrc-core/src/pus/event.rs @@ -0,0 +1,115 @@ +use crate::pus::{source_buffer_large_enough, EcssTmError, EcssTmSender}; +use spacepackets::ecss::EcssEnumeration; +use spacepackets::tm::PusTm; +use spacepackets::tm::PusTmSecondaryHeader; +use spacepackets::{SpHeader, MAX_APID}; + +#[cfg(feature = "alloc")] +pub use allocvec::EventReporterWithVec; + +pub struct EventReporter { + msg_count: u16, + apid: u16, + pub dest_id: u16, +} + +impl EventReporter { + pub fn new(apid: u16) -> Option { + if apid > MAX_APID { + return None; + } + Some(Self { + msg_count: 0, + dest_id: 0, + apid, + }) + } + + pub fn event_info( + &mut self, + buf: &mut [u8], + sender: &mut (impl EcssTmSender + ?Sized), + time_stamp: &[u8], + event_id: impl EcssEnumeration, + aux_data: Option<&[u8]>, + ) -> Result<(), EcssTmError> { + let mut src_data_len = event_id.byte_width(); + if let Some(aux_data) = aux_data { + src_data_len += aux_data.len(); + } + source_buffer_large_enough(buf.len(), src_data_len)?; + let mut sp_header = SpHeader::tm(self.apid, 0, 0).unwrap(); + let sec_header = PusTmSecondaryHeader::new(5, 0, self.msg_count, self.dest_id, time_stamp); + let mut current_idx = 0; + event_id.write_to_bytes(&mut buf[0..event_id.byte_width()])?; + current_idx += event_id.byte_width(); + if let Some(aux_data) = aux_data { + buf[current_idx..current_idx + aux_data.len()].copy_from_slice(aux_data); + current_idx += aux_data.len(); + } + let tm = PusTm::new(&mut sp_header, sec_header, Some(&buf[0..current_idx]), true); + sender.send_tm(tm)?; + self.msg_count += 1; + Ok(()) + } +} + +#[cfg(feature = "alloc")] +mod allocvec { + use super::*; + use alloc::vec; + use alloc::vec::Vec; + + pub struct EventReporterWithVec { + source_data_buf: Vec, + pub reporter: EventReporter, + } + + impl EventReporterWithVec { + pub fn new(apid: u16, max_event_id_and_aux_data: usize) -> Option { + let reporter = EventReporter::new(apid)?; + Some(Self { + source_data_buf: vec![0; max_event_id_and_aux_data], + reporter, + }) + } + pub fn event_info( + &mut self, + sender: &mut (impl EcssTmSender + ?Sized), + time_stamp: &[u8], + event_id: impl EcssEnumeration, + aux_data: Option<&[u8]>, + ) -> Result<(), EcssTmError> { + self.reporter.event_info( + self.source_data_buf.as_mut_slice(), + sender, + time_stamp, + event_id, + aux_data, + ) + } + // pub fn event_low_severity( + // &mut self, + // _sender: &mut (impl EcssTmSender + ?Sized), + // _event_id: impl EcssEnumeration, + // _aux_data: Option<&[u8]>, + // ) { + // } + // + // pub fn event_medium_severity( + // &mut self, + // _sender: &mut (impl EcssTmSender + ?Sized), + // _event_id: impl EcssEnumeration, + // _aux_data: Option<&[u8]>, + // ) { + // } + // + // pub fn event_high_severity( + // &mut self, + // _sender: &mut (impl EcssTmSender + ?Sized), + // _event_id: impl EcssEnumeration, + // _aux_data: Option<&[u8]>, + // ) { + // } + } +} diff --git a/fsrc-core/src/pus/mod.rs b/fsrc-core/src/pus/mod.rs index fb3a317..074402f 100644 --- a/fsrc-core/src/pus/mod.rs +++ b/fsrc-core/src/pus/mod.rs @@ -3,5 +3,52 @@ //! Currenty includes: //! //! 1. PUS Verification Service 1 module inside [verification]. Requires [alloc] support. -#[cfg(feature = "alloc")] +use downcast_rs::{impl_downcast, Downcast}; +use spacepackets::ecss::PusError; +use spacepackets::time::TimestampError; +use spacepackets::tm::PusTm; +use spacepackets::{ByteConversionError, SizeMissmatch}; + +pub mod event; pub mod verification; + +/// Generic error type which is also able to wrap a user send error with the user supplied type E. +#[derive(Debug, Clone)] +pub enum EcssTmError { + /// Errors related to sending the verification telemetry to a TM recipient + SendError(E), + /// Errors related to the time stamp format of the telemetry + TimestampError(TimestampError), + /// Errors related to byte conversion, for example insufficient buffer size for given data + ByteConversionError(ByteConversionError), + /// Errors related to PUS packet format + PusError(PusError), +} + +impl From for EcssTmError { + fn from(e: ByteConversionError) -> Self { + EcssTmError::ByteConversionError(e) + } +} + +/// Generic trait for a user supplied sender object. This sender object is responsible for sending +/// telemetry to a TM sink. The [Downcast] trait +/// is implemented to allow passing the sender as a boxed trait object and still retrieve the +/// concrete type at a later point. +pub trait EcssTmSender: Downcast + Send { + fn send_tm(&mut self, tm: PusTm) -> Result<(), EcssTmError>; +} + +impl_downcast!(EcssTmSender); + +pub(crate) fn source_buffer_large_enough(cap: usize, len: usize) -> Result<(), EcssTmError> { + if len > cap { + return Err(EcssTmError::ByteConversionError( + ByteConversionError::ToSliceTooSmall(SizeMissmatch { + found: cap, + expected: len, + }), + )); + } + Ok(()) +} diff --git a/fsrc-core/src/pus/verification.rs b/fsrc-core/src/pus/verification.rs index 4af6ad6..55bc82d 100644 --- a/fsrc-core/src/pus/verification.rs +++ b/fsrc-core/src/pus/verification.rs @@ -29,7 +29,7 @@ //! let shared_tm_pool: SharedPool = Arc::new(RwLock::new(Box::new(LocalPool::new(pool_cfg.clone())))); //! let (verif_tx, verif_rx) = crossbeam_channel::bounded(10); //! let sender = CrossbeamVerifSender::new(shared_tm_pool.clone(), verif_tx); -//! let cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8); +//! let cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8).unwrap(); //! let mut reporter = VerificationReporterWithSender::new(cfg , Box::new(sender)); //! //! let mut sph = SpHeader::tc(TEST_APID, 0, 0).unwrap(); @@ -71,21 +71,20 @@ //! 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 alloc::boxed::Box; -use alloc::vec; -use alloc::vec::Vec; +use crate::pus::{source_buffer_large_enough, EcssTmError, EcssTmSender}; use core::fmt::{Display, Formatter}; use core::hash::{Hash, Hasher}; use core::marker::PhantomData; use core::mem::size_of; use delegate::delegate; -use downcast_rs::{impl_downcast, Downcast}; -use spacepackets::ecss::{EcssEnumeration, PusError}; +use spacepackets::ecss::EcssEnumeration; use spacepackets::tc::PusTc; -use spacepackets::time::TimestampError; use spacepackets::tm::{PusTm, PusTmSecondaryHeader}; -use spacepackets::{ByteConversionError, SizeMissmatch, SpHeader}; use spacepackets::{CcsdsPacket, PacketId, PacketSequenceCtrl}; +use spacepackets::{SpHeader, MAX_APID}; + +#[cfg(feature = "alloc")] +pub use allocmod::{VerificationReporter, VerificationReporterCfg, VerificationReporterWithSender}; #[cfg(feature = "std")] pub use stdmod::{ @@ -160,39 +159,10 @@ impl RequestId { } } -/// Generic error type which is also able to wrap a user send error with the user supplied type E. -#[derive(Debug, Clone)] -pub enum VerificationError { - /// Errors related to sending the verification telemetry to a TM recipient - SendError(E), - /// Errors related to the time stamp format of the telemetry - TimestampError(TimestampError), - /// Errors related to byte conversion, for example unsufficient buffer size for given data - ByteConversionError(ByteConversionError), - /// Errors related to PUS packet format - PusError(PusError), -} - -impl From for VerificationError { - fn from(e: ByteConversionError) -> Self { - VerificationError::ByteConversionError(e) - } -} - /// If a verification operation fails, the passed token will be returned as well. This allows /// re-trying the operation at a later point. #[derive(Debug, Clone)] -pub struct VerificationErrorWithToken(VerificationError, VerificationToken); - -/// Generic trait for a user supplied sender object. This sender object is responsible for sending -/// PUS Service 1 Verification Telemetry to a verification TM recipient. The [Downcast] trait -/// is implemented to allow passing the sender as a boxed trait object and still retrieve the -/// concrete type at a later point. -pub trait VerificationSender: Downcast + Send { - fn send_verification_tm(&mut self, tm: PusTm) -> Result<(), VerificationError>; -} - -impl_downcast!(VerificationSender); +pub struct VerificationErrorWithToken(EcssTmError, VerificationToken); /// Support token to allow type-state programming. This prevents calling the verification /// steps in an invalid order. @@ -222,41 +192,6 @@ impl VerificationToken { } } -pub struct VerificationReporterCfg { - pub apid: u16, - pub dest_id: u16, - pub step_field_width: usize, - pub fail_code_field_width: usize, - pub max_fail_data_len: usize, -} - -impl VerificationReporterCfg { - /// Create a new configuration for the verification reporter. This includes following parameters: - /// - /// 1. Destination ID and APID, which could remain constant after construction. These parameters - /// can be tweaked in the reporter after construction. - /// 2. Maximum expected field sizes. The parameters of this configuration struct will be used - /// to determine required maximum buffer sizes and there will be no addition allocation or - /// configurable buffer parameters after [VerificationReporter] construction. - /// - /// This means the user has supply the maximum expected field sizes of verification messages - /// before constructing the reporter. - pub fn new( - apid: u16, - step_field_width: usize, - fail_code_field_width: usize, - max_fail_data_len: usize, - ) -> Self { - Self { - apid, - dest_id: 0, - step_field_width, - fail_code_field_width, - max_fail_data_len, - } - } -} - /// Composite helper struct to pass failure parameters to the [VerificationReporter] pub struct FailParams<'a> { time_stamp: &'a [u8], @@ -298,33 +233,42 @@ impl<'a> FailParamsWithStep<'a> { } } -/// 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 struct VerificationReporter { - pub apid: u16, +pub struct VerificationReporterBasic { pub dest_id: u16, + apid: u16, msg_count: u16, - source_data_buf: Vec, } -impl VerificationReporter { - pub fn new(cfg: VerificationReporterCfg) -> Self { - Self { - apid: cfg.apid, - dest_id: cfg.dest_id, - msg_count: 0, - source_data_buf: vec![ - 0; - RequestId::SIZE_AS_BYTES - + cfg.step_field_width as usize - + cfg.fail_code_field_width as usize - + cfg.max_fail_data_len - ], +impl VerificationReporterBasic { + pub fn new(apid: u16) -> Option { + if apid > MAX_APID { + return None; } + Some(Self { + apid, + msg_count: 0, + dest_id: 0, + }) } - pub fn allowed_source_data_len(&self) -> usize { - self.source_data_buf.capacity() + pub fn set_apid(&mut self, apid: u16) -> bool { + if apid > MAX_APID { + return false; + } + self.apid = apid; + true + } + + pub fn apid(&self) -> u16 { + self.apid + } + + pub fn dest_id(&self) -> u16 { + self.dest_id + } + + pub fn set_dest_id(&mut self, dest_id: u16) { + self.dest_id = dest_id; } /// Initialize verification handling by passing a TC reference. This returns a token required @@ -342,12 +286,14 @@ impl VerificationReporter { /// Package and send a PUS TM\[1, 1\] packet, see 8.1.2.1 of the PUS standard pub fn acceptance_success( &mut self, + buf: &mut [u8], token: VerificationToken, - sender: &mut (impl VerificationSender + ?Sized), + sender: &mut (impl EcssTmSender + ?Sized), time_stamp: &[u8], ) -> Result, VerificationErrorWithToken> { let tm = self .create_pus_verif_success_tm( + buf, 1, 1, &token.req_id, @@ -356,7 +302,7 @@ impl VerificationReporter { ) .map_err(|e| VerificationErrorWithToken(e, token))?; sender - .send_verification_tm(tm) + .send_tm(tm) .map_err(|e| VerificationErrorWithToken(e, token))?; self.msg_count += 1; Ok(VerificationToken { @@ -368,15 +314,23 @@ impl VerificationReporter { /// Package and send a PUS TM\[1, 2\] packet, see 8.1.2.2 of the PUS standard pub fn acceptance_failure( &mut self, + buf: &mut [u8], token: VerificationToken, - sender: &mut (impl VerificationSender + ?Sized), + sender: &mut (impl EcssTmSender + ?Sized), params: FailParams, ) -> Result<(), VerificationErrorWithToken> { let tm = self - .create_pus_verif_fail_tm(1, 2, &token.req_id, None::<&dyn EcssEnumeration>, ¶ms) + .create_pus_verif_fail_tm( + buf, + 1, + 2, + &token.req_id, + None::<&dyn EcssEnumeration>, + ¶ms, + ) .map_err(|e| VerificationErrorWithToken(e, token))?; sender - .send_verification_tm(tm) + .send_tm(tm) .map_err(|e| VerificationErrorWithToken(e, token))?; self.msg_count += 1; Ok(()) @@ -387,12 +341,14 @@ impl VerificationReporter { /// Requires a token previously acquired by calling [Self::acceptance_success]. pub fn start_success( &mut self, + buf: &mut [u8], token: VerificationToken, - sender: &mut (impl VerificationSender + ?Sized), + sender: &mut (impl EcssTmSender + ?Sized), time_stamp: &[u8], ) -> Result, VerificationErrorWithToken> { let tm = self .create_pus_verif_success_tm( + buf, 1, 3, &token.req_id, @@ -401,7 +357,7 @@ impl VerificationReporter { ) .map_err(|e| VerificationErrorWithToken(e, token))?; sender - .send_verification_tm(tm) + .send_tm(tm) .map_err(|e| VerificationErrorWithToken(e, token))?; self.msg_count += 1; Ok(VerificationToken { @@ -416,15 +372,23 @@ impl VerificationReporter { /// the token because verification handling is done. pub fn start_failure( &mut self, + buf: &mut [u8], token: VerificationToken, - sender: &mut (impl VerificationSender + ?Sized), + sender: &mut (impl EcssTmSender + ?Sized), params: FailParams, ) -> Result<(), VerificationErrorWithToken> { let tm = self - .create_pus_verif_fail_tm(1, 4, &token.req_id, None::<&dyn EcssEnumeration>, ¶ms) + .create_pus_verif_fail_tm( + buf, + 1, + 4, + &token.req_id, + None::<&dyn EcssEnumeration>, + ¶ms, + ) .map_err(|e| VerificationErrorWithToken(e, token))?; sender - .send_verification_tm(tm) + .send_tm(tm) .map_err(|e| VerificationErrorWithToken(e, token))?; self.msg_count += 1; Ok(()) @@ -435,13 +399,15 @@ impl VerificationReporter { /// Requires a token previously acquired by calling [Self::start_success]. pub fn step_success( &mut self, + buf: &mut [u8], token: &VerificationToken, - sender: &mut (impl VerificationSender + ?Sized), + sender: &mut (impl EcssTmSender + ?Sized), time_stamp: &[u8], step: impl EcssEnumeration, - ) -> Result<(), VerificationError> { - let tm = self.create_pus_verif_success_tm(1, 5, &token.req_id, time_stamp, Some(&step))?; - sender.send_verification_tm(tm)?; + ) -> Result<(), EcssTmError> { + let tm = + self.create_pus_verif_success_tm(buf, 1, 5, &token.req_id, time_stamp, Some(&step))?; + sender.send_tm(tm)?; self.msg_count += 1; Ok(()) } @@ -452,15 +418,16 @@ impl VerificationReporter { /// token because verification handling is done. pub fn step_failure( &mut self, + buf: &mut [u8], token: VerificationToken, - sender: &mut (impl VerificationSender + ?Sized), + sender: &mut (impl EcssTmSender + ?Sized), params: FailParamsWithStep, ) -> Result<(), VerificationErrorWithToken> { let tm = self - .create_pus_verif_fail_tm(1, 6, &token.req_id, Some(params.step), ¶ms.bp) + .create_pus_verif_fail_tm(buf, 1, 6, &token.req_id, Some(params.step), ¶ms.bp) .map_err(|e| VerificationErrorWithToken(e, token))?; sender - .send_verification_tm(tm) + .send_tm(tm) .map_err(|e| VerificationErrorWithToken(e, token))?; self.msg_count += 1; Ok(()) @@ -472,12 +439,14 @@ impl VerificationReporter { /// token because verification handling is done. pub fn completion_success( &mut self, + buf: &mut [u8], token: VerificationToken, - sender: &mut (impl VerificationSender + ?Sized), + sender: &mut (impl EcssTmSender + ?Sized), time_stamp: &[u8], ) -> Result<(), VerificationErrorWithToken> { let tm = self .create_pus_verif_success_tm( + buf, 1, 7, &token.req_id, @@ -486,7 +455,7 @@ impl VerificationReporter { ) .map_err(|e| VerificationErrorWithToken(e, token))?; sender - .send_verification_tm(tm) + .send_tm(tm) .map_err(|e| VerificationErrorWithToken(e, token))?; self.msg_count += 1; Ok(()) @@ -498,15 +467,23 @@ impl VerificationReporter { /// token because verification handling is done. pub fn completion_failure( &mut self, + buf: &mut [u8], token: VerificationToken, - sender: &mut (impl VerificationSender + ?Sized), + sender: &mut (impl EcssTmSender + ?Sized), params: FailParams, ) -> Result<(), VerificationErrorWithToken> { let tm = self - .create_pus_verif_fail_tm(1, 8, &token.req_id, None::<&dyn EcssEnumeration>, ¶ms) + .create_pus_verif_fail_tm( + buf, + 1, + 8, + &token.req_id, + None::<&dyn EcssEnumeration>, + ¶ms, + ) .map_err(|e| VerificationErrorWithToken(e, token))?; sender - .send_verification_tm(tm) + .send_tm(tm) .map_err(|e| VerificationErrorWithToken(e, token))?; self.msg_count += 1; Ok(()) @@ -514,27 +491,29 @@ impl VerificationReporter { fn create_pus_verif_success_tm<'a, E>( &'a mut self, + buf: &'a mut [u8], service: u8, subservice: u8, req_id: &RequestId, time_stamp: &'a [u8], step: Option<&(impl EcssEnumeration + ?Sized)>, - ) -> Result> { + ) -> Result> { let mut source_data_len = size_of::(); if let Some(step) = step { source_data_len += step.byte_width() as usize; } - self.source_buffer_large_enough(source_data_len)?; + source_buffer_large_enough(buf.len(), source_data_len)?; let mut idx = 0; - req_id.to_bytes(&mut self.source_data_buf[0..RequestId::SIZE_AS_BYTES]); + req_id.to_bytes(&mut buf[0..RequestId::SIZE_AS_BYTES]); idx += RequestId::SIZE_AS_BYTES; if let Some(step) = step { // Size check was done beforehand - step.to_bytes(&mut self.source_data_buf[idx..idx + step.byte_width() as usize]) + step.write_to_bytes(&mut buf[idx..idx + step.byte_width() as usize]) .unwrap(); } - let mut sp_header = SpHeader::tm(self.apid, 0, 0).unwrap(); + let mut sp_header = SpHeader::tm(self.apid(), 0, 0).unwrap(); Ok(self.create_pus_verif_tm_base( + buf, service, subservice, &mut sp_header, @@ -545,12 +524,13 @@ impl VerificationReporter { fn create_pus_verif_fail_tm<'a, E>( &'a mut self, + buf: &'a mut [u8], service: u8, subservice: u8, req_id: &RequestId, step: Option<&(impl EcssEnumeration + ?Sized)>, params: &'a FailParams, - ) -> Result> { + ) -> Result> { let mut idx = 0; let mut source_data_len = RequestId::SIZE_AS_BYTES + params.failure_code.byte_width() as usize; @@ -560,24 +540,25 @@ impl VerificationReporter { if let Some(failure_data) = params.failure_data { source_data_len += failure_data.len(); } - self.source_buffer_large_enough(source_data_len)?; - req_id.to_bytes(&mut self.source_data_buf[0..RequestId::SIZE_AS_BYTES]); + source_buffer_large_enough(buf.len(), source_data_len)?; + req_id.to_bytes(&mut buf[0..RequestId::SIZE_AS_BYTES]); idx += RequestId::SIZE_AS_BYTES; if let Some(step) = step { // Size check done beforehand - step.to_bytes(&mut self.source_data_buf[idx..idx + step.byte_width() as usize]) + step.write_to_bytes(&mut buf[idx..idx + step.byte_width() as usize]) .unwrap(); idx += step.byte_width() as usize; } - params.failure_code.to_bytes( - &mut self.source_data_buf[idx..idx + params.failure_code.byte_width() as usize], - )?; + params + .failure_code + .write_to_bytes(&mut buf[idx..idx + params.failure_code.byte_width() as usize])?; idx += params.failure_code.byte_width() as usize; if let Some(failure_data) = params.failure_data { - self.source_data_buf[idx..idx + failure_data.len()].copy_from_slice(failure_data); + buf[idx..idx + failure_data.len()].copy_from_slice(failure_data); } - let mut sp_header = SpHeader::tm(self.apid, 0, 0).unwrap(); + let mut sp_header = SpHeader::tm(self.apid(), 0, 0).unwrap(); Ok(self.create_pus_verif_tm_base( + buf, service, subservice, &mut sp_header, @@ -586,20 +567,9 @@ impl VerificationReporter { )) } - fn source_buffer_large_enough(&self, len: usize) -> Result<(), VerificationError> { - if len > self.source_data_buf.capacity() { - return Err(VerificationError::ByteConversionError( - ByteConversionError::ToSliceTooSmall(SizeMissmatch { - found: self.source_data_buf.capacity(), - expected: len, - }), - )); - } - Ok(()) - } - fn create_pus_verif_tm_base<'a>( &'a mut self, + buf: &'a mut [u8], service: u8, subservice: u8, sp_header: &mut SpHeader, @@ -616,118 +586,328 @@ impl VerificationReporter { PusTm::new( sp_header, tm_sec_header, - Some(&self.source_data_buf[0..source_data_len]), + Some(&buf[0..source_data_len]), true, ) } } -/// Helper object which caches the sender passed as a trait object. Provides the same -/// API as [VerificationReporter] but without the explicit sender arguments. -pub struct VerificationReporterWithSender { - reporter: VerificationReporter, - pub sender: Box>, -} +#[cfg(feature = "alloc")] +mod allocmod { + use super::*; + use alloc::boxed::Box; + use alloc::vec; + use alloc::vec::Vec; -impl VerificationReporterWithSender { - pub fn new(cfg: VerificationReporterCfg, sender: Box>) -> Self { - Self::new_from_reporter(VerificationReporter::new(cfg), sender) + pub struct VerificationReporterCfg { + apid: u16, + pub step_field_width: usize, + pub fail_code_field_width: usize, + pub max_fail_data_len: usize, } - pub fn new_from_reporter( - reporter: VerificationReporter, - sender: Box>, - ) -> Self { - Self { reporter, sender } - } - - delegate! { - to self.reporter { - pub fn add_tc(&mut self, pus_tc: &PusTc) -> VerificationToken; - pub fn add_tc_with_req_id(&mut self, req_id: RequestId) -> VerificationToken; + impl VerificationReporterCfg { + pub fn new( + apid: u16, + step_field_width: usize, + fail_code_field_width: usize, + max_fail_data_len: usize, + ) -> Option { + if apid > MAX_APID { + return None; + } + Some(Self { + apid, + step_field_width, + fail_code_field_width, + max_fail_data_len, + }) } } - pub fn acceptance_success( - &mut self, - token: VerificationToken, - time_stamp: &[u8], - ) -> Result, VerificationErrorWithToken> { - self.reporter - .acceptance_success(token, self.sender.as_mut(), time_stamp) + /// 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 struct VerificationReporter { + source_data_buf: Vec, + pub reporter: VerificationReporterBasic, } - pub fn acceptance_failure( - &mut self, - token: VerificationToken, - params: FailParams, - ) -> Result<(), VerificationErrorWithToken> { - self.reporter - .acceptance_failure(token, self.sender.as_mut(), params) + impl VerificationReporter { + pub fn new(cfg: VerificationReporterCfg) -> Self { + let reporter = VerificationReporterBasic::new(cfg.apid).unwrap(); + Self { + source_data_buf: vec![ + 0; + RequestId::SIZE_AS_BYTES + + cfg.step_field_width as usize + + cfg.fail_code_field_width as usize + + cfg.max_fail_data_len + ], + reporter, + } + } + + delegate!( + to self.reporter { + pub fn set_apid(&mut self, apid: u16) -> bool; + pub fn apid(&self) -> u16; + pub fn add_tc(&mut self, pus_tc: &PusTc) -> VerificationToken; + pub fn add_tc_with_req_id(&mut self, req_id: RequestId) -> VerificationToken; + pub fn dest_id(&self) -> u16; + pub fn set_dest_id(&mut self, dest_id: u16); + } + ); + + pub fn allowed_source_data_len(&self) -> usize { + self.source_data_buf.capacity() + } + + /// Package and send a PUS TM\[1, 1\] packet, see 8.1.2.1 of the PUS standard + pub fn acceptance_success( + &mut self, + token: VerificationToken, + sender: &mut (impl EcssTmSender + ?Sized), + time_stamp: &[u8], + ) -> Result, VerificationErrorWithToken> + { + self.reporter.acceptance_success( + self.source_data_buf.as_mut_slice(), + token, + sender, + time_stamp, + ) + } + + /// Package and send a PUS TM\[1, 2\] packet, see 8.1.2.2 of the PUS standard + pub fn acceptance_failure( + &mut self, + token: VerificationToken, + sender: &mut (impl EcssTmSender + ?Sized), + params: FailParams, + ) -> Result<(), VerificationErrorWithToken> { + self.reporter.acceptance_failure( + self.source_data_buf.as_mut_slice(), + token, + sender, + params, + ) + } + + /// Package and send a PUS TM\[1, 3\] packet, see 8.1.2.3 of the PUS standard. + /// + /// Requires a token previously acquired by calling [Self::acceptance_success]. + pub fn start_success( + &mut self, + token: VerificationToken, + sender: &mut (impl EcssTmSender + ?Sized), + time_stamp: &[u8], + ) -> Result, VerificationErrorWithToken> + { + self.reporter.start_success( + self.source_data_buf.as_mut_slice(), + token, + sender, + time_stamp, + ) + } + + /// Package and send a PUS TM\[1, 4\] packet, see 8.1.2.4 of the PUS standard. + /// + /// Requires a token previously acquired by calling [Self::acceptance_success]. It consumes + /// the token because verification handling is done. + pub fn start_failure( + &mut self, + token: VerificationToken, + sender: &mut (impl EcssTmSender + ?Sized), + params: FailParams, + ) -> Result<(), VerificationErrorWithToken> { + self.reporter + .start_failure(self.source_data_buf.as_mut_slice(), token, sender, params) + } + + /// Package and send a PUS TM\[1, 5\] packet, see 8.1.2.5 of the PUS standard. + /// + /// Requires a token previously acquired by calling [Self::start_success]. + pub fn step_success( + &mut self, + token: &VerificationToken, + sender: &mut (impl EcssTmSender + ?Sized), + time_stamp: &[u8], + step: impl EcssEnumeration, + ) -> Result<(), EcssTmError> { + self.reporter.step_success( + self.source_data_buf.as_mut_slice(), + token, + sender, + time_stamp, + step, + ) + } + + /// Package and send a PUS TM\[1, 6\] packet, see 8.1.2.6 of the PUS standard. + /// + /// Requires a token previously acquired by calling [Self::start_success]. It consumes the + /// token because verification handling is done. + pub fn step_failure( + &mut self, + token: VerificationToken, + sender: &mut (impl EcssTmSender + ?Sized), + params: FailParamsWithStep, + ) -> Result<(), VerificationErrorWithToken> { + self.reporter + .step_failure(self.source_data_buf.as_mut_slice(), token, sender, params) + } + + /// Package and send a PUS TM\[1, 7\] packet, see 8.1.2.7 of the PUS standard. + /// + /// Requires a token previously acquired by calling [Self::start_success]. It consumes the + /// token because verification handling is done. + pub fn completion_success( + &mut self, + token: VerificationToken, + sender: &mut (impl EcssTmSender + ?Sized), + time_stamp: &[u8], + ) -> Result<(), VerificationErrorWithToken> { + self.reporter.completion_success( + self.source_data_buf.as_mut_slice(), + token, + sender, + time_stamp, + ) + } + + /// Package and send a PUS TM\[1, 8\] packet, see 8.1.2.8 of the PUS standard. + /// + /// Requires a token previously acquired by calling [Self::start_success]. It consumes the + /// token because verification handling is done. + pub fn completion_failure( + &mut self, + token: VerificationToken, + sender: &mut (impl EcssTmSender + ?Sized), + params: FailParams, + ) -> Result<(), VerificationErrorWithToken> { + self.reporter.completion_failure( + self.source_data_buf.as_mut_slice(), + token, + sender, + params, + ) + } } - pub fn start_success( - &mut self, - token: VerificationToken, - time_stamp: &[u8], - ) -> Result, VerificationErrorWithToken> { - self.reporter - .start_success(token, self.sender.as_mut(), time_stamp) + /// Helper object which caches the sender passed as a trait object. Provides the same + /// API as [VerificationReporter] but without the explicit sender arguments. + pub struct VerificationReporterWithSender { + pub reporter: VerificationReporter, + pub sender: Box>, } - pub fn start_failure( - &mut self, - token: VerificationToken, - params: FailParams, - ) -> Result<(), VerificationErrorWithToken> { - self.reporter - .start_failure(token, self.sender.as_mut(), params) - } + impl VerificationReporterWithSender { + pub fn new(cfg: VerificationReporterCfg, sender: Box>) -> Self { + let reporter = VerificationReporter::new(cfg); + Self::new_from_reporter(reporter, sender) + } - pub fn step_success( - &mut self, - token: &VerificationToken, - time_stamp: &[u8], - step: impl EcssEnumeration, - ) -> Result<(), VerificationError> { - self.reporter - .step_success(token, self.sender.as_mut(), time_stamp, step) - } + pub fn new_from_reporter( + reporter: VerificationReporter, + sender: Box>, + ) -> Self { + Self { reporter, sender } + } - pub fn step_failure( - &mut self, - token: VerificationToken, - params: FailParamsWithStep, - ) -> Result<(), VerificationErrorWithToken> { - self.reporter - .step_failure(token, self.sender.as_mut(), params) - } + delegate! { + to self.reporter { + pub fn set_apid(&mut self, apid: u16) -> bool; + pub fn apid(&self) -> u16; + pub fn add_tc(&mut self, pus_tc: &PusTc) -> VerificationToken; + pub fn add_tc_with_req_id(&mut self, req_id: RequestId) -> VerificationToken; + pub fn dest_id(&self) -> u16; + pub fn set_dest_id(&mut self, dest_id: u16); + } + } - pub fn completion_success( - &mut self, - token: VerificationToken, - time_stamp: &[u8], - ) -> Result<(), VerificationErrorWithToken> { - self.reporter - .completion_success(token, self.sender.as_mut(), time_stamp) - } + pub fn acceptance_success( + &mut self, + token: VerificationToken, + time_stamp: &[u8], + ) -> Result, VerificationErrorWithToken> + { + self.reporter + .acceptance_success(token, self.sender.as_mut(), time_stamp) + } - pub fn completion_failure( - &mut self, - token: VerificationToken, - params: FailParams, - ) -> Result<(), VerificationErrorWithToken> { - self.reporter - .completion_failure(token, self.sender.as_mut(), params) + pub fn acceptance_failure( + &mut self, + token: VerificationToken, + params: FailParams, + ) -> Result<(), VerificationErrorWithToken> { + self.reporter + .acceptance_failure(token, self.sender.as_mut(), params) + } + + pub fn start_success( + &mut self, + token: VerificationToken, + time_stamp: &[u8], + ) -> Result, VerificationErrorWithToken> + { + self.reporter + .start_success(token, self.sender.as_mut(), time_stamp) + } + + pub fn start_failure( + &mut self, + token: VerificationToken, + params: FailParams, + ) -> Result<(), VerificationErrorWithToken> { + self.reporter + .start_failure(token, self.sender.as_mut(), params) + } + + pub fn step_success( + &mut self, + token: &VerificationToken, + time_stamp: &[u8], + step: impl EcssEnumeration, + ) -> Result<(), EcssTmError> { + self.reporter + .step_success(token, self.sender.as_mut(), time_stamp, step) + } + + pub fn step_failure( + &mut self, + token: VerificationToken, + params: FailParamsWithStep, + ) -> Result<(), VerificationErrorWithToken> { + self.reporter + .step_failure(token, self.sender.as_mut(), params) + } + + pub fn completion_success( + &mut self, + token: VerificationToken, + time_stamp: &[u8], + ) -> Result<(), VerificationErrorWithToken> { + self.reporter + .completion_success(token, self.sender.as_mut(), time_stamp) + } + + pub fn completion_failure( + &mut self, + token: VerificationToken, + params: FailParams, + ) -> Result<(), VerificationErrorWithToken> { + self.reporter + .completion_failure(token, self.sender.as_mut(), params) + } } } #[cfg(feature = "std")] mod stdmod { + use super::allocmod::VerificationReporterWithSender; + use super::*; use crate::pool::{ShareablePoolProvider, SharedPool, StoreAddr, StoreError}; - use crate::pus::verification::{ - VerificationError, VerificationReporterWithSender, VerificationSender, - }; use delegate::delegate; use spacepackets::tm::PusTm; use std::sync::{mpsc, Arc, Mutex, RwLockWriteGuard}; @@ -748,9 +928,9 @@ mod stdmod { } } - impl From for VerificationError { + impl From for EcssTmError { fn from(e: StoreError) -> Self { - VerificationError::SendError(e.into()) + EcssTmError::SendError(e.into()) } } @@ -798,10 +978,10 @@ mod stdmod { } //noinspection RsTraitImplementation - impl VerificationSender for MpscVerifSender { + impl EcssTmSender for MpscVerifSender { delegate!( to self.base { - fn send_verification_tm(&mut self, tm: PusTm) -> Result<(), VerificationError>; + fn send_tm(&mut self, tm: PusTm) -> Result<(), EcssTmError>; } ); } @@ -829,10 +1009,10 @@ mod stdmod { } //noinspection RsTraitImplementation - impl VerificationSender for CrossbeamVerifSender { + impl EcssTmSender for CrossbeamVerifSender { delegate!( to self.base { - fn send_verification_tm(&mut self, tm: PusTm) -> Result<(), VerificationError>; + fn send_tm(&mut self, tm: PusTm) -> Result<(), EcssTmError>; } ); } @@ -840,17 +1020,14 @@ mod stdmod { unsafe impl Sync for CrossbeamVerifSender {} unsafe impl Send for CrossbeamVerifSender {} - impl VerificationSender for StdSenderBase { - fn send_verification_tm( - &mut self, - tm: PusTm, - ) -> Result<(), VerificationError> { + impl EcssTmSender for StdSenderBase { + fn send_tm(&mut self, tm: PusTm) -> Result<(), EcssTmError> { let operation = |mut mg: RwLockWriteGuard| { let (addr, buf) = mg.free_element(tm.len_packed())?; - tm.write_to(buf).map_err(VerificationError::PusError)?; + tm.write_to_bytes(buf).map_err(EcssTmError::PusError)?; drop(mg); self.tx.send(addr).map_err(|_| { - VerificationError::SendError(StdVerifSenderError::RxDisconnected(addr)) + EcssTmError::SendError(StdVerifSenderError::RxDisconnected(addr)) })?; Ok(()) }; @@ -860,9 +1037,7 @@ mod stdmod { if self.ignore_poison_error { operation(poison_error.into_inner()) } else { - Err(VerificationError::SendError( - StdVerifSenderError::PoisonError, - )) + Err(EcssTmError::SendError(StdVerifSenderError::PoisonError)) } } } @@ -873,9 +1048,9 @@ mod stdmod { #[cfg(test)] mod tests { use crate::pus::verification::{ - FailParams, FailParamsWithStep, RequestId, StateNone, VerificationError, + EcssTmError, EcssTmSender, FailParams, FailParamsWithStep, RequestId, StateNone, VerificationReporter, VerificationReporterCfg, VerificationReporterWithSender, - VerificationSender, VerificationToken, + VerificationToken, }; use alloc::boxed::Box; use alloc::format; @@ -905,8 +1080,8 @@ mod tests { pub service_queue: VecDeque, } - impl VerificationSender<()> for TestSender { - fn send_verification_tm(&mut self, tm: PusTm) -> Result<(), VerificationError<()>> { + impl EcssTmSender<()> for TestSender { + fn send_tm(&mut self, tm: PusTm) -> Result<(), EcssTmError<()>> { assert_eq!(PusPacket::service(&tm), 1); assert!(tm.source_data().is_some()); let mut time_stamp = [0; 7]; @@ -938,9 +1113,9 @@ mod tests { #[derive(Default)] struct FallibleSender {} - impl VerificationSender for FallibleSender { - fn send_verification_tm(&mut self, _: PusTm) -> Result<(), VerificationError> { - Err(VerificationError::SendError(DummyError {})) + impl EcssTmSender for FallibleSender { + fn send_tm(&mut self, _: PusTm) -> Result<(), EcssTmError> { + Err(EcssTmError::SendError(DummyError {})) } } @@ -968,7 +1143,7 @@ mod tests { } fn base_reporter() -> VerificationReporter { - let cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8); + let cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8).unwrap(); VerificationReporter::new(cfg) } @@ -1019,6 +1194,14 @@ mod tests { assert_eq!(info, cmp_info); } + #[test] + fn test_state() { + let (mut b, _) = base_init(false); + assert_eq!(b.vr.apid(), TEST_APID); + b.vr.set_apid(TEST_APID + 1); + assert_eq!(b.vr.apid(), TEST_APID + 1); + } + #[test] fn test_basic_acceptance_success() { let (mut b, tok) = base_init(false); @@ -1048,7 +1231,7 @@ mod tests { let err = res.unwrap_err(); assert_eq!(err.1, tok); match err.0 { - VerificationError::SendError(e) => { + EcssTmError::SendError(e) => { assert_eq!(e, DummyError {}) } _ => panic!("{}", format!("Unexpected error {:?}", err.0)), @@ -1073,7 +1256,7 @@ mod tests { #[test] fn test_basic_acceptance_failure() { let (mut b, tok) = base_init(true); - b.rep().dest_id = 5; + b.rep().reporter.dest_id = 5; let stamp_buf = [1, 2, 3, 4, 5, 6, 7]; let mut sender = TestSender::default(); let fail_code = EcssEnumU16::new(2); @@ -1086,7 +1269,7 @@ mod tests { #[test] fn test_basic_acceptance_failure_with_helper() { let (mut b, tok) = base_with_helper_init(); - b.rep().dest_id = 5; + b.rep().reporter.dest_id = 5; let stamp_buf = [1, 2, 3, 4, 5, 6, 7]; let fail_code = EcssEnumU16::new(2); let fail_params = FailParams::new(stamp_buf.as_slice(), &fail_code, None); @@ -1100,7 +1283,7 @@ mod tests { #[test] fn test_acceptance_fail_data_too_large() { let (mut b, tok) = base_with_helper_init(); - b.rep().dest_id = 5; + b.rep().reporter.dest_id = 5; let stamp_buf = [1, 2, 3, 4, 5, 6, 7]; let fail_code = EcssEnumU16::new(2); let fail_data: [u8; 16] = [0; 16]; @@ -1113,7 +1296,7 @@ mod tests { let err_with_token = res.unwrap_err(); assert_eq!(err_with_token.1, tok); match err_with_token.0 { - VerificationError::ByteConversionError(e) => match e { + EcssTmError::ByteConversionError(e) => match e { ByteConversionError::ToSliceTooSmall(missmatch) => { assert_eq!( missmatch.expected, @@ -1138,7 +1321,7 @@ mod tests { let fail_code = EcssEnumU8::new(10); let fail_data = EcssEnumU32::new(12); let mut fail_data_raw = [0; 4]; - fail_data.to_bytes(&mut fail_data_raw).unwrap(); + fail_data.write_to_bytes(&mut fail_data_raw).unwrap(); let fail_params = FailParams::new(&EMPTY_STAMP, &fail_code, Some(fail_data_raw.as_slice())); b.vr.acceptance_failure(tok, &mut sender, fail_params) .expect("Sending acceptance success failed"); diff --git a/fsrc-core/src/tmtc/ccsds_distrib.rs b/fsrc-core/src/tmtc/ccsds_distrib.rs index 92d6c39..e09cb6b 100644 --- a/fsrc-core/src/tmtc/ccsds_distrib.rs +++ b/fsrc-core/src/tmtc/ccsds_distrib.rs @@ -58,7 +58,7 @@ //! let mut pus_tc = PusTc::new_simple(&mut space_packet_header, 17, 1, None, true); //! let mut test_buf: [u8; 32] = [0; 32]; //! let mut size = pus_tc -//! .write_to(test_buf.as_mut_slice()) +//! .write_to_bytes(test_buf.as_mut_slice()) //! .expect("Error writing TC to buffer"); //! let tc_slice = &test_buf[0..size]; //! ccsds_distributor.pass_tc(&tc_slice).expect("Passing TC slice failed"); @@ -66,7 +66,7 @@ //! // Now pass a packet with an unknown APID to the distributor //! pus_tc.set_apid(0x003); //! size = pus_tc -//! .write_to(test_buf.as_mut_slice()) +//! .write_to_bytes(test_buf.as_mut_slice()) //! .expect("Error writing TC to buffer"); //! let tc_slice = &test_buf[0..size]; //! ccsds_distributor.pass_tc(&tc_slice).expect("Passing TC slice failed"); @@ -201,7 +201,9 @@ pub(crate) mod tests { pub fn generate_ping_tc(buf: &mut [u8]) -> &[u8] { let mut sph = SpHeader::tc(0x002, 0x34, 0).unwrap(); let pus_tc = PusTc::new_simple(&mut sph, 17, 1, None, true); - let size = pus_tc.write_to(buf).expect("Error writing TC to buffer"); + let size = pus_tc + .write_to_bytes(buf) + .expect("Error writing TC to buffer"); assert_eq!(size, 13); &buf[0..size] } @@ -314,7 +316,7 @@ pub(crate) mod tests { let pus_tc = PusTc::new_simple(&mut sph, 17, 1, None, true); let mut test_buf: [u8; 32] = [0; 32]; pus_tc - .write_to(test_buf.as_mut_slice()) + .write_to_bytes(test_buf.as_mut_slice()) .expect("Error writing TC to buffer"); ccsds_distrib.pass_tc(&test_buf).expect("Passing TC failed"); let recvd = unknown_packet_queue.lock().unwrap().pop_front(); diff --git a/fsrc-core/src/tmtc/pus_distrib.rs b/fsrc-core/src/tmtc/pus_distrib.rs index 9ee8bc6..bc8bb81 100644 --- a/fsrc-core/src/tmtc/pus_distrib.rs +++ b/fsrc-core/src/tmtc/pus_distrib.rs @@ -47,7 +47,7 @@ //! let mut pus_tc = PusTc::new_simple(&mut space_packet_header, 17, 1, None, true); //! let mut test_buf: [u8; 32] = [0; 32]; //! let mut size = pus_tc -//! .write_to(test_buf.as_mut_slice()) +//! .write_to_bytes(test_buf.as_mut_slice()) //! .expect("Error writing TC to buffer"); //! let tc_slice = &test_buf[0..size]; //! diff --git a/fsrc-core/tests/verification_test.rs b/fsrc-core/tests/verification_test.rs index 22f351e..a19953d 100644 --- a/fsrc-core/tests/verification_test.rs +++ b/fsrc-core/tests/verification_test.rs @@ -25,7 +25,7 @@ const PACKETS_SENT: u8 = 8; /// threads have sent the correct expected verification reports #[test] fn test_shared_reporter() { - let cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8); + let cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8).unwrap(); // Shared pool object to store the verification PUS telemetry let pool_cfg = PoolCfg::new(vec![(10, 32), (10, 64), (10, 128), (10, 1024)]); let shared_tm_pool: SharedPool = @@ -53,14 +53,14 @@ fn test_shared_reporter() { let pus_tc_0 = PusTc::new(&mut sph, tc_header, None, true); req_id_0 = RequestId::new(&pus_tc_0); let (addr, mut buf) = tc_guard.free_element(pus_tc_0.len_packed()).unwrap(); - pus_tc_0.write_to(&mut buf).unwrap(); + pus_tc_0.write_to_bytes(&mut buf).unwrap(); tx_tc_0.send(addr).unwrap(); let mut sph = SpHeader::tc(TEST_APID, 1, 0).unwrap(); let tc_header = PusTcSecondaryHeader::new_simple(5, 1); let pus_tc_1 = PusTc::new(&mut sph, tc_header, None, true); req_id_1 = RequestId::new(&pus_tc_1); let (addr, mut buf) = tc_guard.free_element(pus_tc_0.len_packed()).unwrap(); - pus_tc_1.write_to(&mut buf).unwrap(); + pus_tc_1.write_to_bytes(&mut buf).unwrap(); tx_tc_1.send(addr).unwrap(); } let verif_sender_0 = thread::spawn(move || { diff --git a/fsrc-example/src/bin/client.rs b/fsrc-example/src/bin/client.rs index 1f56418..1b58cf8 100644 --- a/fsrc-example/src/bin/client.rs +++ b/fsrc-example/src/bin/client.rs @@ -18,7 +18,9 @@ fn main() { "Packing and sending PUS ping command TC[17,1] with request ID {}", tc_req_id ); - let size = pus_tc.write_to(&mut buf).expect("Creating PUS TC failed"); + let size = pus_tc + .write_to_bytes(&mut buf) + .expect("Creating PUS TC failed"); client .send_to(&buf[0..size], &addr) .expect(&*format!("Sending to {:?} failed", addr)); diff --git a/fsrc-example/src/bin/obsw/main.rs b/fsrc-example/src/bin/obsw/main.rs index 00ad086..a7c5de1 100644 --- a/fsrc-example/src/bin/obsw/main.rs +++ b/fsrc-example/src/bin/obsw/main.rs @@ -39,7 +39,7 @@ fn main() { let (tm_funnel_tx, tm_funnel_rx) = mpsc::channel(); let (tm_server_tx, tm_server_rx) = mpsc::channel(); let sender = MpscVerifSender::new(tm_store.clone(), tm_funnel_tx.clone()); - let verif_cfg = VerificationReporterCfg::new(PUS_APID, 1, 2, 8); + let verif_cfg = VerificationReporterCfg::new(PUS_APID, 1, 2, 8).unwrap(); let reporter_with_sender_0 = Arc::new(Mutex::new(VerificationReporterWithSender::new( verif_cfg, Box::new(sender), diff --git a/fsrc-example/src/bin/obsw/tmtc.rs b/fsrc-example/src/bin/obsw/tmtc.rs index 5a34d1e..3b3e88e 100644 --- a/fsrc-example/src/bin/obsw/tmtc.rs +++ b/fsrc-example/src/bin/obsw/tmtc.rs @@ -24,7 +24,7 @@ impl TmStore { let mut pg = self.pool.write().expect("Error locking TM store"); let (addr, buf) = pg.free_element(pus_tm.len_packed()).expect("Store error"); pus_tm - .write_to(buf) + .write_to_bytes(buf) .expect("Writing PUS TM to store failed"); addr } diff --git a/spacepackets b/spacepackets index 94489da..fe1a303 160000 --- a/spacepackets +++ b/spacepackets @@ -1 +1 @@ -Subproject commit 94489da00323dc6caf24e05e240c80fc10b5d8cc +Subproject commit fe1a30327bcc9a914cd2695b6af74b869a8b23a2 From 1eee8da4de68790a3f48793c75b0cc9944276cf8 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 11 Sep 2022 21:14:19 +0200 Subject: [PATCH 02/13] implemented basic event reporter --- fsrc-core/src/pus/event.rs | 208 +++++++++++++++++++++++++----- fsrc-core/src/pus/verification.rs | 67 ++++++---- 2 files changed, 213 insertions(+), 62 deletions(-) diff --git a/fsrc-core/src/pus/event.rs b/fsrc-core/src/pus/event.rs index 394b15e..04a11b5 100644 --- a/fsrc-core/src/pus/event.rs +++ b/fsrc-core/src/pus/event.rs @@ -5,15 +5,33 @@ use spacepackets::tm::PusTmSecondaryHeader; use spacepackets::{SpHeader, MAX_APID}; #[cfg(feature = "alloc")] -pub use allocvec::EventReporterWithVec; +pub use allocvec::EventReporter; -pub struct EventReporter { +#[derive(Debug, Eq, PartialEq, Copy, Clone)] +pub enum Subservices { + TmInfoReport = 1, + TmLowSeverityReport = 2, + TmMediumSeverityReport = 3, + TmHighSeverityReport = 4, + TcEnableEventGeneration = 5, + TcDisableEventGeneration = 6, + TcReportDisabledList = 7, + TmDisabledEventsReport = 8, +} + +impl From for u8 { + fn from(enumeration: Subservices) -> Self { + enumeration as u8 + } +} + +pub struct EventReporterBase { msg_count: u16, apid: u16, pub dest_id: u16, } -impl EventReporter { +impl EventReporterBase { pub fn new(apid: u16) -> Option { if apid > MAX_APID { return None; @@ -33,13 +51,106 @@ impl EventReporter { event_id: impl EcssEnumeration, aux_data: Option<&[u8]>, ) -> Result<(), EcssTmError> { + self.generate_and_send_generic_tm( + buf, + Subservices::TmInfoReport, + sender, + time_stamp, + event_id, + aux_data, + ) + } + + pub fn event_low_severity( + &mut self, + buf: &mut [u8], + sender: &mut (impl EcssTmSender + ?Sized), + time_stamp: &[u8], + event_id: impl EcssEnumeration, + aux_data: Option<&[u8]>, + ) -> Result<(), EcssTmError> { + self.generate_and_send_generic_tm( + buf, + Subservices::TmLowSeverityReport, + sender, + time_stamp, + event_id, + aux_data, + ) + } + + pub fn event_medium_severity( + &mut self, + buf: &mut [u8], + sender: &mut (impl EcssTmSender + ?Sized), + time_stamp: &[u8], + event_id: impl EcssEnumeration, + aux_data: Option<&[u8]>, + ) -> Result<(), EcssTmError> { + self.generate_and_send_generic_tm( + buf, + Subservices::TmMediumSeverityReport, + sender, + time_stamp, + event_id, + aux_data, + ) + } + + pub fn event_high_severity( + &mut self, + buf: &mut [u8], + sender: &mut (impl EcssTmSender + ?Sized), + time_stamp: &[u8], + event_id: impl EcssEnumeration, + aux_data: Option<&[u8]>, + ) -> Result<(), EcssTmError> { + self.generate_and_send_generic_tm( + buf, + Subservices::TmHighSeverityReport, + sender, + time_stamp, + event_id, + aux_data, + ) + } + + fn generate_and_send_generic_tm( + &mut self, + buf: &mut [u8], + subservice: Subservices, + sender: &mut (impl EcssTmSender + ?Sized), + time_stamp: &[u8], + event_id: impl EcssEnumeration, + aux_data: Option<&[u8]>, + ) -> Result<(), EcssTmError> { + let tm = self.generate_generic_event_tm(buf, subservice, time_stamp, event_id, aux_data)?; + sender.send_tm(tm)?; + self.msg_count += 1; + Ok(()) + } + + fn generate_generic_event_tm<'a, E>( + &'a self, + buf: &'a mut [u8], + subservice: Subservices, + time_stamp: &'a [u8], + event_id: impl EcssEnumeration, + aux_data: Option<&[u8]>, + ) -> Result> { let mut src_data_len = event_id.byte_width(); if let Some(aux_data) = aux_data { src_data_len += aux_data.len(); } source_buffer_large_enough(buf.len(), src_data_len)?; let mut sp_header = SpHeader::tm(self.apid, 0, 0).unwrap(); - let sec_header = PusTmSecondaryHeader::new(5, 0, self.msg_count, self.dest_id, time_stamp); + let sec_header = PusTmSecondaryHeader::new( + 5, + subservice.into(), + self.msg_count, + self.dest_id, + time_stamp, + ); let mut current_idx = 0; event_id.write_to_bytes(&mut buf[0..event_id.byte_width()])?; current_idx += event_id.byte_width(); @@ -47,10 +158,12 @@ impl EventReporter { buf[current_idx..current_idx + aux_data.len()].copy_from_slice(aux_data); current_idx += aux_data.len(); } - let tm = PusTm::new(&mut sp_header, sec_header, Some(&buf[0..current_idx]), true); - sender.send_tm(tm)?; - self.msg_count += 1; - Ok(()) + Ok(PusTm::new( + &mut sp_header, + sec_header, + Some(&buf[0..current_idx]), + true, + )) } } @@ -60,14 +173,14 @@ mod allocvec { use alloc::vec; use alloc::vec::Vec; - pub struct EventReporterWithVec { + pub struct EventReporter { source_data_buf: Vec, - pub reporter: EventReporter, + pub reporter: EventReporterBase, } - impl EventReporterWithVec { + impl EventReporter { pub fn new(apid: u16, max_event_id_and_aux_data: usize) -> Option { - let reporter = EventReporter::new(apid)?; + let reporter = EventReporterBase::new(apid)?; Some(Self { source_data_buf: vec![0; max_event_id_and_aux_data], reporter, @@ -88,28 +201,53 @@ mod allocvec { aux_data, ) } - // pub fn event_low_severity( - // &mut self, - // _sender: &mut (impl EcssTmSender + ?Sized), - // _event_id: impl EcssEnumeration, - // _aux_data: Option<&[u8]>, - // ) { - // } - // - // pub fn event_medium_severity( - // &mut self, - // _sender: &mut (impl EcssTmSender + ?Sized), - // _event_id: impl EcssEnumeration, - // _aux_data: Option<&[u8]>, - // ) { - // } - // - // pub fn event_high_severity( - // &mut self, - // _sender: &mut (impl EcssTmSender + ?Sized), - // _event_id: impl EcssEnumeration, - // _aux_data: Option<&[u8]>, - // ) { - // } + + pub fn event_low_severity( + &mut self, + sender: &mut (impl EcssTmSender + ?Sized), + time_stamp: &[u8], + event_id: impl EcssEnumeration, + aux_data: Option<&[u8]>, + ) -> Result<(), EcssTmError> { + self.reporter.event_low_severity( + self.source_data_buf.as_mut_slice(), + sender, + time_stamp, + event_id, + aux_data, + ) + } + + pub fn event_medium_severity( + &mut self, + sender: &mut (impl EcssTmSender + ?Sized), + time_stamp: &[u8], + event_id: impl EcssEnumeration, + aux_data: Option<&[u8]>, + ) -> Result<(), EcssTmError> { + self.reporter.event_medium_severity( + self.source_data_buf.as_mut_slice(), + sender, + time_stamp, + event_id, + aux_data, + ) + } + + pub fn event_high_severity( + &mut self, + sender: &mut (impl EcssTmSender + ?Sized), + time_stamp: &[u8], + event_id: impl EcssEnumeration, + aux_data: Option<&[u8]>, + ) -> Result<(), EcssTmError> { + self.reporter.event_high_severity( + self.source_data_buf.as_mut_slice(), + sender, + time_stamp, + event_id, + aux_data, + ) + } } } diff --git a/fsrc-core/src/pus/verification.rs b/fsrc-core/src/pus/verification.rs index 55bc82d..6586d45 100644 --- a/fsrc-core/src/pus/verification.rs +++ b/fsrc-core/src/pus/verification.rs @@ -92,6 +92,24 @@ pub use stdmod::{ StdVerifReporterWithSender, StdVerifSenderError, }; +#[derive(Debug, Eq, PartialEq, Copy, Clone)] +pub enum Subservices { + TmAcceptanceSuccess = 1, + TmAcceptanceFailure = 2, + TmStartSuccess = 3, + TmStartFailure = 4, + TmStepSuccess = 5, + TmStepFailure = 6, + TmCompletionSuccess = 7, + TmCompletionFailure = 8, +} + +impl From for u8 { + fn from(enumeration: Subservices) -> Self { + enumeration as u8 + } +} + /// This is a request identifier as specified in 5.4.11.2 c. of the PUS standard /// This field equivalent to the first two bytes of the CCSDS space packet header. #[derive(Debug, Eq, Copy, Clone)] @@ -294,8 +312,7 @@ impl VerificationReporterBasic { let tm = self .create_pus_verif_success_tm( buf, - 1, - 1, + Subservices::TmAcceptanceSuccess.into(), &token.req_id, time_stamp, None::<&dyn EcssEnumeration>, @@ -322,8 +339,7 @@ impl VerificationReporterBasic { let tm = self .create_pus_verif_fail_tm( buf, - 1, - 2, + Subservices::TmAcceptanceFailure.into(), &token.req_id, None::<&dyn EcssEnumeration>, ¶ms, @@ -349,8 +365,7 @@ impl VerificationReporterBasic { let tm = self .create_pus_verif_success_tm( buf, - 1, - 3, + Subservices::TmStartSuccess.into(), &token.req_id, time_stamp, None::<&dyn EcssEnumeration>, @@ -380,8 +395,7 @@ impl VerificationReporterBasic { let tm = self .create_pus_verif_fail_tm( buf, - 1, - 4, + Subservices::TmStartFailure.into(), &token.req_id, None::<&dyn EcssEnumeration>, ¶ms, @@ -405,8 +419,13 @@ impl VerificationReporterBasic { time_stamp: &[u8], step: impl EcssEnumeration, ) -> Result<(), EcssTmError> { - let tm = - self.create_pus_verif_success_tm(buf, 1, 5, &token.req_id, time_stamp, Some(&step))?; + let tm = self.create_pus_verif_success_tm( + buf, + Subservices::TmStepSuccess.into(), + &token.req_id, + time_stamp, + Some(&step), + )?; sender.send_tm(tm)?; self.msg_count += 1; Ok(()) @@ -424,7 +443,13 @@ impl VerificationReporterBasic { params: FailParamsWithStep, ) -> Result<(), VerificationErrorWithToken> { let tm = self - .create_pus_verif_fail_tm(buf, 1, 6, &token.req_id, Some(params.step), ¶ms.bp) + .create_pus_verif_fail_tm( + buf, + Subservices::TmStepFailure.into(), + &token.req_id, + Some(params.step), + ¶ms.bp, + ) .map_err(|e| VerificationErrorWithToken(e, token))?; sender .send_tm(tm) @@ -447,8 +472,7 @@ impl VerificationReporterBasic { let tm = self .create_pus_verif_success_tm( buf, - 1, - 7, + Subservices::TmCompletionSuccess.into(), &token.req_id, time_stamp, None::<&dyn EcssEnumeration>, @@ -475,8 +499,7 @@ impl VerificationReporterBasic { let tm = self .create_pus_verif_fail_tm( buf, - 1, - 8, + Subservices::TmCompletionFailure.into(), &token.req_id, None::<&dyn EcssEnumeration>, ¶ms, @@ -492,7 +515,6 @@ impl VerificationReporterBasic { fn create_pus_verif_success_tm<'a, E>( &'a mut self, buf: &'a mut [u8], - service: u8, subservice: u8, req_id: &RequestId, time_stamp: &'a [u8], @@ -514,7 +536,6 @@ impl VerificationReporterBasic { let mut sp_header = SpHeader::tm(self.apid(), 0, 0).unwrap(); Ok(self.create_pus_verif_tm_base( buf, - service, subservice, &mut sp_header, time_stamp, @@ -525,7 +546,6 @@ impl VerificationReporterBasic { fn create_pus_verif_fail_tm<'a, E>( &'a mut self, buf: &'a mut [u8], - service: u8, subservice: u8, req_id: &RequestId, step: Option<&(impl EcssEnumeration + ?Sized)>, @@ -559,7 +579,6 @@ impl VerificationReporterBasic { let mut sp_header = SpHeader::tm(self.apid(), 0, 0).unwrap(); Ok(self.create_pus_verif_tm_base( buf, - service, subservice, &mut sp_header, params.time_stamp, @@ -570,19 +589,13 @@ impl VerificationReporterBasic { fn create_pus_verif_tm_base<'a>( &'a mut self, buf: &'a mut [u8], - service: u8, subservice: u8, sp_header: &mut SpHeader, time_stamp: &'a [u8], source_data_len: usize, ) -> PusTm { - let tm_sec_header = PusTmSecondaryHeader::new( - service, - subservice, - self.msg_count, - self.dest_id, - time_stamp, - ); + let tm_sec_header = + PusTmSecondaryHeader::new(1, subservice, self.msg_count, self.dest_id, time_stamp); PusTm::new( sp_header, tm_sec_header, From d34e62101c57528f6d214a0cc1b2d2de28541153 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 13 Sep 2022 10:43:07 +0200 Subject: [PATCH 03/13] bump dependencies --- Cargo.lock | 30 ++++++++++++++-------------- fsrc-core/src/pus/verification.rs | 2 +- fsrc-core/src/tmtc/pus_distrib.rs | 5 ++--- fsrc-core/tests/verification_test.rs | 8 ++++---- fsrc-example/src/bin/client.rs | 3 +-- spacepackets | 2 +- 6 files changed, 24 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0e51f1f..3ea2c46 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -310,9 +310,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.47" +version = "0.1.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c495f162af0bf17656d0014a0eded5f3cd2f365fdd204548c2869db89359dc7" +checksum = "237a0714f28b1ee39ccec0770ccb544eb02c9ef2c82bb096230eefcffa6468b0" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -324,9 +324,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.59" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" dependencies = [ "wasm-bindgen", ] @@ -580,7 +580,7 @@ checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" [[package]] name = "spacepackets" -version = "0.1.0" +version = "0.2.0" dependencies = [ "chrono", "crc", @@ -676,9 +676,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -686,9 +686,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" dependencies = [ "bumpalo", "log", @@ -701,9 +701,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -711,9 +711,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ "proc-macro2", "quote", @@ -724,9 +724,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" [[package]] name = "winapi" diff --git a/fsrc-core/src/pus/verification.rs b/fsrc-core/src/pus/verification.rs index 6586d45..cd26685 100644 --- a/fsrc-core/src/pus/verification.rs +++ b/fsrc-core/src/pus/verification.rs @@ -55,7 +55,7 @@ //! tm_len = slice.len(); //! tm_buf[0..tm_len].copy_from_slice(slice); //! } -//! let (pus_tm, _) = PusTm::new_from_raw_slice(&tm_buf[0..tm_len], 7) +//! let (pus_tm, _) = PusTm::from_bytes(&tm_buf[0..tm_len], 7) //! .expect("Error reading verification TM"); //! if packet_idx == 0 { //! assert_eq!(pus_tm.subservice(), 1); diff --git a/fsrc-core/src/tmtc/pus_distrib.rs b/fsrc-core/src/tmtc/pus_distrib.rs index bc8bb81..3171b4b 100644 --- a/fsrc-core/src/tmtc/pus_distrib.rs +++ b/fsrc-core/src/tmtc/pus_distrib.rs @@ -99,7 +99,7 @@ impl ReceivesTc for PusDistributor { fn pass_tc(&mut self, tm_raw: &[u8]) -> Result<(), Self::Error> { // Convert to ccsds and call pass_ccsds let sp_header = SpHeader::from_raw_slice(tm_raw) - .map_err(|e| PusDistribError::PusError(PusError::PacketError(e)))?; + .map_err(|e| PusDistribError::PusError(PusError::ByteConversionError(e)))?; self.pass_ccsds(&sp_header, tm_raw) } } @@ -107,8 +107,7 @@ impl ReceivesTc for PusDistributor { impl ReceivesCcsdsTc for PusDistributor { type Error = PusDistribError; fn pass_ccsds(&mut self, header: &SpHeader, tm_raw: &[u8]) -> Result<(), Self::Error> { - let (tc, _) = - PusTc::new_from_raw_slice(tm_raw).map_err(|e| PusDistribError::PusError(e))?; + let (tc, _) = PusTc::from_bytes(tm_raw).map_err(|e| PusDistribError::PusError(e))?; self.pass_pus_tc(header, &tc) } } diff --git a/fsrc-core/tests/verification_test.rs b/fsrc-core/tests/verification_test.rs index a19953d..a158706 100644 --- a/fsrc-core/tests/verification_test.rs +++ b/fsrc-core/tests/verification_test.rs @@ -76,7 +76,7 @@ fn test_shared_reporter() { tc_len = buf.len(); tc_buf[0..tc_len].copy_from_slice(buf); } - let (_tc, _) = PusTc::new_from_raw_slice(&tc_buf[0..tc_len]).unwrap(); + let (_tc, _) = PusTc::from_bytes(&tc_buf[0..tc_len]).unwrap(); let accepted_token; { let mut mg = reporter_with_sender_0.lock().expect("Locking mutex failed"); @@ -117,7 +117,7 @@ fn test_shared_reporter() { tc_len = buf.len(); tc_buf[0..tc_len].copy_from_slice(buf); } - let (tc, _) = PusTc::new_from_raw_slice(&tc_buf[0..tc_len]).unwrap(); + let (tc, _) = PusTc::from_bytes(&tc_buf[0..tc_len]).unwrap(); let mut mg = reporter_with_sender_1 .lock() .expect("Locking reporter failed"); @@ -150,8 +150,8 @@ fn test_shared_reporter() { tm_len = slice.len(); tm_buf[0..tm_len].copy_from_slice(slice); } - let (pus_tm, _) = PusTm::new_from_raw_slice(&tm_buf[0..tm_len], 7) - .expect("Error reading verification TM"); + let (pus_tm, _) = + PusTm::from_bytes(&tm_buf[0..tm_len], 7).expect("Error reading verification TM"); let req_id = RequestId::from_bytes( &pus_tm.source_data().expect("Invalid TM source data")[0..RequestId::SIZE_AS_BYTES], ) diff --git a/fsrc-example/src/bin/client.rs b/fsrc-example/src/bin/client.rs index 1b58cf8..59ad725 100644 --- a/fsrc-example/src/bin/client.rs +++ b/fsrc-example/src/bin/client.rs @@ -31,8 +31,7 @@ fn main() { let res = client.recv(&mut buf); match res { Ok(_len) => { - let (pus_tm, size) = - PusTm::new_from_raw_slice(&buf, 7).expect("Parsing PUS TM failed"); + let (pus_tm, size) = PusTm::from_bytes(&buf, 7).expect("Parsing PUS TM failed"); if pus_tm.service() == 17 && pus_tm.subservice() == 2 { println!("Received PUS Ping Reply TM[17,2]") } else if pus_tm.service() == 1 { diff --git a/spacepackets b/spacepackets index fe1a303..638e4cd 160000 --- a/spacepackets +++ b/spacepackets @@ -1 +1 @@ -Subproject commit fe1a30327bcc9a914cd2695b6af74b869a8b23a2 +Subproject commit 638e4cda620fbb0ef6aed9faa0e9375d3762a339 From e4a6810442df88f5369b01228ed576e1208131d2 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sat, 15 Oct 2022 19:36:13 +0200 Subject: [PATCH 04/13] try enum --- fsrc-core/src/pus/verification.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/fsrc-core/src/pus/verification.rs b/fsrc-core/src/pus/verification.rs index cd26685..b242594 100644 --- a/fsrc-core/src/pus/verification.rs +++ b/fsrc-core/src/pus/verification.rs @@ -191,11 +191,17 @@ pub struct VerificationToken { } #[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct StateNone; +pub enum StateNone {} #[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct StateAccepted; +pub enum StateAccepted {} #[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct StateStarted; +pub enum StateStarted {} + +pub enum StateToken { + None(StateNone), + Accepted(StateAccepted), + Started(StateStarted) +} impl VerificationToken { fn new(req_id: RequestId) -> VerificationToken { From 4d415cc0ade3d1621b3b9d21771a14f18e933eaa Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sat, 15 Oct 2022 19:56:53 +0200 Subject: [PATCH 05/13] create shared test module for PUS tests --- fsrc-core/src/pus/event.rs | 17 ++++++++- fsrc-core/src/pus/mod.rs | 55 ++++++++++++++++++++++++++++ fsrc-core/src/pus/verification.rs | 61 ++++--------------------------- spacepackets | 2 +- 4 files changed, 79 insertions(+), 56 deletions(-) diff --git a/fsrc-core/src/pus/event.rs b/fsrc-core/src/pus/event.rs index 04a11b5..9472f6a 100644 --- a/fsrc-core/src/pus/event.rs +++ b/fsrc-core/src/pus/event.rs @@ -179,10 +179,10 @@ mod allocvec { } impl EventReporter { - pub fn new(apid: u16, max_event_id_and_aux_data: usize) -> Option { + pub fn new(apid: u16, max_event_id_and_aux_data_size: usize) -> Option { let reporter = EventReporterBase::new(apid)?; Some(Self { - source_data_buf: vec![0; max_event_id_and_aux_data], + source_data_buf: vec![0; max_event_id_and_aux_data_size], reporter, }) } @@ -251,3 +251,16 @@ mod allocvec { } } } + +#[cfg(test)] +mod tests { + use super::*; + + const EXAMPLE_APID: u16 = 0xee; + + #[test] + fn basic_event_generation() { + let _reporter = EventReporter::new(EXAMPLE_APID, 16); + //reporter. + } +} diff --git a/fsrc-core/src/pus/mod.rs b/fsrc-core/src/pus/mod.rs index 074402f..7e016a8 100644 --- a/fsrc-core/src/pus/mod.rs +++ b/fsrc-core/src/pus/mod.rs @@ -52,3 +52,58 @@ pub(crate) fn source_buffer_large_enough(cap: usize, len: usize) -> Result<() } Ok(()) } + +#[cfg(test)] +pub(crate) mod tests { + use crate::pus::verification::RequestId; + use crate::pus::{EcssTmError, EcssTmSender}; + use alloc::vec::Vec; + use spacepackets::ecss::PusPacket; + use spacepackets::tm::{PusTm, PusTmSecondaryHeaderT}; + use spacepackets::CcsdsPacket; + use std::collections::VecDeque; + + #[derive(Debug, Eq, PartialEq)] + pub(crate) struct TmInfo { + pub subservice: u8, + pub apid: u16, + pub msg_counter: u16, + pub dest_id: u16, + pub time_stamp: [u8; 7], + pub req_id: RequestId, + pub additional_data: Option>, + } + + #[derive(Default)] + pub(crate) struct TestSender { + pub service_queue: VecDeque, + } + + impl EcssTmSender<()> for TestSender { + fn send_tm(&mut self, tm: PusTm) -> Result<(), EcssTmError<()>> { + assert_eq!(PusPacket::service(&tm), 1); + assert!(tm.source_data().is_some()); + let mut time_stamp = [0; 7]; + time_stamp.clone_from_slice(&tm.time_stamp()[0..7]); + let src_data = tm.source_data().unwrap(); + assert!(src_data.len() >= 4); + let req_id = RequestId::from_bytes(&src_data[0..RequestId::SIZE_AS_BYTES]).unwrap(); + let mut vec = None; + if src_data.len() > 4 { + let mut new_vec = Vec::new(); + new_vec.extend_from_slice(&src_data[RequestId::SIZE_AS_BYTES..]); + vec = Some(new_vec); + } + self.service_queue.push_back(TmInfo { + subservice: PusPacket::subservice(&tm), + apid: tm.apid(), + msg_counter: tm.msg_counter(), + dest_id: tm.dest_id(), + time_stamp, + req_id, + additional_data: vec, + }); + Ok(()) + } + } +} diff --git a/fsrc-core/src/pus/verification.rs b/fsrc-core/src/pus/verification.rs index b242594..fd8076f 100644 --- a/fsrc-core/src/pus/verification.rs +++ b/fsrc-core/src/pus/verification.rs @@ -191,16 +191,16 @@ pub struct VerificationToken { } #[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub enum StateNone {} +pub struct StateNone; #[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub enum StateAccepted {} +pub struct StateAccepted; #[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub enum StateStarted {} +pub struct StateStarted; pub enum StateToken { None(StateNone), Accepted(StateAccepted), - Started(StateStarted) + Started(StateStarted), } impl VerificationToken { @@ -1066,6 +1066,7 @@ mod stdmod { #[cfg(test)] mod tests { + use crate::pus::tests::{TestSender, TmInfo}; use crate::pus::verification::{ EcssTmError, EcssTmSender, FailParams, FailParamsWithStep, RequestId, StateNone, VerificationReporter, VerificationReporterCfg, VerificationReporterWithSender, @@ -1073,60 +1074,14 @@ mod tests { }; use alloc::boxed::Box; use alloc::format; - use alloc::vec::Vec; - use spacepackets::ecss::{EcssEnumU16, EcssEnumU32, EcssEnumU8, EcssEnumeration, PusPacket}; + use spacepackets::ecss::{EcssEnumU16, EcssEnumU32, EcssEnumU8, EcssEnumeration}; use spacepackets::tc::{PusTc, PusTcSecondaryHeader}; - use spacepackets::tm::{PusTm, PusTmSecondaryHeaderT}; - use spacepackets::{ByteConversionError, CcsdsPacket, SpHeader}; - use std::collections::VecDeque; + use spacepackets::tm::PusTm; + use spacepackets::{ByteConversionError, SpHeader}; const TEST_APID: u16 = 0x02; const EMPTY_STAMP: [u8; 7] = [0; 7]; - #[derive(Debug, Eq, PartialEq)] - struct TmInfo { - pub subservice: u8, - pub apid: u16, - pub msg_counter: u16, - pub dest_id: u16, - pub time_stamp: [u8; 7], - pub req_id: RequestId, - pub additional_data: Option>, - } - - #[derive(Default)] - struct TestSender { - pub service_queue: VecDeque, - } - - impl EcssTmSender<()> for TestSender { - fn send_tm(&mut self, tm: PusTm) -> Result<(), EcssTmError<()>> { - assert_eq!(PusPacket::service(&tm), 1); - assert!(tm.source_data().is_some()); - let mut time_stamp = [0; 7]; - time_stamp.clone_from_slice(&tm.time_stamp()[0..7]); - let src_data = tm.source_data().unwrap(); - assert!(src_data.len() >= 4); - let req_id = RequestId::from_bytes(&src_data[0..RequestId::SIZE_AS_BYTES]).unwrap(); - let mut vec = None; - if src_data.len() > 4 { - let mut new_vec = Vec::new(); - new_vec.extend_from_slice(&src_data[RequestId::SIZE_AS_BYTES..]); - vec = Some(new_vec); - } - self.service_queue.push_back(TmInfo { - subservice: PusPacket::subservice(&tm), - apid: tm.apid(), - msg_counter: tm.msg_counter(), - dest_id: tm.dest_id(), - time_stamp, - req_id, - additional_data: vec, - }); - Ok(()) - } - } - #[derive(Debug, Copy, Clone, Eq, PartialEq)] struct DummyError {} #[derive(Default)] diff --git a/spacepackets b/spacepackets index 638e4cd..603f688 160000 --- a/spacepackets +++ b/spacepackets @@ -1 +1 @@ -Subproject commit 638e4cda620fbb0ef6aed9faa0e9375d3762a339 +Subproject commit 603f688ac3e914de13037fd22ac544e125b6305b From 0c9571f290d2e96f9285dd812e26bd9817380185 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sat, 15 Oct 2022 20:51:21 +0200 Subject: [PATCH 06/13] impl EcssEnumeration for Event --- fsrc-core/src/events.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/fsrc-core/src/events.rs b/fsrc-core/src/events.rs index be351b9..9df64fb 100644 --- a/fsrc-core/src/events.rs +++ b/fsrc-core/src/events.rs @@ -1,5 +1,8 @@ //! Event support module +use spacepackets::{ByteConversionError, SizeMissmatch}; +use spacepackets::ecss::EcssEnumeration; + pub type GroupId = u16; pub type UniqueId = u16; pub type EventRaw = u32; @@ -91,6 +94,22 @@ impl TryFrom for Event { } } +impl EcssEnumeration for Event { + fn pfc(&self) -> u8 { + 32 + } + + fn write_to_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError> { + if buf.len() < self.byte_width() { + return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch { + found: buf.len(), + expected: self.byte_width() + })) + } + Ok(buf.copy_from_slice(self.raw().to_be_bytes().as_slice())) + } +} + #[cfg(test)] mod tests { use super::Event; From 183aa01b7fd88a2c6ba1a7fb829e46217e852751 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sat, 15 Oct 2022 21:14:27 +0200 Subject: [PATCH 07/13] basic event testing framework --- fsrc-core/src/events.rs | 11 +- fsrc-core/src/pus/event.rs | 36 +++- fsrc-core/src/pus/mod.rs | 38 +---- fsrc-core/src/pus/verification.rs | 270 +++++++++++++++++++----------- 4 files changed, 219 insertions(+), 136 deletions(-) diff --git a/fsrc-core/src/events.rs b/fsrc-core/src/events.rs index 9df64fb..bce6324 100644 --- a/fsrc-core/src/events.rs +++ b/fsrc-core/src/events.rs @@ -1,7 +1,7 @@ //! Event support module -use spacepackets::{ByteConversionError, SizeMissmatch}; use spacepackets::ecss::EcssEnumeration; +use spacepackets::{ByteConversionError, SizeMissmatch}; pub type GroupId = u16; pub type UniqueId = u16; @@ -96,17 +96,18 @@ impl TryFrom for Event { impl EcssEnumeration for Event { fn pfc(&self) -> u8 { - 32 + 32 } fn write_to_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError> { if buf.len() < self.byte_width() { return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch { found: buf.len(), - expected: self.byte_width() - })) + expected: self.byte_width(), + })); } - Ok(buf.copy_from_slice(self.raw().to_be_bytes().as_slice())) + buf.copy_from_slice(self.raw().to_be_bytes().as_slice()); + Ok(()) } } diff --git a/fsrc-core/src/pus/event.rs b/fsrc-core/src/pus/event.rs index 9472f6a..812eb6d 100644 --- a/fsrc-core/src/pus/event.rs +++ b/fsrc-core/src/pus/event.rs @@ -255,12 +255,44 @@ mod allocvec { #[cfg(test)] mod tests { use super::*; + use crate::events::{Event, Severity}; + use crate::pus::tests::CommonTmInfo; + use std::collections::VecDeque; const EXAMPLE_APID: u16 = 0xee; + const EXAMPLE_GROUP_ID: u16 = 2; + const EXAMPLE_EVENT_ID: u16 = 1; + + #[derive(Debug, Eq, PartialEq)] + struct TmInfo { + pub common: CommonTmInfo, + } + + #[derive(Default)] + struct TestSender { + pub service_queue: VecDeque, + } + + impl EcssTmSender<()> for TestSender { + fn send_tm(&mut self, tm: PusTm) -> Result<(), EcssTmError<()>> { + self.service_queue.push_back(TmInfo { + common: CommonTmInfo::new_from_tm(&tm), + }); + Ok(()) + } + } #[test] fn basic_event_generation() { - let _reporter = EventReporter::new(EXAMPLE_APID, 16); - //reporter. + let mut sender = TestSender::default(); + let reporter = EventReporter::new(EXAMPLE_APID, 16); + assert!(reporter.is_some()); + let mut reporter = reporter.unwrap(); + let time_stamp_empty: [u8; 7] = [0; 7]; + let event = Event::new(Severity::INFO, EXAMPLE_GROUP_ID, EXAMPLE_EVENT_ID) + .expect("Error creating example event"); + reporter + .event_info(&mut sender, &time_stamp_empty, event, None) + .expect("Error reporting info event"); } } diff --git a/fsrc-core/src/pus/mod.rs b/fsrc-core/src/pus/mod.rs index 7e016a8..28e1c77 100644 --- a/fsrc-core/src/pus/mod.rs +++ b/fsrc-core/src/pus/mod.rs @@ -55,55 +55,29 @@ pub(crate) fn source_buffer_large_enough(cap: usize, len: usize) -> Result<() #[cfg(test)] pub(crate) mod tests { - use crate::pus::verification::RequestId; - use crate::pus::{EcssTmError, EcssTmSender}; - use alloc::vec::Vec; - use spacepackets::ecss::PusPacket; use spacepackets::tm::{PusTm, PusTmSecondaryHeaderT}; use spacepackets::CcsdsPacket; - use std::collections::VecDeque; #[derive(Debug, Eq, PartialEq)] - pub(crate) struct TmInfo { + pub(crate) struct CommonTmInfo { pub subservice: u8, pub apid: u16, pub msg_counter: u16, pub dest_id: u16, pub time_stamp: [u8; 7], - pub req_id: RequestId, - pub additional_data: Option>, } - #[derive(Default)] - pub(crate) struct TestSender { - pub service_queue: VecDeque, - } - - impl EcssTmSender<()> for TestSender { - fn send_tm(&mut self, tm: PusTm) -> Result<(), EcssTmError<()>> { - assert_eq!(PusPacket::service(&tm), 1); - assert!(tm.source_data().is_some()); + impl CommonTmInfo { + pub fn new_from_tm(tm: &PusTm) -> Self { let mut time_stamp = [0; 7]; time_stamp.clone_from_slice(&tm.time_stamp()[0..7]); - let src_data = tm.source_data().unwrap(); - assert!(src_data.len() >= 4); - let req_id = RequestId::from_bytes(&src_data[0..RequestId::SIZE_AS_BYTES]).unwrap(); - let mut vec = None; - if src_data.len() > 4 { - let mut new_vec = Vec::new(); - new_vec.extend_from_slice(&src_data[RequestId::SIZE_AS_BYTES..]); - vec = Some(new_vec); - } - self.service_queue.push_back(TmInfo { - subservice: PusPacket::subservice(&tm), + Self { + subservice: tm.subservice(), apid: tm.apid(), msg_counter: tm.msg_counter(), dest_id: tm.dest_id(), time_stamp, - req_id, - additional_data: vec, - }); - Ok(()) + } } } } diff --git a/fsrc-core/src/pus/verification.rs b/fsrc-core/src/pus/verification.rs index fd8076f..479dc11 100644 --- a/fsrc-core/src/pus/verification.rs +++ b/fsrc-core/src/pus/verification.rs @@ -1066,7 +1066,7 @@ mod stdmod { #[cfg(test)] mod tests { - use crate::pus::tests::{TestSender, TmInfo}; + use crate::pus::tests::CommonTmInfo; use crate::pus::verification::{ EcssTmError, EcssTmSender, FailParams, FailParamsWithStep, RequestId, StateNone, VerificationReporter, VerificationReporterCfg, VerificationReporterWithSender, @@ -1074,14 +1074,52 @@ mod tests { }; use alloc::boxed::Box; use alloc::format; - use spacepackets::ecss::{EcssEnumU16, EcssEnumU32, EcssEnumU8, EcssEnumeration}; + use spacepackets::ecss::{EcssEnumU16, EcssEnumU32, EcssEnumU8, EcssEnumeration, PusPacket}; use spacepackets::tc::{PusTc, PusTcSecondaryHeader}; use spacepackets::tm::PusTm; use spacepackets::{ByteConversionError, SpHeader}; + use std::collections::VecDeque; + use std::vec::Vec; const TEST_APID: u16 = 0x02; const EMPTY_STAMP: [u8; 7] = [0; 7]; + #[derive(Debug, Eq, PartialEq)] + struct TmInfo { + pub common: CommonTmInfo, + pub req_id: RequestId, + pub additional_data: Option>, + } + + #[derive(Default)] + struct TestSender { + pub service_queue: VecDeque, + } + + impl EcssTmSender<()> for TestSender { + fn send_tm(&mut self, tm: PusTm) -> Result<(), EcssTmError<()>> { + assert_eq!(PusPacket::service(&tm), 1); + assert!(tm.source_data().is_some()); + let mut time_stamp = [0; 7]; + time_stamp.clone_from_slice(&tm.time_stamp()[0..7]); + let src_data = tm.source_data().unwrap(); + assert!(src_data.len() >= 4); + let req_id = RequestId::from_bytes(&src_data[0..RequestId::SIZE_AS_BYTES]).unwrap(); + let mut vec = None; + if src_data.len() > 4 { + let mut new_vec = Vec::new(); + new_vec.extend_from_slice(&src_data[RequestId::SIZE_AS_BYTES..]); + vec = Some(new_vec); + } + self.service_queue.push_back(TmInfo { + common: CommonTmInfo::new_from_tm(&tm), + req_id, + additional_data: vec, + }); + Ok(()) + } + } + #[derive(Debug, Copy, Clone, Eq, PartialEq)] struct DummyError {} #[derive(Default)] @@ -1155,11 +1193,13 @@ mod tests { fn acceptance_check(sender: &mut TestSender, req_id: &RequestId) { let cmp_info = TmInfo { - time_stamp: EMPTY_STAMP, - subservice: 1, - dest_id: 0, - apid: TEST_APID, - msg_counter: 0, + common: CommonTmInfo { + subservice: 1, + apid: TEST_APID, + msg_counter: 0, + dest_id: 0, + time_stamp: EMPTY_STAMP, + }, additional_data: None, req_id: req_id.clone(), }; @@ -1214,11 +1254,13 @@ mod tests { fn acceptance_fail_check(sender: &mut TestSender, req_id: RequestId, stamp_buf: [u8; 7]) { let cmp_info = TmInfo { - time_stamp: stamp_buf, - subservice: 2, - dest_id: 5, - apid: TEST_APID, - msg_counter: 0, + common: CommonTmInfo { + subservice: 2, + apid: TEST_APID, + msg_counter: 0, + dest_id: 5, + time_stamp: stamp_buf, + }, additional_data: Some([0, 2].to_vec()), req_id, }; @@ -1300,11 +1342,13 @@ mod tests { b.vr.acceptance_failure(tok, &mut sender, fail_params) .expect("Sending acceptance success failed"); let cmp_info = TmInfo { - time_stamp: EMPTY_STAMP, - subservice: 2, - dest_id: 0, - apid: TEST_APID, - msg_counter: 0, + common: CommonTmInfo { + subservice: 2, + apid: TEST_APID, + msg_counter: 0, + dest_id: 0, + time_stamp: EMPTY_STAMP, + }, additional_data: Some([10, 0, 0, 0, 12].to_vec()), req_id: tok.req_id, }; @@ -1316,11 +1360,13 @@ mod tests { fn start_fail_check(sender: &mut TestSender, req_id: RequestId, fail_data_raw: [u8; 4]) { assert_eq!(sender.service_queue.len(), 2); let mut cmp_info = TmInfo { - time_stamp: EMPTY_STAMP, - subservice: 1, - dest_id: 0, - apid: TEST_APID, - msg_counter: 0, + common: CommonTmInfo { + subservice: 1, + apid: TEST_APID, + msg_counter: 0, + dest_id: 0, + time_stamp: EMPTY_STAMP, + }, additional_data: None, req_id, }; @@ -1328,11 +1374,13 @@ mod tests { assert_eq!(info, cmp_info); cmp_info = TmInfo { - time_stamp: EMPTY_STAMP, - subservice: 4, - dest_id: 0, - apid: TEST_APID, - msg_counter: 1, + common: CommonTmInfo { + subservice: 4, + apid: TEST_APID, + msg_counter: 1, + dest_id: 0, + time_stamp: EMPTY_STAMP, + }, additional_data: Some([&[22], fail_data_raw.as_slice()].concat().to_vec()), req_id, }; @@ -1384,44 +1432,52 @@ mod tests { fn step_success_check(sender: &mut TestSender, req_id: RequestId) { let mut cmp_info = TmInfo { - time_stamp: EMPTY_STAMP, - subservice: 1, - dest_id: 0, - apid: TEST_APID, - msg_counter: 0, + common: CommonTmInfo { + subservice: 1, + apid: TEST_APID, + msg_counter: 0, + dest_id: 0, + time_stamp: EMPTY_STAMP, + }, additional_data: None, req_id, }; let mut info = sender.service_queue.pop_front().unwrap(); assert_eq!(info, cmp_info); cmp_info = TmInfo { - time_stamp: [0, 1, 0, 1, 0, 1, 0], - subservice: 3, - dest_id: 0, - apid: TEST_APID, - msg_counter: 1, + common: CommonTmInfo { + subservice: 3, + apid: TEST_APID, + msg_counter: 1, + dest_id: 0, + time_stamp: [0, 1, 0, 1, 0, 1, 0], + }, additional_data: None, req_id, }; info = sender.service_queue.pop_front().unwrap(); assert_eq!(info, cmp_info); cmp_info = TmInfo { - time_stamp: EMPTY_STAMP, - subservice: 5, - dest_id: 0, - apid: TEST_APID, - msg_counter: 2, + common: CommonTmInfo { + subservice: 5, + apid: TEST_APID, + msg_counter: 2, + dest_id: 0, + time_stamp: EMPTY_STAMP, + }, additional_data: Some([0].to_vec()), req_id, }; info = sender.service_queue.pop_front().unwrap(); assert_eq!(info, cmp_info); cmp_info = TmInfo { - time_stamp: EMPTY_STAMP, - subservice: 5, - dest_id: 0, - apid: TEST_APID, - msg_counter: 3, + common: CommonTmInfo { + subservice: 5, + apid: TEST_APID, + msg_counter: 3, + dest_id: 0, + time_stamp: EMPTY_STAMP, + }, additional_data: Some([1].to_vec()), req_id, }; @@ -1493,11 +1549,13 @@ mod tests { fn check_step_failure(sender: &mut TestSender, req_id: RequestId, fail_data_raw: [u8; 4]) { assert_eq!(sender.service_queue.len(), 4); let mut cmp_info = TmInfo { - time_stamp: EMPTY_STAMP, - subservice: 1, - dest_id: 0, - apid: TEST_APID, - msg_counter: 0, + common: CommonTmInfo { + subservice: 1, + apid: TEST_APID, + msg_counter: 0, + dest_id: 0, + time_stamp: EMPTY_STAMP, + }, additional_data: None, req_id, }; @@ -1505,11 +1563,13 @@ mod tests { assert_eq!(info, cmp_info); cmp_info = TmInfo { - time_stamp: [0, 1, 0, 1, 0, 1, 0], - subservice: 3, - dest_id: 0, - apid: TEST_APID, - msg_counter: 1, + common: CommonTmInfo { + subservice: 3, + apid: TEST_APID, + msg_counter: 1, + dest_id: 0, + time_stamp: [0, 1, 0, 1, 0, 1, 0], + }, additional_data: None, req_id, }; @@ -1517,11 +1577,13 @@ mod tests { assert_eq!(info, cmp_info); cmp_info = TmInfo { - time_stamp: EMPTY_STAMP, - subservice: 5, - dest_id: 0, - apid: TEST_APID, - msg_counter: 2, + common: CommonTmInfo { + subservice: 5, + apid: TEST_APID, + msg_counter: 2, + dest_id: 0, + time_stamp: EMPTY_STAMP, + }, additional_data: Some([0].to_vec()), req_id, }; @@ -1529,11 +1591,13 @@ mod tests { assert_eq!(info, cmp_info); cmp_info = TmInfo { - time_stamp: EMPTY_STAMP, - subservice: 6, - dest_id: 0, - apid: TEST_APID, - msg_counter: 3, + common: CommonTmInfo { + subservice: 6, + apid: TEST_APID, + msg_counter: 3, + dest_id: 0, + time_stamp: EMPTY_STAMP, + }, additional_data: Some( [ [1].as_slice(), @@ -1630,11 +1694,13 @@ mod tests { assert_eq!(sender.service_queue.len(), 3); let mut cmp_info = TmInfo { - time_stamp: EMPTY_STAMP, - subservice: 1, - dest_id: 0, - apid: TEST_APID, - msg_counter: 0, + common: CommonTmInfo { + subservice: 1, + apid: TEST_APID, + msg_counter: 0, + dest_id: 0, + time_stamp: EMPTY_STAMP, + }, additional_data: None, req_id, }; @@ -1642,11 +1708,13 @@ mod tests { assert_eq!(info, cmp_info); cmp_info = TmInfo { - time_stamp: [0, 1, 0, 1, 0, 1, 0], - subservice: 3, - dest_id: 0, - apid: TEST_APID, - msg_counter: 1, + common: CommonTmInfo { + subservice: 3, + apid: TEST_APID, + msg_counter: 1, + dest_id: 0, + time_stamp: [0, 1, 0, 1, 0, 1, 0], + }, additional_data: None, req_id, }; @@ -1654,11 +1722,13 @@ mod tests { assert_eq!(info, cmp_info); cmp_info = TmInfo { - time_stamp: EMPTY_STAMP, - subservice: 8, - dest_id: 0, - apid: TEST_APID, - msg_counter: 2, + common: CommonTmInfo { + subservice: 8, + apid: TEST_APID, + msg_counter: 2, + dest_id: 0, + time_stamp: EMPTY_STAMP, + }, additional_data: Some([0, 0, 0x10, 0x20].to_vec()), req_id, }; @@ -1714,11 +1784,13 @@ mod tests { fn completion_success_check(sender: &mut TestSender, req_id: RequestId) { assert_eq!(sender.service_queue.len(), 3); let cmp_info = TmInfo { - time_stamp: EMPTY_STAMP, - subservice: 1, - dest_id: 0, - apid: TEST_APID, - msg_counter: 0, + common: CommonTmInfo { + subservice: 1, + apid: TEST_APID, + msg_counter: 0, + dest_id: 0, + time_stamp: EMPTY_STAMP, + }, additional_data: None, req_id, }; @@ -1726,22 +1798,26 @@ mod tests { assert_eq!(info, cmp_info); let cmp_info = TmInfo { - time_stamp: [0, 1, 0, 1, 0, 1, 0], - subservice: 3, - dest_id: 0, - apid: TEST_APID, - msg_counter: 1, + common: CommonTmInfo { + subservice: 3, + apid: TEST_APID, + msg_counter: 1, + dest_id: 0, + time_stamp: [0, 1, 0, 1, 0, 1, 0], + }, additional_data: None, req_id, }; info = sender.service_queue.pop_front().unwrap(); assert_eq!(info, cmp_info); let cmp_info = TmInfo { - time_stamp: EMPTY_STAMP, - subservice: 7, - dest_id: 0, - apid: TEST_APID, - msg_counter: 2, + common: CommonTmInfo { + subservice: 7, + apid: TEST_APID, + msg_counter: 2, + dest_id: 0, + time_stamp: EMPTY_STAMP, + }, additional_data: None, req_id, }; From ac850533e186ed848c62ff7272dbdfd31ac03f96 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 21 Oct 2022 20:07:30 +0200 Subject: [PATCH 08/13] basic event tests --- fsrc-core/src/pus/event.rs | 97 +++++++++++++++++++++++++++++++++++--- 1 file changed, 90 insertions(+), 7 deletions(-) diff --git a/fsrc-core/src/pus/event.rs b/fsrc-core/src/pus/event.rs index 812eb6d..d244321 100644 --- a/fsrc-core/src/pus/event.rs +++ b/fsrc-core/src/pus/event.rs @@ -261,11 +261,14 @@ mod tests { const EXAMPLE_APID: u16 = 0xee; const EXAMPLE_GROUP_ID: u16 = 2; - const EXAMPLE_EVENT_ID: u16 = 1; + const EXAMPLE_EVENT_ID_0: u16 = 1; + #[allow(dead_code)] + const EXAMPLE_EVENT_ID_1: u16 = 2; #[derive(Debug, Eq, PartialEq)] struct TmInfo { pub common: CommonTmInfo, + pub event: Event, } #[derive(Default)] @@ -275,24 +278,104 @@ mod tests { impl EcssTmSender<()> for TestSender { fn send_tm(&mut self, tm: PusTm) -> Result<(), EcssTmError<()>> { + assert!(tm.source_data().is_some()); + let src_data = tm.source_data().unwrap(); + assert!(src_data.len() >= 4); + let event = Event::try_from(u32::from_be_bytes(src_data[0..4].try_into().unwrap())); + assert!(event.is_ok()); + let event = event.unwrap(); self.service_queue.push_back(TmInfo { common: CommonTmInfo::new_from_tm(&tm), + event, }); Ok(()) } } - #[test] - fn basic_event_generation() { + fn severity_to_subservice(severity: Severity) -> Subservices { + match severity { + Severity::INFO => Subservices::TmInfoReport, + Severity::LOW => Subservices::TmLowSeverityReport, + Severity::MEDIUM => Subservices::TmMediumSeverityReport, + Severity::HIGH => Subservices::TmHighSeverityReport, + } + } + + fn report_basic_event( + reporter: &mut EventReporter, + sender: &mut TestSender, + time_stamp: &[u8], + event: Event, + severity: Severity, + ) { + match severity { + Severity::INFO => { + reporter + .event_info(sender, time_stamp, event, None) + .expect("Error reporting info event"); + } + Severity::LOW => { + reporter + .event_low_severity(sender, time_stamp, event, None) + .expect("Error reporting low event"); + } + Severity::MEDIUM => { + reporter + .event_medium_severity(sender, time_stamp, event, None) + .expect("Error reporting medium event"); + } + Severity::HIGH => { + reporter + .event_high_severity(sender, time_stamp, event, None) + .expect("Error reporting high event"); + } + } + } + + fn basic_event_test(severity: Severity) { let mut sender = TestSender::default(); let reporter = EventReporter::new(EXAMPLE_APID, 16); assert!(reporter.is_some()); let mut reporter = reporter.unwrap(); let time_stamp_empty: [u8; 7] = [0; 7]; - let event = Event::new(Severity::INFO, EXAMPLE_GROUP_ID, EXAMPLE_EVENT_ID) + let event = Event::new(severity, EXAMPLE_GROUP_ID, EXAMPLE_EVENT_ID_0) .expect("Error creating example event"); - reporter - .event_info(&mut sender, &time_stamp_empty, event, None) - .expect("Error reporting info event"); + report_basic_event( + &mut reporter, + &mut sender, + &time_stamp_empty, + event, + severity, + ); + assert_eq!(sender.service_queue.len(), 1); + let tm_info = sender.service_queue.pop_front().unwrap(); + assert_eq!( + tm_info.common.subservice, + severity_to_subservice(severity) as u8 + ); + assert_eq!(tm_info.common.dest_id, 0); + assert_eq!(tm_info.common.time_stamp, time_stamp_empty); + assert_eq!(tm_info.common.msg_counter, 0); + assert_eq!(tm_info.common.apid, EXAMPLE_APID); + assert_eq!(tm_info.event, event); + } + #[test] + fn basic_info_event_generation() { + basic_event_test(Severity::INFO); + } + + #[test] + fn basic_low_severity_event() { + basic_event_test(Severity::LOW); + } + + #[test] + fn basic_medium_severity_event() { + basic_event_test(Severity::MEDIUM); + } + + #[test] + fn basic_high_severity_event() { + basic_event_test(Severity::HIGH); } } From 714f4ba89c107c2f7807e1cef0dbfb88159c2a10 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 21 Oct 2022 20:09:55 +0200 Subject: [PATCH 09/13] newline --- fsrc-core/src/pus/event.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/fsrc-core/src/pus/event.rs b/fsrc-core/src/pus/event.rs index d244321..cd33369 100644 --- a/fsrc-core/src/pus/event.rs +++ b/fsrc-core/src/pus/event.rs @@ -359,6 +359,7 @@ mod tests { assert_eq!(tm_info.common.apid, EXAMPLE_APID); assert_eq!(tm_info.event, event); } + #[test] fn basic_info_event_generation() { basic_event_test(Severity::INFO); From 1ef3e13b3dd1559c5202093a40ff9572f0a4f6ac Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 21 Oct 2022 20:22:20 +0200 Subject: [PATCH 10/13] added test with event string --- fsrc-core/src/pus/event.rs | 40 ++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/fsrc-core/src/pus/event.rs b/fsrc-core/src/pus/event.rs index cd33369..d7447e7 100644 --- a/fsrc-core/src/pus/event.rs +++ b/fsrc-core/src/pus/event.rs @@ -257,6 +257,7 @@ mod tests { use super::*; use crate::events::{Event, Severity}; use crate::pus::tests::CommonTmInfo; + use std::vec::Vec; use std::collections::VecDeque; const EXAMPLE_APID: u16 = 0xee; @@ -269,6 +270,7 @@ mod tests { struct TmInfo { pub common: CommonTmInfo, pub event: Event, + pub aux_data: Vec } #[derive(Default)] @@ -284,9 +286,14 @@ mod tests { let event = Event::try_from(u32::from_be_bytes(src_data[0..4].try_into().unwrap())); assert!(event.is_ok()); let event = event.unwrap(); + let mut aux_data = Vec::new(); + if src_data.len() > 4 { + aux_data.extend_from_slice(&src_data[4..]); + } self.service_queue.push_back(TmInfo { common: CommonTmInfo::new_from_tm(&tm), event, + aux_data }); Ok(()) } @@ -307,37 +314,42 @@ mod tests { time_stamp: &[u8], event: Event, severity: Severity, + aux_data: Option<&[u8]> ) { match severity { Severity::INFO => { reporter - .event_info(sender, time_stamp, event, None) + .event_info(sender, time_stamp, event, aux_data) .expect("Error reporting info event"); } Severity::LOW => { reporter - .event_low_severity(sender, time_stamp, event, None) + .event_low_severity(sender, time_stamp, event, aux_data) .expect("Error reporting low event"); } Severity::MEDIUM => { reporter - .event_medium_severity(sender, time_stamp, event, None) + .event_medium_severity(sender, time_stamp, event, aux_data) .expect("Error reporting medium event"); } Severity::HIGH => { reporter - .event_high_severity(sender, time_stamp, event, None) + .event_high_severity(sender, time_stamp, event, aux_data) .expect("Error reporting high event"); } } } - fn basic_event_test(severity: Severity) { + fn basic_event_test(max_event_aux_data_buf: usize, severity: Severity, error_data: Option<&[u8]>) { let mut sender = TestSender::default(); - let reporter = EventReporter::new(EXAMPLE_APID, 16); + let reporter = EventReporter::new(EXAMPLE_APID, max_event_aux_data_buf); assert!(reporter.is_some()); let mut reporter = reporter.unwrap(); let time_stamp_empty: [u8; 7] = [0; 7]; + let mut error_copy = Vec::new(); + if let Some(err_data) = error_data { + error_copy.extend_from_slice(err_data); + } let event = Event::new(severity, EXAMPLE_GROUP_ID, EXAMPLE_EVENT_ID_0) .expect("Error creating example event"); report_basic_event( @@ -346,6 +358,7 @@ mod tests { &time_stamp_empty, event, severity, + error_data ); assert_eq!(sender.service_queue.len(), 1); let tm_info = sender.service_queue.pop_front().unwrap(); @@ -358,25 +371,32 @@ mod tests { assert_eq!(tm_info.common.msg_counter, 0); assert_eq!(tm_info.common.apid, EXAMPLE_APID); assert_eq!(tm_info.event, event); + assert_eq!(tm_info.aux_data, error_copy); } #[test] fn basic_info_event_generation() { - basic_event_test(Severity::INFO); + basic_event_test(4, Severity::INFO, None); } #[test] fn basic_low_severity_event() { - basic_event_test(Severity::LOW); + basic_event_test(4, Severity::LOW, None); } #[test] fn basic_medium_severity_event() { - basic_event_test(Severity::MEDIUM); + basic_event_test(4, Severity::MEDIUM, None); } #[test] fn basic_high_severity_event() { - basic_event_test(Severity::HIGH); + basic_event_test(4, Severity::HIGH, None); + } + + #[test] + fn event_with_info_string() { + let info_string = "Test Information"; + basic_event_test(32, Severity::INFO, Some(info_string.as_bytes())); } } From ed30bef4aaf47c02840b67b312433dd829985002 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sat, 22 Oct 2022 15:00:48 +0200 Subject: [PATCH 11/13] some test code --- Cargo.lock | 1 + fsrc-example/Cargo.toml | 1 + fsrc-example/src/bin/test.rs | 13 +++++++++++++ 3 files changed, 15 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 3ea2c46..b9d6035 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -254,6 +254,7 @@ dependencies = [ "delegate 0.8.0", "fsrc-core", "spacepackets", + "zerocopy", ] [[package]] diff --git a/fsrc-example/Cargo.toml b/fsrc-example/Cargo.toml index 8bccc84..853e98e 100644 --- a/fsrc-example/Cargo.toml +++ b/fsrc-example/Cargo.toml @@ -7,6 +7,7 @@ authors = ["Robin Mueller "] [dependencies] crossbeam-channel = "0.5" delegate = "0.8" +zerocopy = "0.6.1" [dependencies.spacepackets] path = "../spacepackets" diff --git a/fsrc-example/src/bin/test.rs b/fsrc-example/src/bin/test.rs index a979878..62577cd 100644 --- a/fsrc-example/src/bin/test.rs +++ b/fsrc-example/src/bin/test.rs @@ -1,5 +1,6 @@ use crossbeam_channel::{bounded, Receiver, Sender}; use std::thread; +use zerocopy::{FromBytes, AsBytes, Unaligned, U16, NetworkEndian}; trait FieldDataProvider: Send { fn get_data(&self) -> &[u8]; @@ -26,6 +27,18 @@ impl FieldDataProvider for FixedFieldDataWrapper { type FieldDataTraitObj = Box; +struct ExampleMgmSet { + mgm_vec: [f32; 3], + temperature: u16 +} + +#[derive(FromBytes, AsBytes, Unaligned)] +#[repr(C)] +struct ExampleMgmSetZc { + mgm_vec: [u8; 12], + temperatur: U16 +} + fn main() { let (s0, r0): (Sender, Receiver) = bounded(5); let data_wrapper = FixedFieldDataWrapper::from_two_u32(2, 3); From 0f21203d2751edcfb617c16187e31db193c3675c Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sat, 22 Oct 2022 15:31:50 +0200 Subject: [PATCH 12/13] allow patch level updates for deps --- Cargo.lock | 220 ++++++++++++++++++++++++++--------- fsrc-core/Cargo.toml | 16 +-- fsrc-core/src/pus/event.rs | 60 ++++++++-- fsrc-example/Cargo.toml | 2 +- fsrc-example/src/bin/test.rs | 7 +- 5 files changed, 227 insertions(+), 78 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b9d6035..cef630f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -81,9 +81,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bumpalo" -version = "3.11.0" +version = "3.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" +checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" [[package]] name = "bus" @@ -102,6 +102,12 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "cc" +version = "1.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" + [[package]] name = "cfg-if" version = "1.0.0" @@ -126,6 +132,16 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + [[package]] name = "core-foundation-sys" version = "0.8.3" @@ -183,12 +199,55 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc" +checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac" dependencies = [ "cfg-if", +] + +[[package]] +name = "cxx" +version = "1.0.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b7d4e43b25d3c994662706a1d4fcfc32aaa6afd287502c111b237093bb23f3a" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84f8829ddc213e2c1368e51a2564c552b65a8cb6a28f31e576270ac81d5e5827" +dependencies = [ + "cc", + "codespan-reporting", "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e72537424b474af1460806647c41d4b6d35d09ef7fe031c5c2fa5766047cc56a" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "309e4fb93eed90e1e14bea0da16b209f81813ba9fc7830c20ed151dd7bc0a4d7" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -259,9 +318,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ "cfg-if", "libc", @@ -311,18 +370,28 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.48" +version = "0.1.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "237a0714f28b1ee39ccec0770ccb544eb02c9ef2c82bb096230eefcffa6468b0" +checksum = "f5a6ef98976b22b3b7f2f3a806f858cb862044cfa66805aa3ad84cb3d3b785ed" dependencies = [ "android_system_properties", "core-foundation-sys", + "iana-time-zone-haiku", "js-sys", - "once_cell", "wasm-bindgen", "winapi", ] +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +dependencies = [ + "cxx", + "cxx-build", +] + [[package]] name = "js-sys" version = "0.3.60" @@ -340,15 +409,24 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.132" +version = "0.2.135" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" +checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c" + +[[package]] +name = "link-cplusplus" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369" +dependencies = [ + "cc", +] [[package]] name = "lock_api" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f80bf5aacaf25cbfc8210d1cfb718f2bf3b11c4c54e5afe36c236853a8ec390" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" dependencies = [ "autocfg", "scopeguard", @@ -415,15 +493,15 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0" +checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1" [[package]] name = "parking_lot_core" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" +checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0" dependencies = [ "cfg-if", "libc", @@ -445,9 +523,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.43" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" +checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" dependencies = [ "unicode-ident", ] @@ -523,7 +601,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.13", + "semver 1.0.14", ] [[package]] @@ -532,6 +610,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "scratch" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898" + [[package]] name = "semver" version = "0.9.0" @@ -543,9 +627,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f6841e709003d68bb2deee8c343572bf446003ec20a583e76f7b15cebf3711" +checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" [[package]] name = "semver-parser" @@ -555,18 +639,18 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.144" +version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860" +checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.144" +version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00" +checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" dependencies = [ "proc-macro2", "quote", @@ -575,9 +659,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "spacepackets" @@ -609,9 +693,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "syn" -version = "1.0.99" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" +checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" dependencies = [ "proc-macro2", "quote", @@ -619,28 +703,25 @@ dependencies = [ ] [[package]] -name = "synstructure" -version = "0.12.6" +name = "termcolor" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" dependencies = [ - "proc-macro2", - "quote", - "syn", - "unicode-xid", + "winapi-util", ] [[package]] name = "unicode-ident" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" [[package]] -name = "unicode-xid" -version = "0.2.3" +name = "unicode-width" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "vcell" @@ -745,6 +826,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -753,46 +843,60 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ + "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_msvc", "windows_x86_64_gnu", + "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] [[package]] -name = "windows_aarch64_msvc" -version = "0.36.1" +name = "windows_aarch64_gnullvm" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" [[package]] name = "windows_i686_gnu" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" [[package]] name = "windows_i686_msvc" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" [[package]] name = "windows_x86_64_gnu" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" [[package]] name = "windows_x86_64_msvc" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" [[package]] name = "zerocopy" @@ -806,11 +910,11 @@ dependencies = [ [[package]] name = "zerocopy-derive" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0fbc82b82efe24da867ee52e015e58178684bd9dd64c34e66bdf21da2582a9f" +checksum = "6505e6815af7de1746a08f69c69606bb45695a17149517680f3b2149713b19a3" dependencies = [ "proc-macro2", + "quote", "syn", - "synstructure", ] diff --git a/fsrc-core/Cargo.toml b/fsrc-core/Cargo.toml index 8188273..e42e4b6 100644 --- a/fsrc-core/Cargo.toml +++ b/fsrc-core/Cargo.toml @@ -6,19 +6,19 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -delegate = "0.8.0" -hashbrown = "0.12.3" +delegate = "0.8" +hashbrown = "0.12" [dependencies.num-traits] version = "0.2" default-features = false [dependencies.downcast-rs] -version = "1.2.0" +version = "1.2" default-features = false [dependencies.bus] -version = "2.2.3" +version = "2.2" optional = true [dependencies.crossbeam-channel] @@ -29,12 +29,12 @@ default-features = false path = "../spacepackets" [dev-dependencies] -serde = "1.0.143" -zerocopy = "0.6.1" -once_cell = "1.13.1" +serde = "1.0" +zerocopy = "0.6" +once_cell = "1.13" [dev-dependencies.postcard] -version = "1.0.1" +version = "1.0" [features] default = ["std"] diff --git a/fsrc-core/src/pus/event.rs b/fsrc-core/src/pus/event.rs index d7447e7..bea74a4 100644 --- a/fsrc-core/src/pus/event.rs +++ b/fsrc-core/src/pus/event.rs @@ -257,8 +257,9 @@ mod tests { use super::*; use crate::events::{Event, Severity}; use crate::pus::tests::CommonTmInfo; - use std::vec::Vec; + use spacepackets::ByteConversionError; use std::collections::VecDeque; + use std::vec::Vec; const EXAMPLE_APID: u16 = 0xee; const EXAMPLE_GROUP_ID: u16 = 2; @@ -270,7 +271,7 @@ mod tests { struct TmInfo { pub common: CommonTmInfo, pub event: Event, - pub aux_data: Vec + pub aux_data: Vec, } #[derive(Default)] @@ -293,7 +294,7 @@ mod tests { self.service_queue.push_back(TmInfo { common: CommonTmInfo::new_from_tm(&tm), event, - aux_data + aux_data, }); Ok(()) } @@ -314,7 +315,7 @@ mod tests { time_stamp: &[u8], event: Event, severity: Severity, - aux_data: Option<&[u8]> + aux_data: Option<&[u8]>, ) { match severity { Severity::INFO => { @@ -340,15 +341,19 @@ mod tests { } } - fn basic_event_test(max_event_aux_data_buf: usize, severity: Severity, error_data: Option<&[u8]>) { + fn basic_event_test( + max_event_aux_data_buf: usize, + severity: Severity, + error_data: Option<&[u8]>, + ) { let mut sender = TestSender::default(); - let reporter = EventReporter::new(EXAMPLE_APID, max_event_aux_data_buf); + let reporter = EventReporter::new(EXAMPLE_APID, max_event_aux_data_buf); assert!(reporter.is_some()); let mut reporter = reporter.unwrap(); let time_stamp_empty: [u8; 7] = [0; 7]; let mut error_copy = Vec::new(); if let Some(err_data) = error_data { - error_copy.extend_from_slice(err_data); + error_copy.extend_from_slice(err_data); } let event = Event::new(severity, EXAMPLE_GROUP_ID, EXAMPLE_EVENT_ID_0) .expect("Error creating example event"); @@ -358,7 +363,7 @@ mod tests { &time_stamp_empty, event, severity, - error_data + error_data, ); assert_eq!(sender.service_queue.len(), 1); let tm_info = sender.service_queue.pop_front().unwrap(); @@ -399,4 +404,43 @@ mod tests { let info_string = "Test Information"; basic_event_test(32, Severity::INFO, Some(info_string.as_bytes())); } + + #[test] + fn low_severity_with_raw_err_data() { + let raw_err_param: i32 = -1; + let raw_err = raw_err_param.to_be_bytes(); + basic_event_test(8, Severity::LOW, Some(&raw_err)) + } + + fn check_buf_too_small( + reporter: &mut EventReporter, + sender: &mut TestSender, + expected_found_len: usize, + ) { + let time_stamp_empty: [u8; 7] = [0; 7]; + let event = Event::new(Severity::INFO, EXAMPLE_GROUP_ID, EXAMPLE_EVENT_ID_0) + .expect("Error creating example event"); + let err = reporter.event_info(sender, &time_stamp_empty, event, None); + assert!(err.is_err()); + let err = err.unwrap_err(); + if let EcssTmError::ByteConversionError(ByteConversionError::ToSliceTooSmall(missmatch)) = + err + { + assert_eq!(missmatch.expected, 4); + assert_eq!(missmatch.found, expected_found_len); + } else { + panic!("Unexpected error {:?}", err); + } + } + + #[test] + fn insufficient_buffer() { + let mut sender = TestSender::default(); + for i in 0..3 { + let reporter = EventReporter::new(EXAMPLE_APID, i); + assert!(reporter.is_some()); + let mut reporter = reporter.unwrap(); + check_buf_too_small(&mut reporter, &mut sender, i); + } + } } diff --git a/fsrc-example/Cargo.toml b/fsrc-example/Cargo.toml index 853e98e..1bc9f48 100644 --- a/fsrc-example/Cargo.toml +++ b/fsrc-example/Cargo.toml @@ -7,7 +7,7 @@ authors = ["Robin Mueller "] [dependencies] crossbeam-channel = "0.5" delegate = "0.8" -zerocopy = "0.6.1" +zerocopy = "0.6" [dependencies.spacepackets] path = "../spacepackets" diff --git a/fsrc-example/src/bin/test.rs b/fsrc-example/src/bin/test.rs index 62577cd..d88c902 100644 --- a/fsrc-example/src/bin/test.rs +++ b/fsrc-example/src/bin/test.rs @@ -1,6 +1,7 @@ +#![allow(dead_code)] use crossbeam_channel::{bounded, Receiver, Sender}; use std::thread; -use zerocopy::{FromBytes, AsBytes, Unaligned, U16, NetworkEndian}; +use zerocopy::{AsBytes, FromBytes, NetworkEndian, Unaligned, U16}; trait FieldDataProvider: Send { fn get_data(&self) -> &[u8]; @@ -29,14 +30,14 @@ type FieldDataTraitObj = Box; struct ExampleMgmSet { mgm_vec: [f32; 3], - temperature: u16 + temperature: u16, } #[derive(FromBytes, AsBytes, Unaligned)] #[repr(C)] struct ExampleMgmSetZc { mgm_vec: [u8; 12], - temperatur: U16 + temperatur: U16, } fn main() { From e99ce711a5cbb88bac5a8dfbb8b986bb36bd4e46 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sat, 22 Oct 2022 17:16:28 +0200 Subject: [PATCH 13/13] PUS event management backend provider --- Cargo.lock | 1 + fsrc-core/Cargo.toml | 3 +- fsrc-core/src/events.rs | 4 +- fsrc-core/src/pus/event_man.rs | 79 +++++++++++++++++++ fsrc-core/src/pus/mod.rs | 1 + fsrc-core/tests/{pool_test.rs => pools.rs} | 0 fsrc-core/tests/pus_events.rs | 1 + ...rification_test.rs => pus_verification.rs} | 0 8 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 fsrc-core/src/pus/event_man.rs rename fsrc-core/tests/{pool_test.rs => pools.rs} (100%) create mode 100644 fsrc-core/tests/pus_events.rs rename fsrc-core/tests/{verification_test.rs => pus_verification.rs} (100%) diff --git a/Cargo.lock b/Cargo.lock index cef630f..9314533 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -297,6 +297,7 @@ dependencies = [ "delegate 0.8.0", "downcast-rs", "hashbrown", + "heapless", "num-traits", "once_cell", "postcard", diff --git a/fsrc-core/Cargo.toml b/fsrc-core/Cargo.toml index e42e4b6..69df909 100644 --- a/fsrc-core/Cargo.toml +++ b/fsrc-core/Cargo.toml @@ -8,6 +8,7 @@ edition = "2021" [dependencies] delegate = "0.8" hashbrown = "0.12" +heapless = "0.7" [dependencies.num-traits] version = "0.2" @@ -40,4 +41,4 @@ version = "1.0" default = ["std"] std = ["downcast-rs/std", "alloc", "bus", "postcard/use-std", "crossbeam-channel/std"] alloc = [] - +heapless = [] diff --git a/fsrc-core/src/events.rs b/fsrc-core/src/events.rs index bce6324..02bf7f6 100644 --- a/fsrc-core/src/events.rs +++ b/fsrc-core/src/events.rs @@ -7,7 +7,7 @@ pub type GroupId = u16; pub type UniqueId = u16; pub type EventRaw = u32; -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] pub enum Severity { INFO = 1, LOW = 2, @@ -29,7 +29,7 @@ impl TryFrom for Severity { } } -#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub struct Event { severity: Severity, group_id: GroupId, diff --git a/fsrc-core/src/pus/event_man.rs b/fsrc-core/src/pus/event_man.rs new file mode 100644 index 0000000..0a006e1 --- /dev/null +++ b/fsrc-core/src/pus/event_man.rs @@ -0,0 +1,79 @@ +use crate::events::Event; +use hashbrown::HashSet; + +#[cfg(feature = "heapless")] +pub use heapless_mod::*; + +/// This trait allows the PUS event manager implementation to stay generic over various types +/// of backend containers. These backend containers keep track on whether a particular event +/// is enabled or disabled for reporting and also expose a simple API to enable or disable the event +/// reporting. +/// +/// For example, a straight forward implementation for host systems could use a +/// [hash set](https://docs.rs/hashbrown/latest/hashbrown/struct.HashSet.html) +/// structure to track disabled events. A more primitive and embedded friendly +/// solution could track this information in a static or pre-allocated list which contains +/// the disabled events. +pub trait PusEventMgmtBackendProvider { + type Error; + + fn event_enabled(&self, event: &Event) -> bool; + fn enable_event_reporting(&mut self, event: &Event) -> Result; + fn disable_event_reporting(&mut self, event: &Event) -> Result; +} + +/// Default backend provider which uses a hash set as the event reporting status container +/// like mentioned in the example of the [PusEventMgmtBackendProvider] documentation. +/// +/// This provider is a good option for host systems or larger embedded systems where +/// the expected occasional memory allocation performed by the [HashSet] is not an issue. +#[derive(Default)] +pub struct DefaultPusMgmtBackendProvider { + disabled: HashSet, +} + +impl PusEventMgmtBackendProvider for DefaultPusMgmtBackendProvider { + type Error = (); + fn event_enabled(&self, event: &Event) -> bool { + !self.disabled.contains(event) + } + + fn enable_event_reporting(&mut self, event: &Event) -> Result { + Ok(self.disabled.remove(event)) + } + + fn disable_event_reporting(&mut self, event: &Event) -> Result { + Ok(self.disabled.insert(*event)) + } +} + +#[cfg(feature = "heapless")] +pub mod heapless_mod { + use super::*; + use crate::events::EventRaw; + + // TODO: After a new version of heapless is released which uses hash32 version 0.3, try using + // regular Event type again. + #[derive(Default)] + pub struct HeaplessPusMgmtBckendProvider { + disabled: heapless::FnvIndexSet, + } + + impl PusEventMgmtBackendProvider for HeaplessPusMgmtBckendProvider { + type Error = (); + + fn event_enabled(&self, event: &Event) -> bool { + self.disabled.contains(&event.raw()) + } + + fn enable_event_reporting(&mut self, event: &Event) -> Result { + self.disabled.insert(event.raw()).map_err(|_| ()) + } + + fn disable_event_reporting(&mut self, event: &Event) -> Result { + Ok(self.disabled.remove(&event.raw())) + } + } +} + +pub struct PusEventManager {} diff --git a/fsrc-core/src/pus/mod.rs b/fsrc-core/src/pus/mod.rs index 28e1c77..a09b398 100644 --- a/fsrc-core/src/pus/mod.rs +++ b/fsrc-core/src/pus/mod.rs @@ -10,6 +10,7 @@ use spacepackets::tm::PusTm; use spacepackets::{ByteConversionError, SizeMissmatch}; pub mod event; +pub mod event_man; pub mod verification; /// Generic error type which is also able to wrap a user send error with the user supplied type E. diff --git a/fsrc-core/tests/pool_test.rs b/fsrc-core/tests/pools.rs similarity index 100% rename from fsrc-core/tests/pool_test.rs rename to fsrc-core/tests/pools.rs diff --git a/fsrc-core/tests/pus_events.rs b/fsrc-core/tests/pus_events.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/fsrc-core/tests/pus_events.rs @@ -0,0 +1 @@ + diff --git a/fsrc-core/tests/verification_test.rs b/fsrc-core/tests/pus_verification.rs similarity index 100% rename from fsrc-core/tests/verification_test.rs rename to fsrc-core/tests/pus_verification.rs