Merge branch 'pus-event-manager' of https://egit.irs.uni-stuttgart.de/rust/fsrc-launchpad into pus-event-manager

This commit is contained in:
Robin Müller 2022-11-02 11:08:06 +01:00
commit a66e8b009c
6 changed files with 306 additions and 37 deletions

View File

@ -411,7 +411,7 @@ impl EcssEnumeration for EventU32 {
32
}
fn write_to_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError> {
fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError> {
self.base.write_to_bytes(self.raw(), buf, self.byte_width())
}
}
@ -420,7 +420,7 @@ impl EcssEnumeration for EventU32 {
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>;
fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError>;
});
}
@ -542,11 +542,12 @@ impl<SEVERITY: HasSeverity> EventU16TypedSev<SEVERITY> {
impl_event_provider!(EventU16, EventU16TypedSev, u16, u8, u8);
impl EcssEnumeration for EventU16 {
#[inline]
fn pfc(&self) -> u8 {
16
}
fn write_to_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError> {
fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError> {
self.base.write_to_bytes(self.raw(), buf, self.byte_width())
}
}
@ -555,7 +556,7 @@ impl EcssEnumeration for EventU16 {
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>;
fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError>;
});
}
@ -574,6 +575,34 @@ try_from_impls!(SeverityLow, Severity::LOW, u16, EventU16TypedSev);
try_from_impls!(SeverityMedium, Severity::MEDIUM, u16, EventU16TypedSev);
try_from_impls!(SeverityHigh, Severity::HIGH, u16, EventU16TypedSev);
impl<Severity: HasSeverity> PartialEq<EventU32> for EventU32TypedSev<Severity> {
#[inline]
fn eq(&self, other: &EventU32) -> bool {
self.raw() == other.raw()
}
}
impl<Severity: HasSeverity> PartialEq<EventU32TypedSev<Severity>> for EventU32 {
#[inline]
fn eq(&self, other: &EventU32TypedSev<Severity>) -> bool {
self.raw() == other.raw()
}
}
impl<Severity: HasSeverity> PartialEq<EventU16> for EventU16TypedSev<Severity> {
#[inline]
fn eq(&self, other: &EventU16) -> bool {
self.raw() == other.raw()
}
}
impl<Severity: HasSeverity> PartialEq<EventU16TypedSev<Severity>> for EventU16 {
#[inline]
fn eq(&self, other: &EventU16TypedSev<Severity>) -> bool {
self.raw() == other.raw()
}
}
#[cfg(test)]
mod tests {
use super::EventU32TypedSev;
@ -713,7 +742,7 @@ mod tests {
#[test]
fn write_to_buf() {
let mut buf: [u8; 4] = [0; 4];
assert!(HIGH_SEV_EVENT.write_to_bytes(&mut buf).is_ok());
assert!(HIGH_SEV_EVENT.write_to_be_bytes(&mut buf).is_ok());
let val_from_raw = u32::from_be_bytes(buf);
assert_eq!(val_from_raw, 0xFFFFFFFF);
}
@ -721,7 +750,7 @@ mod tests {
#[test]
fn write_to_buf_small() {
let mut buf: [u8; 2] = [0; 2];
assert!(HIGH_SEV_EVENT_SMALL.write_to_bytes(&mut buf).is_ok());
assert!(HIGH_SEV_EVENT_SMALL.write_to_be_bytes(&mut buf).is_ok());
let val_from_raw = u16::from_be_bytes(buf);
assert_eq!(val_from_raw, 0xFFFF);
}
@ -729,7 +758,7 @@ mod tests {
#[test]
fn write_to_buf_insufficient_buf() {
let mut buf: [u8; 3] = [0; 3];
let err = HIGH_SEV_EVENT.write_to_bytes(&mut buf);
let err = HIGH_SEV_EVENT.write_to_be_bytes(&mut buf);
assert!(err.is_err());
let err = err.unwrap_err();
if let ByteConversionError::ToSliceTooSmall(missmatch) = err {
@ -741,7 +770,7 @@ mod tests {
#[test]
fn write_to_buf_small_insufficient_buf() {
let mut buf: [u8; 1] = [0; 1];
let err = HIGH_SEV_EVENT_SMALL.write_to_bytes(&mut buf);
let err = HIGH_SEV_EVENT_SMALL.write_to_be_bytes(&mut buf);
assert!(err.is_err());
let err = err.unwrap_err();
if let ByteConversionError::ToSliceTooSmall(missmatch) = err {

View File

@ -152,7 +152,7 @@ impl EventReporterBase {
time_stamp,
);
let mut current_idx = 0;
event_id.write_to_bytes(&mut buf[0..event_id.byte_width()])?;
event_id.write_to_be_bytes(&mut buf[0..event_id.byte_width()])?;
current_idx += event_id.byte_width();
if let Some(aux_data) = aux_data {
buf[current_idx..current_idx + aux_data.len()].copy_from_slice(aux_data);

View File

@ -536,7 +536,7 @@ impl VerificationReporterBasic {
idx += RequestId::SIZE_AS_BYTES;
if let Some(step) = step {
// Size check was done beforehand
step.write_to_bytes(&mut buf[idx..idx + step.byte_width() as usize])
step.write_to_be_bytes(&mut buf[idx..idx + step.byte_width() as usize])
.unwrap();
}
let mut sp_header = SpHeader::tm(self.apid(), 0, 0).unwrap();
@ -571,13 +571,13 @@ impl VerificationReporterBasic {
idx += RequestId::SIZE_AS_BYTES;
if let Some(step) = step {
// Size check done beforehand
step.write_to_bytes(&mut buf[idx..idx + step.byte_width() as usize])
step.write_to_be_bytes(&mut buf[idx..idx + step.byte_width() as usize])
.unwrap();
idx += step.byte_width() as usize;
}
params
.failure_code
.write_to_bytes(&mut buf[idx..idx + params.failure_code.byte_width() as usize])?;
.write_to_be_bytes(&mut buf[idx..idx + params.failure_code.byte_width() as usize])?;
idx += params.failure_code.byte_width() as usize;
if let Some(failure_data) = params.failure_data {
buf[idx..idx + failure_data.len()].copy_from_slice(failure_data);
@ -1344,7 +1344,7 @@ mod tests {
let fail_code = EcssEnumU8::new(10);
let fail_data = EcssEnumU32::new(12);
let mut fail_data_raw = [0; 4];
fail_data.write_to_bytes(&mut fail_data_raw).unwrap();
fail_data.write_to_be_bytes(&mut fail_data_raw).unwrap();
let fail_params = FailParams::new(&EMPTY_STAMP, &fail_code, Some(fail_data_raw.as_slice()));
b.vr.acceptance_failure(tok, &mut sender, fail_params)
.expect("Sending acceptance success failed");

View File

@ -32,7 +32,40 @@ use core::fmt::Debug;
use core::mem::size_of;
use paste::paste;
pub use spacepackets::ecss::ToBeBytes;
use spacepackets::ecss::{EcssEnumU16, EcssEnumU32, EcssEnumU64, EcssEnumU8};
use spacepackets::ecss::{EcssEnumU16, EcssEnumU32, EcssEnumU64, EcssEnumU8, EcssEnumeration};
use spacepackets::ByteConversionError;
use spacepackets::SizeMissmatch;
/// Generic trait which is used for objects which can be converted into a raw network (big) endian
/// byte format.
pub trait WritableAsBeBytes {
fn raw_len(&self) -> usize;
/// Writes the object to a raw buffer in network endianness (big)
fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError>;
}
macro_rules! param_to_be_bytes_impl {
($Newtype: ident) => {
impl WritableAsBeBytes for $Newtype {
#[inline]
fn raw_len(&self) -> usize {
size_of::<<Self as ToBeBytes>::ByteArray>()
}
fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
let raw_len = self.raw_len();
if buf.len() < raw_len {
return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch {
found: buf.len(),
expected: raw_len,
}));
}
buf[0..raw_len].copy_from_slice(&self.to_be_bytes());
Ok(raw_len)
}
}
};
}
macro_rules! primitive_newtypes_with_eq {
($($ty: ty,)+) => {
@ -45,6 +78,10 @@ macro_rules! primitive_newtypes_with_eq {
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct [<$ty:upper Triplet>](pub $ty, pub $ty, pub $ty);
param_to_be_bytes_impl!([<$ty:upper>]);
param_to_be_bytes_impl!([<$ty:upper Pair>]);
param_to_be_bytes_impl!([<$ty:upper Triplet>]);
impl From<$ty> for [<$ty:upper>] {
fn from(v: $ty) -> Self {
Self(v)
@ -76,6 +113,10 @@ macro_rules! primitive_newtypes {
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct [<$ty:upper Triplet>](pub $ty, pub $ty, pub $ty);
param_to_be_bytes_impl!([<$ty:upper>]);
param_to_be_bytes_impl!([<$ty:upper Pair>]);
param_to_be_bytes_impl!([<$ty:upper Triplet>]);
impl From<$ty> for [<$ty:upper>] {
fn from(v: $ty) -> Self {
Self(v)
@ -99,7 +140,7 @@ macro_rules! primitive_newtypes {
primitive_newtypes_with_eq!(u8, u16, u32, u64, i8, i16, i32, i64,);
primitive_newtypes!(f32, f64,);
macro_rules! scalar_to_be_bytes_impl {
macro_rules! scalar_byte_conversions_impl {
($($ty: ty,)+) => {
$(
paste! {
@ -109,12 +150,26 @@ macro_rules! scalar_to_be_bytes_impl {
self.0.to_be_bytes()
}
}
impl TryFrom<&[u8]> for [<$ty:upper>] {
type Error = ByteConversionError;
fn try_from(v: &[u8]) -> Result<Self, Self::Error> {
if v.len() < size_of::<$ty>() {
return Err(ByteConversionError::FromSliceTooSmall(SizeMissmatch {
expected: size_of::<$ty>(),
found: v.len()
}));
}
Ok([<$ty:upper>]($ty::from_be_bytes(v[0..size_of::<$ty>()].try_into().unwrap())))
}
}
}
)+
}
}
macro_rules! pair_to_be_bytes_impl {
macro_rules! pair_byte_conversions_impl {
($($ty: ty,)+) => {
$(
paste! {
@ -129,6 +184,23 @@ macro_rules! pair_to_be_bytes_impl {
array
}
}
impl TryFrom<&[u8]> for [<$ty:upper Pair>] {
type Error = ByteConversionError;
fn try_from(v: &[u8]) -> Result<Self, Self::Error> {
if v.len() < 2 * size_of::<$ty>() {
return Err(ByteConversionError::FromSliceTooSmall(SizeMissmatch {
expected: 2 * size_of::<$ty>(),
found: v.len()
}));
}
Ok([<$ty:upper Pair>](
$ty::from_be_bytes(v[0..size_of::<$ty>()].try_into().unwrap()),
$ty::from_be_bytes(v[size_of::<$ty>()..2 * size_of::<$ty>()].try_into().unwrap())
))
}
}
}
)+
}
@ -144,20 +216,37 @@ macro_rules! triplet_to_be_bytes_impl {
let mut array = [0; size_of::<$ty>() * 3];
array[0..size_of::<$ty>()].copy_from_slice(&self.0.to_be_bytes());
array[
size_of::<$ty>()..2* size_of::<$ty>()
size_of::<$ty>()..2 * size_of::<$ty>()
].copy_from_slice(&self.1.to_be_bytes());
array[
2 * size_of::<$ty>()..3* size_of::<$ty>()
2 * size_of::<$ty>()..3 * size_of::<$ty>()
].copy_from_slice(&self.2.to_be_bytes());
array
}
}
impl TryFrom<&[u8]> for [<$ty:upper Triplet>] {
type Error = ByteConversionError;
fn try_from(v: &[u8]) -> Result<Self, Self::Error> {
if v.len() < 3 * size_of::<$ty>() {
return Err(ByteConversionError::FromSliceTooSmall(SizeMissmatch {
expected: 3 * size_of::<$ty>(),
found: v.len()
}));
}
Ok([<$ty:upper Triplet>](
$ty::from_be_bytes(v[0..size_of::<$ty>()].try_into().unwrap()),
$ty::from_be_bytes(v[size_of::<$ty>()..2 * size_of::<$ty>()].try_into().unwrap()),
$ty::from_be_bytes(v[2 * size_of::<$ty>()..3 * size_of::<$ty>()].try_into().unwrap())
))
}
}
}
)+
}
}
scalar_to_be_bytes_impl!(u8, u16, u32, u64, i8, i16, i32, i64, f32, f64,);
scalar_byte_conversions_impl!(u8, u16, u32, u64, i8, i16, i32, i64, f32, f64,);
impl ToBeBytes for U8Pair {
type ByteArray = [u8; 2];
@ -205,7 +294,7 @@ impl ToBeBytes for I8Triplet {
}
}
pair_to_be_bytes_impl!(u16, u32, u64, i16, i32, i64, f32, f64,);
pair_byte_conversions_impl!(u16, u32, u64, i16, i32, i64, f32, f64,);
triplet_to_be_bytes_impl!(u16, u32, u64, i16, i32, i64, f32, f64,);
/// Generic enumeration for additonal parameters only consisting of primitive data types.
@ -237,6 +326,66 @@ pub enum ParamsRaw {
F64(F64),
}
impl WritableAsBeBytes for ParamsRaw {
fn raw_len(&self) -> usize {
match self {
ParamsRaw::U8(v) => v.raw_len(),
ParamsRaw::U8Pair(v) => v.raw_len(),
ParamsRaw::U8Triplet(v) => v.raw_len(),
ParamsRaw::I8(v) => v.raw_len(),
ParamsRaw::I8Pair(v) => v.raw_len(),
ParamsRaw::I8Triplet(v) => v.raw_len(),
ParamsRaw::U16(v) => v.raw_len(),
ParamsRaw::U16Pair(v) => v.raw_len(),
ParamsRaw::U16Triplet(v) => v.raw_len(),
ParamsRaw::I16(v) => v.raw_len(),
ParamsRaw::I16Pair(v) => v.raw_len(),
ParamsRaw::I16Triplet(v) => v.raw_len(),
ParamsRaw::U32(v) => v.raw_len(),
ParamsRaw::U32Pair(v) => v.raw_len(),
ParamsRaw::U32Triplet(v) => v.raw_len(),
ParamsRaw::I32(v) => v.raw_len(),
ParamsRaw::I32Pair(v) => v.raw_len(),
ParamsRaw::I32Triplet(v) => v.raw_len(),
ParamsRaw::F32(v) => v.raw_len(),
ParamsRaw::F32Pair(v) => v.raw_len(),
ParamsRaw::F32Triplet(v) => v.raw_len(),
ParamsRaw::U64(v) => v.raw_len(),
ParamsRaw::I64(v) => v.raw_len(),
ParamsRaw::F64(v) => v.raw_len(),
}
}
fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
match self {
ParamsRaw::U8(v) => v.write_to_be_bytes(buf),
ParamsRaw::U8Pair(v) => v.write_to_be_bytes(buf),
ParamsRaw::U8Triplet(v) => v.write_to_be_bytes(buf),
ParamsRaw::I8(v) => v.write_to_be_bytes(buf),
ParamsRaw::I8Pair(v) => v.write_to_be_bytes(buf),
ParamsRaw::I8Triplet(v) => v.write_to_be_bytes(buf),
ParamsRaw::U16(v) => v.write_to_be_bytes(buf),
ParamsRaw::U16Pair(v) => v.write_to_be_bytes(buf),
ParamsRaw::U16Triplet(v) => v.write_to_be_bytes(buf),
ParamsRaw::I16(v) => v.write_to_be_bytes(buf),
ParamsRaw::I16Pair(v) => v.write_to_be_bytes(buf),
ParamsRaw::I16Triplet(v) => v.write_to_be_bytes(buf),
ParamsRaw::U32(v) => v.write_to_be_bytes(buf),
ParamsRaw::U32Pair(v) => v.write_to_be_bytes(buf),
ParamsRaw::U32Triplet(v) => v.write_to_be_bytes(buf),
ParamsRaw::I32(v) => v.write_to_be_bytes(buf),
ParamsRaw::I32Pair(v) => v.write_to_be_bytes(buf),
ParamsRaw::I32Triplet(v) => v.write_to_be_bytes(buf),
ParamsRaw::F32(v) => v.write_to_be_bytes(buf),
ParamsRaw::F32Pair(v) => v.write_to_be_bytes(buf),
ParamsRaw::F32Triplet(v) => v.write_to_be_bytes(buf),
ParamsRaw::U64(v) => v.write_to_be_bytes(buf),
ParamsRaw::I64(v) => v.write_to_be_bytes(buf),
ParamsRaw::F64(v) => v.write_to_be_bytes(buf),
}
}
}
macro_rules! params_raw_from_newtype {
($($newtype: ident,)+) => {
$(
@ -263,6 +412,45 @@ pub enum EcssEnumParams {
U64(EcssEnumU64),
}
macro_rules! writable_as_be_bytes_ecss_enum_impl {
($EnumIdent: ident) => {
impl WritableAsBeBytes for $EnumIdent {
fn raw_len(&self) -> usize {
self.byte_width()
}
fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
EcssEnumeration::write_to_be_bytes(self, buf).map(|_| self.byte_width())
}
}
};
}
writable_as_be_bytes_ecss_enum_impl!(EcssEnumU8);
writable_as_be_bytes_ecss_enum_impl!(EcssEnumU16);
writable_as_be_bytes_ecss_enum_impl!(EcssEnumU32);
writable_as_be_bytes_ecss_enum_impl!(EcssEnumU64);
impl WritableAsBeBytes for EcssEnumParams {
fn raw_len(&self) -> usize {
match self {
EcssEnumParams::U8(e) => e.byte_width(),
EcssEnumParams::U16(e) => e.byte_width(),
EcssEnumParams::U32(e) => e.byte_width(),
EcssEnumParams::U64(e) => e.byte_width(),
}
}
fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
match self {
EcssEnumParams::U8(e) => WritableAsBeBytes::write_to_be_bytes(e, buf),
EcssEnumParams::U16(e) => WritableAsBeBytes::write_to_be_bytes(e, buf),
EcssEnumParams::U32(e) => WritableAsBeBytes::write_to_be_bytes(e, buf),
EcssEnumParams::U64(e) => WritableAsBeBytes::write_to_be_bytes(e, buf),
}
}
}
/// Generic enumeration for parameters which do not rely on heap allocations.
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum ParamsHeapless {

View File

@ -2,7 +2,9 @@ use fsrc_core::event_man::{EventManager, MpscEventReceiver, MpscEventU32SendProv
use fsrc_core::events::{EventU32, EventU32TypedSev, Severity, SeverityInfo};
use fsrc_core::pus::event_man::{DefaultPusMgmtBackendProvider, EventReporter, PusEventTmManager};
use fsrc_core::pus::{EcssTmError, EcssTmSender};
use fsrc_core::util::Params;
use fsrc_core::util::U32Pair;
use fsrc_core::util::{Params, ParamsHeapless, WritableAsBeBytes};
use spacepackets::ecss::PusPacket;
use spacepackets::tm::PusTm;
use std::sync::mpsc::{channel, SendError, TryRecvError};
use std::thread;
@ -42,28 +44,48 @@ fn test_threaded_usage() {
// PUS + Generic event manager thread
let jh0 = thread::spawn(move || {
let mut sender = EventTmSender { sender: event_tx };
let mut event_cnt = 0;
let mut params_array: [u8; 128] = [0; 128];
loop {
let res = event_man.try_event_handling();
assert!(res.is_ok());
match pus_event_man_rx.try_recv() {
Ok((event, aux_data)) => {
// TODO: Convert auxiliary data into raw byte format
if let Some(aux_data) = aux_data {
let mut gen_event = |aux_data| {
pus_event_man.generate_pus_event_tm_generic(
&mut sender,
&EMPTY_STAMP,
event,
aux_data,
)
};
let res = if let Some(aux_data) = aux_data {
match aux_data {
Params::Heapless(_) => {}
Params::Vec(_) => {}
Params::String(_) => {}
Params::Heapless(heapless) => match heapless {
ParamsHeapless::Raw(raw) => {
raw.write_to_be_bytes(&mut params_array)
.expect("Writing raw parameter failed");
gen_event(Some(&params_array[0..raw.raw_len()]))
}
ParamsHeapless::EcssEnum(e) => {
e.write_to_be_bytes(&mut params_array)
.expect("Writing ECSS enum failed");
gen_event(Some(&params_array[0..e.raw_len()]))
}
ParamsHeapless::Store(_) => gen_event(None),
},
Params::Vec(vec) => gen_event(Some(vec.as_slice())),
Params::String(str) => gen_event(Some(str.as_bytes())),
}
}
let res = pus_event_man.generate_pus_event_tm_generic(
&mut sender,
&EMPTY_STAMP,
event,
None,
);
} else {
gen_event(None)
};
event_cnt += 1;
assert!(res.is_ok());
assert!(res.unwrap());
break;
if event_cnt == 2 {
break;
}
}
Err(e) => {
if let TryRecvError::Disconnected = e {
@ -82,7 +104,20 @@ fn test_threaded_usage() {
loop {
match event_rx.try_recv() {
// Event TM received successfully
Ok(_) => break,
Ok(event_tm) => {
let tm =
PusTm::from_bytes(event_tm.as_slice(), 7).expect("Deserializing TM failed");
assert_eq!(tm.0.service(), 5);
assert_eq!(tm.0.subservice(), 1);
let src_data = tm.0.source_data();
assert!(src_data.is_some());
let src_data = src_data.unwrap();
assert_eq!(src_data.len(), 4);
let event =
EventU32::from(u32::from_be_bytes(src_data[0..4].try_into().unwrap()));
assert_eq!(event, INFO_EVENT);
break;
}
Err(e) => {
if let TryRecvError::Disconnected = e {
panic!("Event sender disconnected!")
@ -99,7 +134,24 @@ fn test_threaded_usage() {
loop {
match event_rx.try_recv() {
// Event TM received successfully
Ok(_) => break,
Ok(event_tm) => {
let tm =
PusTm::from_bytes(event_tm.as_slice(), 7).expect("Deserializing TM failed");
assert_eq!(tm.0.service(), 5);
assert_eq!(tm.0.subservice(), 2);
let src_data = tm.0.source_data();
assert!(src_data.is_some());
let src_data = src_data.unwrap();
assert_eq!(src_data.len(), 12);
let event =
EventU32::from(u32::from_be_bytes(src_data[0..4].try_into().unwrap()));
assert_eq!(event, LOW_SEV_EVENT);
let u32_pair: U32Pair =
src_data[4..].try_into().expect("Creating U32Pair failed");
assert_eq!(u32_pair.0, 2);
assert_eq!(u32_pair.1, 3);
break;
}
Err(e) => {
if let TryRecvError::Disconnected = e {
panic!("Event sender disconnected!")

@ -1 +1 @@
Subproject commit 38b789ca6d061239e6cecc76f0843d6ba8b9bd01
Subproject commit f8199ca87a8fc97a51d09bf8bfa57627cd54f74d