getting there..
This commit is contained in:
parent
180e770392
commit
e46b88384f
@ -64,7 +64,7 @@ optional = true
|
||||
# version = "0.6"
|
||||
# path = "../spacepackets"
|
||||
git = "https://egit.irs.uni-stuttgart.de/rust/spacepackets.git"
|
||||
rev = "4969d6c33c6"
|
||||
rev = "e3d2d885385"
|
||||
default-features = false
|
||||
|
||||
[dev-dependencies]
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::pus::{source_buffer_large_enough, EcssTmtcErrorWithSend};
|
||||
use crate::pus::{source_buffer_large_enough, EcssTmtcError};
|
||||
use spacepackets::ecss::{EcssEnumeration, PusError};
|
||||
use spacepackets::tm::PusTm;
|
||||
use spacepackets::tm::PusTmSecondaryHeader;
|
||||
@ -34,7 +34,7 @@ impl EventReporterBase {
|
||||
time_stamp: &[u8],
|
||||
event_id: impl EcssEnumeration,
|
||||
aux_data: Option<&[u8]>,
|
||||
) -> Result<(), EcssTmtcErrorWithSend> {
|
||||
) -> Result<(), EcssTmtcError> {
|
||||
self.generate_and_send_generic_tm(
|
||||
buf,
|
||||
Subservice::TmInfoReport,
|
||||
@ -52,7 +52,7 @@ impl EventReporterBase {
|
||||
time_stamp: &[u8],
|
||||
event_id: impl EcssEnumeration,
|
||||
aux_data: Option<&[u8]>,
|
||||
) -> Result<(), EcssTmtcErrorWithSend> {
|
||||
) -> Result<(), EcssTmtcError> {
|
||||
self.generate_and_send_generic_tm(
|
||||
buf,
|
||||
Subservice::TmLowSeverityReport,
|
||||
@ -70,7 +70,7 @@ impl EventReporterBase {
|
||||
time_stamp: &[u8],
|
||||
event_id: impl EcssEnumeration,
|
||||
aux_data: Option<&[u8]>,
|
||||
) -> Result<(), EcssTmtcErrorWithSend> {
|
||||
) -> Result<(), EcssTmtcError> {
|
||||
self.generate_and_send_generic_tm(
|
||||
buf,
|
||||
Subservice::TmMediumSeverityReport,
|
||||
@ -88,7 +88,7 @@ impl EventReporterBase {
|
||||
time_stamp: &[u8],
|
||||
event_id: impl EcssEnumeration,
|
||||
aux_data: Option<&[u8]>,
|
||||
) -> Result<(), EcssTmtcErrorWithSend> {
|
||||
) -> Result<(), EcssTmtcError> {
|
||||
self.generate_and_send_generic_tm(
|
||||
buf,
|
||||
Subservice::TmHighSeverityReport,
|
||||
@ -107,7 +107,7 @@ impl EventReporterBase {
|
||||
time_stamp: &[u8],
|
||||
event_id: impl EcssEnumeration,
|
||||
aux_data: Option<&[u8]>,
|
||||
) -> Result<(), EcssTmtcErrorWithSend> {
|
||||
) -> 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;
|
||||
@ -121,7 +121,7 @@ impl EventReporterBase {
|
||||
time_stamp: &'a [u8],
|
||||
event_id: impl EcssEnumeration,
|
||||
aux_data: Option<&[u8]>,
|
||||
) -> Result<PusTm, EcssTmtcErrorWithSend> {
|
||||
) -> Result<PusTm, EcssTmtcError> {
|
||||
let mut src_data_len = event_id.size();
|
||||
if let Some(aux_data) = aux_data {
|
||||
src_data_len += aux_data.len();
|
||||
@ -138,7 +138,7 @@ impl EventReporterBase {
|
||||
let mut current_idx = 0;
|
||||
event_id
|
||||
.write_to_be_bytes(&mut buf[0..event_id.size()])
|
||||
.map_err(PusError::ByteConversionError)?;
|
||||
.map_err(PusError::ByteConversion)?;
|
||||
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);
|
||||
@ -178,7 +178,7 @@ mod alloc_mod {
|
||||
time_stamp: &[u8],
|
||||
event_id: impl EcssEnumeration,
|
||||
aux_data: Option<&[u8]>,
|
||||
) -> Result<(), EcssTmtcErrorWithSend> {
|
||||
) -> Result<(), EcssTmtcError> {
|
||||
self.reporter.event_info(
|
||||
self.source_data_buf.as_mut_slice(),
|
||||
sender,
|
||||
@ -194,7 +194,7 @@ mod alloc_mod {
|
||||
time_stamp: &[u8],
|
||||
event_id: impl EcssEnumeration,
|
||||
aux_data: Option<&[u8]>,
|
||||
) -> Result<(), EcssTmtcErrorWithSend> {
|
||||
) -> Result<(), EcssTmtcError> {
|
||||
self.reporter.event_low_severity(
|
||||
self.source_data_buf.as_mut_slice(),
|
||||
sender,
|
||||
@ -210,7 +210,7 @@ mod alloc_mod {
|
||||
time_stamp: &[u8],
|
||||
event_id: impl EcssEnumeration,
|
||||
aux_data: Option<&[u8]>,
|
||||
) -> Result<(), EcssTmtcErrorWithSend> {
|
||||
) -> Result<(), EcssTmtcError> {
|
||||
self.reporter.event_medium_severity(
|
||||
self.source_data_buf.as_mut_slice(),
|
||||
sender,
|
||||
@ -226,7 +226,7 @@ mod alloc_mod {
|
||||
time_stamp: &[u8],
|
||||
event_id: impl EcssEnumeration,
|
||||
aux_data: Option<&[u8]>,
|
||||
) -> Result<(), EcssTmtcErrorWithSend> {
|
||||
) -> Result<(), EcssTmtcError> {
|
||||
self.reporter.event_high_severity(
|
||||
self.source_data_buf.as_mut_slice(),
|
||||
sender,
|
||||
@ -243,7 +243,7 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::events::{EventU32, Severity};
|
||||
use crate::pus::tests::CommonTmInfo;
|
||||
use crate::pus::{EcssSender, PusTmWrapper};
|
||||
use crate::pus::{EcssChannel, PusTmWrapper};
|
||||
use crate::SenderId;
|
||||
use spacepackets::ByteConversionError;
|
||||
use std::cell::RefCell;
|
||||
@ -268,14 +268,14 @@ mod tests {
|
||||
pub service_queue: RefCell<VecDeque<TmInfo>>,
|
||||
}
|
||||
|
||||
impl EcssSender for TestSender {
|
||||
impl EcssChannel for TestSender {
|
||||
fn id(&self) -> SenderId {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
impl EcssTmSenderCore for TestSender {
|
||||
fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcErrorWithSend> {
|
||||
fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> {
|
||||
match tm {
|
||||
PusTmWrapper::InStore(_) => {
|
||||
panic!("TestSender: unexpected call with address");
|
||||
@ -425,7 +425,7 @@ mod tests {
|
||||
let err = reporter.event_info(sender, &time_stamp_empty, event, None);
|
||||
assert!(err.is_err());
|
||||
let err = err.unwrap_err();
|
||||
if let EcssTmtcErrorWithSend::EcssTmtcError(EcssTmtcErrorWithSend::ByteConversion(
|
||||
if let EcssTmtcError::EcssTmtcError(EcssTmtcError::ByteConversion(
|
||||
ByteConversionError::ToSliceTooSmall(missmatch),
|
||||
)) = err
|
||||
{
|
||||
|
@ -13,7 +13,7 @@ pub use crate::pus::event::EventReporter;
|
||||
use crate::pus::verification::TcStateToken;
|
||||
#[cfg(feature = "alloc")]
|
||||
use crate::pus::EcssTmSenderCore;
|
||||
use crate::pus::EcssTmtcErrorWithSend;
|
||||
use crate::pus::EcssTmtcError;
|
||||
#[cfg(feature = "alloc")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
|
||||
pub use alloc_mod::*;
|
||||
@ -96,12 +96,12 @@ pub struct EventRequestWithToken<Event: GenericEvent = EventU32> {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum EventManError {
|
||||
EcssTmtcError(EcssTmtcErrorWithSend),
|
||||
EcssTmtcError(EcssTmtcError),
|
||||
SeverityMissmatch(Severity, Severity),
|
||||
}
|
||||
|
||||
impl From<EcssTmtcErrorWithSend> for EventManError {
|
||||
fn from(v: EcssTmtcErrorWithSend) -> Self {
|
||||
impl From<EcssTmtcError> for EventManError {
|
||||
fn from(v: EcssTmtcError) -> Self {
|
||||
Self::EcssTmtcError(v)
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,8 @@ use crate::pus::verification::{
|
||||
StdVerifReporterWithSender, TcStateAccepted, TcStateToken, VerificationToken,
|
||||
};
|
||||
use crate::pus::{
|
||||
AcceptedTc, EcssTmSender, PartialPusHandlingError, PusPacketHandlerResult,
|
||||
PusPacketHandlingError, PusServiceBase, PusServiceHandler,
|
||||
AcceptedTc, EcssTcReceiver, EcssTmSender, PartialPusHandlingError, PusPacketHandlerResult,
|
||||
PusPacketHandlingError, PusServiceBase, PusServiceHandler, ReceivedTcWrapper,
|
||||
};
|
||||
use spacepackets::ecss::event::Subservice;
|
||||
use spacepackets::ecss::PusPacket;
|
||||
@ -21,15 +21,14 @@ pub struct PusService5EventHandler {
|
||||
|
||||
impl PusService5EventHandler {
|
||||
pub fn new(
|
||||
receiver: Receiver<AcceptedTc>,
|
||||
tc_pool: SharedPool,
|
||||
tc_receiver: Box<dyn EcssTcReceiver>,
|
||||
tm_sender: Box<dyn EcssTmSender>,
|
||||
tm_apid: u16,
|
||||
verification_handler: StdVerifReporterWithSender,
|
||||
event_request_tx: Sender<EventRequestWithToken>,
|
||||
) -> Self {
|
||||
Self {
|
||||
psb: PusServiceBase::new(receiver, tc_pool, tm_sender, tm_apid, verification_handler),
|
||||
psb: PusServiceBase::new(tc_receiver, tm_sender, tm_apid, verification_handler),
|
||||
event_request_tx,
|
||||
}
|
||||
}
|
||||
@ -45,11 +44,16 @@ impl PusServiceHandler for PusService5EventHandler {
|
||||
|
||||
fn handle_one_tc(
|
||||
&mut self,
|
||||
addr: StoreAddr,
|
||||
token: VerificationToken<TcStateAccepted>,
|
||||
tc_in_store_with_token: ReceivedTcWrapper,
|
||||
) -> Result<PusPacketHandlerResult, PusPacketHandlingError> {
|
||||
self.copy_tc_to_buf(addr)?;
|
||||
let (tc, _) = PusTc::from_bytes(&self.psb.pus_buf).unwrap();
|
||||
let ReceivedTcWrapper {
|
||||
tc,
|
||||
token,
|
||||
pool_guard,
|
||||
} = tc_in_store_with_token;
|
||||
// TODO: Better token handling..
|
||||
let token = token.expect("invalid token");
|
||||
let accepted_token = VerificationToken::<TcStateAccepted>::try_from(token).unwrap();
|
||||
let subservice = tc.subservice();
|
||||
let srv = Subservice::try_from(subservice);
|
||||
if srv.is_err() {
|
||||
@ -70,7 +74,7 @@ impl PusServiceHandler for PusService5EventHandler {
|
||||
.psb
|
||||
.verification_handler
|
||||
.borrow_mut()
|
||||
.start_success(token, Some(&stamp))
|
||||
.start_success(accepted_token, Some(&stamp))
|
||||
.map_err(|_| PartialPusHandlingError::Verification);
|
||||
let partial_error = start_token.clone().err();
|
||||
let mut token: TcStateToken = token.into();
|
||||
@ -91,7 +95,7 @@ impl PusServiceHandler for PusService5EventHandler {
|
||||
self.event_request_tx
|
||||
.send(event_req_with_token)
|
||||
.map_err(|_| {
|
||||
PusPacketHandlingError::SendError("Forwarding event request failed".into())
|
||||
PusPacketHandlingError::Other("Forwarding event request failed".into())
|
||||
})?;
|
||||
if let Some(partial_error) = partial_error {
|
||||
return Ok(PusPacketHandlerResult::RequestHandledPartialSuccess(
|
||||
|
@ -28,8 +28,8 @@ pub mod verification;
|
||||
#[cfg(feature = "alloc")]
|
||||
pub use alloc_mod::*;
|
||||
|
||||
use crate::pool::{StoreAddr, StoreError};
|
||||
use crate::pus::verification::TcStateToken;
|
||||
use crate::pool::{PoolGuard, PoolRwGuard, StoreAddr, StoreError};
|
||||
use crate::pus::verification::{TcStateAccepted, TcStateToken, VerificationToken};
|
||||
#[cfg(feature = "std")]
|
||||
pub use std_mod::*;
|
||||
|
||||
@ -51,6 +51,12 @@ impl<'tm> From<PusTm<'tm>> for PusTmWrapper<'tm> {
|
||||
}
|
||||
}
|
||||
|
||||
pub type TcAddrWithToken = (StoreAddr, TcStateToken);
|
||||
|
||||
/// Generic abstraction for a telecommand being sent around after is has been accepted.
|
||||
/// The actual telecommand is stored inside a pre-allocated pool structure.
|
||||
pub type AcceptedTc = (StoreAddr, VerificationToken<TcStateAccepted>);
|
||||
|
||||
/// Generic error type for sending something via a message queue.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum GenericSendError {
|
||||
@ -74,67 +80,100 @@ impl Display for GenericSendError {
|
||||
#[cfg(feature = "std")]
|
||||
impl Error for GenericSendError {}
|
||||
|
||||
/// Generic error type for sending something via a message queue.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum GenericRecvError {
|
||||
Empty,
|
||||
TxDisconnected,
|
||||
}
|
||||
|
||||
impl Display for GenericRecvError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
||||
match self {
|
||||
Self::TxDisconnected => {
|
||||
write!(f, "tx side has disconnected")
|
||||
}
|
||||
Self::Empty => {
|
||||
write!(f, "nothing to receive")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Error for GenericRecvError {}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum EcssTmtcErrorWithSend {
|
||||
pub enum EcssTmtcError {
|
||||
StoreLock,
|
||||
Store(StoreError),
|
||||
Pus(PusError),
|
||||
CantSendAddr(StoreAddr),
|
||||
Send(GenericSendError),
|
||||
Recv(GenericRecvError),
|
||||
}
|
||||
|
||||
impl Display for EcssTmtcErrorWithSend {
|
||||
impl Display for EcssTmtcError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
||||
match self {
|
||||
EcssTmtcErrorWithSend::StoreLock => {
|
||||
EcssTmtcError::StoreLock => {
|
||||
write!(f, "store lock error")
|
||||
}
|
||||
EcssTmtcErrorWithSend::Store(store) => {
|
||||
EcssTmtcError::Store(store) => {
|
||||
write!(f, "store error: {store}")
|
||||
}
|
||||
EcssTmtcErrorWithSend::Pus(pus_e) => {
|
||||
EcssTmtcError::Pus(pus_e) => {
|
||||
write!(f, "PUS error: {pus_e}")
|
||||
}
|
||||
EcssTmtcErrorWithSend::CantSendAddr(addr) => {
|
||||
EcssTmtcError::CantSendAddr(addr) => {
|
||||
write!(f, "can not send address {addr}")
|
||||
}
|
||||
EcssTmtcErrorWithSend::Send(send_e) => {
|
||||
EcssTmtcError::Send(send_e) => {
|
||||
write!(f, "send error {send_e}")
|
||||
}
|
||||
EcssTmtcError::Recv(recv_e) => {
|
||||
write!(f, "recv error {recv_e}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<StoreError> for EcssTmtcErrorWithSend {
|
||||
impl From<StoreError> for EcssTmtcError {
|
||||
fn from(value: StoreError) -> Self {
|
||||
Self::Store(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PusError> for EcssTmtcErrorWithSend {
|
||||
impl From<PusError> for EcssTmtcError {
|
||||
fn from(value: PusError) -> Self {
|
||||
Self::Pus(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<GenericSendError> for EcssTmtcErrorWithSend {
|
||||
impl From<GenericSendError> for EcssTmtcError {
|
||||
fn from(value: GenericSendError) -> Self {
|
||||
Self::Send(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<GenericRecvError> for EcssTmtcError {
|
||||
fn from(value: GenericRecvError) -> Self {
|
||||
Self::Recv(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Error for EcssTmtcErrorWithSend {
|
||||
impl Error for EcssTmtcError {
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match self {
|
||||
EcssTmtcErrorWithSend::Store(e) => Some(e),
|
||||
EcssTmtcErrorWithSend::Pus(e) => Some(e),
|
||||
EcssTmtcErrorWithSend::Send(e) => Some(e),
|
||||
EcssTmtcError::Store(e) => Some(e),
|
||||
EcssTmtcError::Pus(e) => Some(e),
|
||||
EcssTmtcError::Send(e) => Some(e),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
pub trait EcssSender: Send {
|
||||
pub trait EcssChannel: Send {
|
||||
/// Each sender can have an ID associated with it
|
||||
fn id(&self) -> SenderId;
|
||||
fn name(&self) -> &'static str {
|
||||
@ -145,16 +184,35 @@ pub trait EcssSender: Send {
|
||||
/// Generic trait for a user supplied sender object.
|
||||
///
|
||||
/// This sender object is responsible for sending PUS telemetry to a TM sink.
|
||||
pub trait EcssTmSenderCore: EcssSender {
|
||||
fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcErrorWithSend>;
|
||||
pub trait EcssTmSenderCore: EcssChannel {
|
||||
fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError>;
|
||||
}
|
||||
|
||||
/// Generic trait for a user supplied sender object.
|
||||
///
|
||||
/// This sender object is responsible for sending PUS telecommands to a TC recipient. Each
|
||||
/// telecommand can optionally have a token which contains its verification state.
|
||||
pub trait EcssTcSenderCore: EcssSender {
|
||||
fn send_tc(&self, tc: PusTc, token: Option<TcStateToken>) -> Result<(), EcssTmtcErrorWithSend>;
|
||||
pub trait EcssTcSenderCore: EcssChannel {
|
||||
fn send_tc(&self, tc: PusTc, token: Option<TcStateToken>) -> Result<(), EcssTmtcError>;
|
||||
}
|
||||
|
||||
pub struct ReceivedTcWrapper<'raw_tc> {
|
||||
pub pool_guard: PoolGuard<'raw_tc>,
|
||||
pub tc: PusTc<'raw_tc>,
|
||||
pub token: Option<TcStateToken>,
|
||||
}
|
||||
|
||||
/// Generic trait for a user supplied receiver object.
|
||||
pub trait EcssTcReceiverCore: EcssChannel {
|
||||
fn recv_tc<'buf>(&self, buf: &'buf mut [u8]) -> Result<ReceivedTcWrapper<'buf>, EcssTmtcError>;
|
||||
}
|
||||
|
||||
/// Generic trait for objects which can receive ECSS PUS telecommands. This trait is
|
||||
/// implemented by the [crate::tmtc::pus_distrib::PusDistributor] objects to allow passing PUS TC
|
||||
/// packets into it.
|
||||
pub trait ReceivesEcssPusTc {
|
||||
type Error;
|
||||
fn pass_pus_tc(&mut self, header: &SpHeader, pus_tc: &PusTc) -> Result<(), Self::Error>;
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
@ -200,50 +258,66 @@ mod alloc_mod {
|
||||
|
||||
dyn_clone::clone_trait_object!(EcssTcSender);
|
||||
impl_downcast!(EcssTcSender);
|
||||
}
|
||||
|
||||
/// Generic trait for objects which can receive ECSS PUS telecommands. This trait is
|
||||
/// implemented by the [crate::tmtc::pus_distrib::PusDistributor] objects to allow passing PUS TC
|
||||
/// packets into it.
|
||||
pub trait ReceivesEcssPusTc {
|
||||
type Error;
|
||||
fn pass_pus_tc(&mut self, header: &SpHeader, pus_tc: &PusTc) -> Result<(), Self::Error>;
|
||||
/// Extension trait for [EcssTcReceiverCore].
|
||||
///
|
||||
/// It provides additional functionality, for example by implementing the [Downcast] trait
|
||||
/// and the [DynClone] trait.
|
||||
///
|
||||
/// [Downcast] is implemented to allow passing the sender as a boxed trait object and still
|
||||
/// retrieve the concrete type at a later point.
|
||||
///
|
||||
/// [DynClone] allows cloning the trait object as long as the boxed object implements
|
||||
/// [Clone].
|
||||
#[cfg(feature = "alloc")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
|
||||
pub trait EcssTcReceiver: EcssTcReceiverCore + Downcast + DynClone {}
|
||||
|
||||
/// Blanket implementation for all types which implement [EcssTcReceiverCore] and are clonable.
|
||||
impl<T> EcssTcReceiver for T where T: EcssTcReceiverCore + Clone + 'static {}
|
||||
|
||||
dyn_clone::clone_trait_object!(EcssTcReceiver);
|
||||
impl_downcast!(EcssTcReceiver);
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub mod std_mod {
|
||||
use crate::pool::{ShareablePoolProvider, SharedPool, StoreAddr, StoreError};
|
||||
use crate::pool::{SharedPool, StoreAddr};
|
||||
use crate::pus::verification::{
|
||||
StdVerifReporterWithSender, TcStateAccepted, VerificationToken,
|
||||
StdVerifReporterWithSender, TcStateAccepted, TcStateToken, VerificationToken,
|
||||
};
|
||||
use crate::pus::{
|
||||
EcssSender, EcssTmSender, EcssTmSenderCore, EcssTmtcErrorWithSend, GenericSendError,
|
||||
PusTmWrapper,
|
||||
AcceptedTc, EcssChannel, EcssTcReceiver, EcssTcReceiverCore, EcssTmSender,
|
||||
EcssTmSenderCore, EcssTmtcError, GenericRecvError, GenericSendError, PusTmWrapper,
|
||||
ReceivedTcWrapper, TcAddrWithToken,
|
||||
};
|
||||
use crate::tmtc::tm_helper::SharedTmStore;
|
||||
use crate::SenderId;
|
||||
use alloc::boxed::Box;
|
||||
use alloc::vec::Vec;
|
||||
use spacepackets::ecss::{PusError, SerializablePusPacket};
|
||||
use spacepackets::ecss::PusError;
|
||||
use spacepackets::tc::PusTc;
|
||||
use spacepackets::time::cds::TimeProvider;
|
||||
use spacepackets::time::std_mod::StdTimestampError;
|
||||
use spacepackets::time::TimeWriter;
|
||||
use spacepackets::tm::PusTm;
|
||||
use spacepackets::{ByteConversionError, SizeMissmatch};
|
||||
use std::cell::RefCell;
|
||||
use std::format;
|
||||
use std::string::String;
|
||||
use std::sync::mpsc::SendError;
|
||||
use std::sync::{mpsc, RwLockWriteGuard};
|
||||
use std::sync::mpsc;
|
||||
use std::sync::mpsc::{SendError, TryRecvError};
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct MpscTmInStoreSender {
|
||||
id: SenderId,
|
||||
name: &'static str,
|
||||
store_helper: SharedPool,
|
||||
shared_tm_store: SharedTmStore,
|
||||
sender: mpsc::Sender<StoreAddr>,
|
||||
pub ignore_poison_errors: bool,
|
||||
}
|
||||
|
||||
impl EcssSender for MpscTmInStoreSender {
|
||||
impl EcssChannel for MpscTmInStoreSender {
|
||||
fn id(&self) -> SenderId {
|
||||
self.id
|
||||
}
|
||||
@ -253,39 +327,22 @@ pub mod std_mod {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SendError<StoreAddr>> for EcssTmtcErrorWithSend {
|
||||
impl From<SendError<StoreAddr>> for EcssTmtcError {
|
||||
fn from(_: SendError<StoreAddr>) -> Self {
|
||||
Self::Send(GenericSendError::RxDisconnected)
|
||||
}
|
||||
}
|
||||
impl MpscTmInStoreSender {
|
||||
pub fn send_direct_tm(
|
||||
&self,
|
||||
tmtc: impl SerializablePusPacket,
|
||||
) -> Result<(), EcssTmtcErrorWithSend> {
|
||||
let operation = |mut store: RwLockWriteGuard<ShareablePoolProvider>| {
|
||||
let (addr, slice) = store.free_element(tmtc.len_packed())?;
|
||||
tmtc.write_to_bytes(slice)?;
|
||||
self.sender.send(addr)?;
|
||||
Ok(())
|
||||
};
|
||||
match self.store_helper.write() {
|
||||
Ok(pool) => operation(pool),
|
||||
Err(e) => {
|
||||
if self.ignore_poison_errors {
|
||||
operation(e.into_inner())
|
||||
} else {
|
||||
Err(EcssTmtcErrorWithSend::Send(
|
||||
GenericSendError::RxDisconnected,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn send_direct_tm(&self, tm: PusTm) -> Result<(), EcssTmtcError> {
|
||||
let addr = self.shared_tm_store.add_pus_tm(&tm)?;
|
||||
self.sender
|
||||
.send(addr)
|
||||
.map_err(|_| EcssTmtcError::Send(GenericSendError::RxDisconnected))
|
||||
}
|
||||
}
|
||||
|
||||
impl EcssTmSenderCore for MpscTmInStoreSender {
|
||||
fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcErrorWithSend> {
|
||||
fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> {
|
||||
match tm {
|
||||
PusTmWrapper::InStore(addr) => self.sender.send(addr).map_err(|e| e.into()),
|
||||
PusTmWrapper::Direct(tm) => self.send_direct_tm(tm),
|
||||
@ -297,19 +354,66 @@ pub mod std_mod {
|
||||
pub fn new(
|
||||
id: SenderId,
|
||||
name: &'static str,
|
||||
store_helper: SharedPool,
|
||||
shared_tm_store: SharedTmStore,
|
||||
sender: mpsc::Sender<StoreAddr>,
|
||||
) -> Self {
|
||||
Self {
|
||||
id,
|
||||
name,
|
||||
store_helper,
|
||||
shared_tm_store,
|
||||
sender,
|
||||
ignore_poison_errors: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MpscTcInStoreReceiver {
|
||||
id: SenderId,
|
||||
name: &'static str,
|
||||
shared_tc_pool: SharedPool,
|
||||
receiver: mpsc::Receiver<TcAddrWithToken>,
|
||||
pub ignore_poison_errors: bool,
|
||||
}
|
||||
|
||||
impl EcssChannel for MpscTcInStoreReceiver {
|
||||
fn id(&self) -> SenderId {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
self.name
|
||||
}
|
||||
}
|
||||
|
||||
impl EcssTcReceiverCore for MpscTcInStoreReceiver {
|
||||
fn recv_tc<'buf>(
|
||||
&self,
|
||||
buf: &'buf mut [u8],
|
||||
) -> Result<ReceivedTcWrapper<'buf>, EcssTmtcError> {
|
||||
let (addr, token) = self.receiver.try_recv().map_err(|e| match e {
|
||||
TryRecvError::Empty => GenericRecvError::Empty,
|
||||
TryRecvError::Disconnected => GenericRecvError::TxDisconnected,
|
||||
})?;
|
||||
let shared_tc_pool = self
|
||||
.shared_tc_pool
|
||||
.read()
|
||||
.map_err(|_| EcssTmtcError::StoreLock)?;
|
||||
let tc_raw = shared_tc_pool.read(&addr)?;
|
||||
if buf.len() < tc_raw.len() {
|
||||
return Err(
|
||||
PusError::ByteConversion(ByteConversionError::ToSliceTooSmall(SizeMissmatch {
|
||||
found: buf.len(),
|
||||
expected: tc_raw.len(),
|
||||
}))
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
buf[..tc_raw.len()].copy_from_slice(tc_raw);
|
||||
let (tc, _) = PusTc::from_bytes(buf)?;
|
||||
Ok((tc, token))
|
||||
}
|
||||
}
|
||||
|
||||
/// 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
|
||||
@ -321,7 +425,7 @@ pub mod std_mod {
|
||||
name: &'static str,
|
||||
}
|
||||
|
||||
impl From<SendError<Vec<u8>>> for EcssTmtcErrorWithSend {
|
||||
impl From<SendError<Vec<u8>>> for EcssTmtcError {
|
||||
fn from(_: SendError<Vec<u8>>) -> Self {
|
||||
Self::Send(GenericSendError::RxDisconnected)
|
||||
}
|
||||
@ -333,7 +437,7 @@ pub mod std_mod {
|
||||
}
|
||||
}
|
||||
|
||||
impl EcssSender for MpscTmAsVecSender {
|
||||
impl EcssChannel for MpscTmAsVecSender {
|
||||
fn id(&self) -> SenderId {
|
||||
self.id
|
||||
}
|
||||
@ -343,13 +447,12 @@ pub mod std_mod {
|
||||
}
|
||||
|
||||
impl EcssTmSenderCore for MpscTmAsVecSender {
|
||||
fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcErrorWithSend> {
|
||||
fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> {
|
||||
match tm {
|
||||
PusTmWrapper::InStore(addr) => Err(EcssTmtcErrorWithSend::CantSendAddr(addr)),
|
||||
PusTmWrapper::InStore(addr) => Err(EcssTmtcError::CantSendAddr(addr)),
|
||||
PusTmWrapper::Direct(tm) => {
|
||||
let mut vec = Vec::new();
|
||||
tm.append_to_vec(&mut vec)
|
||||
.map_err(EcssTmtcErrorWithSend::Pus)?;
|
||||
tm.append_to_vec(&mut vec).map_err(EcssTmtcError::Pus)?;
|
||||
self.sender.send(vec)?;
|
||||
Ok(())
|
||||
}
|
||||
@ -359,36 +462,32 @@ pub mod std_mod {
|
||||
|
||||
#[derive(Debug, Clone, Error)]
|
||||
pub enum PusPacketHandlingError {
|
||||
#[error("Generic PUS error: {0}")]
|
||||
PusError(#[from] PusError),
|
||||
#[error("Wrong service number {0} for packet handler")]
|
||||
#[error("generic PUS error: {0}")]
|
||||
Pus(#[from] PusError),
|
||||
#[error("wrong service number {0} for packet handler")]
|
||||
WrongService(u8),
|
||||
#[error("Invalid subservice {0}")]
|
||||
#[error("invalid subservice {0}")]
|
||||
InvalidSubservice(u8),
|
||||
#[error("Not enough application data available: {0}")]
|
||||
#[error("not enough application data available: {0}")]
|
||||
NotEnoughAppData(String),
|
||||
#[error("Invalid application data")]
|
||||
#[error("invalid application data")]
|
||||
InvalidAppData(String),
|
||||
#[error("Generic store error: {0}")]
|
||||
StoreError(#[from] StoreError),
|
||||
#[error("Error with the pool RwGuard: {0}")]
|
||||
RwGuardError(String),
|
||||
#[error("MQ send error: {0}")]
|
||||
SendError(String),
|
||||
#[error("TX message queue side has disconnected")]
|
||||
QueueDisconnected,
|
||||
#[error("Other error {0}")]
|
||||
OtherError(String),
|
||||
#[error("generic ECSS tmtc error: {0}")]
|
||||
EcssTmtc(#[from] EcssTmtcError),
|
||||
#[error("other error {0}")]
|
||||
Other(String),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Error)]
|
||||
pub enum PartialPusHandlingError {
|
||||
#[error("Generic timestamp generation error")]
|
||||
#[error("generic timestamp generation error")]
|
||||
Time(#[from] StdTimestampError),
|
||||
#[error("Error sending telemetry: {0}")]
|
||||
TmSend(#[from] EcssTmtcErrorWithSend),
|
||||
#[error("Error sending verification message")]
|
||||
#[error("error sending telemetry: {0}")]
|
||||
TmSend(#[from] EcssTmtcError),
|
||||
#[error("error sending verification message")]
|
||||
Verification,
|
||||
#[error("invalid verification token")]
|
||||
NoVerificationToken,
|
||||
}
|
||||
|
||||
/// Generic result type for handlers which can process PUS packets.
|
||||
@ -396,8 +495,8 @@ pub mod std_mod {
|
||||
pub enum PusPacketHandlerResult {
|
||||
RequestHandled,
|
||||
RequestHandledPartialSuccess(PartialPusHandlingError),
|
||||
SubserviceNotImplemented(u8, VerificationToken<TcStateAccepted>),
|
||||
CustomSubservice(u8, VerificationToken<TcStateAccepted>),
|
||||
SubserviceNotImplemented(u8, TcStateToken),
|
||||
CustomSubservice(u8, TcStateToken),
|
||||
Empty,
|
||||
}
|
||||
|
||||
@ -407,16 +506,11 @@ pub mod std_mod {
|
||||
}
|
||||
}
|
||||
|
||||
/// Generic abstraction for a telecommand being sent around after is has been accepted.
|
||||
/// The actual telecommand is stored inside a pre-allocated pool structure.
|
||||
pub type AcceptedTc = (StoreAddr, VerificationToken<TcStateAccepted>);
|
||||
|
||||
/// Base class for handlers which can handle PUS TC packets. Right now, the message queue
|
||||
/// backend is constrained to [mpsc::channel]s and the verification reporter
|
||||
/// is constrained to the [StdVerifReporterWithSender].
|
||||
pub struct PusServiceBase {
|
||||
pub tc_rx: mpsc::Receiver<AcceptedTc>,
|
||||
pub tc_store: SharedPool,
|
||||
pub tc_receiver: Box<dyn EcssTcReceiver>,
|
||||
pub tm_sender: Box<dyn EcssTmSender>,
|
||||
pub tm_apid: u16,
|
||||
/// The verification handler is wrapped in a [RefCell] to allow the interior mutability
|
||||
@ -428,15 +522,13 @@ pub mod std_mod {
|
||||
|
||||
impl PusServiceBase {
|
||||
pub fn new(
|
||||
receiver: mpsc::Receiver<AcceptedTc>,
|
||||
tc_pool: SharedPool,
|
||||
tc_receiver: Box<dyn EcssTcReceiver>,
|
||||
tm_sender: Box<dyn EcssTmSender>,
|
||||
tm_apid: u16,
|
||||
verification_handler: StdVerifReporterWithSender,
|
||||
) -> Self {
|
||||
Self {
|
||||
tc_rx: receiver,
|
||||
tc_store: tc_pool,
|
||||
tc_receiver,
|
||||
tm_apid,
|
||||
tm_sender,
|
||||
verification_handler: RefCell::new(verification_handler),
|
||||
@ -472,8 +564,7 @@ pub mod std_mod {
|
||||
fn psb(&self) -> &PusServiceBase;
|
||||
fn handle_one_tc(
|
||||
&mut self,
|
||||
addr: StoreAddr,
|
||||
token: VerificationToken<TcStateAccepted>,
|
||||
tc_in_store_with_token: ReceivedTcWrapper,
|
||||
) -> Result<PusPacketHandlerResult, PusPacketHandlingError>;
|
||||
|
||||
fn copy_tc_to_buf(&mut self, addr: StoreAddr) -> Result<(), PusPacketHandlingError> {
|
||||
@ -482,7 +573,7 @@ pub mod std_mod {
|
||||
let mut tc_pool = psb_mut
|
||||
.tc_store
|
||||
.write()
|
||||
.map_err(|e| PusPacketHandlingError::RwGuardError(format!("{e}")))?;
|
||||
.map_err(|_| PusPacketHandlingError::EcssTmtc(EcssTmtcError::StoreLock))?;
|
||||
let tc_guard = tc_pool.read_with_guard(addr);
|
||||
let tc_raw = tc_guard.read().unwrap();
|
||||
psb_mut.pus_buf[0..tc_raw.len()].copy_from_slice(tc_raw);
|
||||
@ -490,26 +581,23 @@ pub mod std_mod {
|
||||
}
|
||||
|
||||
fn handle_next_packet(&mut self) -> Result<PusPacketHandlerResult, PusPacketHandlingError> {
|
||||
return match self.psb().tc_rx.try_recv() {
|
||||
match self.psb().tc_receiver.recv_tc()? {
|
||||
Ok((addr, token)) => self.handle_one_tc(addr, token),
|
||||
Err(e) => match e {
|
||||
mpsc::TryRecvError::Empty => Ok(PusPacketHandlerResult::Empty),
|
||||
mpsc::TryRecvError::Disconnected => {
|
||||
Err(PusPacketHandlingError::QueueDisconnected)
|
||||
}
|
||||
TryRecvError::Empty => Ok(PusPacketHandlerResult::Empty),
|
||||
TryRecvError::Disconnected => Err(PusPacketHandlingError::EcssTmtc(
|
||||
EcssTmtcError::Recv(GenericRecvError::TxDisconnected),
|
||||
)),
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn source_buffer_large_enough(
|
||||
cap: usize,
|
||||
len: usize,
|
||||
) -> Result<(), EcssTmtcErrorWithSend> {
|
||||
pub(crate) fn source_buffer_large_enough(cap: usize, len: usize) -> Result<(), EcssTmtcError> {
|
||||
if len > cap {
|
||||
return Err(
|
||||
PusError::ByteConversionError(ByteConversionError::ToSliceTooSmall(SizeMissmatch {
|
||||
PusError::ByteConversion(ByteConversionError::ToSliceTooSmall(SizeMissmatch {
|
||||
found: cap,
|
||||
expected: len,
|
||||
}))
|
||||
|
@ -2,8 +2,8 @@ use crate::pool::{SharedPool, StoreAddr};
|
||||
use crate::pus::scheduler::PusScheduler;
|
||||
use crate::pus::verification::{StdVerifReporterWithSender, TcStateAccepted, VerificationToken};
|
||||
use crate::pus::{
|
||||
AcceptedTc, EcssTmSender, PusPacketHandlerResult, PusPacketHandlingError, PusServiceBase,
|
||||
PusServiceHandler,
|
||||
AcceptedTc, EcssTcReceiver, EcssTmSender, PusPacketHandlerResult, PusPacketHandlingError,
|
||||
PusServiceBase, PusServiceHandler, ReceivedTcWrapper,
|
||||
};
|
||||
use spacepackets::ecss::{scheduling, PusPacket};
|
||||
use spacepackets::tc::PusTc;
|
||||
@ -26,15 +26,14 @@ pub struct PusService11SchedHandler {
|
||||
|
||||
impl PusService11SchedHandler {
|
||||
pub fn new(
|
||||
receiver: Receiver<AcceptedTc>,
|
||||
tc_pool: SharedPool,
|
||||
tc_receiver: Box<dyn EcssTcReceiver>,
|
||||
tm_sender: Box<dyn EcssTmSender>,
|
||||
tm_apid: u16,
|
||||
verification_handler: StdVerifReporterWithSender,
|
||||
scheduler: PusScheduler,
|
||||
) -> Self {
|
||||
Self {
|
||||
psb: PusServiceBase::new(receiver, tc_pool, tm_sender, tm_apid, verification_handler),
|
||||
psb: PusServiceBase::new(tc_receiver, tm_sender, tm_apid, verification_handler),
|
||||
scheduler,
|
||||
}
|
||||
}
|
||||
@ -58,11 +57,13 @@ impl PusServiceHandler for PusService11SchedHandler {
|
||||
|
||||
fn handle_one_tc(
|
||||
&mut self,
|
||||
addr: StoreAddr,
|
||||
token: VerificationToken<TcStateAccepted>,
|
||||
tc_in_store_with_token: ReceivedTcWrapper,
|
||||
) -> Result<PusPacketHandlerResult, PusPacketHandlingError> {
|
||||
self.copy_tc_to_buf(addr)?;
|
||||
let (tc, _) = PusTc::from_bytes(&self.psb.pus_buf).unwrap();
|
||||
let ReceivedTcWrapper {
|
||||
tc,
|
||||
pool_guard,
|
||||
token,
|
||||
} = tc_in_store_with_token;
|
||||
let std_service = scheduling::Subservice::try_from(tc.subservice());
|
||||
if std_service.is_err() {
|
||||
return Ok(PusPacketHandlerResult::CustomSubservice(
|
||||
|
@ -2,7 +2,7 @@ use crate::pool::{SharedPool, StoreAddr};
|
||||
use crate::pus::verification::{StdVerifReporterWithSender, TcStateAccepted, VerificationToken};
|
||||
use crate::pus::{
|
||||
AcceptedTc, EcssTmSender, PartialPusHandlingError, PusPacketHandlerResult,
|
||||
PusPacketHandlingError, PusServiceBase, PusServiceHandler, PusTmWrapper,
|
||||
PusPacketHandlingError, PusServiceBase, PusServiceHandler, PusTmWrapper, ReceivedTcWrapper,
|
||||
};
|
||||
use spacepackets::ecss::PusPacket;
|
||||
use spacepackets::tc::PusTc;
|
||||
@ -41,11 +41,13 @@ impl PusServiceHandler for PusService17TestHandler {
|
||||
|
||||
fn handle_one_tc(
|
||||
&mut self,
|
||||
addr: StoreAddr,
|
||||
token: VerificationToken<TcStateAccepted>,
|
||||
tc_in_store_with_token: ReceivedTcWrapper,
|
||||
) -> Result<PusPacketHandlerResult, PusPacketHandlingError> {
|
||||
self.copy_tc_to_buf(addr)?;
|
||||
let (tc, _) = PusTc::from_bytes(&self.psb.pus_buf)?;
|
||||
let ReceivedTcWrapper {
|
||||
tc,
|
||||
pool_guard,
|
||||
token,
|
||||
} = tc_in_store_with_token;
|
||||
if tc.service() != 17 {
|
||||
return Err(PusPacketHandlingError::WrongService(tc.service()));
|
||||
}
|
||||
|
@ -73,7 +73,7 @@
|
||||
//! The [integration test](https://egit.irs.uni-stuttgart.de/rust/fsrc-launchpad/src/branch/main/fsrc-core/tests/verification_test.rs)
|
||||
//! for the verification module contains examples how this module could be used in a more complex
|
||||
//! context involving multiple threads
|
||||
use crate::pus::{source_buffer_large_enough, EcssTmSenderCore, EcssTmtcErrorWithSend};
|
||||
use crate::pus::{source_buffer_large_enough, EcssTmSenderCore, EcssTmtcError};
|
||||
use core::fmt::{Debug, Display, Formatter};
|
||||
use core::hash::{Hash, Hasher};
|
||||
use core::marker::PhantomData;
|
||||
@ -172,10 +172,10 @@ impl RequestId {
|
||||
/// If a verification operation fails, the passed token will be returned as well. This allows
|
||||
/// re-trying the operation at a later point.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct VerificationOrSendErrorWithToken<T>(pub EcssTmtcErrorWithSend, pub VerificationToken<T>);
|
||||
pub struct VerificationOrSendErrorWithToken<T>(pub EcssTmtcError, pub VerificationToken<T>);
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct VerificationErrorWithToken<T>(pub EcssTmtcErrorWithSend, pub VerificationToken<T>);
|
||||
pub struct VerificationErrorWithToken<T>(pub EcssTmtcError, pub VerificationToken<T>);
|
||||
|
||||
impl<T> From<VerificationErrorWithToken<T>> for VerificationOrSendErrorWithToken<T> {
|
||||
fn from(value: VerificationErrorWithToken<T>) -> Self {
|
||||
@ -205,7 +205,7 @@ impl WasAtLeastAccepted for TcStateAccepted {}
|
||||
impl WasAtLeastAccepted for TcStateStarted {}
|
||||
impl WasAtLeastAccepted for TcStateCompleted {}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub enum TcStateToken {
|
||||
None(VerificationToken<TcStateNone>),
|
||||
Accepted(VerificationToken<TcStateAccepted>),
|
||||
@ -230,6 +230,19 @@ impl TryFrom<TcStateToken> for VerificationToken<TcStateAccepted> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<TcStateToken> for VerificationToken<TcStateStarted> {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(value: TcStateToken) -> Result<Self, Self::Error> {
|
||||
if let TcStateToken::Started(token) = value {
|
||||
Ok(token)
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<VerificationToken<TcStateAccepted>> for TcStateToken {
|
||||
fn from(t: VerificationToken<TcStateAccepted>) -> Self {
|
||||
TcStateToken::Accepted(t)
|
||||
@ -641,8 +654,7 @@ impl VerificationReporterCore {
|
||||
msg_count: u16,
|
||||
time_stamp: Option<&'src_data [u8]>,
|
||||
step: impl EcssEnumeration,
|
||||
) -> Result<VerificationSendable<'src_data, TcStateStarted, VerifSuccess>, EcssTmtcErrorWithSend>
|
||||
{
|
||||
) -> Result<VerificationSendable<'src_data, TcStateStarted, VerifSuccess>, EcssTmtcError> {
|
||||
Ok(VerificationSendable::new_no_token(
|
||||
self.create_pus_verif_success_tm(
|
||||
src_data_buf,
|
||||
@ -772,7 +784,7 @@ impl VerificationReporterCore {
|
||||
req_id: &RequestId,
|
||||
time_stamp: Option<&'src_data [u8]>,
|
||||
step: Option<&(impl EcssEnumeration + ?Sized)>,
|
||||
) -> Result<PusTm<'src_data>, EcssTmtcErrorWithSend> {
|
||||
) -> Result<PusTm<'src_data>, EcssTmtcError> {
|
||||
let mut source_data_len = size_of::<u32>();
|
||||
if let Some(step) = step {
|
||||
source_data_len += step.size();
|
||||
@ -808,7 +820,7 @@ impl VerificationReporterCore {
|
||||
req_id: &RequestId,
|
||||
step: Option<&(impl EcssEnumeration + ?Sized)>,
|
||||
params: &FailParams<'src_data, '_>,
|
||||
) -> Result<PusTm<'src_data>, EcssTmtcErrorWithSend> {
|
||||
) -> Result<PusTm<'src_data>, EcssTmtcError> {
|
||||
let mut idx = 0;
|
||||
let mut source_data_len = RequestId::SIZE_AS_BYTES + params.failure_code.size();
|
||||
if let Some(step) = step {
|
||||
@ -829,7 +841,7 @@ impl VerificationReporterCore {
|
||||
params
|
||||
.failure_code
|
||||
.write_to_be_bytes(&mut src_data_buf[idx..idx + params.failure_code.size()])
|
||||
.map_err(PusError::ByteConversionError)?;
|
||||
.map_err(PusError::ByteConversion)?;
|
||||
idx += params.failure_code.size();
|
||||
if let Some(failure_data) = params.failure_data {
|
||||
src_data_buf[idx..idx + failure_data.len()].copy_from_slice(failure_data);
|
||||
@ -1063,7 +1075,7 @@ mod alloc_mod {
|
||||
sender: &mut (impl EcssTmSenderCore + ?Sized),
|
||||
time_stamp: Option<&[u8]>,
|
||||
step: impl EcssEnumeration,
|
||||
) -> Result<(), EcssTmtcErrorWithSend> {
|
||||
) -> Result<(), EcssTmtcError> {
|
||||
let seq_count = self
|
||||
.seq_count_provider
|
||||
.as_ref()
|
||||
@ -1250,7 +1262,7 @@ mod alloc_mod {
|
||||
token: &VerificationToken<TcStateStarted>,
|
||||
time_stamp: Option<&[u8]>,
|
||||
step: impl EcssEnumeration,
|
||||
) -> Result<(), EcssTmtcErrorWithSend> {
|
||||
) -> Result<(), EcssTmtcError> {
|
||||
self.reporter
|
||||
.step_success(token, self.sender.as_mut(), time_stamp, step)
|
||||
}
|
||||
@ -1482,11 +1494,11 @@ mod tests {
|
||||
use crate::pool::{LocalPool, PoolCfg, SharedPool};
|
||||
use crate::pus::tests::CommonTmInfo;
|
||||
use crate::pus::verification::{
|
||||
EcssTmSenderCore, EcssTmtcErrorWithSend, FailParams, FailParamsWithStep, RequestId,
|
||||
TcStateNone, VerificationReporter, VerificationReporterCfg, VerificationReporterWithSender,
|
||||
EcssTmSenderCore, EcssTmtcError, FailParams, FailParamsWithStep, RequestId, TcStateNone,
|
||||
VerificationReporter, VerificationReporterCfg, VerificationReporterWithSender,
|
||||
VerificationToken,
|
||||
};
|
||||
use crate::pus::{EcssSender, EcssTmtcErrorWithSend, MpscTmInStoreSender, PusTmWrapper};
|
||||
use crate::pus::{EcssChannel, EcssTmtcError, MpscTmInStoreSender, PusTmWrapper};
|
||||
use crate::SenderId;
|
||||
use alloc::boxed::Box;
|
||||
use alloc::format;
|
||||
@ -1521,7 +1533,7 @@ mod tests {
|
||||
pub service_queue: RefCell<VecDeque<TmInfo>>,
|
||||
}
|
||||
|
||||
impl EcssSender for TestSender {
|
||||
impl EcssChannel for TestSender {
|
||||
fn id(&self) -> SenderId {
|
||||
0
|
||||
}
|
||||
@ -1569,7 +1581,7 @@ mod tests {
|
||||
#[derive(Default, Clone)]
|
||||
struct FallibleSender {}
|
||||
|
||||
impl EcssSender for FallibleSender {
|
||||
impl EcssChannel for FallibleSender {
|
||||
fn id(&self) -> SenderId {
|
||||
0
|
||||
}
|
||||
@ -1705,7 +1717,7 @@ mod tests {
|
||||
let err = res.unwrap_err();
|
||||
assert_eq!(err.1, tok);
|
||||
match err.0 {
|
||||
EcssTmtcErrorWithSend::SendError(e) => {
|
||||
EcssTmtcError::SendError(e) => {
|
||||
assert_eq!(e, DummyError {})
|
||||
}
|
||||
_ => panic!("{}", format!("Unexpected error {:?}", err.0)),
|
||||
@ -1776,20 +1788,18 @@ mod tests {
|
||||
let err_with_token = res.unwrap_err();
|
||||
assert_eq!(err_with_token.1, tok);
|
||||
match err_with_token.0 {
|
||||
EcssTmtcErrorWithSend::EcssTmtcError(EcssTmtcErrorWithSend::ByteConversion(e)) => {
|
||||
match e {
|
||||
ByteConversionError::ToSliceTooSmall(missmatch) => {
|
||||
assert_eq!(
|
||||
missmatch.expected,
|
||||
fail_data.len() + RequestId::SIZE_AS_BYTES + fail_code.size()
|
||||
);
|
||||
assert_eq!(missmatch.found, b.rep().allowed_source_data_len());
|
||||
}
|
||||
_ => {
|
||||
panic!("{}", format!("Unexpected error {:?}", e))
|
||||
}
|
||||
EcssTmtcError::EcssTmtcError(EcssTmtcError::ByteConversion(e)) => match e {
|
||||
ByteConversionError::ToSliceTooSmall(missmatch) => {
|
||||
assert_eq!(
|
||||
missmatch.expected,
|
||||
fail_data.len() + RequestId::SIZE_AS_BYTES + fail_code.size()
|
||||
);
|
||||
assert_eq!(missmatch.found, b.rep().allowed_source_data_len());
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
panic!("{}", format!("Unexpected error {:?}", e))
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
panic!("{}", format!("Unexpected error {:?}", err_with_token.0))
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ impl<E: 'static> ReceivesTcCore for PusDistributor<E> {
|
||||
fn pass_tc(&mut self, tm_raw: &[u8]) -> Result<(), Self::Error> {
|
||||
// Convert to ccsds and call pass_ccsds
|
||||
let (sp_header, _) = SpHeader::from_be_bytes(tm_raw)
|
||||
.map_err(|e| PusDistribError::PusError(PusError::ByteConversionError(e)))?;
|
||||
.map_err(|e| PusDistribError::PusError(PusError::ByteConversion(e)))?;
|
||||
self.pass_ccsds(&sp_header, tm_raw)
|
||||
}
|
||||
}
|
||||
|
@ -8,9 +8,11 @@ pub use std_mod::*;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub mod std_mod {
|
||||
use crate::pool::{SharedPool, StoreAddr};
|
||||
use crate::pool::{ShareablePoolProvider, SharedPool, StoreAddr};
|
||||
use crate::pus::EcssTmtcError;
|
||||
use spacepackets::ecss::SerializablePusPacket;
|
||||
use spacepackets::tm::PusTm;
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SharedTmStore {
|
||||
@ -18,21 +20,23 @@ pub mod std_mod {
|
||||
}
|
||||
|
||||
impl SharedTmStore {
|
||||
pub fn new(backing_pool: SharedPool) -> Self {
|
||||
Self { pool: backing_pool }
|
||||
pub fn new(backing_pool: ShareablePoolProvider) -> Self {
|
||||
Self {
|
||||
pool: Arc::new(RwLock::new(backing_pool)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn backing_pool(&self) -> SharedPool {
|
||||
self.pool.clone()
|
||||
}
|
||||
|
||||
pub fn add_pus_tm(&mut self, pus_tm: &PusTm) -> StoreAddr {
|
||||
let mut pg = self.pool.write().expect("error locking TM store");
|
||||
let (addr, buf) = pg.free_element(pus_tm.len_packed()).expect("Store error");
|
||||
pub fn add_pus_tm(&self, pus_tm: &PusTm) -> Result<StoreAddr, EcssTmtcError> {
|
||||
let mut pg = self.pool.write().map_err(|_| EcssTmtcError::StoreLock)?;
|
||||
let (addr, buf) = pg.free_element(pus_tm.len_packed())?;
|
||||
pus_tm
|
||||
.write_to_bytes(buf)
|
||||
.expect("writing PUS TM to store failed");
|
||||
addr
|
||||
Ok(addr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -64,8 +64,8 @@ fn main() {
|
||||
(15, 1024),
|
||||
(15, 2048),
|
||||
]));
|
||||
let tm_store = SharedTmStore::new(Arc::new(RwLock::new(Box::new(tm_pool))));
|
||||
let tm_store_event = tm_store.clone();
|
||||
let shared_tm_store = SharedTmStore::new(Box::new(tm_pool));
|
||||
let tm_store_event = shared_tm_store.clone();
|
||||
let tc_pool = LocalPool::new(PoolCfg::new(vec![
|
||||
(30, 32),
|
||||
(15, 64),
|
||||
@ -87,7 +87,7 @@ fn main() {
|
||||
let verif_sender = MpscTmInStoreSender::new(
|
||||
TmSenderId::PusVerification as SenderId,
|
||||
"verif_sender",
|
||||
tm_store.backing_pool(),
|
||||
shared_tm_store.clone(),
|
||||
tm_funnel_tx.clone(),
|
||||
);
|
||||
let verif_cfg = VerificationReporterCfg::new(PUS_APID, 1, 2, 8).unwrap();
|
||||
@ -135,13 +135,13 @@ fn main() {
|
||||
tc_receiver: tc_source_rx,
|
||||
};
|
||||
let tm_args = TmArgs {
|
||||
tm_store: tm_store.clone(),
|
||||
tm_store: shared_tm_store.clone(),
|
||||
tm_sink_sender: tm_funnel_tx.clone(),
|
||||
tm_server_rx,
|
||||
};
|
||||
|
||||
let aocs_tm_funnel = tm_funnel_tx.clone();
|
||||
let mut aocs_tm_store = tm_store.clone();
|
||||
let aocs_tm_store = shared_tm_store.clone();
|
||||
|
||||
let (pus_test_tx, pus_test_rx) = channel();
|
||||
let (pus_event_tx, pus_event_rx) = channel();
|
||||
@ -158,7 +158,7 @@ fn main() {
|
||||
let test_srv_tm_sender = MpscTmInStoreSender::new(
|
||||
TmSenderId::PusTest as SenderId,
|
||||
"PUS_17_TM_SENDER",
|
||||
tm_store.backing_pool().clone(),
|
||||
shared_tm_store.clone(),
|
||||
tm_funnel_tx.clone(),
|
||||
);
|
||||
let pus17_handler = PusService17TestHandler::new(
|
||||
@ -176,7 +176,7 @@ fn main() {
|
||||
let sched_srv_tm_sender = MpscTmInStoreSender::new(
|
||||
TmSenderId::PusSched as SenderId,
|
||||
"PUS_11_TM_SENDER",
|
||||
tm_store.backing_pool().clone(),
|
||||
shared_tm_store.clone(),
|
||||
tm_funnel_tx.clone(),
|
||||
);
|
||||
let scheduler = PusScheduler::new_with_current_init_time(Duration::from_secs(5))
|
||||
@ -197,7 +197,7 @@ fn main() {
|
||||
let event_srv_tm_sender = MpscTmInStoreSender::new(
|
||||
TmSenderId::PusEvent as SenderId,
|
||||
"PUS_5_TM_SENDER",
|
||||
tm_store.backing_pool().clone(),
|
||||
shared_tm_store.clone(),
|
||||
tm_funnel_tx.clone(),
|
||||
);
|
||||
let pus_5_handler = PusService5EventHandler::new(
|
||||
@ -213,7 +213,7 @@ fn main() {
|
||||
let action_srv_tm_sender = MpscTmInStoreSender::new(
|
||||
TmSenderId::PusAction as SenderId,
|
||||
"PUS_8_TM_SENDER",
|
||||
tm_store.backing_pool().clone(),
|
||||
shared_tm_store.clone(),
|
||||
tm_funnel_tx.clone(),
|
||||
);
|
||||
let pus_8_handler = PusService8ActionHandler::new(
|
||||
@ -229,7 +229,7 @@ fn main() {
|
||||
let hk_srv_tm_sender = MpscTmInStoreSender::new(
|
||||
TmSenderId::PusHk as SenderId,
|
||||
"PUS_3_TM_SENDER",
|
||||
tm_store.backing_pool().clone(),
|
||||
shared_tm_store.clone(),
|
||||
tm_funnel_tx.clone(),
|
||||
);
|
||||
let pus_3_handler = PusService3HkHandler::new(
|
||||
@ -262,7 +262,7 @@ fn main() {
|
||||
if let Ok(addr) = tm_funnel.tm_funnel_rx.recv() {
|
||||
// Read the TM, set sequence counter and message counter, and finally update
|
||||
// the CRC.
|
||||
let shared_pool = tm_store.backing_pool();
|
||||
let shared_pool = shared_tm_store.backing_pool();
|
||||
let mut pool_guard = shared_pool.write().expect("Locking TM pool failed");
|
||||
let tm_raw = pool_guard
|
||||
.modify(&addr)
|
||||
@ -297,12 +297,8 @@ fn main() {
|
||||
.name("Event".to_string())
|
||||
.spawn(move || {
|
||||
let mut timestamp: [u8; 7] = [0; 7];
|
||||
let mut sender = MpscTmInStoreSender::new(
|
||||
1,
|
||||
"event_sender",
|
||||
tm_store_event.backing_pool(),
|
||||
tm_funnel_tx,
|
||||
);
|
||||
let mut sender =
|
||||
MpscTmInStoreSender::new(1, "event_sender", tm_store_event.clone(), tm_funnel_tx);
|
||||
let mut time_provider = TimeProvider::new_with_u16_days(0, 0);
|
||||
let mut report_completion = |event_req: EventRequestWithToken, timestamp: &[u8]| {
|
||||
reporter_event_handler
|
||||
@ -393,7 +389,9 @@ fn main() {
|
||||
Some(&buf),
|
||||
true,
|
||||
);
|
||||
let addr = aocs_tm_store.add_pus_tm(&pus_tm);
|
||||
let addr = aocs_tm_store
|
||||
.add_pus_tm(&pus_tm)
|
||||
.expect("Adding PUS TM failed");
|
||||
aocs_tm_funnel.send(addr).expect("Sending HK TM failed");
|
||||
}
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ impl PusService8ActionHandler {
|
||||
),
|
||||
)
|
||||
.expect("Sending start failure failed");
|
||||
return Err(PusPacketHandlingError::OtherError(format!(
|
||||
return Err(PusPacketHandlingError::Other(format!(
|
||||
"Unknown target ID {target_id}"
|
||||
)));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user