Clonable Verification Reporter #24
7
Cargo.lock
generated
7
Cargo.lock
generated
@ -284,6 +284,12 @@ version = "1.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
|
checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dyn-clone"
|
||||||
|
version = "1.0.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4f94fa09c2aeea5b8839e414b7b841bf429fd25b9c522116ac97ee87856d88b2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "embed-doc-image"
|
name = "embed-doc-image"
|
||||||
version = "0.1.4"
|
version = "0.1.4"
|
||||||
@ -597,6 +603,7 @@ dependencies = [
|
|||||||
"crossbeam-channel",
|
"crossbeam-channel",
|
||||||
"delegate 0.8.0",
|
"delegate 0.8.0",
|
||||||
"downcast-rs",
|
"downcast-rs",
|
||||||
|
"dyn-clone",
|
||||||
"embed-doc-image",
|
"embed-doc-image",
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
"heapless",
|
"heapless",
|
||||||
|
@ -10,6 +10,7 @@ delegate = "0.8"
|
|||||||
hashbrown = "0.13"
|
hashbrown = "0.13"
|
||||||
heapless = "0.7"
|
heapless = "0.7"
|
||||||
paste = "1.0"
|
paste = "1.0"
|
||||||
|
dyn-clone = "1.0.9"
|
||||||
embed-doc-image = "0.1"
|
embed-doc-image = "0.1"
|
||||||
|
|
||||||
[dependencies.num-traits]
|
[dependencies.num-traits]
|
||||||
|
@ -29,4 +29,5 @@ pub mod params;
|
|||||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
|
||||||
pub mod pool;
|
pub mod pool;
|
||||||
pub mod pus;
|
pub mod pus;
|
||||||
|
pub mod seq_count;
|
||||||
pub mod tmtc;
|
pub mod tmtc;
|
||||||
|
@ -298,14 +298,14 @@ mod tests {
|
|||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
const EXAMPLE_EVENT_ID_1: u16 = 2;
|
const EXAMPLE_EVENT_ID_1: u16 = 2;
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq, Clone)]
|
||||||
struct TmInfo {
|
struct TmInfo {
|
||||||
pub common: CommonTmInfo,
|
pub common: CommonTmInfo,
|
||||||
pub event: EventU32,
|
pub event: EventU32,
|
||||||
pub aux_data: Vec<u8>,
|
pub aux_data: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default, Clone)]
|
||||||
struct TestSender {
|
struct TestSender {
|
||||||
pub service_queue: VecDeque<TmInfo>,
|
pub service_queue: VecDeque<TmInfo>,
|
||||||
}
|
}
|
||||||
|
@ -233,6 +233,7 @@ mod tests {
|
|||||||
const LOW_SEV_EVENT: EventU32 = EventU32::const_new(Severity::LOW, 1, 5);
|
const LOW_SEV_EVENT: EventU32 = EventU32::const_new(Severity::LOW, 1, 5);
|
||||||
const EMPTY_STAMP: [u8; 7] = [0; 7];
|
const EMPTY_STAMP: [u8; 7] = [0; 7];
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
struct EventTmSender {
|
struct EventTmSender {
|
||||||
sender: std::sync::mpsc::Sender<Vec<u8>>,
|
sender: std::sync::mpsc::Sender<Vec<u8>>,
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
//!
|
//!
|
||||||
//! 1. PUS Verification Service 1 module inside [verification]. Requires [alloc] support.
|
//! 1. PUS Verification Service 1 module inside [verification]. Requires [alloc] support.
|
||||||
use downcast_rs::{impl_downcast, Downcast};
|
use downcast_rs::{impl_downcast, Downcast};
|
||||||
|
use dyn_clone::DynClone;
|
||||||
use spacepackets::ecss::PusError;
|
use spacepackets::ecss::PusError;
|
||||||
use spacepackets::time::TimestampError;
|
use spacepackets::time::TimestampError;
|
||||||
use spacepackets::tm::PusTm;
|
use spacepackets::tm::PusTm;
|
||||||
@ -43,13 +44,14 @@ impl<E> From<ByteConversionError> for EcssTmError<E> {
|
|||||||
/// This sender object is responsible for sending telemetry to a TM sink. The [Downcast] trait
|
/// 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
|
/// is implemented to allow passing the sender as a boxed trait object and still retrieve the
|
||||||
/// concrete type at a later point.
|
/// concrete type at a later point.
|
||||||
pub trait EcssTmSender: Downcast + Send {
|
pub trait EcssTmSender: Downcast + Send + DynClone {
|
||||||
type Error;
|
type Error;
|
||||||
|
|
||||||
fn send_tm(&mut self, tm: PusTm) -> Result<(), EcssTmError<Self::Error>>;
|
fn send_tm(&mut self, tm: PusTm) -> Result<(), EcssTmError<Self::Error>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_downcast!(EcssTmSender assoc Error);
|
impl_downcast!(EcssTmSender assoc Error);
|
||||||
|
dyn_clone::clone_trait_object!(<T> EcssTmSender<Error=T>);
|
||||||
|
|
||||||
pub(crate) fn source_buffer_large_enough<E>(cap: usize, len: usize) -> Result<(), EcssTmError<E>> {
|
pub(crate) fn source_buffer_large_enough<E>(cap: usize, len: usize) -> Result<(), EcssTmError<E>> {
|
||||||
if len > cap {
|
if len > cap {
|
||||||
@ -68,7 +70,7 @@ pub(crate) mod tests {
|
|||||||
use spacepackets::tm::{PusTm, PusTmSecondaryHeaderT};
|
use spacepackets::tm::{PusTm, PusTmSecondaryHeaderT};
|
||||||
use spacepackets::CcsdsPacket;
|
use spacepackets::CcsdsPacket;
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq, Clone)]
|
||||||
pub(crate) struct CommonTmInfo {
|
pub(crate) struct CommonTmInfo {
|
||||||
pub subservice: u8,
|
pub subservice: u8,
|
||||||
pub apid: u16,
|
pub apid: u16,
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
//! use std::time::Duration;
|
//! use std::time::Duration;
|
||||||
//! use satrs_core::pool::{LocalPool, PoolCfg, PoolProvider, SharedPool};
|
//! use satrs_core::pool::{LocalPool, PoolCfg, PoolProvider, SharedPool};
|
||||||
//! use satrs_core::pus::verification::{CrossbeamVerifSender, VerificationReporterCfg, VerificationReporterWithSender};
|
//! use satrs_core::pus::verification::{CrossbeamVerifSender, VerificationReporterCfg, VerificationReporterWithSender};
|
||||||
|
//! use satrs_core::seq_count::SimpleSeqCountProvider;
|
||||||
//! use spacepackets::ecss::PusPacket;
|
//! use spacepackets::ecss::PusPacket;
|
||||||
//! use spacepackets::SpHeader;
|
//! use spacepackets::SpHeader;
|
||||||
//! use spacepackets::tc::{PusTc, PusTcSecondaryHeader};
|
//! use spacepackets::tc::{PusTc, PusTcSecondaryHeader};
|
||||||
@ -29,8 +30,8 @@
|
|||||||
//! let shared_tm_pool: SharedPool = Arc::new(RwLock::new(Box::new(LocalPool::new(pool_cfg.clone()))));
|
//! 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 (verif_tx, verif_rx) = crossbeam_channel::bounded(10);
|
||||||
//! let sender = CrossbeamVerifSender::new(shared_tm_pool.clone(), verif_tx);
|
//! let sender = CrossbeamVerifSender::new(shared_tm_pool.clone(), verif_tx);
|
||||||
//! let cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8).unwrap();
|
//! let cfg = VerificationReporterCfg::new(TEST_APID, Box::new(SimpleSeqCountProvider::default()), 1, 2, 8).unwrap();
|
||||||
//! let mut reporter = VerificationReporterWithSender::new(cfg , Box::new(sender));
|
//! let mut reporter = VerificationReporterWithSender::new(&cfg , Box::new(sender));
|
||||||
//!
|
//!
|
||||||
//! let mut sph = SpHeader::tc(TEST_APID, 0, 0).unwrap();
|
//! let mut sph = SpHeader::tc(TEST_APID, 0, 0).unwrap();
|
||||||
//! let tc_header = PusTcSecondaryHeader::new_simple(17, 1);
|
//! let tc_header = PusTcSecondaryHeader::new_simple(17, 1);
|
||||||
@ -83,9 +84,14 @@ use spacepackets::tm::{PusTm, PusTmSecondaryHeader};
|
|||||||
use spacepackets::{CcsdsPacket, PacketId, PacketSequenceCtrl};
|
use spacepackets::{CcsdsPacket, PacketId, PacketSequenceCtrl};
|
||||||
use spacepackets::{SpHeader, MAX_APID};
|
use spacepackets::{SpHeader, MAX_APID};
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
pub use crate::seq_count::SimpleSeqCountProvider;
|
||||||
pub use allocmod::{VerificationReporter, VerificationReporterCfg, VerificationReporterWithSender};
|
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
pub use allocmod::{
|
||||||
|
VerificationReporterCfg, VerificationReporterWithBuf, VerificationReporterWithSender,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::seq_count::SequenceCountProvider;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub use stdmod::{
|
pub use stdmod::{
|
||||||
CrossbeamVerifSender, MpscVerifSender, SharedStdVerifReporterWithSender,
|
CrossbeamVerifSender, MpscVerifSender, SharedStdVerifReporterWithSender,
|
||||||
@ -276,10 +282,10 @@ impl<'a> FailParamsWithStep<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct VerificationReporterBasic {
|
pub struct VerificationReporterBasic {
|
||||||
pub dest_id: u16,
|
pub dest_id: u16,
|
||||||
apid: u16,
|
apid: u16,
|
||||||
msg_count: u16,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VerificationReporterBasic {
|
impl VerificationReporterBasic {
|
||||||
@ -287,11 +293,7 @@ impl VerificationReporterBasic {
|
|||||||
if apid > MAX_APID {
|
if apid > MAX_APID {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
Some(Self {
|
Some(Self { apid, dest_id: 0 })
|
||||||
apid,
|
|
||||||
msg_count: 0,
|
|
||||||
dest_id: 0,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_apid(&mut self, apid: u16) -> bool {
|
pub fn set_apid(&mut self, apid: u16) -> bool {
|
||||||
@ -332,6 +334,7 @@ impl VerificationReporterBasic {
|
|||||||
buf: &mut [u8],
|
buf: &mut [u8],
|
||||||
token: VerificationToken<TcStateNone>,
|
token: VerificationToken<TcStateNone>,
|
||||||
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
|
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
|
||||||
|
seq_counter: &mut (impl SequenceCountProvider<u16> + ?Sized),
|
||||||
time_stamp: &[u8],
|
time_stamp: &[u8],
|
||||||
) -> Result<VerificationToken<TcStateAccepted>, VerificationErrorWithToken<E, TcStateNone>>
|
) -> Result<VerificationToken<TcStateAccepted>, VerificationErrorWithToken<E, TcStateNone>>
|
||||||
{
|
{
|
||||||
@ -339,6 +342,7 @@ impl VerificationReporterBasic {
|
|||||||
.create_pus_verif_success_tm(
|
.create_pus_verif_success_tm(
|
||||||
buf,
|
buf,
|
||||||
Subservices::TmAcceptanceSuccess.into(),
|
Subservices::TmAcceptanceSuccess.into(),
|
||||||
|
seq_counter.get(),
|
||||||
&token.req_id,
|
&token.req_id,
|
||||||
time_stamp,
|
time_stamp,
|
||||||
None::<&dyn EcssEnumeration>,
|
None::<&dyn EcssEnumeration>,
|
||||||
@ -347,7 +351,8 @@ impl VerificationReporterBasic {
|
|||||||
sender
|
sender
|
||||||
.send_tm(tm)
|
.send_tm(tm)
|
||||||
.map_err(|e| VerificationErrorWithToken(e, token))?;
|
.map_err(|e| VerificationErrorWithToken(e, token))?;
|
||||||
self.msg_count += 1;
|
seq_counter.increment();
|
||||||
|
//seq_counter.get_and_increment()
|
||||||
Ok(VerificationToken {
|
Ok(VerificationToken {
|
||||||
state: PhantomData,
|
state: PhantomData,
|
||||||
req_id: token.req_id,
|
req_id: token.req_id,
|
||||||
@ -360,12 +365,14 @@ impl VerificationReporterBasic {
|
|||||||
buf: &mut [u8],
|
buf: &mut [u8],
|
||||||
token: VerificationToken<TcStateNone>,
|
token: VerificationToken<TcStateNone>,
|
||||||
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
|
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
|
||||||
|
seq_counter: &mut (impl SequenceCountProvider<u16> + ?Sized),
|
||||||
params: FailParams,
|
params: FailParams,
|
||||||
) -> Result<(), VerificationErrorWithToken<E, TcStateNone>> {
|
) -> Result<(), VerificationErrorWithToken<E, TcStateNone>> {
|
||||||
let tm = self
|
let tm = self
|
||||||
.create_pus_verif_fail_tm(
|
.create_pus_verif_fail_tm(
|
||||||
buf,
|
buf,
|
||||||
Subservices::TmAcceptanceFailure.into(),
|
Subservices::TmAcceptanceFailure.into(),
|
||||||
|
seq_counter.get(),
|
||||||
&token.req_id,
|
&token.req_id,
|
||||||
None::<&dyn EcssEnumeration>,
|
None::<&dyn EcssEnumeration>,
|
||||||
¶ms,
|
¶ms,
|
||||||
@ -374,7 +381,7 @@ impl VerificationReporterBasic {
|
|||||||
sender
|
sender
|
||||||
.send_tm(tm)
|
.send_tm(tm)
|
||||||
.map_err(|e| VerificationErrorWithToken(e, token))?;
|
.map_err(|e| VerificationErrorWithToken(e, token))?;
|
||||||
self.msg_count += 1;
|
seq_counter.increment();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -386,6 +393,7 @@ impl VerificationReporterBasic {
|
|||||||
buf: &mut [u8],
|
buf: &mut [u8],
|
||||||
token: VerificationToken<TcStateAccepted>,
|
token: VerificationToken<TcStateAccepted>,
|
||||||
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
|
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
|
||||||
|
seq_counter: &mut (impl SequenceCountProvider<u16> + ?Sized),
|
||||||
time_stamp: &[u8],
|
time_stamp: &[u8],
|
||||||
) -> Result<VerificationToken<TcStateStarted>, VerificationErrorWithToken<E, TcStateAccepted>>
|
) -> Result<VerificationToken<TcStateStarted>, VerificationErrorWithToken<E, TcStateAccepted>>
|
||||||
{
|
{
|
||||||
@ -393,6 +401,7 @@ impl VerificationReporterBasic {
|
|||||||
.create_pus_verif_success_tm(
|
.create_pus_verif_success_tm(
|
||||||
buf,
|
buf,
|
||||||
Subservices::TmStartSuccess.into(),
|
Subservices::TmStartSuccess.into(),
|
||||||
|
seq_counter.get(),
|
||||||
&token.req_id,
|
&token.req_id,
|
||||||
time_stamp,
|
time_stamp,
|
||||||
None::<&dyn EcssEnumeration>,
|
None::<&dyn EcssEnumeration>,
|
||||||
@ -401,7 +410,7 @@ impl VerificationReporterBasic {
|
|||||||
sender
|
sender
|
||||||
.send_tm(tm)
|
.send_tm(tm)
|
||||||
.map_err(|e| VerificationErrorWithToken(e, token))?;
|
.map_err(|e| VerificationErrorWithToken(e, token))?;
|
||||||
self.msg_count += 1;
|
seq_counter.increment();
|
||||||
Ok(VerificationToken {
|
Ok(VerificationToken {
|
||||||
state: PhantomData,
|
state: PhantomData,
|
||||||
req_id: token.req_id,
|
req_id: token.req_id,
|
||||||
@ -417,12 +426,14 @@ impl VerificationReporterBasic {
|
|||||||
buf: &mut [u8],
|
buf: &mut [u8],
|
||||||
token: VerificationToken<TcStateAccepted>,
|
token: VerificationToken<TcStateAccepted>,
|
||||||
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
|
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
|
||||||
|
seq_counter: &mut (impl SequenceCountProvider<u16> + ?Sized),
|
||||||
params: FailParams,
|
params: FailParams,
|
||||||
) -> Result<(), VerificationErrorWithToken<E, TcStateAccepted>> {
|
) -> Result<(), VerificationErrorWithToken<E, TcStateAccepted>> {
|
||||||
let tm = self
|
let tm = self
|
||||||
.create_pus_verif_fail_tm(
|
.create_pus_verif_fail_tm(
|
||||||
buf,
|
buf,
|
||||||
Subservices::TmStartFailure.into(),
|
Subservices::TmStartFailure.into(),
|
||||||
|
seq_counter.get(),
|
||||||
&token.req_id,
|
&token.req_id,
|
||||||
None::<&dyn EcssEnumeration>,
|
None::<&dyn EcssEnumeration>,
|
||||||
¶ms,
|
¶ms,
|
||||||
@ -431,7 +442,7 @@ impl VerificationReporterBasic {
|
|||||||
sender
|
sender
|
||||||
.send_tm(tm)
|
.send_tm(tm)
|
||||||
.map_err(|e| VerificationErrorWithToken(e, token))?;
|
.map_err(|e| VerificationErrorWithToken(e, token))?;
|
||||||
self.msg_count += 1;
|
seq_counter.increment();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -443,18 +454,20 @@ impl VerificationReporterBasic {
|
|||||||
buf: &mut [u8],
|
buf: &mut [u8],
|
||||||
token: &VerificationToken<TcStateStarted>,
|
token: &VerificationToken<TcStateStarted>,
|
||||||
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
|
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
|
||||||
|
seq_counter: &mut (impl SequenceCountProvider<u16> + ?Sized),
|
||||||
time_stamp: &[u8],
|
time_stamp: &[u8],
|
||||||
step: impl EcssEnumeration,
|
step: impl EcssEnumeration,
|
||||||
) -> Result<(), EcssTmError<E>> {
|
) -> Result<(), EcssTmError<E>> {
|
||||||
let tm = self.create_pus_verif_success_tm(
|
let tm = self.create_pus_verif_success_tm(
|
||||||
buf,
|
buf,
|
||||||
Subservices::TmStepSuccess.into(),
|
Subservices::TmStepSuccess.into(),
|
||||||
|
seq_counter.get(),
|
||||||
&token.req_id,
|
&token.req_id,
|
||||||
time_stamp,
|
time_stamp,
|
||||||
Some(&step),
|
Some(&step),
|
||||||
)?;
|
)?;
|
||||||
sender.send_tm(tm)?;
|
sender.send_tm(tm)?;
|
||||||
self.msg_count += 1;
|
seq_counter.increment();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -467,12 +480,14 @@ impl VerificationReporterBasic {
|
|||||||
buf: &mut [u8],
|
buf: &mut [u8],
|
||||||
token: VerificationToken<TcStateStarted>,
|
token: VerificationToken<TcStateStarted>,
|
||||||
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
|
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
|
||||||
|
seq_counter: &mut (impl SequenceCountProvider<u16> + ?Sized),
|
||||||
params: FailParamsWithStep,
|
params: FailParamsWithStep,
|
||||||
) -> Result<(), VerificationErrorWithToken<E, TcStateStarted>> {
|
) -> Result<(), VerificationErrorWithToken<E, TcStateStarted>> {
|
||||||
let tm = self
|
let tm = self
|
||||||
.create_pus_verif_fail_tm(
|
.create_pus_verif_fail_tm(
|
||||||
buf,
|
buf,
|
||||||
Subservices::TmStepFailure.into(),
|
Subservices::TmStepFailure.into(),
|
||||||
|
seq_counter.get(),
|
||||||
&token.req_id,
|
&token.req_id,
|
||||||
Some(params.step),
|
Some(params.step),
|
||||||
¶ms.bp,
|
¶ms.bp,
|
||||||
@ -481,7 +496,7 @@ impl VerificationReporterBasic {
|
|||||||
sender
|
sender
|
||||||
.send_tm(tm)
|
.send_tm(tm)
|
||||||
.map_err(|e| VerificationErrorWithToken(e, token))?;
|
.map_err(|e| VerificationErrorWithToken(e, token))?;
|
||||||
self.msg_count += 1;
|
seq_counter.increment();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -494,12 +509,14 @@ impl VerificationReporterBasic {
|
|||||||
buf: &mut [u8],
|
buf: &mut [u8],
|
||||||
token: VerificationToken<TcStateStarted>,
|
token: VerificationToken<TcStateStarted>,
|
||||||
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
|
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
|
||||||
|
seq_counter: &mut (impl SequenceCountProvider<u16> + ?Sized),
|
||||||
time_stamp: &[u8],
|
time_stamp: &[u8],
|
||||||
) -> Result<(), VerificationErrorWithToken<E, TcStateStarted>> {
|
) -> Result<(), VerificationErrorWithToken<E, TcStateStarted>> {
|
||||||
let tm = self
|
let tm = self
|
||||||
.create_pus_verif_success_tm(
|
.create_pus_verif_success_tm(
|
||||||
buf,
|
buf,
|
||||||
Subservices::TmCompletionSuccess.into(),
|
Subservices::TmCompletionSuccess.into(),
|
||||||
|
seq_counter.get(),
|
||||||
&token.req_id,
|
&token.req_id,
|
||||||
time_stamp,
|
time_stamp,
|
||||||
None::<&dyn EcssEnumeration>,
|
None::<&dyn EcssEnumeration>,
|
||||||
@ -508,7 +525,7 @@ impl VerificationReporterBasic {
|
|||||||
sender
|
sender
|
||||||
.send_tm(tm)
|
.send_tm(tm)
|
||||||
.map_err(|e| VerificationErrorWithToken(e, token))?;
|
.map_err(|e| VerificationErrorWithToken(e, token))?;
|
||||||
self.msg_count += 1;
|
seq_counter.increment();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -521,12 +538,14 @@ impl VerificationReporterBasic {
|
|||||||
buf: &mut [u8],
|
buf: &mut [u8],
|
||||||
token: VerificationToken<TcStateStarted>,
|
token: VerificationToken<TcStateStarted>,
|
||||||
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
|
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
|
||||||
|
seq_counter: &mut (impl SequenceCountProvider<u16> + ?Sized),
|
||||||
params: FailParams,
|
params: FailParams,
|
||||||
) -> Result<(), VerificationErrorWithToken<E, TcStateStarted>> {
|
) -> Result<(), VerificationErrorWithToken<E, TcStateStarted>> {
|
||||||
let tm = self
|
let tm = self
|
||||||
.create_pus_verif_fail_tm(
|
.create_pus_verif_fail_tm(
|
||||||
buf,
|
buf,
|
||||||
Subservices::TmCompletionFailure.into(),
|
Subservices::TmCompletionFailure.into(),
|
||||||
|
seq_counter.get(),
|
||||||
&token.req_id,
|
&token.req_id,
|
||||||
None::<&dyn EcssEnumeration>,
|
None::<&dyn EcssEnumeration>,
|
||||||
¶ms,
|
¶ms,
|
||||||
@ -535,7 +554,7 @@ impl VerificationReporterBasic {
|
|||||||
sender
|
sender
|
||||||
.send_tm(tm)
|
.send_tm(tm)
|
||||||
.map_err(|e| VerificationErrorWithToken(e, token))?;
|
.map_err(|e| VerificationErrorWithToken(e, token))?;
|
||||||
self.msg_count += 1;
|
seq_counter.increment();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -543,6 +562,7 @@ impl VerificationReporterBasic {
|
|||||||
&'a mut self,
|
&'a mut self,
|
||||||
buf: &'a mut [u8],
|
buf: &'a mut [u8],
|
||||||
subservice: u8,
|
subservice: u8,
|
||||||
|
msg_counter: u16,
|
||||||
req_id: &RequestId,
|
req_id: &RequestId,
|
||||||
time_stamp: &'a [u8],
|
time_stamp: &'a [u8],
|
||||||
step: Option<&(impl EcssEnumeration + ?Sized)>,
|
step: Option<&(impl EcssEnumeration + ?Sized)>,
|
||||||
@ -564,6 +584,7 @@ impl VerificationReporterBasic {
|
|||||||
Ok(self.create_pus_verif_tm_base(
|
Ok(self.create_pus_verif_tm_base(
|
||||||
buf,
|
buf,
|
||||||
subservice,
|
subservice,
|
||||||
|
msg_counter,
|
||||||
&mut sp_header,
|
&mut sp_header,
|
||||||
time_stamp,
|
time_stamp,
|
||||||
source_data_len,
|
source_data_len,
|
||||||
@ -574,6 +595,7 @@ impl VerificationReporterBasic {
|
|||||||
&'a mut self,
|
&'a mut self,
|
||||||
buf: &'a mut [u8],
|
buf: &'a mut [u8],
|
||||||
subservice: u8,
|
subservice: u8,
|
||||||
|
msg_counter: u16,
|
||||||
req_id: &RequestId,
|
req_id: &RequestId,
|
||||||
step: Option<&(impl EcssEnumeration + ?Sized)>,
|
step: Option<&(impl EcssEnumeration + ?Sized)>,
|
||||||
params: &'a FailParams,
|
params: &'a FailParams,
|
||||||
@ -607,6 +629,7 @@ impl VerificationReporterBasic {
|
|||||||
Ok(self.create_pus_verif_tm_base(
|
Ok(self.create_pus_verif_tm_base(
|
||||||
buf,
|
buf,
|
||||||
subservice,
|
subservice,
|
||||||
|
msg_counter,
|
||||||
&mut sp_header,
|
&mut sp_header,
|
||||||
params.time_stamp,
|
params.time_stamp,
|
||||||
source_data_len,
|
source_data_len,
|
||||||
@ -617,12 +640,13 @@ impl VerificationReporterBasic {
|
|||||||
&'a mut self,
|
&'a mut self,
|
||||||
buf: &'a mut [u8],
|
buf: &'a mut [u8],
|
||||||
subservice: u8,
|
subservice: u8,
|
||||||
|
msg_counter: u16,
|
||||||
sp_header: &mut SpHeader,
|
sp_header: &mut SpHeader,
|
||||||
time_stamp: &'a [u8],
|
time_stamp: &'a [u8],
|
||||||
source_data_len: usize,
|
source_data_len: usize,
|
||||||
) -> PusTm {
|
) -> PusTm {
|
||||||
let tm_sec_header =
|
let tm_sec_header =
|
||||||
PusTmSecondaryHeader::new(1, subservice, self.msg_count, self.dest_id, time_stamp);
|
PusTmSecondaryHeader::new(1, subservice, msg_counter, self.dest_id, time_stamp);
|
||||||
PusTm::new(
|
PusTm::new(
|
||||||
sp_header,
|
sp_header,
|
||||||
tm_sec_header,
|
tm_sec_header,
|
||||||
@ -639,8 +663,10 @@ mod allocmod {
|
|||||||
use alloc::vec;
|
use alloc::vec;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct VerificationReporterCfg {
|
pub struct VerificationReporterCfg {
|
||||||
apid: u16,
|
apid: u16,
|
||||||
|
seq_counter: Box<dyn SequenceCountProvider<u16> + Send>,
|
||||||
pub step_field_width: usize,
|
pub step_field_width: usize,
|
||||||
pub fail_code_field_width: usize,
|
pub fail_code_field_width: usize,
|
||||||
pub max_fail_data_len: usize,
|
pub max_fail_data_len: usize,
|
||||||
@ -649,6 +675,7 @@ mod allocmod {
|
|||||||
impl VerificationReporterCfg {
|
impl VerificationReporterCfg {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
apid: u16,
|
apid: u16,
|
||||||
|
seq_counter: Box<dyn SequenceCountProvider<u16> + Send>,
|
||||||
step_field_width: usize,
|
step_field_width: usize,
|
||||||
fail_code_field_width: usize,
|
fail_code_field_width: usize,
|
||||||
max_fail_data_len: usize,
|
max_fail_data_len: usize,
|
||||||
@ -658,6 +685,7 @@ mod allocmod {
|
|||||||
}
|
}
|
||||||
Some(Self {
|
Some(Self {
|
||||||
apid,
|
apid,
|
||||||
|
seq_counter,
|
||||||
step_field_width,
|
step_field_width,
|
||||||
fail_code_field_width,
|
fail_code_field_width,
|
||||||
max_fail_data_len,
|
max_fail_data_len,
|
||||||
@ -667,13 +695,15 @@ mod allocmod {
|
|||||||
|
|
||||||
/// Primary verification handler. It provides an API to send PUS 1 verification telemetry packets
|
/// 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.
|
/// and verify the various steps of telecommand handling as specified in the PUS standard.
|
||||||
pub struct VerificationReporter {
|
#[derive(Clone)]
|
||||||
|
pub struct VerificationReporterWithBuf {
|
||||||
source_data_buf: Vec<u8>,
|
source_data_buf: Vec<u8>,
|
||||||
|
seq_counter: Box<dyn SequenceCountProvider<u16> + Send + 'static>,
|
||||||
pub reporter: VerificationReporterBasic,
|
pub reporter: VerificationReporterBasic,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VerificationReporter {
|
impl VerificationReporterWithBuf {
|
||||||
pub fn new(cfg: VerificationReporterCfg) -> Self {
|
pub fn new(cfg: &VerificationReporterCfg) -> Self {
|
||||||
let reporter = VerificationReporterBasic::new(cfg.apid).unwrap();
|
let reporter = VerificationReporterBasic::new(cfg.apid).unwrap();
|
||||||
Self {
|
Self {
|
||||||
source_data_buf: vec![
|
source_data_buf: vec![
|
||||||
@ -683,6 +713,7 @@ mod allocmod {
|
|||||||
+ cfg.fail_code_field_width as usize
|
+ cfg.fail_code_field_width as usize
|
||||||
+ cfg.max_fail_data_len
|
+ cfg.max_fail_data_len
|
||||||
],
|
],
|
||||||
|
seq_counter: cfg.seq_counter.clone(),
|
||||||
reporter,
|
reporter,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -714,6 +745,7 @@ mod allocmod {
|
|||||||
self.source_data_buf.as_mut_slice(),
|
self.source_data_buf.as_mut_slice(),
|
||||||
token,
|
token,
|
||||||
sender,
|
sender,
|
||||||
|
self.seq_counter.as_mut(),
|
||||||
time_stamp,
|
time_stamp,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -729,6 +761,7 @@ mod allocmod {
|
|||||||
self.source_data_buf.as_mut_slice(),
|
self.source_data_buf.as_mut_slice(),
|
||||||
token,
|
token,
|
||||||
sender,
|
sender,
|
||||||
|
self.seq_counter.as_mut(),
|
||||||
params,
|
params,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -747,6 +780,7 @@ mod allocmod {
|
|||||||
self.source_data_buf.as_mut_slice(),
|
self.source_data_buf.as_mut_slice(),
|
||||||
token,
|
token,
|
||||||
sender,
|
sender,
|
||||||
|
self.seq_counter.as_mut(),
|
||||||
time_stamp,
|
time_stamp,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -761,8 +795,13 @@ mod allocmod {
|
|||||||
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
|
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
|
||||||
params: FailParams,
|
params: FailParams,
|
||||||
) -> Result<(), VerificationErrorWithToken<E, TcStateAccepted>> {
|
) -> Result<(), VerificationErrorWithToken<E, TcStateAccepted>> {
|
||||||
self.reporter
|
self.reporter.start_failure(
|
||||||
.start_failure(self.source_data_buf.as_mut_slice(), token, sender, params)
|
self.source_data_buf.as_mut_slice(),
|
||||||
|
token,
|
||||||
|
sender,
|
||||||
|
self.seq_counter.as_mut(),
|
||||||
|
params,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Package and send a PUS TM\[1, 5\] packet, see 8.1.2.5 of the PUS standard.
|
/// Package and send a PUS TM\[1, 5\] packet, see 8.1.2.5 of the PUS standard.
|
||||||
@ -779,6 +818,7 @@ mod allocmod {
|
|||||||
self.source_data_buf.as_mut_slice(),
|
self.source_data_buf.as_mut_slice(),
|
||||||
token,
|
token,
|
||||||
sender,
|
sender,
|
||||||
|
self.seq_counter.as_mut(),
|
||||||
time_stamp,
|
time_stamp,
|
||||||
step,
|
step,
|
||||||
)
|
)
|
||||||
@ -794,8 +834,13 @@ mod allocmod {
|
|||||||
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
|
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
|
||||||
params: FailParamsWithStep,
|
params: FailParamsWithStep,
|
||||||
) -> Result<(), VerificationErrorWithToken<E, TcStateStarted>> {
|
) -> Result<(), VerificationErrorWithToken<E, TcStateStarted>> {
|
||||||
self.reporter
|
self.reporter.step_failure(
|
||||||
.step_failure(self.source_data_buf.as_mut_slice(), token, sender, params)
|
self.source_data_buf.as_mut_slice(),
|
||||||
|
token,
|
||||||
|
sender,
|
||||||
|
self.seq_counter.as_mut(),
|
||||||
|
params,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Package and send a PUS TM\[1, 7\] packet, see 8.1.2.7 of the PUS standard.
|
/// Package and send a PUS TM\[1, 7\] packet, see 8.1.2.7 of the PUS standard.
|
||||||
@ -812,6 +857,7 @@ mod allocmod {
|
|||||||
self.source_data_buf.as_mut_slice(),
|
self.source_data_buf.as_mut_slice(),
|
||||||
token,
|
token,
|
||||||
sender,
|
sender,
|
||||||
|
self.seq_counter.as_mut(),
|
||||||
time_stamp,
|
time_stamp,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -830,6 +876,7 @@ mod allocmod {
|
|||||||
self.source_data_buf.as_mut_slice(),
|
self.source_data_buf.as_mut_slice(),
|
||||||
token,
|
token,
|
||||||
sender,
|
sender,
|
||||||
|
self.seq_counter.as_mut(),
|
||||||
params,
|
params,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -837,19 +884,23 @@ mod allocmod {
|
|||||||
|
|
||||||
/// Helper object which caches the sender passed as a trait object. Provides the same
|
/// Helper object which caches the sender passed as a trait object. Provides the same
|
||||||
/// API as [VerificationReporter] but without the explicit sender arguments.
|
/// API as [VerificationReporter] but without the explicit sender arguments.
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct VerificationReporterWithSender<E> {
|
pub struct VerificationReporterWithSender<E> {
|
||||||
pub reporter: VerificationReporter,
|
pub reporter: VerificationReporterWithBuf,
|
||||||
pub sender: Box<dyn EcssTmSender<Error = E>>,
|
pub sender: Box<dyn EcssTmSender<Error = E>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: 'static> VerificationReporterWithSender<E> {
|
impl<E: 'static> VerificationReporterWithSender<E> {
|
||||||
pub fn new(cfg: VerificationReporterCfg, sender: Box<dyn EcssTmSender<Error = E>>) -> Self {
|
pub fn new(
|
||||||
let reporter = VerificationReporter::new(cfg);
|
cfg: &VerificationReporterCfg,
|
||||||
|
sender: Box<dyn EcssTmSender<Error = E>>,
|
||||||
|
) -> Self {
|
||||||
|
let reporter = VerificationReporterWithBuf::new(cfg);
|
||||||
Self::new_from_reporter(reporter, sender)
|
Self::new_from_reporter(reporter, sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_from_reporter(
|
pub fn new_from_reporter(
|
||||||
reporter: VerificationReporter,
|
reporter: VerificationReporterWithBuf,
|
||||||
sender: Box<dyn EcssTmSender<Error = E>>,
|
sender: Box<dyn EcssTmSender<Error = E>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self { reporter, sender }
|
Self { reporter, sender }
|
||||||
@ -955,7 +1006,7 @@ mod stdmod {
|
|||||||
pub type StdVerifReporterWithSender = VerificationReporterWithSender<StdVerifSenderError>;
|
pub type StdVerifReporterWithSender = VerificationReporterWithSender<StdVerifSenderError>;
|
||||||
pub type SharedStdVerifReporterWithSender = Arc<Mutex<StdVerifReporterWithSender>>;
|
pub type SharedStdVerifReporterWithSender = Arc<Mutex<StdVerifReporterWithSender>>;
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq, Clone)]
|
||||||
pub enum StdVerifSenderError {
|
pub enum StdVerifSenderError {
|
||||||
PoisonError,
|
PoisonError,
|
||||||
StoreError(StoreError),
|
StoreError(StoreError),
|
||||||
@ -978,6 +1029,7 @@ mod stdmod {
|
|||||||
fn send(&self, addr: StoreAddr) -> Result<(), StoreAddr>;
|
fn send(&self, addr: StoreAddr) -> Result<(), StoreAddr>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
struct StdSenderBase<S> {
|
struct StdSenderBase<S> {
|
||||||
pub ignore_poison_error: bool,
|
pub ignore_poison_error: bool,
|
||||||
tm_store: SharedPool,
|
tm_store: SharedPool,
|
||||||
@ -1003,6 +1055,7 @@ mod stdmod {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct MpscVerifSender {
|
pub struct MpscVerifSender {
|
||||||
base: StdSenderBase<mpsc::Sender<StoreAddr>>,
|
base: StdSenderBase<mpsc::Sender<StoreAddr>>,
|
||||||
}
|
}
|
||||||
@ -1038,6 +1091,7 @@ mod stdmod {
|
|||||||
|
|
||||||
/// Verification sender with a [crossbeam_channel::Sender] backend.
|
/// Verification sender with a [crossbeam_channel::Sender] backend.
|
||||||
/// It implements the [EcssTmSender] trait to be used as PUS Verification TM sender
|
/// It implements the [EcssTmSender] trait to be used as PUS Verification TM sender
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct CrossbeamVerifSender {
|
pub struct CrossbeamVerifSender {
|
||||||
base: StdSenderBase<crossbeam_channel::Sender<StoreAddr>>,
|
base: StdSenderBase<crossbeam_channel::Sender<StoreAddr>>,
|
||||||
}
|
}
|
||||||
@ -1064,7 +1118,7 @@ mod stdmod {
|
|||||||
unsafe impl Sync for CrossbeamVerifSender {}
|
unsafe impl Sync for CrossbeamVerifSender {}
|
||||||
unsafe impl Send for CrossbeamVerifSender {}
|
unsafe impl Send for CrossbeamVerifSender {}
|
||||||
|
|
||||||
impl<S: SendBackend + 'static> EcssTmSender for StdSenderBase<S> {
|
impl<S: SendBackend + Clone + 'static> EcssTmSender for StdSenderBase<S> {
|
||||||
type Error = StdVerifSenderError;
|
type Error = StdVerifSenderError;
|
||||||
fn send_tm(&mut self, tm: PusTm) -> Result<(), EcssTmError<Self::Error>> {
|
fn send_tm(&mut self, tm: PusTm) -> Result<(), EcssTmError<Self::Error>> {
|
||||||
let operation = |mut mg: RwLockWriteGuard<ShareablePoolProvider>| {
|
let operation = |mut mg: RwLockWriteGuard<ShareablePoolProvider>| {
|
||||||
@ -1095,9 +1149,10 @@ mod tests {
|
|||||||
use crate::pus::tests::CommonTmInfo;
|
use crate::pus::tests::CommonTmInfo;
|
||||||
use crate::pus::verification::{
|
use crate::pus::verification::{
|
||||||
EcssTmError, EcssTmSender, FailParams, FailParamsWithStep, RequestId, TcStateNone,
|
EcssTmError, EcssTmSender, FailParams, FailParamsWithStep, RequestId, TcStateNone,
|
||||||
VerificationReporter, VerificationReporterCfg, VerificationReporterWithSender,
|
VerificationReporterCfg, VerificationReporterWithBuf, VerificationReporterWithSender,
|
||||||
VerificationToken,
|
VerificationToken,
|
||||||
};
|
};
|
||||||
|
use crate::seq_count::SimpleSeqCountProvider;
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use alloc::format;
|
use alloc::format;
|
||||||
use spacepackets::ecss::{EcssEnumU16, EcssEnumU32, EcssEnumU8, EcssEnumeration, PusPacket};
|
use spacepackets::ecss::{EcssEnumU16, EcssEnumU32, EcssEnumU8, EcssEnumeration, PusPacket};
|
||||||
@ -1110,14 +1165,14 @@ mod tests {
|
|||||||
const TEST_APID: u16 = 0x02;
|
const TEST_APID: u16 = 0x02;
|
||||||
const EMPTY_STAMP: [u8; 7] = [0; 7];
|
const EMPTY_STAMP: [u8; 7] = [0; 7];
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq, Clone)]
|
||||||
struct TmInfo {
|
struct TmInfo {
|
||||||
pub common: CommonTmInfo,
|
pub common: CommonTmInfo,
|
||||||
pub req_id: RequestId,
|
pub req_id: RequestId,
|
||||||
pub additional_data: Option<Vec<u8>>,
|
pub additional_data: Option<Vec<u8>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default, Clone)]
|
||||||
struct TestSender {
|
struct TestSender {
|
||||||
pub service_queue: VecDeque<TmInfo>,
|
pub service_queue: VecDeque<TmInfo>,
|
||||||
}
|
}
|
||||||
@ -1149,7 +1204,7 @@ mod tests {
|
|||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
struct DummyError {}
|
struct DummyError {}
|
||||||
#[derive(Default)]
|
#[derive(Default, Clone)]
|
||||||
struct FallibleSender {}
|
struct FallibleSender {}
|
||||||
|
|
||||||
impl EcssTmSender for FallibleSender {
|
impl EcssTmSender for FallibleSender {
|
||||||
@ -1160,13 +1215,13 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct TestBase<'a> {
|
struct TestBase<'a> {
|
||||||
vr: VerificationReporter,
|
vr: VerificationReporterWithBuf,
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
tc: PusTc<'a>,
|
tc: PusTc<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> TestBase<'a> {
|
impl<'a> TestBase<'a> {
|
||||||
fn rep(&mut self) -> &mut VerificationReporter {
|
fn rep(&mut self) -> &mut VerificationReporterWithBuf {
|
||||||
&mut self.vr
|
&mut self.vr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1177,14 +1232,21 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, E> TestBaseWithHelper<'a, E> {
|
impl<'a, E> TestBaseWithHelper<'a, E> {
|
||||||
fn rep(&mut self) -> &mut VerificationReporter {
|
fn rep(&mut self) -> &mut VerificationReporterWithBuf {
|
||||||
&mut self.helper.reporter
|
&mut self.helper.reporter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn base_reporter() -> VerificationReporter {
|
fn base_reporter() -> VerificationReporterWithBuf {
|
||||||
let cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8).unwrap();
|
let cfg = VerificationReporterCfg::new(
|
||||||
VerificationReporter::new(cfg)
|
TEST_APID,
|
||||||
|
Box::new(SimpleSeqCountProvider::default()),
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
8,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
VerificationReporterWithBuf::new(&cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn base_tc_init(app_data: Option<&[u8]>) -> (PusTc, RequestId) {
|
fn base_tc_init(app_data: Option<&[u8]>) -> (PusTc, RequestId) {
|
||||||
|
60
satrs-core/src/seq_count.rs
Normal file
60
satrs-core/src/seq_count.rs
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
use dyn_clone::DynClone;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub use stdmod::*;
|
||||||
|
|
||||||
|
pub trait SequenceCountProvider<Raw>: DynClone {
|
||||||
|
fn get(&self) -> Raw;
|
||||||
|
fn increment(&mut self);
|
||||||
|
fn get_and_increment(&mut self) -> Raw {
|
||||||
|
let val = self.get();
|
||||||
|
self.increment();
|
||||||
|
val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Clone)]
|
||||||
|
pub struct SimpleSeqCountProvider {
|
||||||
|
seq_count: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
dyn_clone::clone_trait_object!(SequenceCountProvider<u16>);
|
||||||
|
|
||||||
|
impl SequenceCountProvider<u16> for SimpleSeqCountProvider {
|
||||||
|
fn get(&self) -> u16 {
|
||||||
|
self.seq_count
|
||||||
|
}
|
||||||
|
|
||||||
|
fn increment(&mut self) {
|
||||||
|
if self.seq_count == u16::MAX {
|
||||||
|
self.seq_count = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.seq_count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub mod stdmod {
|
||||||
|
use super::*;
|
||||||
|
use std::sync::atomic::{AtomicU16, Ordering};
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
#[derive(Clone, Default)]
|
||||||
|
pub struct SyncSeqCountProvider {
|
||||||
|
seq_count: Arc<AtomicU16>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SequenceCountProvider<u16> for SyncSeqCountProvider {
|
||||||
|
fn get(&self) -> u16 {
|
||||||
|
self.seq_count.load(Ordering::SeqCst)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn increment(&mut self) {
|
||||||
|
self.seq_count.fetch_add(1, Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_and_increment(&mut self) -> u16 {
|
||||||
|
self.seq_count.fetch_add(1, Ordering::SeqCst)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,7 +4,9 @@ use satrs_core::event_man::{
|
|||||||
use satrs_core::events::{EventU32, EventU32TypedSev, Severity, SeverityInfo};
|
use satrs_core::events::{EventU32, EventU32TypedSev, Severity, SeverityInfo};
|
||||||
use satrs_core::params::U32Pair;
|
use satrs_core::params::U32Pair;
|
||||||
use satrs_core::params::{Params, ParamsHeapless, WritableToBeBytes};
|
use satrs_core::params::{Params, ParamsHeapless, WritableToBeBytes};
|
||||||
use satrs_core::pus::event_man::{DefaultPusMgmtBackendProvider, EventReporter, PusEventDispatcher};
|
use satrs_core::pus::event_man::{
|
||||||
|
DefaultPusMgmtBackendProvider, EventReporter, PusEventDispatcher,
|
||||||
|
};
|
||||||
use satrs_core::pus::{EcssTmError, EcssTmSender};
|
use satrs_core::pus::{EcssTmError, EcssTmSender};
|
||||||
use spacepackets::ecss::PusPacket;
|
use spacepackets::ecss::PusPacket;
|
||||||
use spacepackets::tm::PusTm;
|
use spacepackets::tm::PusTm;
|
||||||
@ -16,6 +18,7 @@ const INFO_EVENT: EventU32TypedSev<SeverityInfo> =
|
|||||||
const LOW_SEV_EVENT: EventU32 = EventU32::const_new(Severity::LOW, 1, 5);
|
const LOW_SEV_EVENT: EventU32 = EventU32::const_new(Severity::LOW, 1, 5);
|
||||||
const EMPTY_STAMP: [u8; 7] = [0; 7];
|
const EMPTY_STAMP: [u8; 7] = [0; 7];
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
struct EventTmSender {
|
struct EventTmSender {
|
||||||
sender: std::sync::mpsc::Sender<Vec<u8>>,
|
sender: std::sync::mpsc::Sender<Vec<u8>>,
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
|
use hashbrown::HashMap;
|
||||||
use satrs_core::pool::{LocalPool, PoolCfg, PoolProvider, SharedPool};
|
use satrs_core::pool::{LocalPool, PoolCfg, PoolProvider, SharedPool};
|
||||||
use satrs_core::pus::verification::{
|
use satrs_core::pus::verification::{
|
||||||
CrossbeamVerifSender, FailParams, RequestId, VerificationReporterCfg,
|
CrossbeamVerifSender, FailParams, RequestId, VerificationReporterCfg,
|
||||||
VerificationReporterWithSender,
|
VerificationReporterWithSender,
|
||||||
};
|
};
|
||||||
use hashbrown::HashMap;
|
use satrs_core::seq_count::SyncSeqCountProvider;
|
||||||
use spacepackets::ecss::{EcssEnumU16, EcssEnumU8, PusPacket};
|
use spacepackets::ecss::{EcssEnumU16, EcssEnumU8, PusPacket};
|
||||||
use spacepackets::tc::{PusTc, PusTcSecondaryHeader};
|
use spacepackets::tc::{PusTc, PusTcSecondaryHeader};
|
||||||
use spacepackets::tm::PusTm;
|
use spacepackets::tm::PusTm;
|
||||||
use spacepackets::SpHeader;
|
use spacepackets::SpHeader;
|
||||||
use std::sync::{Arc, Mutex, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
@ -25,7 +26,17 @@ const PACKETS_SENT: u8 = 8;
|
|||||||
/// threads have sent the correct expected verification reports
|
/// threads have sent the correct expected verification reports
|
||||||
#[test]
|
#[test]
|
||||||
fn test_shared_reporter() {
|
fn test_shared_reporter() {
|
||||||
let cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8).unwrap();
|
// We use a synced sequence count provider here because both verification reporters have the
|
||||||
|
// the same APID. If they had distinct APIDs, the more correct approach would be to have
|
||||||
|
// each reporter have an own sequence count provider.
|
||||||
|
let cfg = VerificationReporterCfg::new(
|
||||||
|
TEST_APID,
|
||||||
|
Box::new(SyncSeqCountProvider::default()),
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
8,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
// Shared pool object to store the verification PUS telemetry
|
// Shared pool object to store the verification PUS telemetry
|
||||||
let pool_cfg = PoolCfg::new(vec![(10, 32), (10, 64), (10, 128), (10, 1024)]);
|
let pool_cfg = PoolCfg::new(vec![(10, 32), (10, 64), (10, 128), (10, 1024)]);
|
||||||
let shared_tm_pool: SharedPool =
|
let shared_tm_pool: SharedPool =
|
||||||
@ -34,11 +45,8 @@ fn test_shared_reporter() {
|
|||||||
let shared_tc_pool_1 = shared_tc_pool_0.clone();
|
let shared_tc_pool_1 = shared_tc_pool_0.clone();
|
||||||
let (tx, rx) = crossbeam_channel::bounded(5);
|
let (tx, rx) = crossbeam_channel::bounded(5);
|
||||||
let sender = CrossbeamVerifSender::new(shared_tm_pool.clone(), tx.clone());
|
let sender = CrossbeamVerifSender::new(shared_tm_pool.clone(), tx.clone());
|
||||||
let reporter_with_sender_0 = Arc::new(Mutex::new(VerificationReporterWithSender::new(
|
let mut reporter_with_sender_0 = VerificationReporterWithSender::new(&cfg, Box::new(sender));
|
||||||
cfg,
|
let mut reporter_with_sender_1 = reporter_with_sender_0.clone();
|
||||||
Box::new(sender),
|
|
||||||
)));
|
|
||||||
let reporter_with_sender_1 = reporter_with_sender_0.clone();
|
|
||||||
// For test purposes, we retrieve the request ID from the TCs and pass them to the receiver
|
// For test purposes, we retrieve the request ID from the TCs and pass them to the receiver
|
||||||
// tread.
|
// tread.
|
||||||
let req_id_0;
|
let req_id_0;
|
||||||
@ -78,29 +86,28 @@ fn test_shared_reporter() {
|
|||||||
}
|
}
|
||||||
let (_tc, _) = PusTc::from_bytes(&tc_buf[0..tc_len]).unwrap();
|
let (_tc, _) = PusTc::from_bytes(&tc_buf[0..tc_len]).unwrap();
|
||||||
let accepted_token;
|
let accepted_token;
|
||||||
{
|
|
||||||
let mut mg = reporter_with_sender_0.lock().expect("Locking mutex failed");
|
let token = reporter_with_sender_0.add_tc_with_req_id(req_id_0);
|
||||||
let token = mg.add_tc_with_req_id(req_id_0);
|
accepted_token = reporter_with_sender_0
|
||||||
accepted_token = mg
|
|
||||||
.acceptance_success(token, &FIXED_STAMP)
|
.acceptance_success(token, &FIXED_STAMP)
|
||||||
.expect("Acceptance success failed");
|
.expect("Acceptance success failed");
|
||||||
}
|
|
||||||
// Do some start handling here
|
// Do some start handling here
|
||||||
let started_token;
|
let started_token;
|
||||||
{
|
started_token = reporter_with_sender_0
|
||||||
let mut mg = reporter_with_sender_0.lock().expect("Locking mutex failed");
|
|
||||||
started_token = mg
|
|
||||||
.start_success(accepted_token, &FIXED_STAMP)
|
.start_success(accepted_token, &FIXED_STAMP)
|
||||||
.expect("Start success failed");
|
.expect("Start success failed");
|
||||||
// Do some step handling here
|
// Do some step handling here
|
||||||
mg.step_success(&started_token, &FIXED_STAMP, EcssEnumU8::new(0))
|
reporter_with_sender_0
|
||||||
|
.step_success(&started_token, &FIXED_STAMP, EcssEnumU8::new(0))
|
||||||
.expect("Start success failed");
|
.expect("Start success failed");
|
||||||
}
|
|
||||||
// Finish up
|
// Finish up
|
||||||
let mut mg = reporter_with_sender_0.lock().expect("Locking mutex failed");
|
reporter_with_sender_0
|
||||||
mg.step_success(&started_token, &FIXED_STAMP, EcssEnumU8::new(1))
|
.step_success(&started_token, &FIXED_STAMP, EcssEnumU8::new(1))
|
||||||
.expect("Start success failed");
|
.expect("Start success failed");
|
||||||
mg.completion_success(started_token, &FIXED_STAMP)
|
reporter_with_sender_0
|
||||||
|
.completion_success(started_token, &FIXED_STAMP)
|
||||||
.expect("Completion success failed");
|
.expect("Completion success failed");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -118,19 +125,17 @@ fn test_shared_reporter() {
|
|||||||
tc_buf[0..tc_len].copy_from_slice(buf);
|
tc_buf[0..tc_len].copy_from_slice(buf);
|
||||||
}
|
}
|
||||||
let (tc, _) = PusTc::from_bytes(&tc_buf[0..tc_len]).unwrap();
|
let (tc, _) = PusTc::from_bytes(&tc_buf[0..tc_len]).unwrap();
|
||||||
let mut mg = reporter_with_sender_1
|
let token = reporter_with_sender_1.add_tc(&tc);
|
||||||
.lock()
|
let accepted_token = reporter_with_sender_1
|
||||||
.expect("Locking reporter failed");
|
|
||||||
let token = mg.add_tc(&tc);
|
|
||||||
let accepted_token = mg
|
|
||||||
.acceptance_success(token, &FIXED_STAMP)
|
.acceptance_success(token, &FIXED_STAMP)
|
||||||
.expect("Acceptance success failed");
|
.expect("Acceptance success failed");
|
||||||
let started_token = mg
|
let started_token = reporter_with_sender_1
|
||||||
.start_success(accepted_token, &FIXED_STAMP)
|
.start_success(accepted_token, &FIXED_STAMP)
|
||||||
.expect("Start success failed");
|
.expect("Start success failed");
|
||||||
let fail_code = EcssEnumU16::new(2);
|
let fail_code = EcssEnumU16::new(2);
|
||||||
let params = FailParams::new(&FIXED_STAMP, &fail_code, None);
|
let params = FailParams::new(&FIXED_STAMP, &fail_code, None);
|
||||||
mg.completion_failure(started_token, params)
|
reporter_with_sender_1
|
||||||
|
.completion_failure(started_token, params)
|
||||||
.expect("Completion success failed");
|
.expect("Completion success failed");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use crossbeam_channel::{bounded, Receiver, Sender};
|
use crossbeam_channel::{bounded, Receiver, Sender};
|
||||||
|
use std::sync::atomic::{AtomicU16, Ordering};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use zerocopy::{AsBytes, FromBytes, NetworkEndian, Unaligned, U16};
|
use zerocopy::{AsBytes, FromBytes, NetworkEndian, Unaligned, U16};
|
||||||
|
|
||||||
@ -52,4 +54,13 @@ fn main() {
|
|||||||
let jh1 = thread::spawn(|| {});
|
let jh1 = thread::spawn(|| {});
|
||||||
jh0.join().unwrap();
|
jh0.join().unwrap();
|
||||||
jh1.join().unwrap();
|
jh1.join().unwrap();
|
||||||
|
//let mut max_val: u16 = u16::MAX;
|
||||||
|
//max_val += 1;
|
||||||
|
//println!("Max val: {}", max_val);
|
||||||
|
let atomic_u16: AtomicU16 = AtomicU16::new(u16::MAX);
|
||||||
|
atomic_u16.fetch_add(1, Ordering::SeqCst);
|
||||||
|
println!(
|
||||||
|
"atomic after overflow: {}",
|
||||||
|
atomic_u16.load(Ordering::SeqCst)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ use satrs_core::pus::verification::{
|
|||||||
MpscVerifSender, VerificationReporterCfg, VerificationReporterWithSender,
|
MpscVerifSender, VerificationReporterCfg, VerificationReporterWithSender,
|
||||||
};
|
};
|
||||||
use satrs_core::pus::{EcssTmError, EcssTmSender};
|
use satrs_core::pus::{EcssTmError, EcssTmSender};
|
||||||
|
use satrs_core::seq_count::SimpleSeqCountProvider;
|
||||||
use satrs_core::tmtc::CcsdsError;
|
use satrs_core::tmtc::CcsdsError;
|
||||||
use satrs_example::{OBSW_SERVER_ADDR, SERVER_PORT};
|
use satrs_example::{OBSW_SERVER_ADDR, SERVER_PORT};
|
||||||
use spacepackets::time::{CdsShortTimeProvider, TimeWriter};
|
use spacepackets::time::{CdsShortTimeProvider, TimeWriter};
|
||||||
@ -39,6 +40,7 @@ struct UdpTmtcServer {
|
|||||||
|
|
||||||
unsafe impl Send for UdpTmtcServer {}
|
unsafe impl Send for UdpTmtcServer {}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
struct EventTmSender {
|
struct EventTmSender {
|
||||||
store_helper: TmStore,
|
store_helper: TmStore,
|
||||||
sender: mpsc::Sender<StoreAddr>,
|
sender: mpsc::Sender<StoreAddr>,
|
||||||
@ -73,9 +75,16 @@ fn main() {
|
|||||||
let (tm_funnel_tx, tm_funnel_rx) = channel();
|
let (tm_funnel_tx, tm_funnel_rx) = channel();
|
||||||
let (tm_server_tx, tm_server_rx) = channel();
|
let (tm_server_tx, tm_server_rx) = channel();
|
||||||
let sender = MpscVerifSender::new(tm_store.clone(), tm_funnel_tx.clone());
|
let sender = MpscVerifSender::new(tm_store.clone(), tm_funnel_tx.clone());
|
||||||
let verif_cfg = VerificationReporterCfg::new(PUS_APID, 1, 2, 8).unwrap();
|
let verif_cfg = VerificationReporterCfg::new(
|
||||||
|
PUS_APID,
|
||||||
|
Box::new(SimpleSeqCountProvider::default()),
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
8,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
let reporter_with_sender_0 = Arc::new(Mutex::new(VerificationReporterWithSender::new(
|
let reporter_with_sender_0 = Arc::new(Mutex::new(VerificationReporterWithSender::new(
|
||||||
verif_cfg,
|
&verif_cfg,
|
||||||
Box::new(sender),
|
Box::new(sender),
|
||||||
)));
|
)));
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user