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

View File

@ -1,6 +1,7 @@
//! Event support module //! Event support module
use core::hash::Hash; use core::hash::Hash;
use delegate::delegate;
use spacepackets::ecss::{EcssEnumeration, ToBeBytes}; use spacepackets::ecss::{EcssEnumeration, ToBeBytes};
use spacepackets::{ByteConversionError, SizeMissmatch}; use spacepackets::{ByteConversionError, SizeMissmatch};
use std::marker::PhantomData; use std::marker::PhantomData;
@ -18,7 +19,34 @@ pub enum Severity {
HIGH = 3, 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 Raw;
type GroupId; type GroupId;
type UniqueId; 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 { macro_rules! impl_event_provider {
type Raw = u32; ($BaseIdent: ident, $TypedIdent: ident, $raw: ty, $gid: ty, $uid: ty) => {
type GroupId = u16; impl GenericEvent for $BaseIdent {
type UniqueId = u16; type Raw = $raw;
type GroupId = $gid;
type UniqueId = $uid;
event_provider_impl!(); event_provider_impl!();
fn raw_as_largest_type(&self) -> LargestEventRaw { fn raw_as_largest_type(&self) -> LargestEventRaw {
self.raw() self.raw().into()
} }
fn group_id_as_largest_type(&self) -> LargestGroupIdRaw { 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 { macro_rules! try_from_impls {
/// Generate an event. The raw representation of an event has 32 bits. ($SevIdent: ident, $severity: path, $raw: ty, $TypedSevIdent: ident) => {
/// If the passed group ID is invalid (too large), None wil be returned impl TryFrom<$raw> for $TypedSevIdent<$SevIdent> {
/// type Error = Severity;
/// # Parameter
/// fn try_from(raw: $raw) -> Result<Self, Self::Error> {
/// * `severity`: Each event has a [severity][Severity]. The raw value of the severity will Self::try_from_generic($severity, raw)
/// 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
#[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( pub fn new(
severity: Severity, severity: Severity,
group_id: <Self as EventProvider>::GroupId, group_id: <Self as GenericEvent>::GroupId,
unique_id: <Self as EventProvider>::UniqueId, unique_id: <Self as GenericEvent>::UniqueId,
) -> Option<Self> { ) -> Option<Self> {
if group_id > (2u16.pow(14) - 1) { if group_id > (2u16.pow(14) - 1) {
return None; 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( pub const fn const_new(
severity: Severity, severity: Severity,
group_id: <Self as EventProvider>::GroupId, group_id: <Self as GenericEvent>::GroupId,
unique_id: <Self as EventProvider>::UniqueId, unique_id: <Self as GenericEvent>::UniqueId,
) -> Self { ) -> Self {
if group_id > (2u16.pow(14) - 1) { if group_id > (2u16.pow(14) - 1) {
panic!("Group ID too large"); 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 { fn from(raw: u32) -> Self {
// Severity conversion from u8 should never fail // Severity conversion from u8 should never fail
let severity = Severity::try_from(((raw >> 30) & 0b11) as u8).unwrap(); 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 { fn pfc(&self) -> u8 {
32 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)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct EventSmall { pub struct EventU16 {
base: EventBase<u16, u8, u8>, 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. /// 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 /// If the passed group ID is invalid (too large), [None] wil be returned
/// ///
@ -260,8 +387,8 @@ impl EventSmall {
/// raw event ID /// raw event ID
pub fn new( pub fn new(
severity: Severity, severity: Severity,
group_id: <Self as EventProvider>::GroupId, group_id: <Self as GenericEvent>::GroupId,
unique_id: <Self as EventProvider>::UniqueId, unique_id: <Self as GenericEvent>::UniqueId,
) -> Option<Self> { ) -> Option<Self> {
if group_id > (2u8.pow(6) - 1) { if group_id > (2u8.pow(6) - 1) {
return None; return None;
@ -278,8 +405,8 @@ impl EventSmall {
pub const fn const_new( pub const fn const_new(
severity: Severity, severity: Severity,
group_id: <Self as EventProvider>::GroupId, group_id: <Self as GenericEvent>::GroupId,
unique_id: <Self as EventProvider>::UniqueId, unique_id: <Self as GenericEvent>::UniqueId,
) -> Self { ) -> Self {
if group_id > (2u8.pow(6) - 1) { if group_id > (2u8.pow(6) - 1) {
panic!("Group ID too large"); panic!("Group ID too large");
@ -294,24 +421,55 @@ impl EventSmall {
} }
} }
} }
impl<SEVERITY: HasSeverity> EventU16TypedSev<SEVERITY> {
impl EventProvider for EventSmall { /// Generate a small event. The raw representation of a small event has 16 bits.
type Raw = u16; /// If the passed group ID is invalid (too large), [None] wil be returned
type GroupId = u8; ///
type UniqueId = u8; /// # Parameter
///
event_provider_impl!(); /// * `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
fn raw_as_largest_type(&self) -> LargestEventRaw { /// * `group_id`: Related events can be grouped using a group ID. The group ID will occupy the
self.raw().into() /// 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 { pub const fn const_new(
self.group_id().into() 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 { fn pfc(&self) -> u8 {
16 16
} }
@ -321,8 +479,16 @@ impl EcssEnumeration for EventSmall {
} }
} }
impl From<u16> for EventSmall { //noinspection RsTraitImplementation
fn from(raw: <Self as EventProvider>::Raw) -> Self { 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 severity = Severity::try_from(((raw >> 14) & 0b11) as u8).unwrap();
let group_id = ((raw >> 8) & 0x3F) as u8; let group_id = ((raw >> 8) & 0x3F) as u8;
let unique_id = (raw & 0xFF) 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)] #[cfg(test)]
mod tests { mod tests {
use super::Event; use super::EventU32TypedSev;
use crate::events::{EventProvider, EventSmall, Severity}; use super::*;
use spacepackets::ecss::EcssEnumeration; use spacepackets::ecss::EcssEnumeration;
use spacepackets::ByteConversionError; use spacepackets::ByteConversionError;
use std::mem::size_of; use std::mem::size_of;
@ -343,20 +514,24 @@ mod tests {
assert_eq!(size_of::<T>(), val); assert_eq!(size_of::<T>(), val);
} }
const INFO_EVENT: Event = Event::const_new(Severity::INFO, 0, 0); const INFO_EVENT: EventU32TypedSev<SeverityInfo> = EventU32TypedSev::const_new(0, 0);
const INFO_EVENT_SMALL: EventSmall = EventSmall::const_new(Severity::INFO, 0, 0); const INFO_EVENT_SMALL: EventU16TypedSev<SeverityInfo> = EventU16TypedSev::const_new(0, 0);
const HIGH_SEV_EVENT: Event = Event::const_new(Severity::HIGH, 0x3FFF, 0xFFFF); const HIGH_SEV_EVENT: EventU32TypedSev<SeverityHigh> =
const HIGH_SEV_EVENT_SMALL: EventSmall = EventSmall::const_new(Severity::HIGH, 0x3F, 0xff); EventU32TypedSev::const_new(0x3FFF, 0xFFFF);
const HIGH_SEV_EVENT_SMALL: EventU16TypedSev<SeverityHigh> =
EventU16TypedSev::const_new(0x3F, 0xff);
#[test] #[test]
fn test_normal_from_raw_conversion() { 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); assert_eq!(conv_from_raw, INFO_EVENT);
} }
#[test] #[test]
fn test_small_from_raw_conversion() { 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); assert_eq!(conv_from_raw, INFO_EVENT_SMALL);
} }
@ -408,18 +583,18 @@ mod tests {
#[test] #[test]
fn invalid_group_id_normal() { 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] #[test]
fn invalid_group_id_small() { 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] #[test]
fn regular_new() { fn regular_new() {
assert_eq!( 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 INFO_EVENT
); );
} }
@ -427,7 +602,7 @@ mod tests {
#[test] #[test]
fn small_new() { fn small_new() {
assert_eq!( 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 INFO_EVENT_SMALL
); );
} }

View File

@ -255,7 +255,7 @@ mod allocvec {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::events::{Event, Severity}; use crate::events::{EventU32, Severity};
use crate::pus::tests::CommonTmInfo; use crate::pus::tests::CommonTmInfo;
use spacepackets::ByteConversionError; use spacepackets::ByteConversionError;
use std::collections::VecDeque; use std::collections::VecDeque;
@ -270,7 +270,7 @@ mod tests {
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Eq, PartialEq)]
struct TmInfo { struct TmInfo {
pub common: CommonTmInfo, pub common: CommonTmInfo,
pub event: Event, pub event: EventU32,
pub aux_data: Vec<u8>, pub aux_data: Vec<u8>,
} }
@ -284,9 +284,7 @@ mod tests {
assert!(tm.source_data().is_some()); assert!(tm.source_data().is_some());
let src_data = tm.source_data().unwrap(); let src_data = tm.source_data().unwrap();
assert!(src_data.len() >= 4); assert!(src_data.len() >= 4);
let event = Event::try_from(u32::from_be_bytes(src_data[0..4].try_into().unwrap())); let event = EventU32::from(u32::from_be_bytes(src_data[0..4].try_into().unwrap()));
assert!(event.is_ok());
let event = event.unwrap();
let mut aux_data = Vec::new(); let mut aux_data = Vec::new();
if src_data.len() > 4 { if src_data.len() > 4 {
aux_data.extend_from_slice(&src_data[4..]); aux_data.extend_from_slice(&src_data[4..]);
@ -313,7 +311,7 @@ mod tests {
reporter: &mut EventReporter, reporter: &mut EventReporter,
sender: &mut TestSender, sender: &mut TestSender,
time_stamp: &[u8], time_stamp: &[u8],
event: Event, event: EventU32,
severity: Severity, severity: Severity,
aux_data: Option<&[u8]>, aux_data: Option<&[u8]>,
) { ) {
@ -355,7 +353,7 @@ mod tests {
if let Some(err_data) = error_data { if let Some(err_data) = error_data {
error_copy.extend_from_slice(err_data); error_copy.extend_from_slice(err_data);
} }
let event = Event::new(severity, EXAMPLE_GROUP_ID, EXAMPLE_EVENT_ID_0) let event = EventU32::new(severity, EXAMPLE_GROUP_ID, EXAMPLE_EVENT_ID_0)
.expect("Error creating example event"); .expect("Error creating example event");
report_basic_event( report_basic_event(
&mut reporter, &mut reporter,
@ -418,7 +416,7 @@ mod tests {
expected_found_len: usize, expected_found_len: usize,
) { ) {
let time_stamp_empty: [u8; 7] = [0; 7]; 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"); .expect("Error creating example event");
let err = reporter.event_info(sender, &time_stamp_empty, event, None); let err = reporter.event_info(sender, &time_stamp_empty, event, None);
assert!(err.is_err()); 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 alloc::boxed::Box;
use core::hash::Hash;
use hashbrown::HashSet; use hashbrown::HashSet;
use crate::pus::event::EventReporter; use crate::pus::event::EventReporter;
@ -17,7 +18,7 @@ pub use heapless_mod::*;
/// structure to track disabled events. A more primitive and embedded friendly /// 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 /// solution could track this information in a static or pre-allocated list which contains
/// the disabled events. /// the disabled events.
pub trait PusEventMgmtBackendProvider<Provider: EventProvider> { pub trait PusEventMgmtBackendProvider<Provider: GenericEvent> {
type Error; type Error;
fn event_enabled(&self, event: &Provider) -> bool; 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 /// 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. /// the expected occasional memory allocation performed by the [HashSet] is not an issue.
#[derive(Default)] #[derive(Default)]
pub struct DefaultPusMgmtBackendProvider<Provider: EventProvider> { pub struct DefaultPusMgmtBackendProvider<Provider: GenericEvent> {
disabled: HashSet<Provider>, disabled: HashSet<Provider>,
} }
impl<Provider: EventProvider> PusEventMgmtBackendProvider<Provider> impl<Provider: GenericEvent + PartialEq + Eq + Hash + Copy + Clone>
for DefaultPusMgmtBackendProvider<Provider> PusEventMgmtBackendProvider<Provider> for DefaultPusMgmtBackendProvider<Provider>
{ {
type Error = (); type Error = ();
fn event_enabled(&self, event: &Provider) -> bool { fn event_enabled(&self, event: &Provider) -> bool {
@ -55,18 +56,18 @@ impl<Provider: EventProvider> PusEventMgmtBackendProvider<Provider>
#[cfg(feature = "heapless")] #[cfg(feature = "heapless")]
pub mod heapless_mod { pub mod heapless_mod {
use super::*; use super::*;
use crate::events::{EventProvider, LargestEventRaw}; use crate::events::{GenericEvent, LargestEventRaw};
use std::marker::PhantomData; use std::marker::PhantomData;
// TODO: After a new version of heapless is released which uses hash32 version 0.3, try using // TODO: After a new version of heapless is released which uses hash32 version 0.3, try using
// regular Event type again. // regular Event type again.
#[derive(Default)] #[derive(Default)]
pub struct HeaplessPusMgmtBckendProvider<const N: usize, Provider: EventProvider> { pub struct HeaplessPusMgmtBckendProvider<const N: usize, Provider: GenericEvent> {
disabled: heapless::FnvIndexSet<LargestEventRaw, N>, disabled: heapless::FnvIndexSet<LargestEventRaw, N>,
phantom: PhantomData<Provider>, phantom: PhantomData<Provider>,
} }
impl<const N: usize, Provider: EventProvider> PusEventMgmtBackendProvider<Provider> impl<const N: usize, Provider: GenericEvent> PusEventMgmtBackendProvider<Provider>
for HeaplessPusMgmtBckendProvider<N, Provider> for HeaplessPusMgmtBckendProvider<N, Provider>
{ {
type Error = (); type Error = ();
@ -87,24 +88,76 @@ pub mod heapless_mod {
} }
} }
pub struct PusEventManager<BackendError, Provider: EventProvider> { pub struct PusEventManager<BackendError, Provider: GenericEvent> {
reporter: EventReporter, reporter: EventReporter,
backend: Box<dyn PusEventMgmtBackendProvider<Provider, Error = BackendError>>, backend: Box<dyn PusEventMgmtBackendProvider<Provider, Error = BackendError>>,
} }
impl<BackendError, Provider: EventProvider> PusEventManager<BackendError, Provider> { impl<BackendError, Event: GenericEvent> PusEventManager<BackendError, Event> {
pub fn handle_event<E>( 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, &mut self,
severity: Severity,
sender: &mut (impl EcssTmSender<E> + ?Sized), sender: &mut (impl EcssTmSender<E> + ?Sized),
time_stamp: &[u8], time_stamp: &[u8],
event: Provider, event: Event,
aux_data: Option<&[u8]>, aux_data: Option<&[u8]>,
) -> Result<bool, EcssTmError<E>> { ) -> Result<bool, EcssTmError<E>> {
if !self.backend.event_enabled(&event) { if !self.backend.event_enabled(&event) {
return Ok(false); return Ok(false);
} }
self.reporter match severity {
Severity::INFO => self
.reporter
.event_info(sender, time_stamp, event, aux_data) .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)] #![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 { struct GroupIdIntrospection {
name: &'static str, name: &'static str,
id: LargestGroupIdRaw, id: LargestGroupIdRaw,
} }
struct EventIntrospection { struct EventIntrospection<SEVERITY: HasSeverity + 'static> {
name: &'static str, name: &'static str,
group_id: GroupIdIntrospection, group_id: GroupIdIntrospection,
event: &'static Event, event: &'static EventU32TypedSev<SEVERITY>,
info: &'static str, info: &'static str,
} }
//#[event(descr="This is some info event")] //#[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 // This is ideally auto-generated
const INFO_EVENT_0_INTROSPECTION: EventIntrospection = EventIntrospection { const INFO_EVENT_0_INTROSPECTION: EventIntrospection<SeverityInfo> = EventIntrospection {
name: "INFO_EVENT_0", name: "INFO_EVENT_0",
group_id: GroupIdIntrospection { group_id: GroupIdIntrospection {
id: 0, id: 0,
@ -28,9 +31,9 @@ const INFO_EVENT_0_INTROSPECTION: EventIntrospection = EventIntrospection {
}; };
//#[event(descr="This is some low severity event")] //#[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] //#[event_group]
const TEST_GROUP_NAME: u16 = 1; 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"; const TEST_GROUP_NAME_NAME: &'static str = "TEST_GROUP_NAME";
//#[event(desc="Some medium severity event")] //#[event(desc="Some medium severity event")]
const MEDIUM_SEV_EVENT_IN_OTHER_GROUP: Event = const MEDIUM_SEV_EVENT_IN_OTHER_GROUP: EventU32TypedSev<SeverityMedium> =
Event::const_new(Severity::MEDIUM, TEST_GROUP_NAME, 0); EventU32TypedSev::const_new(TEST_GROUP_NAME, 0);
// Also auto-generated // 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", name: "MEDIUM_SEV_EVENT_IN_OTHER_GROUP",
group_id: GroupIdIntrospection { group_id: GroupIdIntrospection {
name: TEST_GROUP_NAME_NAME, 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, event: &MEDIUM_SEV_EVENT_IN_OTHER_GROUP,
info: "Some medium severity event", info: "Some medium severity event",
}; };
#[test] #[test]
fn main() { fn main() {
let test = stringify!(INFO_EVENT); //let test = stringify!(INFO_EVENT);
println!("{:?}", test); //println!("{:?}", test);
for event in EVENT_LIST { //for event in EVENT_LIST {
println!("{:?}", event); // println!("{:?}", event);
} //}
//let test_struct = //let test_struct =
} }