Continue update
Some checks failed
Rust/sat-rs/pipeline/pr-main There was a failure building this commit
Some checks failed
Rust/sat-rs/pipeline/pr-main There was a failure building this commit
This commit is contained in:
@ -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]
|
||||
|
@ -19,8 +19,8 @@ impl HkRequest {
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum HkRequestVariant {
|
||||
OneShot,
|
||||
Enable,
|
||||
Disable,
|
||||
EnablePeriodic,
|
||||
DisablePeriodic,
|
||||
ModifyCollectionInterval(CollectionIntervalFactor),
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
)
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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
@ -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();
|
||||
|
@ -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
@ -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 {
|
||||
|
@ -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>;
|
||||
|
@ -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);
|
||||
|
@ -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],
|
||||
|
@ -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(())
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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");
|
||||
|
Reference in New Issue
Block a user