Continue update
Some checks failed
Rust/sat-rs/pipeline/pr-main There was a failure building this commit

This commit is contained in:
2024-04-02 09:55:30 +02:00
parent 5c1acfe912
commit bc04275763
44 changed files with 3384 additions and 3437 deletions

View File

@ -71,7 +71,9 @@ features = ["all"]
optional = true
[dependencies.spacepackets]
git = "https://egit.irs.uni-stuttgart.de/rust/spacepackets.git"
version = "0.11.0-rc.0"
branch = "main"
default-features = false
[dependencies.cobs]

View File

@ -19,8 +19,8 @@ impl HkRequest {
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum HkRequestVariant {
OneShot,
Enable,
Disable,
EnablePeriodic,
DisablePeriodic,
ModifyCollectionInterval(CollectionIntervalFactor),
}

View File

@ -12,7 +12,7 @@ pub use std_mod::*;
use crate::{
queue::GenericTargetedMessagingError,
request::{GenericMessage, MessageReceiver, MessageReceiverWithId, RequestId},
request::{GenericMessage, MessageMetadata, MessageReceiver, MessageReceiverWithId, RequestId},
ComponentId,
};
@ -109,6 +109,8 @@ impl TargetedModeCommand {
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum ModeRequest {
/// Mode information. Can be used to notify other components of changed modes.
ModeInfo(ModeAndSubmode),
SetMode(ModeAndSubmode),
ReadMode,
AnnounceMode,
@ -125,8 +127,6 @@ pub struct TargetedModeRequest {
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum ModeReply {
/// Unrequest mode information. Can be used to notify other components of changed modes.
ModeInfo(ModeAndSubmode),
/// Reply to a mode request to confirm the commanded mode was reached.
ModeReply(ModeAndSubmode),
// Can not reach the commanded mode. Contains a reason as a [ResultU16].
@ -184,13 +184,20 @@ impl From<GenericTargetedMessagingError> for ModeError {
pub trait ModeRequestHandler: ModeProvider {
fn start_transition(
&mut self,
request_id: RequestId,
sender_id: ComponentId,
requestor: MessageMetadata,
mode_and_submode: ModeAndSubmode,
) -> Result<(), ModeError>;
fn announce_mode(&self, request_id: RequestId, sender_id: ComponentId, recursive: bool);
fn handle_mode_reached(&mut self) -> Result<(), GenericTargetedMessagingError>;
fn announce_mode(&self, requestor_info: MessageMetadata, recursive: bool);
fn handle_mode_reached(
&mut self,
requestor_info: Option<MessageMetadata>,
) -> Result<(), GenericTargetedMessagingError>;
fn send_mode_reply(
&self,
requestor_info: MessageMetadata,
reply: ModeReply,
) -> Result<(), GenericTargetedMessagingError>;
}
pub trait ModeReplyReceiver {
@ -210,10 +217,10 @@ impl<R: MessageReceiver<ModeReply>> ModeReplyReceiver for MessageReceiverWithId<
pub trait ModeReplySender {
fn local_channel_id(&self) -> ComponentId;
/// The requestor is assumed to be the target of the reply.
fn send_mode_reply(
&self,
request_id: RequestId,
target_id: ComponentId,
requestor_info: MessageMetadata,
reply: ModeReply,
) -> Result<(), GenericTargetedMessagingError>;
}
@ -225,7 +232,7 @@ pub mod alloc_mod {
mode::ModeRequest,
queue::GenericTargetedMessagingError,
request::{
MessageSender, MessageSenderAndReceiver, MessageSenderMap, MessageSenderMapWithId,
MessageMetadata, MessageSender, MessageSenderAndReceiver, MessageSenderMap,
RequestAndReplySenderAndReceiver, RequestId,
},
ComponentId,
@ -236,12 +243,11 @@ pub mod alloc_mod {
impl<S: MessageSender<ModeReply>> MessageSenderMap<ModeReply, S> {
pub fn send_mode_reply(
&self,
request_id: RequestId,
local_id: ComponentId,
requestor_info: MessageMetadata,
target_id: ComponentId,
request: ModeReply,
) -> Result<(), GenericTargetedMessagingError> {
self.send_message(request_id, local_id, target_id, request)
self.send_message(requestor_info, target_id, request)
}
pub fn add_reply_target(&mut self, target_id: ComponentId, request_sender: S) {
@ -249,6 +255,7 @@ pub mod alloc_mod {
}
}
/*
impl<S: MessageSender<ModeReply>> ModeReplySender for MessageSenderMapWithId<ModeReply, S> {
fn send_mode_reply(
&self,
@ -263,6 +270,7 @@ pub mod alloc_mod {
self.local_channel_id
}
}
*/
impl<FROM, S: MessageSender<ModeReply>, R: MessageReceiver<FROM>> ModeReplySender
for MessageSenderAndReceiver<ModeReply, FROM, S, R>
@ -273,14 +281,12 @@ pub mod alloc_mod {
fn send_mode_reply(
&self,
request_id: RequestId,
target_id: ComponentId,
requestor_info: MessageMetadata,
request: ModeReply,
) -> Result<(), GenericTargetedMessagingError> {
self.message_sender_map.send_mode_reply(
request_id,
self.local_channel_id(),
target_id,
MessageMetadata::new(requestor_info.request_id(), self.local_channel_id()),
requestor_info.sender_id(),
request,
)
}
@ -324,14 +330,12 @@ pub mod alloc_mod {
fn send_mode_reply(
&self,
request_id: RequestId,
target_id: ComponentId,
requestor_info: MessageMetadata,
request: ModeReply,
) -> Result<(), GenericTargetedMessagingError> {
self.reply_sender_map.send_mode_reply(
request_id,
self.local_channel_id(),
target_id,
MessageMetadata::new(requestor_info.request_id(), self.local_channel_id()),
requestor_info.sender_id(),
request,
)
}
@ -368,11 +372,14 @@ pub mod alloc_mod {
pub fn send_mode_reply(
&self,
request_id: RequestId,
target_id: ComponentId,
requestor_info: MessageMetadata,
reply: ModeReply,
) -> Result<(), GenericTargetedMessagingError> {
self.send_message(request_id, target_id, reply)
self.send_message(
requestor_info.request_id(),
requestor_info.sender_id(),
reply,
)
}
}
@ -405,12 +412,11 @@ pub mod alloc_mod {
impl<S: MessageSender<ModeRequest>> MessageSenderMap<ModeRequest, S> {
pub fn send_mode_request(
&self,
request_id: RequestId,
local_id: ComponentId,
requestor_info: MessageMetadata,
target_id: ComponentId,
request: ModeRequest,
) -> Result<(), GenericTargetedMessagingError> {
self.send_message(request_id, local_id, target_id, request)
self.send_message(requestor_info, target_id, request)
}
pub fn add_request_target(&mut self, target_id: ComponentId, request_sender: S) {
@ -418,6 +424,7 @@ pub mod alloc_mod {
}
}
/*
impl<S: MessageSender<ModeRequest>> ModeRequestSender for MessageSenderMapWithId<ModeRequest, S> {
fn local_channel_id(&self) -> ComponentId {
self.local_channel_id
@ -432,6 +439,7 @@ pub mod alloc_mod {
self.send_message(request_id, target_id, request)
}
}
*/
impl<TO, S: MessageSender<TO>, R: MessageReceiver<ModeRequest>> ModeRequestReceiver
for MessageSenderAndReceiver<TO, ModeRequest, S, R>
@ -457,8 +465,7 @@ pub mod alloc_mod {
request: ModeRequest,
) -> Result<(), GenericTargetedMessagingError> {
self.message_sender_map.send_mode_request(
request_id,
self.local_channel_id(),
MessageMetadata::new(request_id, self.local_channel_id()),
target_id,
request,
)
@ -499,8 +506,7 @@ pub mod alloc_mod {
request: ModeRequest,
) -> Result<(), GenericTargetedMessagingError> {
self.request_sender_map.send_mode_request(
request_id,
self.local_channel_id(),
MessageMetadata::new(request_id, self.local_channel_id()),
target_id,
request,
)

View File

@ -1,8 +1,7 @@
use crate::{
action::{ActionId, ActionRequest},
params::Params,
request::{GenericMessage, RequestId},
ComponentId,
request::{GenericMessage, MessageMetadata, RequestId},
};
use satrs_shared::res_code::ResultU16;
@ -57,12 +56,11 @@ pub type GenericActionReplyPus = GenericMessage<PusActionReply>;
impl GenericActionReplyPus {
pub fn new_action_reply(
request_id: RequestId,
sender_id: ComponentId,
requestor_info: MessageMetadata,
action_id: ActionId,
reply: ActionReplyVariant,
) -> Self {
Self::new(request_id, sender_id, PusActionReply::new(action_id, reply))
Self::new(requestor_info, PusActionReply::new(action_id, reply))
}
}

View File

@ -2,6 +2,7 @@ use crate::pus::{source_buffer_large_enough, EcssTmtcError};
use spacepackets::ecss::tm::PusTmCreator;
use spacepackets::ecss::tm::PusTmSecondaryHeader;
use spacepackets::ecss::{EcssEnumeration, PusError};
use spacepackets::ByteConversionError;
use spacepackets::{SpHeader, MAX_APID};
use crate::pus::EcssTmSenderCore;
@ -9,145 +10,125 @@ use crate::pus::EcssTmSenderCore;
pub use alloc_mod::EventReporter;
pub use spacepackets::ecss::event::*;
pub struct EventReporterBase {
msg_count: u16,
pub struct EventReportCreator {
apid: u16,
pub dest_id: u16,
}
impl EventReporterBase {
impl EventReportCreator {
pub fn new(apid: u16) -> Option<Self> {
if apid > MAX_APID {
return None;
}
Some(Self {
msg_count: 0,
// msg_count: 0,
dest_id: 0,
apid,
})
}
pub fn event_info(
&mut self,
buf: &mut [u8],
sender: &mut (impl EcssTmSenderCore + ?Sized),
time_stamp: &[u8],
pub fn event_info<'time, 'src_data>(
&self,
src_data_buf: &'src_data mut [u8],
time_stamp: &'time [u8],
event_id: impl EcssEnumeration,
aux_data: Option<&[u8]>,
) -> Result<(), EcssTmtcError> {
aux_data: Option<&'src_data [u8]>,
) -> Result<PusTmCreator<'time, 'src_data>, ByteConversionError> {
self.generate_and_send_generic_tm(
buf,
src_data_buf,
Subservice::TmInfoReport,
sender,
time_stamp,
event_id,
aux_data,
)
}
pub fn event_low_severity(
&mut self,
buf: &mut [u8],
sender: &mut (impl EcssTmSenderCore + ?Sized),
time_stamp: &[u8],
pub fn event_low_severity<'time, 'src_data>(
&self,
src_data_buf: &'src_data mut [u8],
time_stamp: &'time [u8],
event_id: impl EcssEnumeration,
aux_data: Option<&[u8]>,
) -> Result<(), EcssTmtcError> {
aux_data: Option<&'src_data [u8]>,
) -> Result<PusTmCreator<'time, 'src_data>, ByteConversionError> {
self.generate_and_send_generic_tm(
buf,
src_data_buf,
Subservice::TmLowSeverityReport,
sender,
time_stamp,
event_id,
aux_data,
)
}
pub fn event_medium_severity(
&mut self,
buf: &mut [u8],
sender: &mut (impl EcssTmSenderCore + ?Sized),
time_stamp: &[u8],
pub fn event_medium_severity<'time, 'src_data>(
&self,
buf: &'src_data mut [u8],
time_stamp: &'time [u8],
event_id: impl EcssEnumeration,
aux_data: Option<&[u8]>,
) -> Result<(), EcssTmtcError> {
aux_data: Option<&'src_data [u8]>,
) -> Result<PusTmCreator<'time, 'src_data>, ByteConversionError> {
self.generate_and_send_generic_tm(
buf,
Subservice::TmMediumSeverityReport,
sender,
time_stamp,
event_id,
aux_data,
)
}
pub fn event_high_severity(
&mut self,
buf: &mut [u8],
sender: &mut (impl EcssTmSenderCore + ?Sized),
time_stamp: &[u8],
pub fn event_high_severity<'time, 'src_data>(
&self,
src_data_buf: &'src_data mut [u8],
time_stamp: &'time [u8],
event_id: impl EcssEnumeration,
aux_data: Option<&[u8]>,
) -> Result<(), EcssTmtcError> {
aux_data: Option<&'src_data [u8]>,
) -> Result<PusTmCreator<'time, 'src_data>, ByteConversionError> {
self.generate_and_send_generic_tm(
buf,
src_data_buf,
Subservice::TmHighSeverityReport,
sender,
time_stamp,
event_id,
aux_data,
)
}
fn generate_and_send_generic_tm(
&mut self,
buf: &mut [u8],
fn generate_and_send_generic_tm<'time, 'src_data>(
&self,
src_data_buf: &'src_data mut [u8],
subservice: Subservice,
sender: &mut (impl EcssTmSenderCore + ?Sized),
time_stamp: &[u8],
time_stamp: &'time [u8],
event_id: impl EcssEnumeration,
aux_data: Option<&[u8]>,
) -> Result<(), EcssTmtcError> {
let tm = self.generate_generic_event_tm(buf, subservice, time_stamp, event_id, aux_data)?;
sender.send_tm(tm.into())?;
self.msg_count += 1;
Ok(())
aux_data: Option<&'src_data [u8]>,
) -> Result<PusTmCreator<'time, 'src_data>, ByteConversionError> {
self.generate_generic_event_tm(src_data_buf, subservice, time_stamp, event_id, aux_data)
}
fn generate_generic_event_tm<'a>(
&'a self,
buf: &'a mut [u8],
fn generate_generic_event_tm<'time, 'src_data>(
&self,
src_data_buf: &'src_data mut [u8],
subservice: Subservice,
time_stamp: &'a [u8],
time_stamp: &'time [u8],
event_id: impl EcssEnumeration,
aux_data: Option<&[u8]>,
) -> Result<PusTmCreator, EcssTmtcError> {
aux_data: Option<&'src_data [u8]>,
) -> Result<PusTmCreator<'time, 'src_data>, ByteConversionError> {
let mut src_data_len = event_id.size();
if let Some(aux_data) = aux_data {
src_data_len += aux_data.len();
}
source_buffer_large_enough(buf.len(), src_data_len)?;
source_buffer_large_enough(src_data_buf.len(), src_data_len)?;
let mut sp_header = SpHeader::tm_unseg(self.apid, 0, 0).unwrap();
let sec_header = PusTmSecondaryHeader::new(
5,
subservice.into(),
self.msg_count,
self.dest_id,
Some(time_stamp),
);
let sec_header =
PusTmSecondaryHeader::new(5, subservice.into(), 0, self.dest_id, Some(time_stamp));
let mut current_idx = 0;
event_id
.write_to_be_bytes(&mut buf[0..event_id.size()])
.map_err(PusError::ByteConversion)?;
event_id.write_to_be_bytes(&mut src_data_buf[0..event_id.size()])?;
current_idx += event_id.size();
if let Some(aux_data) = aux_data {
buf[current_idx..current_idx + aux_data.len()].copy_from_slice(aux_data);
src_data_buf[current_idx..current_idx + aux_data.len()].copy_from_slice(aux_data);
current_idx += aux_data.len();
}
Ok(PusTmCreator::new(
&mut sp_header,
sec_header,
&buf[0..current_idx],
&src_data_buf[0..current_idx],
true,
))
}
@ -156,84 +137,95 @@ impl EventReporterBase {
#[cfg(feature = "alloc")]
mod alloc_mod {
use super::*;
use crate::ComponentId;
use alloc::vec;
use alloc::vec::Vec;
use core::cell::RefCell;
pub struct EventReporter {
source_data_buf: Vec<u8>,
pub reporter: EventReporterBase,
id: ComponentId,
// Use interior mutability pattern here. This is just an intermediate buffer to the PUS event packet
// generation.
source_data_buf: RefCell<Vec<u8>>,
pub report_creator: EventReportCreator,
}
impl EventReporter {
pub fn new(apid: u16, max_event_id_and_aux_data_size: usize) -> Option<Self> {
let reporter = EventReporterBase::new(apid)?;
pub fn new(
id: ComponentId,
apid: u16,
max_event_id_and_aux_data_size: usize,
) -> Option<Self> {
let reporter = EventReportCreator::new(apid)?;
Some(Self {
source_data_buf: vec![0; max_event_id_and_aux_data_size],
reporter,
id,
source_data_buf: RefCell::new(vec![0; max_event_id_and_aux_data_size]),
report_creator: reporter,
})
}
pub fn event_info(
&mut self,
sender: &mut (impl EcssTmSenderCore + ?Sized),
&self,
sender: &(impl EcssTmSenderCore + ?Sized),
time_stamp: &[u8],
event_id: impl EcssEnumeration,
aux_data: Option<&[u8]>,
) -> Result<(), EcssTmtcError> {
self.reporter.event_info(
self.source_data_buf.as_mut_slice(),
sender,
time_stamp,
event_id,
aux_data,
)
let mut mut_buf = self.source_data_buf.borrow_mut();
let tm_creator = self
.report_creator
.event_info(mut_buf.as_mut_slice(), time_stamp, event_id, aux_data)
.map_err(PusError::ByteConversion)?;
sender.send_tm(self.id, tm_creator.into())?;
Ok(())
}
pub fn event_low_severity(
&mut self,
sender: &mut (impl EcssTmSenderCore + ?Sized),
&self,
sender: &(impl EcssTmSenderCore + ?Sized),
time_stamp: &[u8],
event_id: impl EcssEnumeration,
aux_data: Option<&[u8]>,
) -> Result<(), EcssTmtcError> {
self.reporter.event_low_severity(
self.source_data_buf.as_mut_slice(),
sender,
time_stamp,
event_id,
aux_data,
)
let mut mut_buf = self.source_data_buf.borrow_mut();
let tm_creator = self
.report_creator
.event_low_severity(mut_buf.as_mut_slice(), time_stamp, event_id, aux_data)
.map_err(PusError::ByteConversion)?;
sender.send_tm(self.id, tm_creator.into())?;
Ok(())
}
pub fn event_medium_severity(
&mut self,
sender: &mut (impl EcssTmSenderCore + ?Sized),
&self,
sender: &(impl EcssTmSenderCore + ?Sized),
time_stamp: &[u8],
event_id: impl EcssEnumeration,
aux_data: Option<&[u8]>,
) -> Result<(), EcssTmtcError> {
self.reporter.event_medium_severity(
self.source_data_buf.as_mut_slice(),
sender,
time_stamp,
event_id,
aux_data,
)
let mut mut_buf = self.source_data_buf.borrow_mut();
let tm_creator = self
.report_creator
.event_medium_severity(mut_buf.as_mut_slice(), time_stamp, event_id, aux_data)
.map_err(PusError::ByteConversion)?;
sender.send_tm(self.id, tm_creator.into())?;
Ok(())
}
pub fn event_high_severity(
&mut self,
sender: &mut (impl EcssTmSenderCore + ?Sized),
&self,
sender: &(impl EcssTmSenderCore + ?Sized),
time_stamp: &[u8],
event_id: impl EcssEnumeration,
aux_data: Option<&[u8]>,
) -> Result<(), EcssTmtcError> {
self.reporter.event_high_severity(
self.source_data_buf.as_mut_slice(),
sender,
time_stamp,
event_id,
aux_data,
)
let mut mut_buf = self.source_data_buf.borrow_mut();
let tm_creator = self
.report_creator
.event_high_severity(mut_buf.as_mut_slice(), time_stamp, event_id, aux_data)
.map_err(PusError::ByteConversion)?;
sender.send_tm(self.id, tm_creator.into())?;
Ok(())
}
}
}
@ -243,7 +235,7 @@ mod tests {
use super::*;
use crate::events::{EventU32, Severity};
use crate::pus::tests::CommonTmInfo;
use crate::pus::{EcssChannel, PusTmWrapper};
use crate::pus::{ChannelWithId, PusTmVariant};
use crate::ComponentId;
use spacepackets::ByteConversionError;
use std::cell::RefCell;
@ -268,19 +260,19 @@ mod tests {
pub service_queue: RefCell<VecDeque<TmInfo>>,
}
impl EcssChannel for TestSender {
impl ChannelWithId for TestSender {
fn id(&self) -> ComponentId {
0
}
}
impl EcssTmSenderCore for TestSender {
fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> {
fn send_tm(&self, sender_id: ComponentId, tm: PusTmVariant) -> Result<(), EcssTmtcError> {
match tm {
PusTmWrapper::InStore(_) => {
PusTmVariant::InStore(_) => {
panic!("TestSender: unexpected call with address");
}
PusTmWrapper::Direct(tm) => {
PusTmVariant::Direct(tm) => {
assert!(!tm.source_data().is_empty());
let src_data = tm.source_data();
assert!(src_data.len() >= 4);
@ -348,7 +340,7 @@ mod tests {
error_data: Option<&[u8]>,
) {
let mut sender = TestSender::default();
let reporter = EventReporter::new(EXAMPLE_APID, max_event_aux_data_buf);
let reporter = EventReporter::new(0, EXAMPLE_APID, max_event_aux_data_buf);
assert!(reporter.is_some());
let mut reporter = reporter.unwrap();
let time_stamp_empty: [u8; 7] = [0; 7];
@ -440,7 +432,7 @@ mod tests {
fn insufficient_buffer() {
let mut sender = TestSender::default();
for i in 0..3 {
let reporter = EventReporter::new(EXAMPLE_APID, i);
let reporter = EventReporter::new(0, EXAMPLE_APID, i);
assert!(reporter.is_some());
let mut reporter = reporter.unwrap();
check_buf_too_small(&mut reporter, &mut sender, i);

View File

@ -177,8 +177,8 @@ pub mod alloc_mod {
}
pub fn generate_pus_event_tm_generic(
&mut self,
sender: &mut (impl EcssTmSenderCore + ?Sized),
&self,
sender: &(impl EcssTmSenderCore + ?Sized),
time_stamp: &[u8],
event: EV,
aux_data: Option<&[u8]>,
@ -239,8 +239,8 @@ pub mod alloc_mod {
}
pub fn generate_pus_event_tm<Severity: HasSeverity>(
&mut self,
sender: &mut (impl EcssTmSenderCore + ?Sized),
&self,
sender: &(impl EcssTmSenderCore + ?Sized),
time_stamp: &[u8],
event: EventU32TypedSev<Severity>,
aux_data: Option<&[u8]>,
@ -257,20 +257,26 @@ pub mod alloc_mod {
#[cfg(test)]
mod tests {
use super::*;
use crate::{events::SeverityInfo, pus::TmAsVecSenderWithMpsc};
use crate::events::SeverityInfo;
use crate::pus::PusTmAsVec;
use crate::request::UniqueApidTargetId;
use std::sync::mpsc::{self, TryRecvError};
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];
const TEST_APID: u16 = 0x02;
const TEST_ID: UniqueApidTargetId = UniqueApidTargetId::new(TEST_APID, 0x05);
fn create_basic_man_1() -> DefaultPusEventU32Dispatcher<()> {
let reporter = EventReporter::new(0x02, 128).expect("Creating event repoter failed");
let reporter = EventReporter::new(TEST_ID.raw(), TEST_APID, 128)
.expect("Creating event repoter failed");
PusEventDispatcher::new_with_default_backend(reporter)
}
fn create_basic_man_2() -> DefaultPusEventU32Dispatcher<()> {
let reporter = EventReporter::new(0x02, 128).expect("Creating event repoter failed");
let reporter = EventReporter::new(TEST_ID.raw(), TEST_APID, 128)
.expect("Creating event repoter failed");
let backend = DefaultPusEventMgmtBackend::default();
PusEventDispatcher::new(reporter, backend)
}
@ -278,10 +284,9 @@ mod tests {
#[test]
fn test_basic() {
let mut event_man = create_basic_man_1();
let (event_tx, event_rx) = mpsc::channel();
let mut sender = TmAsVecSenderWithMpsc::new(0, "test_sender", event_tx);
let (mut event_tx, event_rx) = mpsc::channel::<PusTmAsVec>();
let event_sent = event_man
.generate_pus_event_tm(&mut sender, &EMPTY_STAMP, INFO_EVENT, None)
.generate_pus_event_tm(&mut event_tx, &EMPTY_STAMP, INFO_EVENT, None)
.expect("Sending info event failed");
assert!(event_sent);
@ -292,13 +297,13 @@ mod tests {
#[test]
fn test_disable_event() {
let mut event_man = create_basic_man_2();
let (event_tx, event_rx) = mpsc::channel();
let mut sender = TmAsVecSenderWithMpsc::new(0, "test", event_tx);
let (event_tx, event_rx) = mpsc::channel::<PusTmAsVec>();
// let mut sender = TmAsVecSenderWithMpsc::new(0, "test", event_tx);
let res = event_man.disable_tm_for_event(&LOW_SEV_EVENT);
assert!(res.is_ok());
assert!(res.unwrap());
let mut event_sent = event_man
.generate_pus_event_tm_generic(&mut sender, &EMPTY_STAMP, LOW_SEV_EVENT, None)
.generate_pus_event_tm_generic(&event_tx, &EMPTY_STAMP, LOW_SEV_EVENT, None)
.expect("Sending low severity event failed");
assert!(!event_sent);
let res = event_rx.try_recv();
@ -306,7 +311,7 @@ mod tests {
assert!(matches!(res.unwrap_err(), TryRecvError::Empty));
// Check that only the low severity event was disabled
event_sent = event_man
.generate_pus_event_tm(&mut sender, &EMPTY_STAMP, INFO_EVENT, None)
.generate_pus_event_tm(&event_tx, &EMPTY_STAMP, INFO_EVENT, None)
.expect("Sending info event failed");
assert!(event_sent);
event_rx.try_recv().expect("No info event received");
@ -315,8 +320,7 @@ mod tests {
#[test]
fn test_reenable_event() {
let mut event_man = create_basic_man_1();
let (event_tx, event_rx) = mpsc::channel();
let mut sender = TmAsVecSenderWithMpsc::new(0, "test", event_tx);
let (event_tx, event_rx) = mpsc::channel::<PusTmAsVec>();
let mut res = event_man.disable_tm_for_event_with_sev(&INFO_EVENT);
assert!(res.is_ok());
assert!(res.unwrap());
@ -324,7 +328,7 @@ mod tests {
assert!(res.is_ok());
assert!(res.unwrap());
let event_sent = event_man
.generate_pus_event_tm(&mut sender, &EMPTY_STAMP, INFO_EVENT, None)
.generate_pus_event_tm(&event_tx, &EMPTY_STAMP, INFO_EVENT, None)
.expect("Sending info event failed");
assert!(event_sent);
event_rx.try_recv().expect("No info event received");

View File

@ -13,7 +13,7 @@ use super::{
GenericRoutingError, PusServiceHelper,
};
pub struct PusService5EventHandler<
pub struct PusEventServiceHandler<
TcReceiver: EcssTcReceiverCore,
TmSender: EcssTmSenderCore,
TcInMemConverter: EcssTcInMemConverter,
@ -29,7 +29,7 @@ impl<
TmSender: EcssTmSenderCore,
TcInMemConverter: EcssTcInMemConverter,
VerificationReporter: VerificationReportingProvider,
> PusService5EventHandler<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>
> PusEventServiceHandler<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>
{
pub fn new(
service_helper: PusServiceHelper<
@ -83,7 +83,12 @@ impl<
.service_helper
.common
.verif_reporter
.start_success(ecss_tc_and_token.token, time_stamp)
.start_success(
self.service_helper.common.id,
&self.service_helper.common.tm_sender,
ecss_tc_and_token.token,
time_stamp,
)
.map_err(|_| PartialPusHandlingError::Verification);
let partial_error = start_token.clone().err();
let mut token: TcStateToken = ecss_tc_and_token.token.into();
@ -161,9 +166,9 @@ mod tests {
use crate::pus::event_man::EventRequest;
use crate::pus::test_util::{PusTestHarness, SimplePusPacketHandler, TEST_APID};
use crate::pus::verification::{
RequestId, VerificationReporterWithSharedPoolMpscBoundedSender,
RequestId, VerificationReporter, VerificationReportingProvider,
};
use crate::pus::{GenericConversionError, MpscTcReceiver, TmInSharedPoolSenderWithBoundedMpsc};
use crate::pus::{GenericConversionError, MpscTcReceiver, MpscTmInSharedPoolSenderBounded};
use crate::{
events::EventU32,
pus::{
@ -174,34 +179,48 @@ mod tests {
},
};
use super::PusService5EventHandler;
use super::PusEventServiceHandler;
const TEST_EVENT_0: EventU32 = EventU32::const_new(crate::events::Severity::INFO, 5, 25);
struct Pus5HandlerWithStoreTester {
common: PusServiceHandlerWithSharedStoreCommon,
handler: PusService5EventHandler<
handler: PusEventServiceHandler<
MpscTcReceiver,
TmInSharedPoolSenderWithBoundedMpsc,
MpscTmInSharedPoolSenderBounded,
EcssTcInSharedStoreConverter,
VerificationReporterWithSharedPoolMpscBoundedSender,
VerificationReporter,
>,
}
impl Pus5HandlerWithStoreTester {
pub fn new(event_request_tx: Sender<EventRequestWithToken>) -> Self {
let (common, srv_handler) = PusServiceHandlerWithSharedStoreCommon::new();
let (common, srv_handler) = PusServiceHandlerWithSharedStoreCommon::new(0);
Self {
common,
handler: PusService5EventHandler::new(srv_handler, event_request_tx),
handler: PusEventServiceHandler::new(srv_handler, event_request_tx),
}
}
}
impl PusTestHarness for Pus5HandlerWithStoreTester {
fn init_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> {
let init_token = self.handler.service_helper.verif_reporter_mut().add_tc(tc);
self.handler
.service_helper
.verif_reporter()
.acceptance_success(
self.handler.service_helper.id(),
self.handler.service_helper.tm_sender(),
init_token,
&[0; 7],
)
.expect("acceptance success failure")
}
delegate! {
to self.common {
fn send_tc(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted>;
fn send_tc(&self, token: &VerificationToken<TcStateAccepted>, tc: &PusTcCreator);
fn read_next_tm(&mut self) -> PusTmReader<'_>;
fn check_no_tm_available(&self) -> bool;
fn check_next_verification_tm(&self, subservice: u8, expected_request_id: RequestId);
@ -212,7 +231,7 @@ mod tests {
impl SimplePusPacketHandler for Pus5HandlerWithStoreTester {
fn handle_one_tc(&mut self) -> Result<PusPacketHandlerResult, PusPacketHandlingError> {
let time_stamp = cds::TimeProvider::new_with_u16_days(0, 0).to_vec().unwrap();
let time_stamp = cds::CdsTime::new_with_u16_days(0, 0).to_vec().unwrap();
self.handler.poll_and_handle_next_tc(&time_stamp)
}
}
@ -230,7 +249,8 @@ mod tests {
.write_to_be_bytes(&mut app_data)
.expect("writing test event failed");
let ping_tc = PusTcCreator::new(&mut sp_header, sec_header, &app_data, true);
let token = test_harness.send_tc(&ping_tc);
let token = test_harness.init_verification(&ping_tc);
test_harness.send_tc(&token, &ping_tc);
let request_id = token.request_id();
test_harness.handle_one_tc().unwrap();
test_harness.check_next_verification_tm(1, request_id);
@ -287,7 +307,8 @@ mod tests {
let mut sp_header = SpHeader::tc(TEST_APID, SequenceFlags::Unsegmented, 0, 0).unwrap();
let sec_header = PusTcSecondaryHeader::new_simple(5, 200);
let ping_tc = PusTcCreator::new_no_app_data(&mut sp_header, sec_header, true);
test_harness.send_tc(&ping_tc);
let token = test_harness.init_verification(&ping_tc);
test_harness.send_tc(&token, &ping_tc);
let result = test_harness.handle_one_tc();
assert!(result.is_ok());
let result = result.unwrap();
@ -306,7 +327,8 @@ mod tests {
let sec_header =
PusTcSecondaryHeader::new_simple(5, Subservice::TcEnableEventGeneration as u8);
let ping_tc = PusTcCreator::new(&mut sp_header, sec_header, &[0, 1, 2], true);
test_harness.send_tc(&ping_tc);
let token = test_harness.init_verification(&ping_tc);
test_harness.send_tc(&token, &ping_tc);
let result = test_harness.handle_one_tc();
assert!(result.is_err());
let result = result.unwrap_err();

View File

@ -5,7 +5,7 @@
use crate::pool::{StoreAddr, StoreError};
use crate::pus::verification::{TcStateAccepted, TcStateToken, VerificationToken};
use crate::queue::{GenericReceiveError, GenericSendError};
use crate::request::{GenericMessage, RequestId};
use crate::request::{GenericMessage, MessageMetadata, RequestId};
use crate::ComponentId;
use core::fmt::{Display, Formatter};
use core::time::Duration;
@ -43,19 +43,19 @@ pub use std_mod::*;
use self::verification::VerificationReportingProvider;
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum PusTmWrapper<'tm> {
pub enum PusTmVariant<'time, 'src_data> {
InStore(StoreAddr),
Direct(PusTmCreator<'tm>),
Direct(PusTmCreator<'time, 'src_data>),
}
impl From<StoreAddr> for PusTmWrapper<'_> {
impl From<StoreAddr> for PusTmVariant<'_, '_> {
fn from(value: StoreAddr) -> Self {
Self::InStore(value)
}
}
impl<'tm> From<PusTmCreator<'tm>> for PusTmWrapper<'tm> {
fn from(value: PusTmCreator<'tm>) -> Self {
impl<'time, 'src_data> From<PusTmCreator<'time, 'src_data>> for PusTmVariant<'time, 'src_data> {
fn from(value: PusTmCreator<'time, 'src_data>) -> Self {
Self::Direct(value)
}
}
@ -142,7 +142,7 @@ impl Error for EcssTmtcError {
}
}
}
pub trait EcssChannel: Send {
pub trait ChannelWithId: Send {
/// Each sender can have an ID associated with it
fn id(&self) -> ComponentId;
fn name(&self) -> &'static str {
@ -154,7 +154,7 @@ pub trait EcssChannel: Send {
///
/// This sender object is responsible for sending PUS telemetry to a TM sink.
pub trait EcssTmSenderCore: Send {
fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError>;
fn send_tm(&self, source_id: ComponentId, tm: PusTmVariant) -> Result<(), EcssTmtcError>;
}
/// Generic trait for a user supplied sender object.
@ -165,6 +165,16 @@ pub trait EcssTcSenderCore {
fn send_tc(&self, tc: PusTcCreator, token: Option<TcStateToken>) -> Result<(), EcssTmtcError>;
}
/// Dummy object which can be useful for tests.
#[derive(Default)]
pub struct EcssTmDummySender {}
impl EcssTmSenderCore for EcssTmDummySender {
fn send_tm(&self, _source_id: ComponentId, _tm: PusTmVariant) -> Result<(), EcssTmtcError> {
Ok(())
}
}
/// A PUS telecommand packet can be stored in memory using different methods. Right now,
/// storage inside a pool structure like [crate::pool::StaticMemoryPool], and storage inside a
/// `Vec<u8>` are supported.
@ -259,7 +269,7 @@ impl From<StoreError> for TryRecvTmtcError {
}
/// Generic trait for a user supplied receiver object.
pub trait EcssTcReceiverCore: EcssChannel {
pub trait EcssTcReceiverCore {
fn recv_tc(&self) -> Result<EcssTcAndToken, TryRecvTmtcError>;
}
@ -301,8 +311,7 @@ pub trait PusRequestRouter<Request> {
fn route(
&self,
request_id: RequestId,
source_id: ComponentId,
requestor_info: MessageMetadata,
target_id: ComponentId,
request: Request,
) -> Result<(), Self::Error>;
@ -315,15 +324,17 @@ pub trait PusReplyHandler<ActiveRequestInfo: ActiveRequestProvider, ReplyType> {
/// is finished. A finished PUS request will be removed from the active request map.
fn handle_reply(
&mut self,
caller_id: ComponentId,
reply: &GenericMessage<ReplyType>,
active_request: &ActiveRequestInfo,
tm_sender: &impl EcssTmSenderCore,
verification_handler: &impl VerificationReportingProvider,
time_stamp: &[u8],
tm_sender: &impl EcssTmSenderCore,
) -> Result<bool, Self::Error>;
fn handle_unrequested_reply(
&mut self,
caller_id: ComponentId,
reply: &GenericMessage<ReplyType>,
tm_sender: &impl EcssTmSenderCore,
) -> Result<(), Self::Error>;
@ -331,10 +342,11 @@ pub trait PusReplyHandler<ActiveRequestInfo: ActiveRequestProvider, ReplyType> {
/// Handle the timeout of an active request.
fn handle_request_timeout(
&mut self,
caller_id: ComponentId,
active_request: &ActiveRequestInfo,
tm_sender: &impl EcssTmSenderCore,
verification_handler: &impl VerificationReportingProvider,
time_stamp: &[u8],
tm_sender: &impl EcssTmSenderCore,
) -> Result<(), Self::Error>;
}
@ -445,10 +457,12 @@ pub mod alloc_mod {
type Error;
fn convert(
&mut self,
caller_id: ComponentId,
token: VerificationToken<TcStateAccepted>,
tc: &PusTcReader,
time_stamp: &[u8],
tm_sender: &(impl EcssTmSenderCore + ?Sized),
verif_reporter: &impl VerificationReportingProvider,
time_stamp: &[u8],
) -> Result<(ActiveRequestInfo, Request), Self::Error>;
}
@ -647,8 +661,8 @@ pub mod std_mod {
};
use crate::pus::verification::{TcStateAccepted, VerificationToken};
use crate::pus::{
EcssChannel, EcssTcAndToken, EcssTcReceiverCore, EcssTmSenderCore, EcssTmtcError,
GenericReceiveError, GenericSendError, PusTmWrapper, TryRecvTmtcError,
EcssTcAndToken, EcssTcReceiverCore, EcssTmSenderCore, EcssTmtcError, GenericReceiveError,
GenericSendError, PusTmVariant, TryRecvTmtcError,
};
use crate::tmtc::tm_helper::SharedTmPool;
use crate::ComponentId;
@ -670,54 +684,82 @@ pub mod std_mod {
use super::verification::{TcStateToken, VerificationReportingProvider};
use super::{AcceptedEcssTcAndToken, ActiveRequestProvider, TcInMemory};
#[derive(Debug)]
pub struct PusTmInPool {
pub source_id: ComponentId,
pub store_addr: StoreAddr,
}
impl From<mpsc::SendError<StoreAddr>> for EcssTmtcError {
fn from(_: mpsc::SendError<StoreAddr>) -> Self {
Self::Send(GenericSendError::RxDisconnected)
}
}
impl EcssTmSenderCore for mpsc::Sender<StoreAddr> {
fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> {
impl EcssTmSenderCore for mpsc::Sender<PusTmInPool> {
fn send_tm(&self, source_id: ComponentId, tm: PusTmVariant) -> Result<(), EcssTmtcError> {
match tm {
PusTmWrapper::InStore(addr) => self
.send(addr)
PusTmVariant::InStore(store_addr) => self
.send(PusTmInPool {
source_id,
store_addr,
})
.map_err(|_| GenericSendError::RxDisconnected)?,
PusTmWrapper::Direct(_) => return Err(EcssTmtcError::CantSendDirectTm),
PusTmVariant::Direct(_) => return Err(EcssTmtcError::CantSendDirectTm),
};
Ok(())
}
}
impl EcssTmSenderCore for mpsc::SyncSender<StoreAddr> {
fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> {
impl EcssTmSenderCore for mpsc::SyncSender<PusTmInPool> {
fn send_tm(&self, source_id: ComponentId, tm: PusTmVariant) -> Result<(), EcssTmtcError> {
match tm {
PusTmWrapper::InStore(addr) => self
.try_send(addr)
PusTmVariant::InStore(store_addr) => self
.try_send(PusTmInPool {
source_id,
store_addr,
})
.map_err(|e| EcssTmtcError::Send(e.into()))?,
PusTmWrapper::Direct(_) => return Err(EcssTmtcError::CantSendDirectTm),
PusTmVariant::Direct(_) => return Err(EcssTmtcError::CantSendDirectTm),
};
Ok(())
}
}
impl EcssTmSenderCore for mpsc::Sender<Vec<u8>> {
fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> {
#[derive(Debug)]
pub struct PusTmAsVec {
pub source_id: ComponentId,
pub packet: Vec<u8>,
}
pub type MpscTmAsVecSender = mpsc::Sender<PusTmAsVec>;
impl EcssTmSenderCore for MpscTmAsVecSender {
fn send_tm(&self, source_id: ComponentId, tm: PusTmVariant) -> Result<(), EcssTmtcError> {
match tm {
PusTmWrapper::InStore(addr) => return Err(EcssTmtcError::CantSendAddr(addr)),
PusTmWrapper::Direct(tm) => self
.send(tm.to_vec()?)
PusTmVariant::InStore(addr) => return Err(EcssTmtcError::CantSendAddr(addr)),
PusTmVariant::Direct(tm) => self
.send(PusTmAsVec {
source_id,
packet: tm.to_vec()?,
})
.map_err(|e| EcssTmtcError::Send(e.into()))?,
};
Ok(())
}
}
impl EcssTmSenderCore for mpsc::SyncSender<Vec<u8>> {
fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> {
pub type MpscTmAsVecSenderBounded = mpsc::SyncSender<PusTmAsVec>;
impl EcssTmSenderCore for MpscTmAsVecSenderBounded {
fn send_tm(&self, source_id: ComponentId, tm: PusTmVariant) -> Result<(), EcssTmtcError> {
match tm {
PusTmWrapper::InStore(addr) => return Err(EcssTmtcError::CantSendAddr(addr)),
PusTmWrapper::Direct(tm) => self
.send(tm.to_vec()?)
PusTmVariant::InStore(addr) => return Err(EcssTmtcError::CantSendAddr(addr)),
PusTmVariant::Direct(tm) => self
.send(PusTmAsVec {
source_id,
packet: tm.to_vec()?,
})
.map_err(|e| EcssTmtcError::Send(e.into()))?,
};
Ok(())
@ -725,67 +767,52 @@ pub mod std_mod {
}
#[derive(Clone)]
pub struct TmInSharedPoolSenderWithId<Sender: EcssTmSenderCore> {
channel_id: ComponentId,
name: &'static str,
pub struct TmInSharedPoolSender<Sender: EcssTmSenderCore> {
shared_tm_store: SharedTmPool,
sender: Sender,
}
impl<Sender: EcssTmSenderCore> EcssChannel for TmInSharedPoolSenderWithId<Sender> {
fn id(&self) -> ComponentId {
self.channel_id
}
fn name(&self) -> &'static str {
self.name
}
}
impl<Sender: EcssTmSenderCore> TmInSharedPoolSenderWithId<Sender> {
pub fn send_direct_tm(&self, tm: PusTmCreator) -> Result<(), EcssTmtcError> {
impl<Sender: EcssTmSenderCore> TmInSharedPoolSender<Sender> {
pub fn send_direct_tm(
&self,
source_id: ComponentId,
tm: PusTmCreator,
) -> Result<(), EcssTmtcError> {
let addr = self.shared_tm_store.add_pus_tm(&tm)?;
self.sender.send_tm(PusTmWrapper::InStore(addr))
self.sender.send_tm(source_id, PusTmVariant::InStore(addr))
}
}
impl<Sender: EcssTmSenderCore> EcssTmSenderCore for TmInSharedPoolSenderWithId<Sender> {
fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> {
if let PusTmWrapper::Direct(tm) = tm {
return self.send_direct_tm(tm);
impl<Sender: EcssTmSenderCore> EcssTmSenderCore for TmInSharedPoolSender<Sender> {
fn send_tm(&self, source_id: ComponentId, tm: PusTmVariant) -> Result<(), EcssTmtcError> {
if let PusTmVariant::Direct(tm) = tm {
return self.send_direct_tm(source_id, tm);
}
self.sender.send_tm(tm)
self.sender.send_tm(source_id, tm)
}
}
impl<Sender: EcssTmSenderCore> TmInSharedPoolSenderWithId<Sender> {
pub fn new(
id: ComponentId,
name: &'static str,
shared_tm_store: SharedTmPool,
sender: Sender,
) -> Self {
impl<Sender: EcssTmSenderCore> TmInSharedPoolSender<Sender> {
pub fn new(shared_tm_store: SharedTmPool, sender: Sender) -> Self {
Self {
channel_id: id,
name,
shared_tm_store,
sender,
}
}
}
pub type TmInSharedPoolSenderWithMpsc = TmInSharedPoolSenderWithId<mpsc::Sender<StoreAddr>>;
pub type TmInSharedPoolSenderWithBoundedMpsc =
TmInSharedPoolSenderWithId<mpsc::SyncSender<StoreAddr>>;
pub type MpscTmInSharedPoolSender = TmInSharedPoolSender<mpsc::Sender<PusTmInPool>>;
pub type MpscTmInSharedPoolSenderBounded = TmInSharedPoolSender<mpsc::SyncSender<PusTmInPool>>;
/*
/// This class can be used if frequent heap allocations during run-time are not an issue.
/// PUS TM packets will be sent around as [Vec]s. Please note that the current implementation
/// of this class can not deal with store addresses, so it is assumed that is is always
/// going to be called with direct packets.
#[derive(Clone)]
pub struct TmAsVecSenderWithId<Sender: EcssTmSenderCore> {
id: ComponentId,
name: &'static str,
// id: ComponentId,
//name: &'static str,
sender: Sender,
}
@ -801,7 +828,7 @@ pub mod std_mod {
}
}
impl<Sender: EcssTmSenderCore> EcssChannel for TmAsVecSenderWithId<Sender> {
impl<Sender: EcssTmSenderCore> ChannelWithId for TmAsVecSenderWithId<Sender> {
fn id(&self) -> ComponentId {
self.id
}
@ -811,58 +838,34 @@ pub mod std_mod {
}
impl<Sender: EcssTmSenderCore> EcssTmSenderCore for TmAsVecSenderWithId<Sender> {
fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> {
fn send_tm(&self, tm: PusTmVariant) -> Result<(), EcssTmtcError> {
self.sender.send_tm(tm)
}
}
pub type TmAsVecSenderWithMpsc = TmAsVecSenderWithId<mpsc::Sender<Vec<u8>>>;
pub type TmAsVecSenderWithBoundedMpsc = TmAsVecSenderWithId<mpsc::SyncSender<Vec<u8>>>;
*/
pub struct MpscTcReceiver {
id: ComponentId,
name: &'static str,
receiver: mpsc::Receiver<EcssTcAndToken>,
}
impl EcssChannel for MpscTcReceiver {
fn id(&self) -> ComponentId {
self.id
}
fn name(&self) -> &'static str {
self.name
}
}
pub type MpscTcReceiver = mpsc::Receiver<EcssTcAndToken>;
impl EcssTcReceiverCore for MpscTcReceiver {
fn recv_tc(&self) -> Result<EcssTcAndToken, TryRecvTmtcError> {
self.receiver.try_recv().map_err(|e| match e {
self.try_recv().map_err(|e| match e {
TryRecvError::Empty => TryRecvTmtcError::Empty,
TryRecvError::Disconnected => TryRecvTmtcError::Tmtc(EcssTmtcError::from(
GenericReceiveError::TxDisconnected(Some(self.id())),
GenericReceiveError::TxDisconnected(None),
)),
})
}
}
impl MpscTcReceiver {
pub fn new(
id: ComponentId,
name: &'static str,
receiver: mpsc::Receiver<EcssTcAndToken>,
) -> Self {
Self { id, name, receiver }
}
}
#[cfg(feature = "crossbeam")]
pub mod cb_mod {
use super::*;
use crossbeam_channel as cb;
pub type TmInSharedPoolSenderWithCrossbeam =
TmInSharedPoolSenderWithId<cb::Sender<StoreAddr>>;
pub type TmInSharedPoolSenderWithCrossbeam = TmInSharedPoolSender<cb::Sender<PusTmInPool>>;
impl From<cb::SendError<StoreAddr>> for EcssTmtcError {
fn from(_: cb::SendError<StoreAddr>) -> Self {
@ -881,65 +884,44 @@ pub mod std_mod {
}
}
impl EcssTmSenderCore for cb::Sender<StoreAddr> {
fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> {
impl EcssTmSenderCore for cb::Sender<PusTmInPool> {
fn send_tm(
&self,
source_id: ComponentId,
tm: PusTmVariant,
) -> Result<(), EcssTmtcError> {
match tm {
PusTmWrapper::InStore(addr) => self
.try_send(addr)
PusTmVariant::InStore(addr) => self
.try_send(PusTmInPool {
source_id,
store_addr: addr,
})
.map_err(|e| EcssTmtcError::Send(e.into()))?,
PusTmWrapper::Direct(_) => return Err(EcssTmtcError::CantSendDirectTm),
PusTmVariant::Direct(_) => return Err(EcssTmtcError::CantSendDirectTm),
};
Ok(())
}
}
impl EcssTmSenderCore for cb::Sender<Vec<u8>> {
fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> {
impl EcssTmSenderCore for cb::Sender<PusTmAsVec> {
fn send_tm(
&self,
source_id: ComponentId,
tm: PusTmVariant,
) -> Result<(), EcssTmtcError> {
match tm {
PusTmWrapper::InStore(addr) => return Err(EcssTmtcError::CantSendAddr(addr)),
PusTmWrapper::Direct(tm) => self
.send(tm.to_vec()?)
PusTmVariant::InStore(addr) => return Err(EcssTmtcError::CantSendAddr(addr)),
PusTmVariant::Direct(tm) => self
.send(PusTmAsVec {
source_id,
packet: tm.to_vec()?,
})
.map_err(|e| EcssTmtcError::Send(e.into()))?,
};
Ok(())
}
}
pub struct CrossbeamTcReceiver {
id: ComponentId,
name: &'static str,
receiver: cb::Receiver<EcssTcAndToken>,
}
impl CrossbeamTcReceiver {
pub fn new(
id: ComponentId,
name: &'static str,
receiver: cb::Receiver<EcssTcAndToken>,
) -> Self {
Self { id, name, receiver }
}
}
impl EcssChannel for CrossbeamTcReceiver {
fn id(&self) -> ComponentId {
self.id
}
fn name(&self) -> &'static str {
self.name
}
}
impl EcssTcReceiverCore for CrossbeamTcReceiver {
fn recv_tc(&self) -> Result<EcssTcAndToken, TryRecvTmtcError> {
self.receiver.try_recv().map_err(|e| match e {
cb::TryRecvError::Empty => TryRecvTmtcError::Empty,
cb::TryRecvError::Disconnected => TryRecvTmtcError::Tmtc(EcssTmtcError::from(
GenericReceiveError::TxDisconnected(Some(self.id())),
)),
})
}
}
pub type CrossbeamTcReceiver = cb::Receiver<EcssTcAndToken>;
}
/// This is a high-level handler for the generic PUS services which need to convert PUS
@ -1294,9 +1276,9 @@ pub mod std_mod {
TmSender: EcssTmSenderCore,
VerificationReporter: VerificationReportingProvider,
> {
pub id: ComponentId,
pub tc_receiver: TcReceiver,
pub tm_sender: TmSender,
pub tm_apid: u16,
pub verif_reporter: VerificationReporter,
}
@ -1327,23 +1309,31 @@ pub mod std_mod {
> PusServiceHelper<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>
{
pub fn new(
id: ComponentId,
tc_receiver: TcReceiver,
tm_sender: TmSender,
tm_apid: u16,
verification_handler: VerificationReporter,
tc_in_mem_converter: TcInMemConverter,
) -> Self {
Self {
common: PusServiceBase {
id,
tc_receiver,
tm_sender,
tm_apid,
verif_reporter: verification_handler,
},
tc_in_mem_converter,
}
}
pub fn id(&self) -> ComponentId {
self.common.id
}
pub fn tm_sender(&self) -> &TmSender {
&self.common.tm_sender
}
/// This function can be used to poll the internal [EcssTcReceiverCore] object for the next
/// telecommand packet. It will return `Ok(None)` if there are not packets available.
/// In any other case, it will perform the acceptance of the ECSS TC packet using the
@ -1378,6 +1368,9 @@ pub mod std_mod {
pub fn verif_reporter(&self) -> &VerificationReporter {
&self.common.verif_reporter
}
pub fn verif_reporter_mut(&mut self) -> &mut VerificationReporter {
&mut self.common.verif_reporter
}
pub fn tc_in_mem_converter(&self) -> &TcInMemConverter {
&self.tc_in_mem_converter
@ -1388,50 +1381,47 @@ pub mod std_mod {
}
}
pub type PusServiceHelperDynWithMpsc<TcInMemConverter, VerificationReporter> = PusServiceHelper<
MpscTcReceiver,
TmAsVecSenderWithMpsc,
TcInMemConverter,
VerificationReporter,
>;
pub type PusServiceHelperDynWithMpsc<TcInMemConverter, VerificationReporter> =
PusServiceHelper<MpscTcReceiver, MpscTmAsVecSender, TcInMemConverter, VerificationReporter>;
pub type PusServiceHelperDynWithBoundedMpsc<TcInMemConverter, VerificationReporter> =
PusServiceHelper<
MpscTcReceiver,
TmAsVecSenderWithBoundedMpsc,
MpscTmAsVecSenderBounded,
TcInMemConverter,
VerificationReporter,
>;
pub type PusServiceHelperStaticWithMpsc<TcInMemConverter, VerificationReporter> =
PusServiceHelper<
MpscTcReceiver,
TmInSharedPoolSenderWithMpsc,
MpscTmInSharedPoolSender,
TcInMemConverter,
VerificationReporter,
>;
pub type PusServiceHelperStaticWithBoundedMpsc<TcInMemConverter, VerificationReporter> =
PusServiceHelper<
MpscTcReceiver,
TmInSharedPoolSenderWithBoundedMpsc,
MpscTmInSharedPoolSenderBounded,
TcInMemConverter,
VerificationReporter,
>;
}
pub(crate) fn source_buffer_large_enough(cap: usize, len: usize) -> Result<(), EcssTmtcError> {
pub(crate) fn source_buffer_large_enough(
cap: usize,
len: usize,
) -> Result<(), ByteConversionError> {
if len > cap {
return Err(
PusError::ByteConversion(ByteConversionError::ToSliceTooSmall {
found: cap,
expected: len,
})
.into(),
);
return Err(ByteConversionError::ToSliceTooSmall {
found: cap,
expected: len,
});
}
Ok(())
}
#[cfg(any(feature = "test_util", test))]
pub mod test_util {
use crate::request::UniqueApidTargetId;
use spacepackets::ecss::{tc::PusTcCreator, tm::PusTmReader};
use super::{
@ -1440,9 +1430,13 @@ pub mod test_util {
};
pub const TEST_APID: u16 = 0x101;
pub const TEST_UNIQUE_ID: u32 = 0x05;
pub const TEST_COMPONENT_ID: UniqueApidTargetId =
UniqueApidTargetId::new(TEST_APID, TEST_UNIQUE_ID);
pub trait PusTestHarness {
fn send_tc(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted>;
fn init_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted>;
fn send_tc(&self, token: &VerificationToken<TcStateAccepted>, tc: &PusTcCreator);
fn read_next_tm(&mut self) -> PusTmReader<'_>;
fn check_no_tm_available(&self) -> bool;
fn check_next_verification_tm(
@ -1471,22 +1465,16 @@ pub mod tests {
use spacepackets::ecss::{PusPacket, WritablePusPacket};
use spacepackets::CcsdsPacket;
use crate::pool::{
PoolProvider, SharedStaticMemoryPool, StaticMemoryPool, StaticPoolConfig, StoreAddr,
};
use crate::pus::verification::RequestId;
use crate::pool::{PoolProvider, SharedStaticMemoryPool, StaticMemoryPool, StaticPoolConfig};
use crate::pus::verification::{RequestId, VerificationReporter};
use crate::tmtc::tm_helper::SharedTmPool;
use crate::ComponentId;
use super::test_util::TEST_APID;
use super::test_util::{TEST_APID, TEST_COMPONENT_ID};
use super::verification::std_mod::{
VerificationReporterWithSharedPoolMpscBoundedSender, VerificationReporterWithVecMpscSender,
};
use super::verification::test_util::{SharedVerificationMap, TestVerificationReporter};
use super::verification::test_util::TestVerificationReporter;
use super::verification::{
TcStateAccepted, VerificationReporterCfg, VerificationReporterWithSender,
VerificationReportingProvider, VerificationToken,
TcStateAccepted, VerificationReporterCfg, VerificationReportingProvider, VerificationToken,
};
use super::*;
@ -1515,20 +1503,19 @@ pub mod tests {
/// Common fields for a PUS service test harness.
pub struct PusServiceHandlerWithSharedStoreCommon {
pus_buf: [u8; 2048],
pus_buf: RefCell<[u8; 2048]>,
tm_buf: [u8; 2048],
tc_pool: SharedStaticMemoryPool,
tm_pool: SharedTmPool,
tc_sender: mpsc::SyncSender<EcssTcAndToken>,
tm_receiver: mpsc::Receiver<StoreAddr>,
verification_handler: VerificationReporterWithSharedPoolMpscBoundedSender,
tm_receiver: mpsc::Receiver<PusTmInPool>,
}
pub type PusServiceHelperStatic = PusServiceHelper<
MpscTcReceiver,
TmInSharedPoolSenderWithBoundedMpsc,
MpscTmInSharedPoolSenderBounded,
EcssTcInSharedStoreConverter,
VerificationReporterWithSharedPoolMpscBoundedSender,
VerificationReporter,
>;
impl PusServiceHandlerWithSharedStoreCommon {
@ -1536,7 +1523,7 @@ pub mod tests {
/// [PusServiceHandler] which might be required for a specific PUS service handler.
///
/// The PUS service handler is instantiated with a [EcssTcInStoreConverter].
pub fn new() -> (Self, PusServiceHelperStatic) {
pub fn new(id: ComponentId) -> (Self, PusServiceHelperStatic) {
let pool_cfg = StaticPoolConfig::new(alloc::vec![(16, 16), (8, 32), (4, 64)], false);
let tc_pool = StaticMemoryPool::new(pool_cfg.clone());
let tm_pool = StaticMemoryPool::new(pool_cfg);
@ -1545,62 +1532,47 @@ pub mod tests {
let (test_srv_tc_tx, test_srv_tc_rx) = mpsc::sync_channel(10);
let (tm_tx, tm_rx) = mpsc::sync_channel(10);
let verif_sender = TmInSharedPoolSenderWithBoundedMpsc::new(
0,
"verif_sender",
shared_tm_pool.clone(),
tm_tx.clone(),
);
let verif_cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8).unwrap();
let verification_handler =
VerificationReporterWithSharedPoolMpscBoundedSender::new(&verif_cfg, verif_sender);
let test_srv_tm_sender =
TmInSharedPoolSenderWithId::new(0, "TEST_SENDER", shared_tm_pool.clone(), tm_tx);
let test_srv_tc_receiver = MpscTcReceiver::new(0, "TEST_RECEIVER", test_srv_tc_rx);
let verification_handler = VerificationReporter::new(&verif_cfg);
let test_srv_tm_sender = TmInSharedPoolSender::new(shared_tm_pool.clone(), tm_tx);
let in_store_converter =
EcssTcInSharedStoreConverter::new(shared_tc_pool.clone(), 2048);
(
Self {
pus_buf: [0; 2048],
pus_buf: RefCell::new([0; 2048]),
tm_buf: [0; 2048],
tc_pool: shared_tc_pool,
tm_pool: shared_tm_pool,
tc_sender: test_srv_tc_tx,
tm_receiver: tm_rx,
verification_handler: verification_handler.clone(),
},
PusServiceHelper::new(
test_srv_tc_receiver,
id,
test_srv_tc_rx,
test_srv_tm_sender,
TEST_APID,
verification_handler,
in_store_converter,
),
)
}
pub fn send_tc(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> {
let token = self.verification_handler.add_tc(tc);
let token = self
.verification_handler
.acceptance_success(token, &[0; 7])
.unwrap();
let tc_size = tc.write_to_bytes(&mut self.pus_buf).unwrap();
pub fn send_tc(&self, token: &VerificationToken<TcStateAccepted>, tc: &PusTcCreator) {
let mut mut_buf = self.pus_buf.borrow_mut();
let tc_size = tc.write_to_bytes(mut_buf.as_mut_slice()).unwrap();
let mut tc_pool = self.tc_pool.write().unwrap();
let addr = tc_pool.add(&self.pus_buf[..tc_size]).unwrap();
let addr = tc_pool.add(&mut_buf[..tc_size]).unwrap();
drop(tc_pool);
// Send accepted TC to test service handler.
self.tc_sender
.send(EcssTcAndToken::new(addr, token))
.send(EcssTcAndToken::new(addr, *token))
.expect("sending tc failed");
token
}
pub fn read_next_tm(&mut self) -> PusTmReader<'_> {
let next_msg = self.tm_receiver.try_recv();
assert!(next_msg.is_ok());
let tm_addr = next_msg.unwrap();
let tm_in_pool = next_msg.unwrap();
let tm_pool = self.tm_pool.0.read().unwrap();
let tm_raw = tm_pool.read_as_vec(&tm_addr).unwrap();
let tm_raw = tm_pool.read_as_vec(&tm_in_pool.store_addr).unwrap();
self.tm_buf[0..tm_raw.len()].copy_from_slice(&tm_raw);
PusTmReader::new(&self.tm_buf, 7).unwrap().0
}
@ -1616,9 +1588,9 @@ pub mod tests {
pub fn check_next_verification_tm(&self, subservice: u8, expected_request_id: RequestId) {
let next_msg = self.tm_receiver.try_recv();
assert!(next_msg.is_ok());
let tm_addr = next_msg.unwrap();
let tm_in_pool = next_msg.unwrap();
let tm_pool = self.tm_pool.0.read().unwrap();
let tm_raw = tm_pool.read_as_vec(&tm_addr).unwrap();
let tm_raw = tm_pool.read_as_vec(&tm_in_pool.store_addr).unwrap();
let tm = PusTmReader::new(&tm_raw, 7).unwrap().0;
assert_eq!(PusPacket::service(&tm), 1);
assert_eq!(PusPacket::subservice(&tm), subservice);
@ -1629,56 +1601,49 @@ pub mod tests {
}
}
pub struct PusServiceHandlerWithVecCommon<VerificationReporter: VerificationReportingProvider> {
current_tm: Option<alloc::vec::Vec<u8>>,
pub struct PusServiceHandlerWithVecCommon {
current_tm: Option<Vec<u8>>,
tc_sender: mpsc::Sender<EcssTcAndToken>,
tm_receiver: mpsc::Receiver<alloc::vec::Vec<u8>>,
pub verification_handler: VerificationReporter,
tm_receiver: mpsc::Receiver<PusTmAsVec>,
}
pub type PusServiceHelperDynamic = PusServiceHelper<
MpscTcReceiver,
TmAsVecSenderWithMpsc,
MpscTmAsVecSender,
EcssTcInVecConverter,
VerificationReporterWithVecMpscSender,
TestVerificationReporter,
>;
impl PusServiceHandlerWithVecCommon<VerificationReporterWithVecMpscSender> {
pub fn new_with_standard_verif_reporter() -> (Self, PusServiceHelperDynamic) {
impl PusServiceHandlerWithVecCommon {
pub fn new_with_standard_verif_reporter(
id: ComponentId,
) -> (Self, PusServiceHelperDynamic) {
let (test_srv_tc_tx, test_srv_tc_rx) = mpsc::channel();
let (tm_tx, tm_rx) = mpsc::channel();
let verif_sender = TmAsVecSenderWithId::new(0, "verififcatio-sender", tm_tx.clone());
let verif_cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8).unwrap();
let verification_handler =
VerificationReporterWithSender::new(&verif_cfg, verif_sender);
let test_srv_tm_sender = TmAsVecSenderWithId::new(0, "test-sender", tm_tx);
let test_srv_tc_receiver = MpscTcReceiver::new(0, "test-receiver", test_srv_tc_rx);
let in_store_converter = EcssTcInVecConverter::default();
(
Self {
current_tm: None,
tc_sender: test_srv_tc_tx,
tm_receiver: tm_rx,
verification_handler: verification_handler.clone(),
},
PusServiceHelper::new(
test_srv_tc_receiver,
test_srv_tm_sender,
TEST_APID,
verification_handler,
id,
test_srv_tc_rx,
tm_tx,
TestVerificationReporter::default(),
in_store_converter,
),
)
}
}
impl PusServiceHandlerWithVecCommon<TestVerificationReporter> {
impl PusServiceHandlerWithVecCommon {
pub fn new_with_test_verif_sender() -> (
Self,
PusServiceHelper<
MpscTcReceiver,
TmAsVecSenderWithMpsc,
MpscTmAsVecSender,
EcssTcInVecConverter,
TestVerificationReporter,
>,
@ -1686,22 +1651,19 @@ pub mod tests {
let (test_srv_tc_tx, test_srv_tc_rx) = mpsc::channel();
let (tm_tx, tm_rx) = mpsc::channel();
let test_srv_tm_sender = TmAsVecSenderWithId::new(0, "test-sender", tm_tx);
let test_srv_tc_receiver = MpscTcReceiver::new(0, "test-receiver", test_srv_tc_rx);
let in_store_converter = EcssTcInVecConverter::default();
let shared_verif_map = SharedVerificationMap::default();
let verification_handler = TestVerificationReporter::new(shared_verif_map);
let verification_handler = TestVerificationReporter::default();
(
Self {
current_tm: None,
tc_sender: test_srv_tc_tx,
tm_receiver: tm_rx,
verification_handler: verification_handler.clone(),
//verification_handler: verification_handler.clone(),
},
PusServiceHelper::new(
test_srv_tc_receiver,
test_srv_tm_sender,
TEST_APID,
TEST_COMPONENT_ID.raw(),
test_srv_tc_rx,
tm_tx,
verification_handler,
in_store_converter,
),
@ -1709,29 +1671,21 @@ pub mod tests {
}
}
impl<VerificationReporter: VerificationReportingProvider>
PusServiceHandlerWithVecCommon<VerificationReporter>
{
pub fn send_tc(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> {
let token = self.verification_handler.add_tc(tc);
let token = self
.verification_handler
.acceptance_success(token, &[0; 7])
.unwrap();
impl PusServiceHandlerWithVecCommon {
pub fn send_tc(&self, token: &VerificationToken<TcStateAccepted>, tc: &PusTcCreator) {
// Send accepted TC to test service handler.
self.tc_sender
.send(EcssTcAndToken::new(
TcInMemory::Vec(tc.to_vec().expect("pus tc conversion to vec failed")),
token,
*token,
))
.expect("sending tc failed");
token
}
pub fn read_next_tm(&mut self) -> PusTmReader<'_> {
let next_msg = self.tm_receiver.try_recv();
assert!(next_msg.is_ok());
self.current_tm = Some(next_msg.unwrap());
self.current_tm = Some(next_msg.unwrap().packet);
PusTmReader::new(self.current_tm.as_ref().unwrap(), 7)
.unwrap()
.0
@ -1749,7 +1703,7 @@ pub mod tests {
let next_msg = self.tm_receiver.try_recv();
assert!(next_msg.is_ok());
let next_msg = next_msg.unwrap();
let tm = PusTmReader::new(next_msg.as_slice(), 7).unwrap().0;
let tm = PusTmReader::new(next_msg.packet.as_slice(), 7).unwrap().0;
assert_eq!(PusPacket::service(&tm), 1);
assert_eq!(PusPacket::subservice(&tm), subservice);
assert_eq!(tm.apid(), TEST_APID);

View File

@ -31,139 +31,7 @@ pub mod alloc_mod {}
#[cfg(feature = "alloc")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
pub mod std_mod {
/*
use spacepackets::{
ecss::tm::{PusTmCreator, PusTmSecondaryHeader},
util::UnsignedEnum,
SpHeader,
};
pub trait ModeReplyHook: ReplyHandlerHook<ActivePusRequest, ModeReply> {
fn wrong_mode_result_code(&self) -> ResultU16;
fn can_not_reach_mode_result_code(&self) -> ResultU16;
}
/// Type definition for a PUS mode servicd reply handler which constrains the
/// [PusServiceReplyHandler] active request and reply generics to the [ActiveActionRequest] and
/// [ActionReplyPusWithIds] type.
pub type PusModeServiceReplyHandler<
VerificationReporter,
ActiveRequestMap,
UserHook,
TmSender,
> = PusServiceReplyHandler<
VerificationReporter,
ActiveRequestMap,
UserHook,
TmSender,
ActivePusRequest,
ModeReply,
>;
impl<
VerificationReporter: VerificationReportingProvider,
ActiveRequestMap: ActiveRequestMapProvider<ActivePusRequest>,
UserHook: ModeReplyHook,
TmSender: EcssTmSenderCore,
> PusModeServiceReplyHandler<VerificationReporter, ActiveRequestMap, UserHook, TmSender>
{
/// Helper method to register a recently routed action request.
pub fn add_routed_mode_request(
&mut self,
request_id: verification::RequestId,
target_id: TargetId,
token: VerificationToken<TcStateStarted>,
timeout: Duration,
) {
self.active_request_map.insert(
&request_id.into(),
ActivePusRequest {
target_id,
token,
start_time: self.current_time,
timeout,
},
)
}
/// Main handler function to handle all received action replies.
pub fn handle_mode_reply(
&mut self,
mode_reply_with_id: &GenericModeReply,
time_stamp: &[u8],
) -> Result<(), EcssTmtcError> {
let active_req = self.active_request_map.get(mode_reply_with_id.request_id);
if active_req.is_none() {
self.user_hook.handle_unexpected_reply(mode_reply_with_id);
return Ok(());
}
let active_req = active_req.unwrap().clone();
let remove_entry = match mode_reply_with_id.message {
ModeReply::ModeReply(reply) => {
reply.write_to_be_bytes(&mut self.tm_buf)?;
let req_id = verification::RequestId::from(mode_reply_with_id.request_id);
let mut sp_header = SpHeader::tm_unseg(
req_id.packet_id().apid(),
req_id.packet_seq_ctrl().seq_count(),
0,
)
.expect("space packet header creation error");
let sec_header = PusTmSecondaryHeader::new(
MODE_SERVICE_ID,
Subservice::TmModeReply as u8,
0,
0,
Some(time_stamp),
);
let pus_tm = PusTmCreator::new(&mut sp_header, sec_header, &self.tm_buf, true);
self.tm_sender.send_tm(PusTmWrapper::Direct(pus_tm))?;
self.verification_reporter
.completion_success(active_req.token, time_stamp)
.map_err(|e| e.0)?;
true
}
ModeReply::CantReachMode(reason) => {
let fail_data_len = reason.write_to_be_bytes(&mut self.tm_buf)?;
self.verification_reporter
.completion_failure(
active_req.token,
FailParams::new(
time_stamp,
&self.user_hook.can_not_reach_mode_result_code(),
&self.tm_buf[0..fail_data_len],
),
)
.map_err(|e| e.0)?;
true
}
ModeReply::WrongMode { expected, reached } => {
let expected_len = expected.write_to_be_bytes(&mut self.tm_buf)?;
let reached_len =
reached.write_to_be_bytes(&mut self.tm_buf[expected_len..])?;
self.verification_reporter
.completion_failure(
active_req.token,
FailParams::new(
time_stamp,
&self.user_hook.can_not_reach_mode_result_code(),
&self.tm_buf[0..expected_len + reached_len],
),
)
.map_err(|e| e.0)?;
true
}
_ => true,
};
if remove_entry {
self.active_request_map
.remove(mode_reply_with_id.request_id);
}
Ok(())
}
}
*/
}
pub mod std_mod {}
#[cfg(test)]
mod tests {
@ -175,7 +43,7 @@ mod tests {
ModeAndSubmode, ModeReply, ModeReplySender, ModeRequest, ModeRequestSender,
ModeRequestorAndHandlerMpsc, ModeRequestorMpsc,
},
request::GenericMessage,
request::{GenericMessage, MessageMetadata},
};
const TEST_COMPONENT_ID_0: u64 = 5;
@ -196,24 +64,23 @@ mod tests {
.send_mode_request(request_id, TEST_COMPONENT_ID_1, sent_request)
.expect("send failed");
let request = request_receiver.recv().expect("recv failed");
assert_eq!(request.request_id, 2);
assert_eq!(request.sender_id, TEST_COMPONENT_ID_0);
assert_eq!(request.request_id(), 2);
assert_eq!(request.sender_id(), TEST_COMPONENT_ID_0);
assert_eq!(request.message, sent_request);
// Send a reply and verify it arrives at the requestor.
let mode_reply = ModeReply::ModeReply(ModeAndSubmode::new(1, 5));
reply_sender
.send(GenericMessage::new(
request_id,
TEST_COMPONENT_ID_1,
MessageMetadata::new(request_id, TEST_COMPONENT_ID_1),
mode_reply,
))
.expect("send failed");
let reply = mode_requestor.try_recv_mode_reply().expect("recv failed");
assert!(reply.is_some());
let reply = reply.unwrap();
assert_eq!(reply.sender_id, TEST_COMPONENT_ID_1);
assert_eq!(reply.request_id, 2);
assert_eq!(reply.sender_id(), TEST_COMPONENT_ID_1);
assert_eq!(reply.request_id(), 2);
assert_eq!(reply.message, mode_reply);
}
@ -252,8 +119,8 @@ mod tests {
.expect("send failed");
let request = request_receiver_channel_1.recv().expect("recv failed");
assert_eq!(request.request_id, 2);
assert_eq!(request.sender_id, TEST_COMPONENT_ID_0);
assert_eq!(request.request_id(), 2);
assert_eq!(request.sender_id(), TEST_COMPONENT_ID_0);
assert_eq!(request.message, ModeRequest::ReadMode);
}
@ -272,13 +139,16 @@ mod tests {
// Send a request and verify it arrives at the receiver.
let request_id = 2;
let sent_reply = ModeReply::ModeInfo(ModeAndSubmode::new(3, 5));
let sent_reply = ModeReply::ModeReply(ModeAndSubmode::new(3, 5));
mode_connector
.send_mode_reply(request_id, TEST_COMPONENT_ID_2, sent_reply)
.send_mode_reply(
MessageMetadata::new(request_id, TEST_COMPONENT_ID_0),
sent_reply,
)
.expect("send failed");
let reply = reply_receiver_channel_2.recv().expect("recv failed");
assert_eq!(reply.request_id, 2);
assert_eq!(reply.sender_id, TEST_COMPONENT_ID_0);
assert_eq!(reply.request_id(), 2);
assert_eq!(reply.sender_id(), TEST_COMPONENT_ID_0);
assert_eq!(reply.message, sent_reply);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,19 +1,16 @@
use super::scheduler::PusSchedulerProvider;
use super::verification::{
VerificationReporterWithSharedPoolMpscBoundedSender,
VerificationReporterWithSharedPoolMpscSender, VerificationReporterWithVecMpscBoundedSender,
VerificationReporterWithVecMpscSender, VerificationReportingProvider,
};
use super::verification::{VerificationReporter, VerificationReportingProvider};
use super::{
EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter, EcssTcReceiverCore,
EcssTmSenderCore, MpscTcReceiver, PusServiceHelper, TmAsVecSenderWithBoundedMpsc,
TmAsVecSenderWithMpsc, TmInSharedPoolSenderWithBoundedMpsc, TmInSharedPoolSenderWithMpsc,
EcssTmSenderCore, MpscTcReceiver, MpscTmInSharedPoolSender, MpscTmInSharedPoolSenderBounded,
PusServiceHelper, PusTmAsVec,
};
use crate::pool::PoolProvider;
use crate::pus::{PusPacketHandlerResult, PusPacketHandlingError};
use alloc::string::ToString;
use spacepackets::ecss::{scheduling, PusPacket};
use spacepackets::time::cds::TimeProvider;
use spacepackets::time::cds::CdsTime;
use std::sync::mpsc;
/// This is a helper class for [std] environments to handle generic PUS 11 (scheduling service)
/// packets. This handler is able to handle the most important PUS requests for a scheduling
@ -23,7 +20,7 @@ use spacepackets::time::cds::TimeProvider;
/// telecommands inside the scheduler. The user can retrieve the wrapped scheduler via the
/// [Self::scheduler] and [Self::scheduler_mut] function and then use the scheduler API to release
/// telecommands when applicable.
pub struct PusService11SchedHandler<
pub struct PusSchedServiceHandler<
TcReceiver: EcssTcReceiverCore,
TmSender: EcssTmSenderCore,
TcInMemConverter: EcssTcInMemConverter,
@ -42,13 +39,7 @@ impl<
VerificationReporter: VerificationReportingProvider,
Scheduler: PusSchedulerProvider,
>
PusService11SchedHandler<
TcReceiver,
TmSender,
TcInMemConverter,
VerificationReporter,
Scheduler,
>
PusSchedServiceHandler<TcReceiver, TmSender, TcInMemConverter, VerificationReporter, Scheduler>
{
pub fn new(
service_helper: PusServiceHelper<
@ -101,14 +92,24 @@ impl<
let start_token = self
.service_helper
.verif_reporter()
.start_success(ecss_tc_and_token.token, time_stamp)
.start_success(
self.service_helper.common.id,
&self.service_helper.common.tm_sender,
ecss_tc_and_token.token,
time_stamp,
)
.expect("Error sending start success");
self.scheduler.enable();
if self.scheduler.is_enabled() {
self.service_helper
.verif_reporter()
.completion_success(start_token, time_stamp)
.completion_success(
self.service_helper.common.id,
&self.service_helper.common.tm_sender,
start_token,
time_stamp,
)
.expect("Error sending completion success");
} else {
return Err(PusPacketHandlingError::Other(
@ -120,14 +121,24 @@ impl<
let start_token = self
.service_helper
.verif_reporter()
.start_success(ecss_tc_and_token.token, time_stamp)
.start_success(
self.service_helper.common.id,
&self.service_helper.common.tm_sender,
ecss_tc_and_token.token,
time_stamp,
)
.expect("Error sending start success");
self.scheduler.disable();
if !self.scheduler.is_enabled() {
self.service_helper
.verif_reporter()
.completion_success(start_token, time_stamp)
.completion_success(
self.service_helper.common.id,
&self.service_helper.common.tm_sender,
start_token,
time_stamp,
)
.expect("Error sending completion success");
} else {
return Err(PusPacketHandlingError::Other(
@ -139,7 +150,12 @@ impl<
let start_token = self
.service_helper
.verif_reporter()
.start_success(ecss_tc_and_token.token, time_stamp)
.start_success(
self.service_helper.common.id,
&self.service_helper.common.tm_sender,
ecss_tc_and_token.token,
time_stamp,
)
.expect("Error sending start success");
self.scheduler
@ -148,7 +164,12 @@ impl<
self.service_helper
.verif_reporter()
.completion_success(start_token, time_stamp)
.completion_success(
self.service_helper.common.id,
&self.service_helper.common.tm_sender,
start_token,
time_stamp,
)
.expect("Error sending completion success");
}
scheduling::Subservice::TcInsertActivity => {
@ -156,17 +177,27 @@ impl<
.service_helper
.common
.verif_reporter
.start_success(ecss_tc_and_token.token, time_stamp)
.start_success(
self.service_helper.common.id,
&self.service_helper.common.tm_sender,
ecss_tc_and_token.token,
time_stamp,
)
.expect("error sending start success");
// let mut pool = self.sched_tc_pool.write().expect("locking pool failed");
self.scheduler
.insert_wrapped_tc::<TimeProvider>(&tc, sched_tc_pool)
.insert_wrapped_tc::<CdsTime>(&tc, sched_tc_pool)
.expect("insertion of activity into pool failed");
self.service_helper
.verif_reporter()
.completion_success(start_token, time_stamp)
.completion_success(
self.service_helper.common.id,
&self.service_helper.common.tm_sender,
start_token,
time_stamp,
)
.expect("sending completion success failed");
}
_ => {
@ -187,38 +218,38 @@ impl<
}
/// Helper type definition for a PUS 11 handler with a dynamic TMTC memory backend and regular
/// mpsc queues.
pub type PusService11SchedHandlerDynWithMpsc<PusScheduler> = PusService11SchedHandler<
pub type PusService11SchedHandlerDynWithMpsc<PusScheduler> = PusSchedServiceHandler<
MpscTcReceiver,
TmAsVecSenderWithMpsc,
mpsc::Sender<PusTmAsVec>,
EcssTcInVecConverter,
VerificationReporterWithVecMpscSender,
VerificationReporter,
PusScheduler,
>;
/// Helper type definition for a PUS 11 handler with a dynamic TMTC memory backend and bounded MPSC
/// queues.
pub type PusService11SchedHandlerDynWithBoundedMpsc<PusScheduler> = PusService11SchedHandler<
pub type PusService11SchedHandlerDynWithBoundedMpsc<PusScheduler> = PusSchedServiceHandler<
MpscTcReceiver,
TmAsVecSenderWithBoundedMpsc,
mpsc::SyncSender<PusTmAsVec>,
EcssTcInVecConverter,
VerificationReporterWithVecMpscBoundedSender,
VerificationReporter,
PusScheduler,
>;
/// Helper type definition for a PUS 11 handler with a shared store TMTC memory backend and regular
/// mpsc queues.
pub type PusService11SchedHandlerStaticWithMpsc<PusScheduler> = PusService11SchedHandler<
pub type PusService11SchedHandlerStaticWithMpsc<PusScheduler> = PusSchedServiceHandler<
MpscTcReceiver,
TmInSharedPoolSenderWithMpsc,
MpscTmInSharedPoolSender,
EcssTcInSharedStoreConverter,
VerificationReporterWithSharedPoolMpscSender,
VerificationReporter,
PusScheduler,
>;
/// Helper type definition for a PUS 11 handler with a shared store TMTC memory backend and bounded
/// mpsc queues.
pub type PusService11SchedHandlerStaticWithBoundedMpsc<PusScheduler> = PusService11SchedHandler<
pub type PusService11SchedHandlerStaticWithBoundedMpsc<PusScheduler> = PusSchedServiceHandler<
MpscTcReceiver,
TmInSharedPoolSenderWithBoundedMpsc,
MpscTmInSharedPoolSenderBounded,
EcssTcInSharedStoreConverter,
VerificationReporterWithSharedPoolMpscBoundedSender,
VerificationReporter,
PusScheduler,
>;
@ -226,7 +257,8 @@ pub type PusService11SchedHandlerStaticWithBoundedMpsc<PusScheduler> = PusServic
mod tests {
use crate::pool::{StaticMemoryPool, StaticPoolConfig};
use crate::pus::test_util::{PusTestHarness, TEST_APID};
use crate::pus::verification::VerificationReporterWithSharedPoolMpscBoundedSender;
use crate::pus::verification::{VerificationReporter, VerificationReportingProvider};
use crate::pus::{
scheduler::{self, PusSchedulerProvider, TcInfo},
tests::PusServiceHandlerWithSharedStoreCommon,
@ -234,8 +266,8 @@ mod tests {
EcssTcInSharedStoreConverter,
};
use crate::pus::{
MpscTcReceiver, PusPacketHandlerResult, PusPacketHandlingError,
TmInSharedPoolSenderWithBoundedMpsc,
MpscTcReceiver, MpscTmInSharedPoolSenderBounded, PusPacketHandlerResult,
PusPacketHandlingError,
};
use alloc::collections::VecDeque;
use delegate::delegate;
@ -249,15 +281,15 @@ mod tests {
time::cds,
};
use super::PusService11SchedHandler;
use super::PusSchedServiceHandler;
struct Pus11HandlerWithStoreTester {
common: PusServiceHandlerWithSharedStoreCommon,
handler: PusService11SchedHandler<
handler: PusSchedServiceHandler<
MpscTcReceiver,
TmInSharedPoolSenderWithBoundedMpsc,
MpscTmInSharedPoolSenderBounded,
EcssTcInSharedStoreConverter,
VerificationReporterWithSharedPoolMpscBoundedSender,
VerificationReporter,
TestScheduler,
>,
sched_tc_pool: StaticMemoryPool,
@ -268,25 +300,39 @@ mod tests {
let test_scheduler = TestScheduler::default();
let pool_cfg = StaticPoolConfig::new(alloc::vec![(16, 16), (8, 32), (4, 64)], false);
let sched_tc_pool = StaticMemoryPool::new(pool_cfg.clone());
let (common, srv_handler) = PusServiceHandlerWithSharedStoreCommon::new();
let (common, srv_handler) = PusServiceHandlerWithSharedStoreCommon::new(0);
Self {
common,
handler: PusService11SchedHandler::new(srv_handler, test_scheduler),
handler: PusSchedServiceHandler::new(srv_handler, test_scheduler),
sched_tc_pool,
}
}
pub fn handle_one_tc(&mut self) -> Result<PusPacketHandlerResult, PusPacketHandlingError> {
let time_stamp = cds::TimeProvider::new_with_u16_days(0, 0).to_vec().unwrap();
let time_stamp = cds::CdsTime::new_with_u16_days(0, 0).to_vec().unwrap();
self.handler
.poll_and_handle_next_tc(&time_stamp, &mut self.sched_tc_pool)
}
}
impl PusTestHarness for Pus11HandlerWithStoreTester {
fn init_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> {
let init_token = self.handler.service_helper.verif_reporter_mut().add_tc(tc);
self.handler
.service_helper
.verif_reporter()
.acceptance_success(
self.handler.service_helper.id(),
self.handler.service_helper.tm_sender(),
init_token,
&[0; 7],
)
.expect("acceptance success failure")
}
delegate! {
to self.common {
fn send_tc(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted>;
fn send_tc(&self, token: &VerificationToken<TcStateAccepted>, tc: &PusTcCreator);
fn read_next_tm(&mut self) -> PusTmReader<'_>;
fn check_no_tm_available(&self) -> bool;
fn check_next_verification_tm(&self, subservice: u8, expected_request_id: RequestId);
@ -304,7 +350,7 @@ mod tests {
}
impl PusSchedulerProvider for TestScheduler {
type TimeProvider = cds::TimeProvider;
type TimeProvider = cds::CdsTime;
fn reset(
&mut self,
@ -330,7 +376,7 @@ mod tests {
fn insert_unwrapped_and_stored_tc(
&mut self,
_time_stamp: spacepackets::time::UnixTimestamp,
_time_stamp: spacepackets::time::UnixTime,
info: crate::pus::scheduler::TcInfo,
) -> Result<(), crate::pus::scheduler::ScheduleError> {
self.inserted_tcs.push_back(info);
@ -345,10 +391,11 @@ mod tests {
let mut reply_header = SpHeader::tm_unseg(TEST_APID, 0, 0).unwrap();
let tc_header = PusTcSecondaryHeader::new_simple(11, subservice as u8);
let enable_scheduling = PusTcCreator::new(&mut reply_header, tc_header, &[0; 7], true);
let token = test_harness.send_tc(&enable_scheduling);
let token = test_harness.init_verification(&enable_scheduling);
test_harness.send_tc(&token, &enable_scheduling);
let request_id = token.request_id();
let time_stamp = cds::TimeProvider::new_with_u16_days(0, 0).to_vec().unwrap();
let time_stamp = cds::CdsTime::new_with_u16_days(0, 0).to_vec().unwrap();
test_harness
.handler
.poll_and_handle_next_tc(&time_stamp, &mut test_harness.sched_tc_pool)
@ -392,7 +439,7 @@ mod tests {
let mut sec_header = PusTcSecondaryHeader::new_simple(17, 1);
let ping_tc = PusTcCreator::new(&mut reply_header, sec_header, &[], true);
let req_id_ping_tc = scheduler::RequestId::from_tc(&ping_tc);
let stamper = cds::TimeProvider::from_now_with_u16_days().expect("time provider failed");
let stamper = cds::CdsTime::now_with_u16_days().expect("time provider failed");
let mut sched_app_data: [u8; 64] = [0; 64];
let mut written_len = stamper.write_to_bytes(&mut sched_app_data).unwrap();
let ping_raw = ping_tc.to_vec().expect("generating raw tc failed");
@ -406,7 +453,8 @@ mod tests {
&sched_app_data[..written_len],
true,
);
let token = test_harness.send_tc(&enable_scheduling);
let token = test_harness.init_verification(&enable_scheduling);
test_harness.send_tc(&token, &enable_scheduling);
let request_id = token.request_id();
test_harness.handle_one_tc().unwrap();

View File

@ -1,20 +1,17 @@
use crate::pus::{
PartialPusHandlingError, PusPacketHandlerResult, PusPacketHandlingError, PusTmWrapper,
PartialPusHandlingError, PusPacketHandlerResult, PusPacketHandlingError, PusTmAsVec,
PusTmInPool, PusTmVariant,
};
use spacepackets::ecss::tm::{PusTmCreator, PusTmSecondaryHeader};
use spacepackets::ecss::PusPacket;
use spacepackets::SpHeader;
use std::sync::mpsc;
use super::verification::{
VerificationReporterWithSharedPoolMpscBoundedSender,
VerificationReporterWithSharedPoolMpscSender, VerificationReporterWithVecMpscBoundedSender,
VerificationReporterWithVecMpscSender, VerificationReportingProvider,
};
use super::verification::{VerificationReporter, VerificationReportingProvider};
use super::{
EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter, EcssTcReceiverCore,
EcssTmSenderCore, GenericConversionError, MpscTcReceiver, PusServiceHelper,
TmAsVecSenderWithBoundedMpsc, TmAsVecSenderWithMpsc, TmInSharedPoolSenderWithBoundedMpsc,
TmInSharedPoolSenderWithMpsc,
EcssTmSenderCore, GenericConversionError, MpscTcReceiver, MpscTmInSharedPoolSender,
MpscTmInSharedPoolSenderBounded, PusServiceHelper,
};
/// This is a helper class for [std] environments to handle generic PUS 17 (test service) packets.
@ -68,7 +65,12 @@ impl<
let result = self
.service_helper
.verif_reporter()
.start_success(ecss_tc_and_token.token, time_stamp)
.start_success(
self.service_helper.common.id,
&self.service_helper.common.tm_sender,
ecss_tc_and_token.token,
time_stamp,
)
.map_err(|_| PartialPusHandlingError::Verification);
let start_token = if let Ok(result) = result {
Some(result)
@ -78,14 +80,14 @@ impl<
};
// Sequence count will be handled centrally in TM funnel.
let mut reply_header =
SpHeader::tm_unseg(self.service_helper.common.tm_apid, 0, 0).unwrap();
SpHeader::tm_unseg(self.service_helper.verif_reporter().apid(), 0, 0).unwrap();
let tc_header = PusTmSecondaryHeader::new_simple(17, 2, time_stamp);
let ping_reply = PusTmCreator::new(&mut reply_header, tc_header, &[], true);
let result = self
.service_helper
.common
.tm_sender
.send_tm(PusTmWrapper::Direct(ping_reply))
.send_tm(self.service_helper.id(), PusTmVariant::Direct(ping_reply))
.map_err(PartialPusHandlingError::TmSend);
if let Err(err) = result {
partial_error = Some(err);
@ -95,7 +97,12 @@ impl<
if self
.service_helper
.verif_reporter()
.completion_success(start_token, time_stamp)
.completion_success(
self.service_helper.common.id,
&self.service_helper.common.tm_sender,
start_token,
time_stamp,
)
.is_err()
{
partial_error = Some(PartialPusHandlingError::Verification)
@ -120,33 +127,33 @@ impl<
/// mpsc queues.
pub type PusService17TestHandlerDynWithMpsc = PusService17TestHandler<
MpscTcReceiver,
TmAsVecSenderWithMpsc,
mpsc::Sender<PusTmAsVec>,
EcssTcInVecConverter,
VerificationReporterWithVecMpscSender,
VerificationReporter,
>;
/// Helper type definition for a PUS 17 handler with a dynamic TMTC memory backend and bounded MPSC
/// queues.
pub type PusService17TestHandlerDynWithBoundedMpsc = PusService17TestHandler<
MpscTcReceiver,
TmAsVecSenderWithBoundedMpsc,
mpsc::SyncSender<PusTmInPool>,
EcssTcInVecConverter,
VerificationReporterWithVecMpscBoundedSender,
VerificationReporter,
>;
/// Helper type definition for a PUS 17 handler with a shared store TMTC memory backend and regular
/// mpsc queues.
pub type PusService17TestHandlerStaticWithMpsc = PusService17TestHandler<
MpscTcReceiver,
TmInSharedPoolSenderWithMpsc,
MpscTmInSharedPoolSender,
EcssTcInSharedStoreConverter,
VerificationReporterWithSharedPoolMpscSender,
VerificationReporter,
>;
/// Helper type definition for a PUS 17 handler with a shared store TMTC memory backend and bounded
/// mpsc queues.
pub type PusService17TestHandlerStaticWithBoundedMpsc = PusService17TestHandler<
MpscTcReceiver,
TmInSharedPoolSenderWithBoundedMpsc,
MpscTmInSharedPoolSenderBounded,
EcssTcInSharedStoreConverter,
VerificationReporterWithSharedPoolMpscBoundedSender,
VerificationReporter,
>;
#[cfg(test)]
@ -155,16 +162,17 @@ mod tests {
use crate::pus::tests::{
PusServiceHandlerWithSharedStoreCommon, PusServiceHandlerWithVecCommon,
};
use crate::pus::verification::std_mod::{
VerificationReporterWithSharedPoolMpscBoundedSender, VerificationReporterWithVecMpscSender,
use crate::pus::verification::test_util::TestVerificationReporter;
use crate::pus::verification::{
RequestId, VerificationReporter, VerificationReportingProvider,
};
use crate::pus::verification::RequestId;
use crate::pus::verification::{TcStateAccepted, VerificationToken};
use crate::pus::{
EcssTcInSharedStoreConverter, EcssTcInVecConverter, GenericConversionError, MpscTcReceiver,
PusPacketHandlerResult, PusPacketHandlingError, TmAsVecSenderWithMpsc,
TmInSharedPoolSenderWithBoundedMpsc,
MpscTmAsVecSender, MpscTmInSharedPoolSenderBounded, PusPacketHandlerResult,
PusPacketHandlingError,
};
use crate::ComponentId;
use delegate::delegate;
use spacepackets::ecss::tc::{PusTcCreator, PusTcSecondaryHeader};
use spacepackets::ecss::tm::PusTmReader;
@ -178,15 +186,15 @@ mod tests {
common: PusServiceHandlerWithSharedStoreCommon,
handler: PusService17TestHandler<
MpscTcReceiver,
TmInSharedPoolSenderWithBoundedMpsc,
MpscTmInSharedPoolSenderBounded,
EcssTcInSharedStoreConverter,
VerificationReporterWithSharedPoolMpscBoundedSender,
VerificationReporter,
>,
}
impl Pus17HandlerWithStoreTester {
pub fn new() -> Self {
let (common, srv_handler) = PusServiceHandlerWithSharedStoreCommon::new();
pub fn new(id: ComponentId) -> Self {
let (common, srv_handler) = PusServiceHandlerWithSharedStoreCommon::new(id);
let pus_17_handler = PusService17TestHandler::new(srv_handler);
Self {
common,
@ -196,10 +204,24 @@ mod tests {
}
impl PusTestHarness for Pus17HandlerWithStoreTester {
fn init_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> {
let init_token = self.handler.service_helper.verif_reporter_mut().add_tc(tc);
self.handler
.service_helper
.verif_reporter()
.acceptance_success(
self.handler.service_helper.id(),
self.handler.service_helper.tm_sender(),
init_token,
&[0; 7],
)
.expect("acceptance success failure")
}
delegate! {
to self.common {
fn send_tc(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted>;
fn read_next_tm(&mut self) -> PusTmReader<'_>;
fn send_tc(&self, token: &VerificationToken<TcStateAccepted>, tc: &PusTcCreator);
fn check_no_tm_available(&self) -> bool;
fn check_next_verification_tm(
&self,
@ -211,25 +233,25 @@ mod tests {
}
impl SimplePusPacketHandler for Pus17HandlerWithStoreTester {
fn handle_one_tc(&mut self) -> Result<PusPacketHandlerResult, PusPacketHandlingError> {
let time_stamp = cds::TimeProvider::new_with_u16_days(0, 0).to_vec().unwrap();
let time_stamp = cds::CdsTime::new_with_u16_days(0, 0).to_vec().unwrap();
self.handler.poll_and_handle_next_tc(&time_stamp)
}
}
struct Pus17HandlerWithVecTester {
common: PusServiceHandlerWithVecCommon<VerificationReporterWithVecMpscSender>,
common: PusServiceHandlerWithVecCommon,
handler: PusService17TestHandler<
MpscTcReceiver,
TmAsVecSenderWithMpsc,
MpscTmAsVecSender,
EcssTcInVecConverter,
VerificationReporterWithVecMpscSender,
TestVerificationReporter,
>,
}
impl Pus17HandlerWithVecTester {
pub fn new() -> Self {
pub fn new(id: ComponentId) -> Self {
let (common, srv_handler) =
PusServiceHandlerWithVecCommon::new_with_standard_verif_reporter();
PusServiceHandlerWithVecCommon::new_with_standard_verif_reporter(id);
Self {
common,
handler: PusService17TestHandler::new(srv_handler),
@ -238,9 +260,23 @@ mod tests {
}
impl PusTestHarness for Pus17HandlerWithVecTester {
fn init_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> {
let init_token = self.handler.service_helper.verif_reporter_mut().add_tc(tc);
self.handler
.service_helper
.verif_reporter()
.acceptance_success(
self.handler.service_helper.id(),
self.handler.service_helper.tm_sender(),
init_token,
&[0; 7],
)
.expect("acceptance success failure")
}
delegate! {
to self.common {
fn send_tc(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted>;
fn send_tc(&self, token: &VerificationToken<TcStateAccepted>, tc: &PusTcCreator);
fn read_next_tm(&mut self) -> PusTmReader<'_>;
fn check_no_tm_available(&self) -> bool;
fn check_next_verification_tm(
@ -253,7 +289,7 @@ mod tests {
}
impl SimplePusPacketHandler for Pus17HandlerWithVecTester {
fn handle_one_tc(&mut self) -> Result<PusPacketHandlerResult, PusPacketHandlingError> {
let time_stamp = cds::TimeProvider::new_with_u16_days(0, 0).to_vec().unwrap();
let time_stamp = cds::CdsTime::new_with_u16_days(0, 0).to_vec().unwrap();
self.handler.poll_and_handle_next_tc(&time_stamp)
}
}
@ -263,7 +299,8 @@ mod tests {
let mut sp_header = SpHeader::tc(TEST_APID, SequenceFlags::Unsegmented, 0, 0).unwrap();
let sec_header = PusTcSecondaryHeader::new_simple(17, 1);
let ping_tc = PusTcCreator::new_no_app_data(&mut sp_header, sec_header, true);
let token = test_harness.send_tc(&ping_tc);
let token = test_harness.init_verification(&ping_tc);
test_harness.send_tc(&token, &ping_tc);
let request_id = token.request_id();
let result = test_harness.handle_one_tc();
assert!(result.is_ok());
@ -288,19 +325,19 @@ mod tests {
#[test]
fn test_basic_ping_processing_using_store() {
let mut test_harness = Pus17HandlerWithStoreTester::new();
let mut test_harness = Pus17HandlerWithStoreTester::new(0);
ping_test(&mut test_harness);
}
#[test]
fn test_basic_ping_processing_using_vec() {
let mut test_harness = Pus17HandlerWithVecTester::new();
let mut test_harness = Pus17HandlerWithVecTester::new(0);
ping_test(&mut test_harness);
}
#[test]
fn test_empty_tc_queue() {
let mut test_harness = Pus17HandlerWithStoreTester::new();
let mut test_harness = Pus17HandlerWithStoreTester::new(0);
let result = test_harness.handle_one_tc();
assert!(result.is_ok());
let result = result.unwrap();
@ -312,11 +349,12 @@ mod tests {
#[test]
fn test_sending_unsupported_service() {
let mut test_harness = Pus17HandlerWithStoreTester::new();
let mut test_harness = Pus17HandlerWithStoreTester::new(0);
let mut sp_header = SpHeader::tc(TEST_APID, SequenceFlags::Unsegmented, 0, 0).unwrap();
let sec_header = PusTcSecondaryHeader::new_simple(3, 1);
let ping_tc = PusTcCreator::new_no_app_data(&mut sp_header, sec_header, true);
test_harness.send_tc(&ping_tc);
let token = test_harness.init_verification(&ping_tc);
test_harness.send_tc(&token, &ping_tc);
let result = test_harness.handle_one_tc();
assert!(result.is_err());
let error = result.unwrap_err();
@ -332,11 +370,12 @@ mod tests {
#[test]
fn test_sending_custom_subservice() {
let mut test_harness = Pus17HandlerWithStoreTester::new();
let mut test_harness = Pus17HandlerWithStoreTester::new(0);
let mut sp_header = SpHeader::tc(TEST_APID, SequenceFlags::Unsegmented, 0, 0).unwrap();
let sec_header = PusTcSecondaryHeader::new_simple(17, 200);
let ping_tc = PusTcCreator::new_no_app_data(&mut sp_header, sec_header, true);
test_harness.send_tc(&ping_tc);
let token = test_harness.init_verification(&ping_tc);
test_harness.send_tc(&token, &ping_tc);
let result = test_harness.handle_one_tc();
assert!(result.is_ok());
let result = result.unwrap();

File diff suppressed because it is too large Load Diff

View File

@ -25,21 +25,24 @@ pub type RequestId = u32;
pub type Apid = u16;
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub struct TargetAndApidId {
pub struct UniqueApidTargetId {
pub apid: Apid,
pub target: u32,
pub unique_id: u32,
}
impl TargetAndApidId {
impl UniqueApidTargetId {
pub const fn new(apid: Apid, target: u32) -> Self {
Self { apid, target }
Self {
apid,
unique_id: target,
}
}
pub fn raw(&self) -> ComponentId {
((self.apid as u64) << 32) | (self.target as u64)
((self.apid as u64) << 32) | (self.unique_id as u64)
}
pub fn full_target_id(&self) -> ComponentId {
pub fn id(&self) -> ComponentId {
self.raw()
}
@ -61,49 +64,78 @@ impl TargetAndApidId {
}
}
impl From<u64> for TargetAndApidId {
impl From<u64> for UniqueApidTargetId {
fn from(raw: u64) -> Self {
Self {
apid: (raw >> 32) as u16,
target: raw as u32,
unique_id: raw as u32,
}
}
}
impl From<TargetAndApidId> for u64 {
fn from(target_and_apid_id: TargetAndApidId) -> Self {
impl From<UniqueApidTargetId> for u64 {
fn from(target_and_apid_id: UniqueApidTargetId) -> Self {
target_and_apid_id.raw()
}
}
impl fmt::Display for TargetAndApidId {
impl fmt::Display for UniqueApidTargetId {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"Target and APID ID with APID {:#03x} and target {}",
self.apid, self.target
self.apid, self.unique_id
)
}
}
#[derive(Debug, Copy, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct MessageMetadata {
request_id: RequestId,
sender_id: ComponentId,
}
impl MessageMetadata {
pub const fn new(request_id: RequestId, sender_id: ComponentId) -> Self {
Self {
request_id,
sender_id,
}
}
pub fn request_id(&self) -> RequestId {
self.request_id
}
pub fn sender_id(&self) -> ComponentId {
self.sender_id
}
}
/// Generic message type which is associated with a sender using a [ChannelId] and associated
/// with a request using a [RequestId].
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct GenericMessage<MSG> {
pub request_id: RequestId,
pub sender_id: ComponentId,
pub requestor_info: MessageMetadata,
pub message: MSG,
}
impl<MSG> GenericMessage<MSG> {
pub fn new(request_id: RequestId, sender_id: ComponentId, message: MSG) -> Self {
pub fn new(requestor_info: MessageMetadata, message: MSG) -> Self {
Self {
request_id,
sender_id,
requestor_info,
message,
}
}
delegate::delegate! {
to self.requestor_info {
pub fn request_id(&self) -> RequestId;
pub fn sender_id(&self) -> ComponentId;
}
}
}
/// Generic trait for objects which can send targeted messages.
@ -186,8 +218,7 @@ pub mod alloc_mod {
pub fn send_message(
&self,
request_id: RequestId,
local_channel_id: ComponentId,
requestor_info: MessageMetadata,
target_channel_id: ComponentId,
message: MSG,
) -> Result<(), GenericTargetedMessagingError> {
@ -196,45 +227,12 @@ pub mod alloc_mod {
.0
.get(&target_channel_id)
.unwrap()
.send(GenericMessage::new(request_id, local_channel_id, message));
.send(GenericMessage::new(requestor_info, message));
}
Err(GenericSendError::TargetDoesNotExist(target_channel_id).into())
}
}
pub struct MessageSenderMapWithId<MSG, S: MessageSender<MSG>> {
pub local_channel_id: ComponentId,
pub message_sender_map: MessageSenderMap<MSG, S>,
}
impl<MSG, S: MessageSender<MSG>> MessageSenderMapWithId<MSG, S> {
pub fn new(local_channel_id: ComponentId) -> Self {
Self {
local_channel_id,
message_sender_map: Default::default(),
}
}
pub fn send_message(
&self,
request_id: RequestId,
target_channel_id: ComponentId,
message: MSG,
) -> Result<(), GenericTargetedMessagingError> {
self.message_sender_map.send_message(
request_id,
self.local_channel_id,
target_channel_id,
message,
)
}
pub fn add_message_target(&mut self, target_id: ComponentId, message_sender: S) {
self.message_sender_map
.add_message_target(target_id, message_sender)
}
}
pub struct MessageSenderAndReceiver<TO, FROM, S: MessageSender<TO>, R: MessageReceiver<FROM>> {
pub local_channel_id: ComponentId,
pub message_sender_map: MessageSenderMap<TO, S>,
@ -265,13 +263,12 @@ pub mod alloc_mod {
pub fn send_message(
&self,
request_id: RequestId,
target_channel_id: ComponentId,
target_id: ComponentId,
message: TO,
) -> Result<(), GenericTargetedMessagingError> {
self.message_sender_map.send_message(
request_id,
self.local_channel_id_generic(),
target_channel_id,
MessageMetadata::new(request_id, self.local_channel_id_generic()),
target_id,
message,
)
}
@ -390,9 +387,12 @@ mod tests {
ByteConversionError, SpHeader,
};
use crate::queue::{GenericReceiveError, GenericSendError, GenericTargetedMessagingError};
use crate::{
queue::{GenericReceiveError, GenericSendError, GenericTargetedMessagingError},
request::{MessageMetadata, MessageSenderMap},
};
use super::{GenericMessage, MessageReceiverWithId, MessageSenderMapWithId, TargetAndApidId};
use super::{GenericMessage, MessageReceiverWithId, UniqueApidTargetId};
const TEST_CHANNEL_ID_0: u64 = 1;
const TEST_CHANNEL_ID_1: u64 = 2;
@ -400,15 +400,15 @@ mod tests {
#[test]
fn test_basic_target_id_with_apid() {
let id = TargetAndApidId::new(0x111, 0x01);
let id = UniqueApidTargetId::new(0x111, 0x01);
assert_eq!(id.apid, 0x111);
assert_eq!(id.target, 0x01);
assert_eq!(id.full_target_id(), id.raw());
assert_eq!(id.unique_id, 0x01);
assert_eq!(id.id(), id.raw());
assert_eq!(u64::from(id), id.raw());
let id_raw = id.raw();
let id_from_raw = TargetAndApidId::from(id_raw);
let id_from_raw = UniqueApidTargetId::from(id_raw);
assert_eq!(id_from_raw, id);
assert_eq!(id.full_target_id(), (0x111 << 32) | 0x01);
assert_eq!(id.id(), (0x111 << 32) | 0x01);
let string = id.to_string();
assert_eq!(
string,
@ -421,9 +421,9 @@ mod tests {
let mut sp_header = SpHeader::tc_unseg(0x111, 5, 0).unwrap();
let app_data = 1_u32.to_be_bytes();
let pus_tc = PusTcCreator::new_simple(&mut sp_header, 17, 1, Some(&app_data), true);
let id = TargetAndApidId::from_pus_tc(&pus_tc).unwrap();
let id = UniqueApidTargetId::from_pus_tc(&pus_tc).unwrap();
assert_eq!(id.apid, 0x111);
assert_eq!(id.target, 1);
assert_eq!(id.unique_id, 1);
}
#[test]
@ -431,7 +431,7 @@ mod tests {
let mut sp_header = SpHeader::tc_unseg(0x111, 5, 0).unwrap();
let sec_header = PusTcSecondaryHeader::new_simple(17, 1);
let pus_tc = PusTcCreator::new_no_app_data(&mut sp_header, sec_header, true);
let error = TargetAndApidId::from_pus_tc(&pus_tc);
let error = UniqueApidTargetId::from_pus_tc(&pus_tc);
assert!(error.is_err());
let error = error.unwrap_err();
if let ByteConversionError::FromSliceTooSmall { found, expected } = error {
@ -449,14 +449,17 @@ mod tests {
let receiver = MessageReceiverWithId::new(TEST_CHANNEL_ID_0, receiver);
let request_id = 5;
sender
.send(GenericMessage::new(request_id, TEST_CHANNEL_ID_1, 5))
.send(GenericMessage::new(
MessageMetadata::new(request_id, TEST_CHANNEL_ID_1),
5,
))
.unwrap();
let reply = receiver.try_recv_message().unwrap();
assert!(reply.is_some());
assert_eq!(receiver.local_channel_id(), TEST_CHANNEL_ID_0);
let reply = reply.unwrap();
assert_eq!(reply.request_id, request_id);
assert_eq!(reply.sender_id, TEST_CHANNEL_ID_1);
assert_eq!(reply.requestor_info.request_id, request_id);
assert_eq!(reply.requestor_info.sender_id, TEST_CHANNEL_ID_1);
assert_eq!(reply.message, 5);
}
@ -490,31 +493,43 @@ mod tests {
fn test_sender_map() {
let (sender0, receiver0) = mpsc::channel();
let (sender1, receiver1) = mpsc::channel();
let mut sender_map_with_id = MessageSenderMapWithId::new(TEST_CHANNEL_ID_0);
let mut sender_map_with_id = MessageSenderMap::default();
sender_map_with_id.add_message_target(TEST_CHANNEL_ID_1, sender0);
sender_map_with_id.add_message_target(TEST_CHANNEL_ID_2, sender1);
sender_map_with_id
.send_message(1, TEST_CHANNEL_ID_1, 5)
.send_message(
MessageMetadata::new(1, TEST_CHANNEL_ID_0),
TEST_CHANNEL_ID_1,
5,
)
.expect("sending message failed");
let mut reply = receiver0.recv().expect("receiving message failed");
assert_eq!(reply.request_id, 1);
assert_eq!(reply.sender_id, TEST_CHANNEL_ID_0);
assert_eq!(reply.request_id(), 1);
assert_eq!(reply.sender_id(), TEST_CHANNEL_ID_0);
assert_eq!(reply.message, 5);
sender_map_with_id
.send_message(2, TEST_CHANNEL_ID_2, 10)
.send_message(
MessageMetadata::new(2, TEST_CHANNEL_ID_1),
TEST_CHANNEL_ID_2,
10,
)
.expect("sending message failed");
reply = receiver1.recv().expect("receiving message failed");
assert_eq!(reply.request_id, 2);
assert_eq!(reply.sender_id, TEST_CHANNEL_ID_0);
assert_eq!(reply.request_id(), 2);
assert_eq!(reply.sender_id(), TEST_CHANNEL_ID_0);
assert_eq!(reply.message, 10);
}
#[test]
fn test_sender_map_target_does_not_exist() {
let (sender0, _) = mpsc::channel();
let mut sender_map_with_id = MessageSenderMapWithId::new(TEST_CHANNEL_ID_0);
let mut sender_map_with_id = MessageSenderMap::default();
sender_map_with_id.add_message_target(TEST_CHANNEL_ID_1, sender0);
let result = sender_map_with_id.send_message(1, TEST_CHANNEL_ID_2, 5);
let result = sender_map_with_id.send_message(
MessageMetadata::new(1, TEST_CHANNEL_ID_0),
TEST_CHANNEL_ID_2,
5,
);
assert!(result.is_err());
let error = result.unwrap_err();
if let GenericTargetedMessagingError::Send(GenericSendError::TargetDoesNotExist(target)) =
@ -528,12 +543,20 @@ mod tests {
#[test]
fn test_sender_map_queue_full() {
let (sender0, _receiver0) = mpsc::sync_channel(1);
let mut sender_map_with_id = MessageSenderMapWithId::new(TEST_CHANNEL_ID_0);
let mut sender_map_with_id = MessageSenderMap::default();
sender_map_with_id.add_message_target(TEST_CHANNEL_ID_1, sender0);
sender_map_with_id
.send_message(1, TEST_CHANNEL_ID_1, 5)
.send_message(
MessageMetadata::new(1, TEST_CHANNEL_ID_0),
TEST_CHANNEL_ID_1,
5,
)
.expect("sending message failed");
let result = sender_map_with_id.send_message(1, TEST_CHANNEL_ID_1, 5);
let result = sender_map_with_id.send_message(
MessageMetadata::new(1, TEST_CHANNEL_ID_0),
TEST_CHANNEL_ID_1,
5,
);
assert!(result.is_err());
let error = result.unwrap_err();
if let GenericTargetedMessagingError::Send(GenericSendError::QueueFull(capacity)) = error {
@ -546,10 +569,14 @@ mod tests {
#[test]
fn test_sender_map_queue_receiver_disconnected() {
let (sender0, receiver0) = mpsc::sync_channel(1);
let mut sender_map_with_id = MessageSenderMapWithId::new(TEST_CHANNEL_ID_0);
let mut sender_map_with_id = MessageSenderMap::default();
sender_map_with_id.add_message_target(TEST_CHANNEL_ID_1, sender0);
drop(receiver0);
let result = sender_map_with_id.send_message(1, TEST_CHANNEL_ID_1, 5);
let result = sender_map_with_id.send_message(
MessageMetadata::new(1, TEST_CHANNEL_ID_0),
TEST_CHANNEL_ID_1,
5,
);
assert!(result.is_err());
let error = result.unwrap_err();
if let GenericTargetedMessagingError::Send(GenericSendError::RxDisconnected) = error {

View File

@ -22,7 +22,7 @@
//! use satrs::tmtc::{ReceivesTc, ReceivesTcCore};
//! use spacepackets::{CcsdsPacket, SpHeader};
//! use spacepackets::ecss::WritablePusPacket;
//! use spacepackets::ecss::tc::{PusTc, PusTcCreator};
//! use spacepackets::ecss::tc::PusTcCreator;
//!
//! #[derive (Default)]
//! struct ConcreteApidHandler {
@ -96,6 +96,7 @@ use std::error::Error;
pub trait CcsdsPacketHandler {
type Error;
// TODO: Rework this to return a boolean based on u16 input..
fn valid_apids(&self) -> &'static [u16];
fn handle_known_apid(&mut self, sp_header: &SpHeader, tc_raw: &[u8])
-> Result<(), Self::Error>;

View File

@ -1,5 +1,5 @@
use spacepackets::ecss::tm::{PusTmCreator, PusTmSecondaryHeader};
use spacepackets::time::cds::TimeProvider;
use spacepackets::time::cds::CdsTime;
use spacepackets::time::TimeWriter;
use spacepackets::SpHeader;
@ -68,7 +68,7 @@ impl PusTmWithCdsShortHelper {
source_data: &'a [u8],
seq_count: u16,
) -> PusTmCreator {
let time_stamp = TimeProvider::from_now_with_u16_days().unwrap();
let time_stamp = CdsTime::now_with_u16_days().unwrap();
time_stamp.write_to_bytes(&mut self.cds_short_buf).unwrap();
self.create_pus_tm_common(service, subservice, source_data, seq_count)
}
@ -78,7 +78,7 @@ impl PusTmWithCdsShortHelper {
service: u8,
subservice: u8,
source_data: &'a [u8],
stamper: &TimeProvider,
stamper: &CdsTime,
seq_count: u16,
) -> PusTmCreator {
stamper.write_to_bytes(&mut self.cds_short_buf).unwrap();
@ -100,14 +100,14 @@ impl PusTmWithCdsShortHelper {
#[cfg(test)]
mod tests {
use spacepackets::{ecss::PusPacket, time::cds::TimeProvider, CcsdsPacket};
use spacepackets::{ecss::PusPacket, time::cds::CdsTime, CcsdsPacket};
use super::PusTmWithCdsShortHelper;
#[test]
fn test_helper_with_stamper() {
let mut pus_tm_helper = PusTmWithCdsShortHelper::new(0x123);
let stamper = TimeProvider::new_with_u16_days(0, 0);
let stamper = CdsTime::new_with_u16_days(0, 0);
let tm = pus_tm_helper.create_pus_tm_with_stamper(17, 1, &[1, 2, 3, 4], &stamper, 25);
assert_eq!(tm.service(), 17);
assert_eq!(tm.subservice(), 1);

View File

@ -2,7 +2,7 @@
use core::mem::size_of;
use serde::{Deserialize, Serialize};
use spacepackets::ecss::{PfcReal, PfcUnsigned, Ptc};
use spacepackets::time::cds::TimeProvider;
use spacepackets::time::cds::CdsTime;
use spacepackets::time::{CcsdsTimeProvider, TimeWriter};
enum NumOfParamsInfo {
@ -36,7 +36,7 @@ struct TestMgmHkWithIndividualValidity {
#[derive(Serialize, Deserialize)]
struct TestMgmHkWithGroupValidity {
last_valid_stamp: TimeProvider,
last_valid_stamp: CdsTime,
valid: bool,
temp: f32,
mgm_vals: [u16; 3],
@ -150,7 +150,7 @@ pub fn main() {
// The easiest and probably best approach, trading off big advantages for TM downlink capacity:
// Use a JSON format
let mgm_hk_group_validity = TestMgmHkWithGroupValidity {
last_valid_stamp: TimeProvider::from_now_with_u16_days().unwrap(),
last_valid_stamp: CdsTime::now_with_u16_days().unwrap(),
valid: false,
temp: 20.0,
mgm_vals: [0x1f1f, 0x2f2f, 0x3f3f],

View File

@ -1,13 +1,12 @@
use core::cell::Cell;
use std::{println, sync::mpsc};
use satrs::action::ActionRequest;
use satrs::mode::{
ModeError, ModeProvider, ModeReplyReceiver, ModeReplySender, ModeRequestHandler,
ModeRequestHandlerMpscBounded, ModeRequestReceiver, ModeRequestorAndHandlerMpscBounded,
ModeRequestorBoundedMpsc,
};
use satrs::request::RequestId;
use satrs::request::{MessageMetadata, RequestId};
use satrs::{
mode::{ModeAndSubmode, ModeReply, ModeRequest},
queue::GenericTargetedMessagingError,
@ -46,11 +45,30 @@ struct TestDevice {
pub name: String,
pub mode_node: ModeRequestHandlerMpscBounded,
pub mode_and_submode: ModeAndSubmode,
pub mode_requestor_info: Option<(RequestId, ComponentId)>,
// pub action_queue: mpsc::Receiver<GenericMessage<ActionRequest>>,
pub mode_requestor_info: Option<MessageMetadata>,
}
pub struct ModeLeafDeviceHelper {}
fn mode_leaf_node_req_handler(
handler: &mut impl ModeRequestHandler,
request: GenericMessage<ModeRequest>,
) {
match request.message {
ModeRequest::SetMode(mode_and_submode) => {
handler
.start_transition(request.requestor_info, mode_and_submode)
.unwrap();
}
ModeRequest::ReadMode => handler
.send_mode_reply(
request.requestor_info,
ModeReply::ModeReply(handler.mode_and_submode()),
)
.unwrap(),
ModeRequest::AnnounceMode => handler.announce_mode(request.requestor_info, false),
ModeRequest::AnnounceModeRecursive => handler.announce_mode(request.requestor_info, true),
ModeRequest::ModeInfo(_) => todo!(),
}
}
impl TestDevice {
pub fn run(&mut self) {
@ -61,24 +79,22 @@ impl TestDevice {
if let Some(request) = self.mode_node.try_recv_mode_request()? {
match request.message {
ModeRequest::SetMode(mode_and_submode) => {
self.start_transition(request.request_id, request.sender_id, mode_and_submode)
self.start_transition(request.requestor_info, mode_and_submode)
.unwrap();
self.mode_requestor_info = Some((request.request_id, request.sender_id));
self.mode_requestor_info = Some(request.requestor_info);
}
ModeRequest::ReadMode => self
.mode_node
.send_mode_reply(
request.request_id,
request.sender_id,
request.requestor_info,
ModeReply::ModeReply(self.mode_and_submode),
)
.unwrap(),
ModeRequest::AnnounceMode => {
self.announce_mode(request.request_id, request.sender_id, false)
}
ModeRequest::AnnounceMode => self.announce_mode(request.requestor_info, false),
ModeRequest::AnnounceModeRecursive => {
self.announce_mode(request.request_id, request.sender_id, true)
self.announce_mode(request.requestor_info, true)
}
ModeRequest::ModeInfo(_) => todo!(),
}
}
Ok(())
@ -90,39 +106,49 @@ impl ModeProvider for TestDevice {
self.mode_and_submode
}
}
impl ModeRequestHandler for TestDevice {
fn start_transition(
&mut self,
_request_id: RequestId,
_sender_id: ComponentId,
requestor: MessageMetadata,
mode_and_submode: ModeAndSubmode,
) -> Result<(), ModeError> {
self.mode_and_submode = mode_and_submode;
self.handle_mode_reached()?;
self.handle_mode_reached(Some(requestor))?;
Ok(())
}
fn announce_mode(&self, _request_id: RequestId, _sender_id: ComponentId, _recursive: bool) {
fn announce_mode(&self, requestor_info: MessageMetadata, _recursive: bool) {
println!(
"{}: announcing mode: {:?}",
self.name, self.mode_and_submode
);
}
fn handle_mode_reached(&mut self) -> Result<(), GenericTargetedMessagingError> {
let (req_id, sender_id) = self.mode_requestor_info.unwrap();
self.mode_node.send_mode_reply(
req_id,
sender_id,
ModeReply::ModeReply(self.mode_and_submode),
)?;
fn handle_mode_reached(
&mut self,
requestor: Option<MessageMetadata>,
) -> Result<(), GenericTargetedMessagingError> {
if let Some(requestor) = requestor {
self.send_mode_reply(requestor, ModeReply::ModeReply(self.mode_and_submode))?;
}
Ok(())
}
fn send_mode_reply(
&self,
requestor_info: MessageMetadata,
reply: ModeReply,
) -> Result<(), GenericTargetedMessagingError> {
self.mode_node
.send_mode_reply(requestor_info, ModeReply::ModeReply(self.mode_and_submode))?;
Ok(())
}
}
struct TestAssembly {
pub mode_node: ModeRequestorAndHandlerMpscBounded,
pub mode_requestor_info: Option<(RequestId, ComponentId)>,
pub mode_requestor_info: Option<MessageMetadata>,
pub mode_and_submode: ModeAndSubmode,
pub target_mode_and_submode: Option<ModeAndSubmode>,
}
@ -143,23 +169,21 @@ impl TestAssembly {
if let Some(request) = self.mode_node.try_recv_mode_request()? {
match request.message {
ModeRequest::SetMode(mode_and_submode) => {
self.start_transition(request.request_id, request.sender_id, mode_and_submode)
self.start_transition(request.requestor_info, mode_and_submode)
.unwrap();
}
ModeRequest::ReadMode => self
.mode_node
.send_mode_reply(
request.request_id,
request.sender_id,
request.requestor_info,
ModeReply::ModeReply(self.mode_and_submode),
)
.unwrap(),
ModeRequest::AnnounceMode => {
self.announce_mode(request.request_id, request.sender_id, false)
}
ModeRequest::AnnounceMode => self.announce_mode(request.requestor_info, false),
ModeRequest::AnnounceModeRecursive => {
self.announce_mode(request.request_id, request.sender_id, true)
self.announce_mode(request.requestor_info, true)
}
ModeRequest::ModeInfo(_) => todo!(),
}
}
Ok(())
@ -168,18 +192,20 @@ impl TestAssembly {
pub fn check_mode_replies(&mut self) -> Result<(), GenericTargetedMessagingError> {
if let Some(reply_and_id) = self.mode_node.try_recv_mode_reply()? {
match reply_and_id.message {
ModeReply::ModeInfo(_) => todo!(),
ModeReply::ModeReply(reply) => {
println!(
"TestAssembly: Received mode reply from {:?}, reached: {:?}",
reply_and_id.sender_id, reply
reply_and_id.sender_id(),
reply
);
}
ModeReply::CantReachMode(_) => todo!(),
ModeReply::WrongMode { expected, reached } => {
println!(
"TestAssembly: Wrong mode reply from {:?}, reached {:?}, expected {:?}",
reply_and_id.sender_id, reached, expected
reply_and_id.sender_id(),
reached,
expected
);
}
}
@ -191,16 +217,15 @@ impl TestAssembly {
impl ModeRequestHandler for TestAssembly {
fn start_transition(
&mut self,
request_id: RequestId,
sender_id: ComponentId,
requestor: MessageMetadata,
mode_and_submode: ModeAndSubmode,
) -> Result<(), ModeError> {
self.mode_requestor_info = Some((request_id, sender_id));
self.mode_requestor_info = Some(requestor);
self.target_mode_and_submode = Some(mode_and_submode);
Ok(())
}
fn announce_mode(&self, request_id: RequestId, _sender_id: ComponentId, recursive: bool) {
fn announce_mode(&self, requestor_info: MessageMetadata, recursive: bool) {
println!(
"TestAssembly: Announcing mode (recursively: {}): {:?}",
recursive, self.mode_and_submode
@ -217,21 +242,33 @@ impl ModeRequestHandler for TestAssembly {
.for_each(|(_, sender)| {
sender
.send(GenericMessage::new(
request_id,
self.mode_node.local_channel_id_generic(),
MessageMetadata::new(
requestor_info.request_id(),
self.mode_node.local_channel_id_generic(),
),
mode_request,
))
.expect("sending mode request failed");
});
}
fn handle_mode_reached(&mut self) -> Result<(), GenericTargetedMessagingError> {
let (req_id, sender_id) = self.mode_requestor_info.unwrap();
self.mode_node.send_mode_reply(
req_id,
sender_id,
ModeReply::ModeReply(self.mode_and_submode),
)?;
fn handle_mode_reached(
&mut self,
mode_requestor: Option<MessageMetadata>,
) -> Result<(), GenericTargetedMessagingError> {
if let Some(requestor) = mode_requestor {
self.send_mode_reply(requestor, ModeReply::ModeReply(self.mode_and_submode))?;
}
Ok(())
}
fn send_mode_reply(
&self,
requestor: MessageMetadata,
reply: ModeReply,
) -> Result<(), GenericTargetedMessagingError> {
self.mode_node
.send_mode_reply(requestor, ModeReply::ModeReply(self.mode_and_submode))?;
Ok(())
}
}

View File

@ -5,7 +5,8 @@ use satrs::events::{EventU32, EventU32TypedSev, Severity, SeverityInfo};
use satrs::params::U32Pair;
use satrs::params::{Params, ParamsHeapless, WritableToBeBytes};
use satrs::pus::event_man::{DefaultPusEventMgmtBackend, EventReporter, PusEventDispatcher};
use satrs::pus::TmAsVecSenderWithMpsc;
use satrs::pus::PusTmAsVec;
use satrs::request::UniqueApidTargetId;
use spacepackets::ecss::tm::PusTmReader;
use spacepackets::ecss::{PusError, PusPacket};
use std::sync::mpsc::{self, SendError, TryRecvError};
@ -15,6 +16,8 @@ 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];
const TEST_APID: u16 = 0x02;
const TEST_ID: UniqueApidTargetId = UniqueApidTargetId::new(TEST_APID, 0x05);
#[derive(Debug, Clone)]
pub enum CustomTmSenderError {
@ -32,13 +35,12 @@ fn test_threaded_usage() {
let pus_event_man_send_provider = EventU32SenderMpsc::new(1, pus_event_man_tx);
event_man.subscribe_all(pus_event_man_send_provider.target_id());
event_man.add_sender(pus_event_man_send_provider);
let (event_tx, event_rx) = mpsc::channel();
let reporter = EventReporter::new(0x02, 128).expect("Creating event reporter failed");
let mut pus_event_man =
PusEventDispatcher::new(reporter, DefaultPusEventMgmtBackend::default());
let (event_tx, event_rx) = mpsc::channel::<PusTmAsVec>();
let reporter =
EventReporter::new(TEST_ID.raw(), 0x02, 128).expect("Creating event reporter failed");
let pus_event_man = PusEventDispatcher::new(reporter, DefaultPusEventMgmtBackend::default());
// PUS + Generic event manager thread
let jh0 = thread::spawn(move || {
let mut sender = TmAsVecSenderWithMpsc::new(0, "event_sender", event_tx);
let mut event_cnt = 0;
let mut params_array: [u8; 128] = [0; 128];
loop {
@ -46,9 +48,9 @@ fn test_threaded_usage() {
assert!(res.is_ok());
match pus_event_man_rx.try_recv() {
Ok((event, aux_data)) => {
let mut gen_event = |aux_data| {
let gen_event = |aux_data| {
pus_event_man.generate_pus_event_tm_generic(
&mut sender,
&event_tx,
&EMPTY_STAMP,
event,
aux_data,
@ -101,8 +103,8 @@ fn test_threaded_usage() {
match event_rx.try_recv() {
// Event TM received successfully
Ok(event_tm) => {
let tm =
PusTmReader::new(event_tm.as_slice(), 7).expect("Deserializing TM failed");
let tm = PusTmReader::new(event_tm.packet.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();
@ -127,8 +129,8 @@ fn test_threaded_usage() {
match event_rx.try_recv() {
// Event TM received successfully
Ok(event_tm) => {
let tm =
PusTmReader::new(event_tm.as_slice(), 7).expect("Deserializing TM failed");
let tm = PusTmReader::new(event_tm.packet.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();

View File

@ -3,10 +3,11 @@ pub mod crossbeam_test {
use hashbrown::HashMap;
use satrs::pool::{PoolProvider, PoolProviderWithGuards, StaticMemoryPool, StaticPoolConfig};
use satrs::pus::verification::{
FailParams, RequestId, VerificationReporterCfg, VerificationReporterWithSender,
FailParams, RequestId, VerificationReporter, VerificationReporterCfg,
VerificationReportingProvider,
};
use satrs::pus::TmInSharedPoolSenderWithCrossbeam;
use satrs::request::UniqueApidTargetId;
use satrs::tmtc::tm_helper::SharedTmPool;
use spacepackets::ecss::tc::{PusTcCreator, PusTcReader, PusTcSecondaryHeader};
use spacepackets::ecss::tm::PusTmReader;
@ -17,6 +18,8 @@ pub mod crossbeam_test {
use std::time::Duration;
const TEST_APID: u16 = 0x03;
const TEST_ID: TargetAndApidId = TargetAndApidId::new(TEST_APID, 0x05);
const FIXED_STAMP: [u8; 7] = [0; 7];
const PACKETS_SENT: u8 = 8;
@ -40,13 +43,9 @@ pub mod crossbeam_test {
let shared_tc_pool_0 = Arc::new(RwLock::new(StaticMemoryPool::new(pool_cfg)));
let shared_tc_pool_1 = shared_tc_pool_0.clone();
let (tx, rx) = crossbeam_channel::bounded(10);
let sender = TmInSharedPoolSenderWithCrossbeam::new(
0,
"verif_sender",
shared_tm_pool.clone(),
tx.clone(),
);
let mut reporter_with_sender_0 = VerificationReporterWithSender::new(&cfg, sender);
let sender_0 = TmInSharedPoolSenderWithCrossbeam::new(shared_tm_pool.clone(), tx.clone());
let sender_1 = sender_0.clone();
let mut reporter_with_sender_0 = VerificationReporter::new(&cfg);
let mut reporter_with_sender_1 = reporter_with_sender_0.clone();
// For test purposes, we retrieve the request ID from the TCs and pass them to the receiver
// tread.
@ -93,24 +92,36 @@ pub mod crossbeam_test {
let token = reporter_with_sender_0.add_tc_with_req_id(req_id_0);
let accepted_token = reporter_with_sender_0
.acceptance_success(token, &FIXED_STAMP)
.acceptance_success(TEST_ID.raw(), &sender_0, token, &FIXED_STAMP)
.expect("Acceptance success failed");
// Do some start handling here
let started_token = reporter_with_sender_0
.start_success(accepted_token, &FIXED_STAMP)
.start_success(TEST_ID.raw(), &sender_0, accepted_token, &FIXED_STAMP)
.expect("Start success failed");
// Do some step handling here
reporter_with_sender_0
.step_success(&started_token, &FIXED_STAMP, EcssEnumU8::new(0))
.step_success(
TEST_ID.raw(),
&sender_0,
&started_token,
&FIXED_STAMP,
EcssEnumU8::new(0),
)
.expect("Start success failed");
// Finish up
reporter_with_sender_0
.step_success(&started_token, &FIXED_STAMP, EcssEnumU8::new(1))
.step_success(
TEST_ID.raw(),
&sender_0,
&started_token,
&FIXED_STAMP,
EcssEnumU8::new(1),
)
.expect("Start success failed");
reporter_with_sender_0
.completion_success(started_token, &FIXED_STAMP)
.completion_success(TEST_ID.raw(), &sender_0, started_token, &FIXED_STAMP)
.expect("Completion success failed");
});
@ -128,15 +139,15 @@ pub mod crossbeam_test {
let (tc, _) = PusTcReader::new(&tc_buf[0..tc_len]).unwrap();
let token = reporter_with_sender_1.add_tc(&tc);
let accepted_token = reporter_with_sender_1
.acceptance_success(token, &FIXED_STAMP)
.acceptance_success(TEST_ID.raw(), &sender_1, token, &FIXED_STAMP)
.expect("Acceptance success failed");
let started_token = reporter_with_sender_1
.start_success(accepted_token, &FIXED_STAMP)
.start_success(TEST_ID.raw(), &sender_1, accepted_token, &FIXED_STAMP)
.expect("Start success failed");
let fail_code = EcssEnumU16::new(2);
let params = FailParams::new_no_fail_data(&FIXED_STAMP, &fail_code);
reporter_with_sender_1
.completion_failure(started_token, params)
.completion_failure(TEST_ID.raw(), &sender_1, started_token, params)
.expect("Completion success failed");
});
@ -145,14 +156,14 @@ pub mod crossbeam_test {
let mut tm_buf: [u8; 1024] = [0; 1024];
let mut verif_map = HashMap::new();
while packet_counter < PACKETS_SENT {
let verif_addr = rx
let tm_in_pool = rx
.recv_timeout(Duration::from_millis(50))
.expect("Packet reception timeout");
let tm_len;
let shared_tm_store = shared_tm_pool.clone_backing_pool();
{
let mut rg = shared_tm_store.write().expect("Error locking shared pool");
let store_guard = rg.read_with_guard(verif_addr);
let store_guard = rg.read_with_guard(tm_in_pool.store_addr);
tm_len = store_guard
.read(&mut tm_buf)
.expect("Error reading TM slice");