PUS Event Manager #19

Merged
muellerr merged 41 commits from pus-event-manager into main 2022-11-19 12:26:17 +01:00
6 changed files with 150 additions and 75 deletions
Showing only changes of commit 01766464eb - Show all commits

View File

@ -10,9 +10,9 @@
#![no_std]
#[cfg(feature = "alloc")]
extern crate alloc;
extern crate downcast_rs;
#[cfg(any(feature = "std", test))]
extern crate std;
extern crate downcast_rs;
pub mod error;
#[cfg(feature = "alloc")]

View File

@ -46,7 +46,7 @@ impl EventReporterBase {
pub fn event_info<E>(
&mut self,
buf: &mut [u8],
sender: &mut (impl EcssTmSender<E> + ?Sized),
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
time_stamp: &[u8],
event_id: impl EcssEnumeration,
aux_data: Option<&[u8]>,
@ -64,7 +64,7 @@ impl EventReporterBase {
pub fn event_low_severity<E>(
&mut self,
buf: &mut [u8],
sender: &mut (impl EcssTmSender<E> + ?Sized),
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
time_stamp: &[u8],
event_id: impl EcssEnumeration,
aux_data: Option<&[u8]>,
@ -82,7 +82,7 @@ impl EventReporterBase {
pub fn event_medium_severity<E>(
&mut self,
buf: &mut [u8],
sender: &mut (impl EcssTmSender<E> + ?Sized),
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
time_stamp: &[u8],
event_id: impl EcssEnumeration,
aux_data: Option<&[u8]>,
@ -100,7 +100,7 @@ impl EventReporterBase {
pub fn event_high_severity<E>(
&mut self,
buf: &mut [u8],
sender: &mut (impl EcssTmSender<E> + ?Sized),
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
time_stamp: &[u8],
event_id: impl EcssEnumeration,
aux_data: Option<&[u8]>,
@ -119,7 +119,7 @@ impl EventReporterBase {
&mut self,
buf: &mut [u8],
subservice: Subservices,
sender: &mut (impl EcssTmSender<E> + ?Sized),
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
time_stamp: &[u8],
event_id: impl EcssEnumeration,
aux_data: Option<&[u8]>,
@ -188,7 +188,7 @@ mod allocvec {
}
pub fn event_info<E>(
&mut self,
sender: &mut (impl EcssTmSender<E> + ?Sized),
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
time_stamp: &[u8],
event_id: impl EcssEnumeration,
aux_data: Option<&[u8]>,
@ -204,7 +204,7 @@ mod allocvec {
pub fn event_low_severity<E>(
&mut self,
sender: &mut (impl EcssTmSender<E> + ?Sized),
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
time_stamp: &[u8],
event_id: impl EcssEnumeration,
aux_data: Option<&[u8]>,
@ -220,7 +220,7 @@ mod allocvec {
pub fn event_medium_severity<E>(
&mut self,
sender: &mut (impl EcssTmSender<E> + ?Sized),
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
time_stamp: &[u8],
event_id: impl EcssEnumeration,
aux_data: Option<&[u8]>,
@ -236,7 +236,7 @@ mod allocvec {
pub fn event_high_severity<E>(
&mut self,
sender: &mut (impl EcssTmSender<E> + ?Sized),
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
time_stamp: &[u8],
event_id: impl EcssEnumeration,
aux_data: Option<&[u8]>,
@ -279,7 +279,9 @@ mod tests {
pub service_queue: VecDeque<TmInfo>,
}
impl EcssTmSender<()> for TestSender {
impl EcssTmSender for TestSender {
type Error = ();
fn send_tm(&mut self, tm: PusTm) -> Result<(), EcssTmError<()>> {
assert!(tm.source_data().is_some());
let src_data = tm.source_data().unwrap();

View File

@ -1,9 +1,10 @@
use crate::events::{EventU16TypedSev, EventU32TypedSev, GenericEvent, HasSeverity, Severity};
use crate::events::{EventU32, EventU32TypedSev, GenericEvent, HasSeverity, Severity};
use alloc::boxed::Box;
use core::hash::Hash;
use hashbrown::HashSet;
use crate::pus::event::EventReporter;
#[cfg(feature = "alloc")]
pub use crate::pus::event::EventReporter;
use crate::pus::{EcssTmError, EcssTmSender};
#[cfg(feature = "heapless")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "heapless")))]
@ -33,9 +34,16 @@ pub trait PusEventMgmtBackendProvider<Provider: GenericEvent> {
///
/// 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<Provider: GenericEvent> {
disabled: HashSet<Provider>,
pub struct DefaultPusMgmtBackendProvider<Event: GenericEvent = EventU32> {
disabled: HashSet<Event>,
}
impl<Event: GenericEvent> Default for DefaultPusMgmtBackendProvider<Event> {
fn default() -> Self {
Self {
disabled: HashSet::default(),
}
}
}
impl<Provider: GenericEvent + PartialEq + Eq + Hash + Copy + Clone>
@ -91,12 +99,33 @@ pub mod heapless_mod {
}
}
pub struct PusEventManager<BackendError, Provider: GenericEvent> {
#[derive(Debug)]
pub enum EventManError<SenderE> {
EcssTmError(EcssTmError<SenderE>),
SeverityMissmatch(Severity, Severity),
}
impl<SenderE> From<EcssTmError<SenderE>> for EventManError<SenderE> {
fn from(v: EcssTmError<SenderE>) -> Self {
Self::EcssTmError(v)
}
}
pub struct PusEventTmManager<BackendError, Provider: GenericEvent> {
reporter: EventReporter,
backend: Box<dyn PusEventMgmtBackendProvider<Provider, Error = BackendError>>,
}
impl<BackendError, Event: GenericEvent> PusEventManager<BackendError, Event> {
impl<BackendError, Provider: GenericEvent> PusEventTmManager<BackendError, Provider> {
pub fn new(
reporter: EventReporter,
backend: Box<dyn PusEventMgmtBackendProvider<Provider, Error = BackendError>>,
) -> Self {
Self { reporter, backend }
}
}
impl<BackendError, Event: GenericEvent> PusEventTmManager<BackendError, Event> {
pub fn enable_tm_for_event(&mut self, event: &Event) -> Result<bool, BackendError> {
self.backend.enable_event_reporting(event)
}
@ -108,59 +137,56 @@ impl<BackendError, Event: GenericEvent> PusEventManager<BackendError, Event> {
pub fn generate_pus_event_tm_generic<E>(
&mut self,
severity: Severity,
sender: &mut (impl EcssTmSender<E> + ?Sized),
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
time_stamp: &[u8],
event: Event,
aux_data: Option<&[u8]>,
) -> Result<bool, EcssTmError<E>> {
) -> Result<bool, EventManError<E>> {
if !self.backend.event_enabled(&event) {
return Ok(false);
}
if event.severity() != severity {
return Err(EventManError::SeverityMissmatch(severity, event.severity()));
}
match severity {
Severity::INFO => self
.reporter
.event_info(sender, time_stamp, event, aux_data)
.map(|_| true),
.map(|_| true)
.map_err(|e| e.into()),
Severity::LOW => self
.reporter
.event_low_severity(sender, time_stamp, event, aux_data)
.map(|_| true),
.map(|_| true)
.map_err(|e| e.into()),
Severity::MEDIUM => self
.reporter
.event_medium_severity(sender, time_stamp, event, aux_data)
.map(|_| true),
.map(|_| true)
.map_err(|e| e.into()),
Severity::HIGH => self
.reporter
.event_high_severity(sender, time_stamp, event, aux_data)
.map(|_| true),
.map(|_| true)
.map_err(|e| e.into()),
}
}
}
impl<BackendError, SEVERITY: HasSeverity>
PusEventManager<BackendError, EventU32TypedSev<SEVERITY>>
{
pub fn generate_pus_event_tm<E>(
impl<BackendError> PusEventTmManager<BackendError, EventU32> {
pub fn generate_pus_event_tm<E, Severity: HasSeverity>(
&mut self,
sender: &mut (impl EcssTmSender<E> + ?Sized),
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
time_stamp: &[u8],
event: EventU32TypedSev<SEVERITY>,
event: EventU32TypedSev<Severity>,
aux_data: Option<&[u8]>,
) -> Result<bool, EcssTmError<E>> {
self.generate_pus_event_tm_generic(SEVERITY::SEVERITY, sender, time_stamp, event, aux_data)
}
}
impl<BackendError, SEVERITY: HasSeverity>
PusEventManager<BackendError, EventU16TypedSev<SEVERITY>>
{
pub fn generate_pus_event_tm<E>(
&mut self,
sender: &mut (impl EcssTmSender<E> + ?Sized),
time_stamp: &[u8],
event: EventU16TypedSev<SEVERITY>,
aux_data: Option<&[u8]>,
) -> Result<bool, EcssTmError<E>> {
self.generate_pus_event_tm_generic(SEVERITY::SEVERITY, sender, time_stamp, event, aux_data)
) -> Result<bool, EventManError<E>> {
self.generate_pus_event_tm_generic(
Severity::SEVERITY,
sender,
time_stamp,
event.into(),
aux_data,
)
}
}

View File

@ -26,6 +26,12 @@ pub enum EcssTmError<E> {
PusError(PusError),
}
impl<E> From<PusError> for EcssTmError<E> {
fn from(e: PusError) -> Self {
EcssTmError::PusError(e)
}
}
impl<E> From<ByteConversionError> for EcssTmError<E> {
fn from(e: ByteConversionError) -> Self {
EcssTmError::ByteConversionError(e)
@ -37,11 +43,13 @@ impl<E> From<ByteConversionError> for EcssTmError<E> {
/// 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<E>: Downcast + Send {
fn send_tm(&mut self, tm: PusTm) -> Result<(), EcssTmError<E>>;
pub trait EcssTmSender: Downcast + Send {
type Error;
fn send_tm(&mut self, tm: PusTm) -> Result<(), EcssTmError<Self::Error>>;
}
impl_downcast!(EcssTmSender<E>);
impl_downcast!(EcssTmSender assoc Error);
pub(crate) fn source_buffer_large_enough<E>(cap: usize, len: usize) -> Result<(), EcssTmError<E>> {
if len > cap {

View File

@ -312,7 +312,7 @@ impl VerificationReporterBasic {
&mut self,
buf: &mut [u8],
token: VerificationToken<StateNone>,
sender: &mut (impl EcssTmSender<E> + ?Sized),
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
time_stamp: &[u8],
) -> Result<VerificationToken<StateAccepted>, VerificationErrorWithToken<E, StateNone>> {
let tm = self
@ -339,7 +339,7 @@ impl VerificationReporterBasic {
&mut self,
buf: &mut [u8],
token: VerificationToken<StateNone>,
sender: &mut (impl EcssTmSender<E> + ?Sized),
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
params: FailParams,
) -> Result<(), VerificationErrorWithToken<E, StateNone>> {
let tm = self
@ -365,7 +365,7 @@ impl VerificationReporterBasic {
&mut self,
buf: &mut [u8],
token: VerificationToken<StateAccepted>,
sender: &mut (impl EcssTmSender<E> + ?Sized),
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
time_stamp: &[u8],
) -> Result<VerificationToken<StateStarted>, VerificationErrorWithToken<E, StateAccepted>> {
let tm = self
@ -395,7 +395,7 @@ impl VerificationReporterBasic {
&mut self,
buf: &mut [u8],
token: VerificationToken<StateAccepted>,
sender: &mut (impl EcssTmSender<E> + ?Sized),
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
params: FailParams,
) -> Result<(), VerificationErrorWithToken<E, StateAccepted>> {
let tm = self
@ -421,7 +421,7 @@ impl VerificationReporterBasic {
&mut self,
buf: &mut [u8],
token: &VerificationToken<StateStarted>,
sender: &mut (impl EcssTmSender<E> + ?Sized),
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
time_stamp: &[u8],
step: impl EcssEnumeration,
) -> Result<(), EcssTmError<E>> {
@ -445,7 +445,7 @@ impl VerificationReporterBasic {
&mut self,
buf: &mut [u8],
token: VerificationToken<StateStarted>,
sender: &mut (impl EcssTmSender<E> + ?Sized),
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
params: FailParamsWithStep,
) -> Result<(), VerificationErrorWithToken<E, StateStarted>> {
let tm = self
@ -472,7 +472,7 @@ impl VerificationReporterBasic {
&mut self,
buf: &mut [u8],
token: VerificationToken<StateStarted>,
sender: &mut (impl EcssTmSender<E> + ?Sized),
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
time_stamp: &[u8],
) -> Result<(), VerificationErrorWithToken<E, StateStarted>> {
let tm = self
@ -499,7 +499,7 @@ impl VerificationReporterBasic {
&mut self,
buf: &mut [u8],
token: VerificationToken<StateStarted>,
sender: &mut (impl EcssTmSender<E> + ?Sized),
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
params: FailParams,
) -> Result<(), VerificationErrorWithToken<E, StateStarted>> {
let tm = self
@ -685,7 +685,7 @@ mod allocmod {
pub fn acceptance_success<E>(
&mut self,
token: VerificationToken<StateNone>,
sender: &mut (impl EcssTmSender<E> + ?Sized),
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
time_stamp: &[u8],
) -> Result<VerificationToken<StateAccepted>, VerificationErrorWithToken<E, StateNone>>
{
@ -701,7 +701,7 @@ mod allocmod {
pub fn acceptance_failure<E>(
&mut self,
token: VerificationToken<StateNone>,
sender: &mut (impl EcssTmSender<E> + ?Sized),
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
params: FailParams,
) -> Result<(), VerificationErrorWithToken<E, StateNone>> {
self.reporter.acceptance_failure(
@ -718,7 +718,7 @@ mod allocmod {
pub fn start_success<E>(
&mut self,
token: VerificationToken<StateAccepted>,
sender: &mut (impl EcssTmSender<E> + ?Sized),
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
time_stamp: &[u8],
) -> Result<VerificationToken<StateStarted>, VerificationErrorWithToken<E, StateAccepted>>
{
@ -737,7 +737,7 @@ mod allocmod {
pub fn start_failure<E>(
&mut self,
token: VerificationToken<StateAccepted>,
sender: &mut (impl EcssTmSender<E> + ?Sized),
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
params: FailParams,
) -> Result<(), VerificationErrorWithToken<E, StateAccepted>> {
self.reporter
@ -750,7 +750,7 @@ mod allocmod {
pub fn step_success<E>(
&mut self,
token: &VerificationToken<StateStarted>,
sender: &mut (impl EcssTmSender<E> + ?Sized),
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
time_stamp: &[u8],
step: impl EcssEnumeration,
) -> Result<(), EcssTmError<E>> {
@ -770,7 +770,7 @@ mod allocmod {
pub fn step_failure<E>(
&mut self,
token: VerificationToken<StateStarted>,
sender: &mut (impl EcssTmSender<E> + ?Sized),
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
params: FailParamsWithStep,
) -> Result<(), VerificationErrorWithToken<E, StateStarted>> {
self.reporter
@ -784,7 +784,7 @@ mod allocmod {
pub fn completion_success<E>(
&mut self,
token: VerificationToken<StateStarted>,
sender: &mut (impl EcssTmSender<E> + ?Sized),
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
time_stamp: &[u8],
) -> Result<(), VerificationErrorWithToken<E, StateStarted>> {
self.reporter.completion_success(
@ -802,7 +802,7 @@ mod allocmod {
pub fn completion_failure<E>(
&mut self,
token: VerificationToken<StateStarted>,
sender: &mut (impl EcssTmSender<E> + ?Sized),
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
params: FailParams,
) -> Result<(), VerificationErrorWithToken<E, StateStarted>> {
self.reporter.completion_failure(
@ -818,18 +818,18 @@ mod allocmod {
/// API as [VerificationReporter] but without the explicit sender arguments.
pub struct VerificationReporterWithSender<E> {
pub reporter: VerificationReporter,
pub sender: Box<dyn EcssTmSender<E>>,
pub sender: Box<dyn EcssTmSender<Error = E>>,
}
impl<E: 'static> VerificationReporterWithSender<E> {
pub fn new(cfg: VerificationReporterCfg, sender: Box<dyn EcssTmSender<E>>) -> Self {
pub fn new(cfg: VerificationReporterCfg, sender: Box<dyn EcssTmSender<Error = E>>) -> Self {
let reporter = VerificationReporter::new(cfg);
Self::new_from_reporter(reporter, sender)
}
pub fn new_from_reporter(
reporter: VerificationReporter,
sender: Box<dyn EcssTmSender<E>>,
sender: Box<dyn EcssTmSender<Error = E>>,
) -> Self {
Self { reporter, sender }
}
@ -997,7 +997,9 @@ mod stdmod {
}
//noinspection RsTraitImplementation
impl EcssTmSender<StdVerifSenderError> for MpscVerifSender {
impl EcssTmSender for MpscVerifSender {
type Error = StdVerifSenderError;
delegate!(
to self.base {
fn send_tm(&mut self, tm: PusTm) -> Result<(), EcssTmError<StdVerifSenderError>>;
@ -1028,7 +1030,9 @@ mod stdmod {
}
//noinspection RsTraitImplementation
impl EcssTmSender<StdVerifSenderError> for CrossbeamVerifSender {
impl EcssTmSender for CrossbeamVerifSender {
type Error = StdVerifSenderError;
delegate!(
to self.base {
fn send_tm(&mut self, tm: PusTm) -> Result<(), EcssTmError<StdVerifSenderError>>;
@ -1039,8 +1043,9 @@ mod stdmod {
unsafe impl Sync for CrossbeamVerifSender {}
unsafe impl Send for CrossbeamVerifSender {}
impl<S: SendBackend + 'static> EcssTmSender<StdVerifSenderError> for StdSenderBase<S> {
fn send_tm(&mut self, tm: PusTm) -> Result<(), EcssTmError<StdVerifSenderError>> {
impl<S: SendBackend + 'static> EcssTmSender for StdSenderBase<S> {
type Error = StdVerifSenderError;
fn send_tm(&mut self, tm: PusTm) -> Result<(), EcssTmError<Self::Error>> {
let operation = |mut mg: RwLockWriteGuard<ShareablePoolProvider>| {
let (addr, buf) = mg.free_element(tm.len_packed())?;
tm.write_to_bytes(buf).map_err(EcssTmError::PusError)?;
@ -1096,8 +1101,9 @@ mod tests {
pub service_queue: VecDeque<TmInfo>,
}
impl EcssTmSender<()> for TestSender {
fn send_tm(&mut self, tm: PusTm) -> Result<(), EcssTmError<()>> {
impl EcssTmSender for TestSender {
type Error = ();
fn send_tm(&mut self, tm: PusTm) -> Result<(), EcssTmError<Self::Error>> {
assert_eq!(PusPacket::service(&tm), 1);
assert!(tm.source_data().is_some());
let mut time_stamp = [0; 7];

View File

@ -1,6 +1,39 @@
use fsrc_core::events::{EventU32, EventU32TypedSev, Severity, SeverityInfo};
use fsrc_core::pus::event_man::{DefaultPusMgmtBackendProvider, EventReporter, PusEventTmManager};
use fsrc_core::pus::{EcssTmError, EcssTmSender};
use spacepackets::tm::PusTm;
use std::sync::mpsc::{channel, SendError};
const INFO_EVENT: EventU32TypedSev<SeverityInfo> =
EventU32TypedSev::<SeverityInfo>::const_new(1, 0);
const LOW_SEV_EVENT: EventU32 = EventU32::const_new(Severity::LOW, 1, 5);
const EMPTY_STAMP: [u8; 7] = [0; 7];
struct EventTmSender {
sender: std::sync::mpsc::Sender<Vec<u8>>,
}
impl EcssTmSender for EventTmSender {
type Error = SendError<Vec<u8>>;
fn send_tm(&mut self, tm: PusTm) -> Result<(), EcssTmError<Self::Error>> {
let mut vec = Vec::new();
tm.append_to_vec(&mut vec)?;
self.sender.send(vec).map_err(EcssTmError::SendError)?;
Ok(())
}
}
#[test]
fn main() {
let reporter = EventReporter::new(0x02, 128).expect("Creating event repoter failed");
let backend = DefaultPusMgmtBackendProvider::<EventU32>::default();
let mut event_man = PusEventTmManager::new(reporter, Box::new(backend));
let (event_tx, event_rx) = channel();
let mut sender = EventTmSender { sender: event_tx };
event_man
.generate_pus_event_tm(&mut sender, &EMPTY_STAMP, INFO_EVENT, None)
.expect("Sending info event failed");
let packet = event_rx.recv().expect("Receiving event TM failed");
println!("{:?}", packet);
//let event_man;
}