basic PUS event manager

This commit is contained in:
Robin Müller 2022-10-24 01:51:33 +02:00
parent 6fe3738364
commit 478673327b
No known key found for this signature in database
GPG Key ID: 9C287E88FED11DF3
5 changed files with 385 additions and 151 deletions

View File

@ -1,5 +1,5 @@
//! [Event][crate::events::Event] management and forwarding
use crate::events::{Event, EventProvider, EventSmall};
use crate::events::{EventU16TypedSev, EventU32, GenericEvent, HasSeverity};
use alloc::boxed::Box;
use alloc::vec;
use alloc::vec::Vec;
@ -11,34 +11,34 @@ enum ListenerType {
Group(u16),
}
pub trait EventListener<Provider: EventProvider = Event> {
pub trait EventListener<Provider: GenericEvent> {
type Error;
fn id(&self) -> u32;
fn send_to(&mut self, event: Provider) -> Result<(), Self::Error>;
}
struct Listener<E, Provider: EventProvider = Event> {
struct Listener<E, Provider: GenericEvent> {
ltype: ListenerType,
dest: Box<dyn EventListener<Provider, Error = E>>,
}
pub trait ReceivesAllEvent<Provider: EventProvider = Event> {
pub trait ReceivesAllEvent<Provider: GenericEvent> {
fn receive(&mut self) -> Option<Provider>;
}
pub struct EventManager<E, Provider: EventProvider = Event> {
pub struct EventManager<E, Provider: GenericEvent> {
listeners: HashMap<ListenerType, Vec<Listener<E, Provider>>>,
event_receiver: Box<dyn ReceivesAllEvent<Provider>>,
}
pub enum HandlerResult<Provider: EventProvider = Event> {
pub enum HandlerResult<Provider: GenericEvent> {
Empty,
Handled(u32, Provider),
}
impl<E> EventManager<E, Event> {
pub fn new(event_receiver: Box<dyn ReceivesAllEvent<Event>>) -> Self {
impl<E> EventManager<E, EventU32> {
pub fn new(event_receiver: Box<dyn ReceivesAllEvent<EventU32>>) -> Self {
EventManager {
listeners: HashMap::new(),
event_receiver,
@ -46,43 +46,43 @@ impl<E> EventManager<E, Event> {
}
}
impl<E> EventManager<E, Event> {
impl<E> EventManager<E, EventU32> {
pub fn subscribe_single(
&mut self,
event: Event,
dest: impl EventListener<Event, Error = E> + 'static,
event: EventU32,
dest: impl EventListener<EventU32, Error = E> + 'static,
) {
self.update_listeners(ListenerType::Single(event.raw_as_largest_type()), dest);
}
pub fn subscribe_group(
&mut self,
group_id: <Event as EventProvider>::GroupId,
dest: impl EventListener<Event, Error = E> + 'static,
group_id: <EventU32 as GenericEvent>::GroupId,
dest: impl EventListener<EventU32, Error = E> + 'static,
) {
self.update_listeners(ListenerType::Group(group_id), dest);
}
}
impl<E> EventManager<E, EventSmall> {
impl<E, SEVERITY: HasSeverity + Copy> EventManager<E, EventU16TypedSev<SEVERITY>> {
pub fn subscribe_single(
&mut self,
event: EventSmall,
dest: impl EventListener<EventSmall, Error = E> + 'static,
event: EventU16TypedSev<SEVERITY>,
dest: impl EventListener<EventU16TypedSev<SEVERITY>, Error = E> + 'static,
) {
self.update_listeners(ListenerType::Single(event.raw_as_largest_type()), dest);
}
pub fn subscribe_group(
&mut self,
group_id: <EventSmall as EventProvider>::GroupId,
dest: impl EventListener<EventSmall, Error = E> + 'static,
group_id: <EventU16TypedSev<SEVERITY> as GenericEvent>::GroupId,
dest: impl EventListener<EventU16TypedSev<SEVERITY>, Error = E> + 'static,
) {
self.update_listeners(ListenerType::Group(group_id.into()), dest);
}
}
impl<E, Provider: EventProvider> EventManager<E, Provider> {
impl<E, Provider: GenericEvent + Copy> EventManager<E, Provider> {
fn update_listeners(
&mut self,
key: ListenerType,
@ -145,17 +145,17 @@ impl<E, Provider: EventProvider> EventManager<E, Provider> {
mod tests {
use super::{EventListener, HandlerResult, ReceivesAllEvent};
use crate::event_man::EventManager;
use crate::events::{Event, EventProvider, Severity};
use crate::events::{EventU32, GenericEvent, Severity};
use alloc::boxed::Box;
use std::sync::mpsc::{channel, Receiver, SendError, Sender};
use std::thread;
use std::time::Duration;
struct EventReceiver {
mpsc_receiver: Receiver<Event>,
mpsc_receiver: Receiver<EventU32>,
}
impl ReceivesAllEvent<Event> for EventReceiver {
fn receive(&mut self) -> Option<Event> {
impl ReceivesAllEvent<EventU32> for EventReceiver {
fn receive(&mut self) -> Option<EventU32> {
self.mpsc_receiver.try_recv().ok()
}
}
@ -163,21 +163,21 @@ mod tests {
#[derive(Clone)]
struct MpscEventSenderQueue {
id: u32,
mpsc_sender: Sender<Event>,
mpsc_sender: Sender<EventU32>,
}
impl EventListener<Event> for MpscEventSenderQueue {
type Error = SendError<Event>;
impl EventListener<EventU32> for MpscEventSenderQueue {
type Error = SendError<EventU32>;
fn id(&self) -> u32 {
self.id
}
fn send_to(&mut self, event: Event) -> Result<(), Self::Error> {
fn send_to(&mut self, event: EventU32) -> Result<(), Self::Error> {
self.mpsc_sender.send(event)
}
}
fn check_next_event(expected: Event, receiver: &Receiver<Event>) {
fn check_next_event(expected: EventU32, receiver: &Receiver<EventU32>) {
for _ in 0..5 {
if let Ok(event) = receiver.try_recv() {
assert_eq!(event, expected);
@ -187,7 +187,11 @@ mod tests {
}
}
fn check_handled_event(res: HandlerResult, expected: Event, expected_num_sent: u32) {
fn check_handled_event(
res: HandlerResult<EventU32>,
expected: EventU32,
expected_num_sent: u32,
) {
assert!(matches!(res, HandlerResult::Handled { .. }));
if let HandlerResult::Handled(num_recipients, event) = res {
assert_eq!(event, expected);
@ -201,10 +205,10 @@ mod tests {
let event_man_receiver = EventReceiver {
mpsc_receiver: manager_queue,
};
let mut event_man: EventManager<SendError<Event>, Event> =
let mut event_man: EventManager<SendError<EventU32>, EventU32> =
EventManager::new(Box::new(event_man_receiver));
let event_grp_0 = Event::new(Severity::INFO, 0, 0).unwrap();
let event_grp_1_0 = Event::new(Severity::HIGH, 1, 0).unwrap();
let event_grp_0 = EventU32::new(Severity::INFO, 0, 0).unwrap();
let event_grp_1_0 = EventU32::new(Severity::HIGH, 1, 0).unwrap();
let (single_event_sender, single_event_receiver) = channel();
let single_event_listener = MpscEventSenderQueue {
id: 0,
@ -244,15 +248,15 @@ mod tests {
let event_man_receiver = EventReceiver {
mpsc_receiver: manager_queue,
};
let mut event_man: EventManager<SendError<Event>, Event> =
let mut event_man: EventManager<SendError<EventU32>, EventU32> =
EventManager::new(Box::new(event_man_receiver));
let res = event_man.try_event_handling();
assert!(res.is_ok());
let hres = res.unwrap();
assert!(matches!(hres, HandlerResult::Empty));
let event_grp_0 = Event::new(Severity::INFO, 0, 0).unwrap();
let event_grp_1_0 = Event::new(Severity::HIGH, 1, 0).unwrap();
let event_grp_0 = EventU32::new(Severity::INFO, 0, 0).unwrap();
let event_grp_1_0 = EventU32::new(Severity::HIGH, 1, 0).unwrap();
let (event_grp_0_sender, event_grp_0_receiver) = channel();
let event_grp_0_and_1_listener = MpscEventSenderQueue {
id: 0,
@ -286,10 +290,10 @@ mod tests {
let event_man_receiver = EventReceiver {
mpsc_receiver: manager_queue,
};
let mut event_man: EventManager<SendError<Event>, Event> =
let mut event_man: EventManager<SendError<EventU32>, EventU32> =
EventManager::new(Box::new(event_man_receiver));
let event_0 = Event::new(Severity::INFO, 0, 5).unwrap();
let event_1 = Event::new(Severity::HIGH, 1, 0).unwrap();
let event_0 = EventU32::new(Severity::INFO, 0, 5).unwrap();
let event_1 = EventU32::new(Severity::HIGH, 1, 0).unwrap();
let (event_0_tx_0, event_0_rx_0) = channel();
let (event_0_tx_1, event_0_rx_1) = channel();
let event_listener_0 = MpscEventSenderQueue {

View File

@ -1,6 +1,7 @@
//! Event support module
use core::hash::Hash;
use delegate::delegate;
use spacepackets::ecss::{EcssEnumeration, ToBeBytes};
use spacepackets::{ByteConversionError, SizeMissmatch};
use std::marker::PhantomData;
@ -18,7 +19,34 @@ pub enum Severity {
HIGH = 3,
}
pub trait EventProvider: EcssEnumeration + PartialEq + Eq + Copy + Clone + Hash {
pub trait HasSeverity {
const SEVERITY: Severity;
}
#[derive(Debug, PartialEq, Eq)]
pub struct SeverityInfo {}
impl HasSeverity for SeverityInfo {
const SEVERITY: Severity = Severity::INFO;
}
#[derive(Debug, PartialEq, Eq)]
pub struct SeverityLow {}
impl HasSeverity for SeverityLow {
const SEVERITY: Severity = Severity::LOW;
}
#[derive(Debug, PartialEq, Eq)]
pub struct SeverityMedium {}
impl HasSeverity for SeverityMedium {
const SEVERITY: Severity = Severity::MEDIUM;
}
#[derive(Debug, PartialEq, Eq)]
pub struct SeverityHigh {}
impl HasSeverity for SeverityHigh {
const SEVERITY: Severity = Severity::HIGH;
}
pub trait GenericEvent: EcssEnumeration {
type Raw;
type GroupId;
type UniqueId;
@ -149,43 +177,78 @@ macro_rules! event_provider_impl {
}
};
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct Event {
base: EventBase<u32, u16, u16>,
}
impl EventProvider for Event {
type Raw = u32;
type GroupId = u16;
type UniqueId = u16;
macro_rules! impl_event_provider {
($BaseIdent: ident, $TypedIdent: ident, $raw: ty, $gid: ty, $uid: ty) => {
impl GenericEvent for $BaseIdent {
type Raw = $raw;
type GroupId = $gid;
type UniqueId = $uid;
event_provider_impl!();
fn raw_as_largest_type(&self) -> LargestEventRaw {
self.raw()
self.raw().into()
}
fn group_id_as_largest_type(&self) -> LargestGroupIdRaw {
self.group_id()
self.group_id().into()
}
}
impl<SEVERITY: HasSeverity> GenericEvent for $TypedIdent<SEVERITY> {
type Raw = $raw;
type GroupId = $gid;
type UniqueId = $uid;
delegate!(to self.event {
fn raw(&self) -> Self::Raw;
fn severity(&self) -> Severity;
fn group_id(&self) -> Self::GroupId;
fn unique_id(&self) -> Self::UniqueId;
fn raw_as_largest_type(&self) -> LargestEventRaw;
fn group_id_as_largest_type(&self) -> LargestGroupIdRaw;
});
}
}
}
impl Event {
/// Generate an event. The raw representation of an event has 32 bits.
/// If the passed group ID is invalid (too large), None wil be returned
///
/// # Parameter
///
/// * `severity`: Each event has a [severity][Severity]. The raw value of the severity will
/// be stored inside the uppermost 2 bits of the raw event ID
/// * `group_id`: Related events can be grouped using a group ID. The group ID will occupy the
/// next 14 bits after the severity. Therefore, the size is limited by dec 16383 hex 0x3FFF.
/// * `unique_id`: Each event has a unique 16 bit ID occupying the last 16 bits of the
/// raw event ID
macro_rules! try_from_impls {
($SevIdent: ident, $severity: path, $raw: ty, $TypedSevIdent: ident) => {
impl TryFrom<$raw> for $TypedSevIdent<$SevIdent> {
type Error = Severity;
fn try_from(raw: $raw) -> Result<Self, Self::Error> {
Self::try_from_generic($severity, raw)
}
}
};
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct EventU32 {
base: EventBase<u32, u16, u16>,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct EventU32TypedSev<SEVERITY> {
event: EventU32,
phantom: PhantomData<SEVERITY>,
}
impl<SEVERITY: HasSeverity> From<EventU32TypedSev<SEVERITY>> for EventU32 {
fn from(e: EventU32TypedSev<SEVERITY>) -> Self {
Self { base: e.event.base }
}
}
impl_event_provider!(EventU32, EventU32TypedSev, u32, u16, u16);
impl EventU32 {
pub fn new(
severity: Severity,
group_id: <Self as EventProvider>::GroupId,
unique_id: <Self as EventProvider>::UniqueId,
group_id: <Self as GenericEvent>::GroupId,
unique_id: <Self as GenericEvent>::UniqueId,
) -> Option<Self> {
if group_id > (2u16.pow(14) - 1) {
return None;
@ -199,12 +262,10 @@ impl Event {
},
})
}
/// Const version of [new], but panics on invalid group ID input values.
pub const fn const_new(
severity: Severity,
group_id: <Self as EventProvider>::GroupId,
unique_id: <Self as EventProvider>::UniqueId,
group_id: <Self as GenericEvent>::GroupId,
unique_id: <Self as GenericEvent>::UniqueId,
) -> Self {
if group_id > (2u16.pow(14) - 1) {
panic!("Group ID too large");
@ -220,7 +281,54 @@ impl Event {
}
}
impl From<u32> for Event {
impl<SEVERITY: HasSeverity> EventU32TypedSev<SEVERITY> {
/// Generate an event. The raw representation of an event has 32 bits.
/// If the passed group ID is invalid (too large), None wil be returned
///
/// # Parameter
///
/// * `severity`: Each event has a [severity][Severity]. The raw value of the severity will
/// be stored inside the uppermost 2 bits of the raw event ID
/// * `group_id`: Related events can be grouped using a group ID. The group ID will occupy the
/// next 14 bits after the severity. Therefore, the size is limited by dec 16383 hex 0x3FFF.
/// * `unique_id`: Each event has a unique 16 bit ID occupying the last 16 bits of the
/// raw event ID
pub fn new(
group_id: <Self as GenericEvent>::GroupId,
unique_id: <Self as GenericEvent>::UniqueId,
) -> Option<Self> {
let event = EventU32::new(SEVERITY::SEVERITY, group_id, unique_id)?;
Some(Self {
event,
phantom: PhantomData,
})
}
/// Const version of [new], but panics on invalid group ID input values.
pub const fn const_new(
group_id: <Self as GenericEvent>::GroupId,
unique_id: <Self as GenericEvent>::UniqueId,
) -> Self {
let event = EventU32::const_new(SEVERITY::SEVERITY, group_id, unique_id);
Self {
event,
phantom: PhantomData,
}
}
fn try_from_generic(expected: Severity, raw: u32) -> Result<Self, Severity> {
let severity = Severity::try_from(((raw >> 30) & 0b11) as u8).unwrap();
if severity != expected {
return Err(severity);
}
Ok(Self::const_new(
((raw >> 16) & 0x3FFF) as u16,
(raw & 0xFFFF) as u16,
))
}
}
impl From<u32> for EventU32 {
fn from(raw: u32) -> Self {
// Severity conversion from u8 should never fail
let severity = Severity::try_from(((raw >> 30) & 0b11) as u8).unwrap();
@ -231,7 +339,12 @@ impl From<u32> for Event {
}
}
impl EcssEnumeration for Event {
try_from_impls!(SeverityInfo, Severity::INFO, u32, EventU32TypedSev);
try_from_impls!(SeverityLow, Severity::LOW, u32, EventU32TypedSev);
try_from_impls!(SeverityMedium, Severity::MEDIUM, u32, EventU32TypedSev);
try_from_impls!(SeverityHigh, Severity::HIGH, u32, EventU32TypedSev);
impl EcssEnumeration for EventU32 {
fn pfc(&self) -> u8 {
32
}
@ -241,12 +354,26 @@ impl EcssEnumeration for Event {
}
}
//noinspection RsTraitImplementation
impl<SEVERITY: HasSeverity> EcssEnumeration for EventU32TypedSev<SEVERITY> {
delegate!(to self.event {
fn pfc(&self) -> u8;
fn write_to_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError>;
});
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct EventSmall {
pub struct EventU16 {
base: EventBase<u16, u8, u8>,
}
impl EventSmall {
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct EventU16TypedSev<SEVERITY> {
event: EventU16,
phantom: PhantomData<SEVERITY>,
}
impl EventU16 {
/// Generate a small event. The raw representation of a small event has 16 bits.
/// If the passed group ID is invalid (too large), [None] wil be returned
///
@ -260,8 +387,8 @@ impl EventSmall {
/// raw event ID
pub fn new(
severity: Severity,
group_id: <Self as EventProvider>::GroupId,
unique_id: <Self as EventProvider>::UniqueId,
group_id: <Self as GenericEvent>::GroupId,
unique_id: <Self as GenericEvent>::UniqueId,
) -> Option<Self> {
if group_id > (2u8.pow(6) - 1) {
return None;
@ -278,8 +405,8 @@ impl EventSmall {
pub const fn const_new(
severity: Severity,
group_id: <Self as EventProvider>::GroupId,
unique_id: <Self as EventProvider>::UniqueId,
group_id: <Self as GenericEvent>::GroupId,
unique_id: <Self as GenericEvent>::UniqueId,
) -> Self {
if group_id > (2u8.pow(6) - 1) {
panic!("Group ID too large");
@ -294,24 +421,55 @@ impl EventSmall {
}
}
}
impl EventProvider for EventSmall {
type Raw = u16;
type GroupId = u8;
type UniqueId = u8;
event_provider_impl!();
fn raw_as_largest_type(&self) -> LargestEventRaw {
self.raw().into()
impl<SEVERITY: HasSeverity> EventU16TypedSev<SEVERITY> {
/// Generate a small event. The raw representation of a small event has 16 bits.
/// If the passed group ID is invalid (too large), [None] wil be returned
///
/// # Parameter
///
/// * `severity`: Each event has a [severity][Severity]. The raw value of the severity will
/// be stored inside the uppermost 2 bits of the raw event ID
/// * `group_id`: Related events can be grouped using a group ID. The group ID will occupy the
/// next 6 bits after the severity. Therefore, the size is limited by dec 63 hex 0x3F.
/// * `unique_id`: Each event has a unique 8 bit ID occupying the last 8 bits of the
/// raw event ID
pub fn new(
group_id: <Self as GenericEvent>::GroupId,
unique_id: <Self as GenericEvent>::UniqueId,
) -> Option<Self> {
let event = EventU16::new(SEVERITY::SEVERITY, group_id, unique_id)?;
Some(Self {
event,
phantom: PhantomData,
})
}
fn group_id_as_largest_type(&self) -> LargestGroupIdRaw {
self.group_id().into()
pub const fn const_new(
group_id: <Self as GenericEvent>::GroupId,
unique_id: <Self as GenericEvent>::UniqueId,
) -> Self {
let event = EventU16::const_new(SEVERITY::SEVERITY, group_id, unique_id);
Self {
event,
phantom: PhantomData,
}
}
fn try_from_generic(expected: Severity, raw: u16) -> Result<Self, Severity> {
let severity = Severity::try_from(((raw >> 14) & 0b11) as u8).unwrap();
if severity != expected {
return Err(severity);
}
Ok(Self::const_new(
((raw >> 8) & 0x3F) as u8,
(raw & 0xFF) as u8,
))
}
}
impl EcssEnumeration for EventSmall {
impl_event_provider!(EventU16, EventU16TypedSev, u16, u8, u8);
impl EcssEnumeration for EventU16 {
fn pfc(&self) -> u8 {
16
}
@ -321,8 +479,16 @@ impl EcssEnumeration for EventSmall {
}
}
impl From<u16> for EventSmall {
fn from(raw: <Self as EventProvider>::Raw) -> Self {
//noinspection RsTraitImplementation
impl<SEVERITY: HasSeverity> EcssEnumeration for EventU16TypedSev<SEVERITY> {
delegate!(to self.event {
fn pfc(&self) -> u8;
fn write_to_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError>;
});
}
impl From<u16> for EventU16 {
fn from(raw: <Self as GenericEvent>::Raw) -> Self {
let severity = Severity::try_from(((raw >> 14) & 0b11) as u8).unwrap();
let group_id = ((raw >> 8) & 0x3F) as u8;
let unique_id = (raw & 0xFF) as u8;
@ -331,10 +497,15 @@ impl From<u16> for EventSmall {
}
}
try_from_impls!(SeverityInfo, Severity::INFO, u16, EventU16TypedSev);
try_from_impls!(SeverityLow, Severity::LOW, u16, EventU16TypedSev);
try_from_impls!(SeverityMedium, Severity::MEDIUM, u16, EventU16TypedSev);
try_from_impls!(SeverityHigh, Severity::HIGH, u16, EventU16TypedSev);
#[cfg(test)]
mod tests {
use super::Event;
use crate::events::{EventProvider, EventSmall, Severity};
use super::EventU32TypedSev;
use super::*;
use spacepackets::ecss::EcssEnumeration;
use spacepackets::ByteConversionError;
use std::mem::size_of;
@ -343,20 +514,24 @@ mod tests {
assert_eq!(size_of::<T>(), val);
}
const INFO_EVENT: Event = Event::const_new(Severity::INFO, 0, 0);
const INFO_EVENT_SMALL: EventSmall = EventSmall::const_new(Severity::INFO, 0, 0);
const HIGH_SEV_EVENT: Event = Event::const_new(Severity::HIGH, 0x3FFF, 0xFFFF);
const HIGH_SEV_EVENT_SMALL: EventSmall = EventSmall::const_new(Severity::HIGH, 0x3F, 0xff);
const INFO_EVENT: EventU32TypedSev<SeverityInfo> = EventU32TypedSev::const_new(0, 0);
const INFO_EVENT_SMALL: EventU16TypedSev<SeverityInfo> = EventU16TypedSev::const_new(0, 0);
const HIGH_SEV_EVENT: EventU32TypedSev<SeverityHigh> =
EventU32TypedSev::const_new(0x3FFF, 0xFFFF);
const HIGH_SEV_EVENT_SMALL: EventU16TypedSev<SeverityHigh> =
EventU16TypedSev::const_new(0x3F, 0xff);
#[test]
fn test_normal_from_raw_conversion() {
let conv_from_raw = Event::from(INFO_EVENT.raw());
let conv_from_raw = EventU32TypedSev::<SeverityInfo>::try_from(INFO_EVENT.raw())
.expect("Creating typed EventU32 failed");
assert_eq!(conv_from_raw, INFO_EVENT);
}
#[test]
fn test_small_from_raw_conversion() {
let conv_from_raw = EventSmall::from(INFO_EVENT_SMALL.raw());
let conv_from_raw = EventU16TypedSev::<SeverityInfo>::try_from(INFO_EVENT_SMALL.raw())
.expect("Creating typed EventU16 failed");
assert_eq!(conv_from_raw, INFO_EVENT_SMALL);
}
@ -408,18 +583,18 @@ mod tests {
#[test]
fn invalid_group_id_normal() {
assert!(Event::new(Severity::MEDIUM, 2_u16.pow(14), 0).is_none());
assert!(EventU32TypedSev::<SeverityMedium>::new(2_u16.pow(14), 0).is_none());
}
#[test]
fn invalid_group_id_small() {
assert!(EventSmall::new(Severity::MEDIUM, 2_u8.pow(6), 0).is_none());
assert!(EventU16TypedSev::<SeverityMedium>::new(2_u8.pow(6), 0).is_none());
}
#[test]
fn regular_new() {
assert_eq!(
Event::new(Severity::INFO, 0, 0).expect("Creating regular event failed"),
EventU32TypedSev::<SeverityInfo>::new(0, 0).expect("Creating regular event failed"),
INFO_EVENT
);
}
@ -427,7 +602,7 @@ mod tests {
#[test]
fn small_new() {
assert_eq!(
EventSmall::new(Severity::INFO, 0, 0).expect("Creating regular event failed"),
EventU16TypedSev::<SeverityInfo>::new(0, 0).expect("Creating regular event failed"),
INFO_EVENT_SMALL
);
}

View File

@ -255,7 +255,7 @@ mod allocvec {
#[cfg(test)]
mod tests {
use super::*;
use crate::events::{Event, Severity};
use crate::events::{EventU32, Severity};
use crate::pus::tests::CommonTmInfo;
use spacepackets::ByteConversionError;
use std::collections::VecDeque;
@ -270,7 +270,7 @@ mod tests {
#[derive(Debug, Eq, PartialEq)]
struct TmInfo {
pub common: CommonTmInfo,
pub event: Event,
pub event: EventU32,
pub aux_data: Vec<u8>,
}
@ -284,9 +284,7 @@ mod tests {
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();
let event = EventU32::from(u32::from_be_bytes(src_data[0..4].try_into().unwrap()));
let mut aux_data = Vec::new();
if src_data.len() > 4 {
aux_data.extend_from_slice(&src_data[4..]);
@ -313,7 +311,7 @@ mod tests {
reporter: &mut EventReporter,
sender: &mut TestSender,
time_stamp: &[u8],
event: Event,
event: EventU32,
severity: Severity,
aux_data: Option<&[u8]>,
) {
@ -355,7 +353,7 @@ mod tests {
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)
let event = EventU32::new(severity, EXAMPLE_GROUP_ID, EXAMPLE_EVENT_ID_0)
.expect("Error creating example event");
report_basic_event(
&mut reporter,
@ -418,7 +416,7 @@ mod tests {
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)
let event = EventU32::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());

View File

@ -1,5 +1,6 @@
use crate::events::EventProvider;
use crate::events::{EventU16TypedSev, EventU32TypedSev, GenericEvent, HasSeverity, Severity};
use alloc::boxed::Box;
use core::hash::Hash;
use hashbrown::HashSet;
use crate::pus::event::EventReporter;
@ -17,7 +18,7 @@ pub use heapless_mod::*;
/// 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<Provider: EventProvider> {
pub trait PusEventMgmtBackendProvider<Provider: GenericEvent> {
type Error;
fn event_enabled(&self, event: &Provider) -> bool;
@ -31,12 +32,12 @@ pub trait PusEventMgmtBackendProvider<Provider: EventProvider> {
/// 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: EventProvider> {
pub struct DefaultPusMgmtBackendProvider<Provider: GenericEvent> {
disabled: HashSet<Provider>,
}
impl<Provider: EventProvider> PusEventMgmtBackendProvider<Provider>
for DefaultPusMgmtBackendProvider<Provider>
impl<Provider: GenericEvent + PartialEq + Eq + Hash + Copy + Clone>
PusEventMgmtBackendProvider<Provider> for DefaultPusMgmtBackendProvider<Provider>
{
type Error = ();
fn event_enabled(&self, event: &Provider) -> bool {
@ -55,18 +56,18 @@ impl<Provider: EventProvider> PusEventMgmtBackendProvider<Provider>
#[cfg(feature = "heapless")]
pub mod heapless_mod {
use super::*;
use crate::events::{EventProvider, LargestEventRaw};
use crate::events::{GenericEvent, LargestEventRaw};
use std::marker::PhantomData;
// 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<const N: usize, Provider: EventProvider> {
pub struct HeaplessPusMgmtBckendProvider<const N: usize, Provider: GenericEvent> {
disabled: heapless::FnvIndexSet<LargestEventRaw, N>,
phantom: PhantomData<Provider>,
}
impl<const N: usize, Provider: EventProvider> PusEventMgmtBackendProvider<Provider>
impl<const N: usize, Provider: GenericEvent> PusEventMgmtBackendProvider<Provider>
for HeaplessPusMgmtBckendProvider<N, Provider>
{
type Error = ();
@ -87,24 +88,76 @@ pub mod heapless_mod {
}
}
pub struct PusEventManager<BackendError, Provider: EventProvider> {
pub struct PusEventManager<BackendError, Provider: GenericEvent> {
reporter: EventReporter,
backend: Box<dyn PusEventMgmtBackendProvider<Provider, Error = BackendError>>,
}
impl<BackendError, Provider: EventProvider> PusEventManager<BackendError, Provider> {
pub fn handle_event<E>(
impl<BackendError, Event: GenericEvent> PusEventManager<BackendError, Event> {
pub fn enable_tm_for_event(&mut self, event: &Event) -> Result<bool, BackendError> {
self.backend.enable_event_reporting(event)
}
pub fn disable_tm_for_event(&mut self, event: &Event) -> Result<bool, BackendError> {
self.backend.disable_event_reporting(event)
}
pub fn generate_pus_event_tm_generic<E>(
&mut self,
severity: Severity,
sender: &mut (impl EcssTmSender<E> + ?Sized),
time_stamp: &[u8],
event: Provider,
event: Event,
aux_data: Option<&[u8]>,
) -> Result<bool, EcssTmError<E>> {
if !self.backend.event_enabled(&event) {
return Ok(false);
}
self.reporter
match severity {
Severity::INFO => self
.reporter
.event_info(sender, time_stamp, event, aux_data)
.map(|_| true)
.map(|_| true),
Severity::LOW => self
.reporter
.event_low_severity(sender, time_stamp, event, aux_data)
.map(|_| true),
Severity::MEDIUM => self
.reporter
.event_medium_severity(sender, time_stamp, event, aux_data)
.map(|_| true),
Severity::HIGH => self
.reporter
.event_high_severity(sender, time_stamp, event, aux_data)
.map(|_| true),
}
}
}
impl<BackendError, SEVERITY: HasSeverity>
PusEventManager<BackendError, EventU32TypedSev<SEVERITY>>
{
pub fn generate_pus_event_tm<E>(
&mut self,
sender: &mut (impl EcssTmSender<E> + ?Sized),
time_stamp: &[u8],
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)
}
}

View File

@ -1,23 +1,26 @@
#![allow(dead_code, unused_imports)]
use fsrc_core::events::{Event, EventProvider, LargestEventRaw, LargestGroupIdRaw, Severity};
use fsrc_core::events::{
EventU32TypedSev, GenericEvent, HasSeverity, LargestEventRaw, LargestGroupIdRaw, Severity,
SeverityInfo, SeverityLow, SeverityMedium,
};
struct GroupIdIntrospection {
name: &'static str,
id: LargestGroupIdRaw,
}
struct EventIntrospection {
struct EventIntrospection<SEVERITY: HasSeverity + 'static> {
name: &'static str,
group_id: GroupIdIntrospection,
event: &'static Event,
event: &'static EventU32TypedSev<SEVERITY>,
info: &'static str,
}
//#[event(descr="This is some info event")]
const INFO_EVENT_0: Event = Event::const_new(Severity::INFO, 0, 0);
const INFO_EVENT_0: EventU32TypedSev<SeverityInfo> = EventU32TypedSev::const_new(0, 0);
// This is ideally auto-generated
const INFO_EVENT_0_INTROSPECTION: EventIntrospection = EventIntrospection {
const INFO_EVENT_0_INTROSPECTION: EventIntrospection<SeverityInfo> = EventIntrospection {
name: "INFO_EVENT_0",
group_id: GroupIdIntrospection {
id: 0,
@ -28,9 +31,9 @@ const INFO_EVENT_0_INTROSPECTION: EventIntrospection = EventIntrospection {
};
//#[event(descr="This is some low severity event")]
const SOME_LOW_SEV_EVENT: Event = Event::const_new(Severity::LOW, 0, 12);
const SOME_LOW_SEV_EVENT: EventU32TypedSev<SeverityLow> = EventU32TypedSev::const_new(0, 12);
const EVENT_LIST: [&'static Event; 2] = [&INFO_EVENT_0, &SOME_LOW_SEV_EVENT];
//const EVENT_LIST: [&'static Event; 2] = [&INFO_EVENT_0, &SOME_LOW_SEV_EVENT];
//#[event_group]
const TEST_GROUP_NAME: u16 = 1;
@ -38,11 +41,12 @@ const TEST_GROUP_NAME: u16 = 1;
const TEST_GROUP_NAME_NAME: &'static str = "TEST_GROUP_NAME";
//#[event(desc="Some medium severity event")]
const MEDIUM_SEV_EVENT_IN_OTHER_GROUP: Event =
Event::const_new(Severity::MEDIUM, TEST_GROUP_NAME, 0);
const MEDIUM_SEV_EVENT_IN_OTHER_GROUP: EventU32TypedSev<SeverityMedium> =
EventU32TypedSev::const_new(TEST_GROUP_NAME, 0);
// Also auto-generated
const MEDIUM_SEV_EVENT_IN_OTHER_GROUP_INTROSPECTION: EventIntrospection = EventIntrospection {
const MEDIUM_SEV_EVENT_IN_OTHER_GROUP_INTROSPECTION: EventIntrospection<SeverityMedium> =
EventIntrospection {
name: "MEDIUM_SEV_EVENT_IN_OTHER_GROUP",
group_id: GroupIdIntrospection {
name: TEST_GROUP_NAME_NAME,
@ -50,14 +54,14 @@ const MEDIUM_SEV_EVENT_IN_OTHER_GROUP_INTROSPECTION: EventIntrospection = EventI
},
event: &MEDIUM_SEV_EVENT_IN_OTHER_GROUP,
info: "Some medium severity event",
};
};
#[test]
fn main() {
let test = stringify!(INFO_EVENT);
println!("{:?}", test);
for event in EVENT_LIST {
println!("{:?}", event);
}
//let test = stringify!(INFO_EVENT);
//println!("{:?}", test);
//for event in EVENT_LIST {
// println!("{:?}", event);
//}
//let test_struct =
}