continue the pain

This commit is contained in:
Robin Müller 2024-02-27 14:33:14 +01:00
parent f5acdaeffc
commit 656229a542
5 changed files with 128 additions and 56 deletions

View File

@ -1,8 +1,4 @@
use crate::{ use crate::{params::Params, pool::StoreAddr, TargetId};
params::{Params, ParamsHeapless},
pool::StoreAddr,
TargetId,
};
pub type ActionId = u32; pub type ActionId = u32;

View File

@ -1,10 +1,14 @@
use crate::{ use crate::{
action::{ActionId, ActionReply, ActionRequest}, action::{ActionId, ActionRequest},
params::Params,
TargetId, TargetId,
}; };
use super::verification::{TcStateAccepted, VerificationToken}; use super::verification::{TcStateAccepted, VerificationToken};
use satrs_shared::res_code::ResultU16;
use spacepackets::ecss::EcssEnumU16;
#[cfg(feature = "std")] #[cfg(feature = "std")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
pub use std_mod::*; pub use std_mod::*;
@ -13,6 +17,24 @@ pub use std_mod::*;
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
pub use alloc_mod::*; pub use alloc_mod::*;
/// A reply to an action request, but tailored to the PUS standard verification process.
#[non_exhaustive]
#[derive(Clone, Debug)]
pub enum ActionReplyPus {
CompletionFailed {
id: ActionId,
error_code: ResultU16,
params: Params,
},
StepFailed {
id: ActionId,
error_code: ResultU16,
step: EcssEnumU16,
params: Params,
},
Completed(ActionId),
}
/// This trait is an abstraction for the routing of PUS service 8 action requests to a dedicated /// This trait is an abstraction for the routing of PUS service 8 action requests to a dedicated
/// recipient using the generic [TargetId]. /// recipient using the generic [TargetId].
pub trait PusActionRequestRouter { pub trait PusActionRequestRouter {
@ -65,15 +87,19 @@ pub mod alloc_mod {
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
pub mod std_mod { pub mod std_mod {
use hashbrown::HashMap; use hashbrown::HashMap;
use spacepackets::ByteConversionError;
use crate::{ use crate::{
params::WritableToBeBytes, params::WritableToBeBytes,
pus::{ pus::{
get_current_cds_short_timestamp, get_current_cds_short_timestamp,
verification::{FailParams, TcStateStarted, VerificationReportingProvider}, verification::{
EcssTcInMemConverter, EcssTcReceiverCore, EcssTmSenderCore, GenericRoutingError, FailParams, FailParamsWithStep, RequestId, TcStateStarted,
PusPacketHandlerResult, PusPacketHandlingError, PusRoutingErrorHandler, VerificationReportingProvider,
PusServiceHelper, },
EcssTcInMemConverter, EcssTcReceiverCore, EcssTmSenderCore, EcssTmtcError,
GenericRoutingError, PusPacketHandlerResult, PusPacketHandlingError,
PusRoutingErrorHandler, PusServiceHelper,
}, },
}; };
@ -185,8 +211,15 @@ pub mod std_mod {
Ok(PusPacketHandlerResult::RequestHandled) Ok(PusPacketHandlerResult::RequestHandled)
} }
} }
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ActiveRequest {
action_id: ActionId,
target_id: TargetId,
}
pub struct PusService8ReplyHandler<VerificationReporter: VerificationReportingProvider> { pub struct PusService8ReplyHandler<VerificationReporter: VerificationReportingProvider> {
active_requests: HashMap<TargetId, ActionId>, active_requests: HashMap<RequestId, ActiveRequest>,
verification_reporter: VerificationReporter, verification_reporter: VerificationReporter,
fail_data_buf: alloc::vec::Vec<u8>, fail_data_buf: alloc::vec::Vec<u8>,
} }
@ -194,29 +227,68 @@ pub mod std_mod {
impl<VerificationReporter: VerificationReportingProvider> impl<VerificationReporter: VerificationReportingProvider>
PusService8ReplyHandler<VerificationReporter> PusService8ReplyHandler<VerificationReporter>
{ {
pub fn add_routed_request(&mut self, target_id: TargetId, action_id: ActionId) { pub fn add_routed_request(
self.active_requests.insert(target_id, action_id);
}
pub fn handle_action_reply(
&mut self, &mut self,
reply: ActionReply, request_id: RequestId,
token: VerificationToken<TcStateStarted>, target_id: TargetId,
time_stamp: &[u8], action_id: ActionId,
) { ) {
match reply { self.active_requests.insert(
ActionReply::CompletionFailed { id, reason } => { request_id,
reason.write_to_be_bytes(self.fail_data_buf.as_mut_slice()); ActiveRequest {
self.verification_reporter.completion_failure( target_id,
token, action_id,
FailParams::new(time_stamp, failure_code, failure_data), },
); );
} }
ActionReply::StepFailed { id, step, reason } => {}
ActionReply::Completed(id) => {} pub fn handle_action_reply(
ActionReply::CompletedStringId(id) => {} &mut self,
ActionReply::CompletionFailedStringId { id, reason } => {} reply: ActionReplyPus,
ActionReply::StepFailedStringId { id, step, reason } => {} token: VerificationToken<TcStateStarted>,
time_stamp: &[u8],
) -> Result<(), EcssTmtcError> {
match reply {
ActionReplyPus::CompletionFailed {
id: _,
error_code,
params,
} => {
params.write_to_be_bytes(&mut self.fail_data_buf)?;
self.verification_reporter
.completion_failure(
token,
FailParams::new(time_stamp, &error_code, &self.fail_data_buf),
)
.map_err(|e| e.0)?;
} }
ActionReplyPus::StepFailed {
id: _,
error_code,
step,
params,
} => {
params.write_to_be_bytes(&mut self.fail_data_buf)?;
self.verification_reporter
.step_failure(
token,
FailParamsWithStep::new(
time_stamp,
&step,
&error_code,
&self.fail_data_buf,
),
)
.expect("step failure");
}
ActionReplyPus::Completed(id) => {
self.active_requests.remove(&id);
self.verification_reporter
.completion_success(token, time_stamp)
.expect("completion success");
}
}
Ok(())
} }
} }
} }

View File

@ -4,7 +4,7 @@
//! The satrs-example application contains various usage examples of these components. //! The satrs-example application contains various usage examples of these components.
use crate::pool::{StoreAddr, StoreError}; use crate::pool::{StoreAddr, StoreError};
use crate::pus::verification::{TcStateAccepted, TcStateToken, VerificationToken}; use crate::pus::verification::{TcStateAccepted, TcStateToken, VerificationToken};
use crate::queue::{GenericRecvError, GenericSendError}; use crate::queue::{GenericReceiveError, GenericSendError};
use crate::ChannelId; use crate::ChannelId;
use core::fmt::{Display, Formatter}; use core::fmt::{Display, Formatter};
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
@ -59,26 +59,26 @@ impl<'tm> From<PusTmCreator<'tm>> for PusTmWrapper<'tm> {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum EcssTmtcError { pub enum EcssTmtcError {
StoreLock,
Store(StoreError), Store(StoreError),
ByteConversion(ByteConversionError),
Pus(PusError), Pus(PusError),
CantSendAddr(StoreAddr), CantSendAddr(StoreAddr),
CantSendDirectTm, CantSendDirectTm,
Send(GenericSendError), Send(GenericSendError),
Recv(GenericRecvError), Receive(GenericReceiveError),
} }
impl Display for EcssTmtcError { impl Display for EcssTmtcError {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self { match self {
EcssTmtcError::StoreLock => {
write!(f, "store lock error")
}
EcssTmtcError::Store(store) => { EcssTmtcError::Store(store) => {
write!(f, "store error: {store}") write!(f, "ecss tmtc error: {store}")
} }
EcssTmtcError::Pus(pus_e) => { EcssTmtcError::ByteConversion(e) => {
write!(f, "PUS error: {pus_e}") write!(f, "ecss tmtc error: {e}")
}
EcssTmtcError::Pus(e) => {
write!(f, "ecss tmtc error: {e}")
} }
EcssTmtcError::CantSendAddr(addr) => { EcssTmtcError::CantSendAddr(addr) => {
write!(f, "can not send address {addr}") write!(f, "can not send address {addr}")
@ -86,11 +86,11 @@ impl Display for EcssTmtcError {
EcssTmtcError::CantSendDirectTm => { EcssTmtcError::CantSendDirectTm => {
write!(f, "can not send TM directly") write!(f, "can not send TM directly")
} }
EcssTmtcError::Send(send_e) => { EcssTmtcError::Send(e) => {
write!(f, "send error {send_e}") write!(f, "ecss tmtc error: {e}")
} }
EcssTmtcError::Recv(recv_e) => { EcssTmtcError::Receive(e) => {
write!(f, "recv error {recv_e}") write!(f, "ecss tmtc error {e}")
} }
} }
} }
@ -114,9 +114,9 @@ impl From<GenericSendError> for EcssTmtcError {
} }
} }
impl From<GenericRecvError> for EcssTmtcError { impl From<GenericReceiveError> for EcssTmtcError {
fn from(value: GenericRecvError) -> Self { fn from(value: GenericReceiveError) -> Self {
Self::Recv(value) Self::Receive(value)
} }
} }
@ -125,9 +125,10 @@ impl Error for EcssTmtcError {
fn source(&self) -> Option<&(dyn Error + 'static)> { fn source(&self) -> Option<&(dyn Error + 'static)> {
match self { match self {
EcssTmtcError::Store(e) => Some(e), EcssTmtcError::Store(e) => Some(e),
EcssTmtcError::ByteConversion(e) => Some(e),
EcssTmtcError::Pus(e) => Some(e), EcssTmtcError::Pus(e) => Some(e),
EcssTmtcError::Send(e) => Some(e), EcssTmtcError::Send(e) => Some(e),
EcssTmtcError::Recv(e) => Some(e), EcssTmtcError::Receive(e) => Some(e),
_ => None, _ => None,
} }
} }
@ -368,11 +369,13 @@ mod alloc_mod {
#[cfg(feature = "std")] #[cfg(feature = "std")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
pub mod std_mod { pub mod std_mod {
use crate::pool::{PoolProvider, PoolProviderWithGuards, SharedStaticMemoryPool, StoreAddr}; use crate::pool::{
PoolProvider, PoolProviderWithGuards, SharedStaticMemoryPool, StoreAddr, StoreError,
};
use crate::pus::verification::{TcStateAccepted, VerificationToken}; use crate::pus::verification::{TcStateAccepted, VerificationToken};
use crate::pus::{ use crate::pus::{
EcssChannel, EcssTcAndToken, EcssTcReceiverCore, EcssTmSenderCore, EcssTmtcError, EcssChannel, EcssTcAndToken, EcssTcReceiverCore, EcssTmSenderCore, EcssTmtcError,
GenericRecvError, GenericSendError, PusTmWrapper, TryRecvTmtcError, GenericReceiveError, GenericSendError, PusTmWrapper, TryRecvTmtcError,
}; };
use crate::tmtc::tm_helper::SharedTmPool; use crate::tmtc::tm_helper::SharedTmPool;
use crate::{ChannelId, TargetId}; use crate::{ChannelId, TargetId};
@ -564,7 +567,7 @@ pub mod std_mod {
self.receiver.try_recv().map_err(|e| match e { self.receiver.try_recv().map_err(|e| match e {
TryRecvError::Empty => TryRecvTmtcError::Empty, TryRecvError::Empty => TryRecvTmtcError::Empty,
TryRecvError::Disconnected => { TryRecvError::Disconnected => {
TryRecvTmtcError::Tmtc(EcssTmtcError::from(GenericRecvError::TxDisconnected)) TryRecvTmtcError::Tmtc(EcssTmtcError::from(GenericReceiveError::TxDisconnected))
} }
}) })
} }
@ -659,7 +662,7 @@ pub mod std_mod {
self.receiver.try_recv().map_err(|e| match e { self.receiver.try_recv().map_err(|e| match e {
cb::TryRecvError::Empty => TryRecvTmtcError::Empty, cb::TryRecvError::Empty => TryRecvTmtcError::Empty,
cb::TryRecvError::Disconnected => TryRecvTmtcError::Tmtc(EcssTmtcError::from( cb::TryRecvError::Disconnected => TryRecvTmtcError::Tmtc(EcssTmtcError::from(
GenericRecvError::TxDisconnected, GenericReceiveError::TxDisconnected,
)), )),
}) })
} }
@ -805,10 +808,9 @@ pub mod std_mod {
pub fn copy_tc_to_buf(&mut self, addr: StoreAddr) -> Result<(), PusPacketHandlingError> { pub fn copy_tc_to_buf(&mut self, addr: StoreAddr) -> Result<(), PusPacketHandlingError> {
// Keep locked section as short as possible. // Keep locked section as short as possible.
let mut tc_pool = self let mut tc_pool = self.shared_tc_store.write().map_err(|_| {
.shared_tc_store PusPacketHandlingError::EcssTmtc(EcssTmtcError::Store(StoreError::LockError))
.write() })?;
.map_err(|_| PusPacketHandlingError::EcssTmtc(EcssTmtcError::StoreLock))?;
let tc_size = tc_pool let tc_size = tc_pool
.len_of_data(&addr) .len_of_data(&addr)
.map_err(|e| PusPacketHandlingError::EcssTmtc(EcssTmtcError::Store(e)))?; .map_err(|e| PusPacketHandlingError::EcssTmtc(EcssTmtcError::Store(e)))?;

View File

@ -29,12 +29,12 @@ impl Error for GenericSendError {}
/// Generic error type for sending something via a message queue. /// Generic error type for sending something via a message queue.
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub enum GenericRecvError { pub enum GenericReceiveError {
Empty, Empty,
TxDisconnected, TxDisconnected,
} }
impl Display for GenericRecvError { impl Display for GenericReceiveError {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self { match self {
Self::TxDisconnected => { Self::TxDisconnected => {
@ -48,7 +48,7 @@ impl Display for GenericRecvError {
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
impl Error for GenericRecvError {} impl Error for GenericReceiveError {}
#[cfg(feature = "std")] #[cfg(feature = "std")]
impl<T> From<mpsc::SendError<T>> for GenericSendError { impl<T> From<mpsc::SendError<T>> for GenericSendError {

View File

@ -8,7 +8,9 @@ pub use std_mod::*;
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub mod std_mod { pub mod std_mod {
use crate::pool::{PoolProvider, SharedStaticMemoryPool, StaticMemoryPool, StoreAddr}; use crate::pool::{
PoolProvider, SharedStaticMemoryPool, StaticMemoryPool, StoreAddr, StoreError,
};
use crate::pus::EcssTmtcError; use crate::pus::EcssTmtcError;
use spacepackets::ecss::tm::PusTmCreator; use spacepackets::ecss::tm::PusTmCreator;
use spacepackets::ecss::WritablePusPacket; use spacepackets::ecss::WritablePusPacket;
@ -34,7 +36,7 @@ pub mod std_mod {
} }
pub fn add_pus_tm(&self, pus_tm: &PusTmCreator) -> Result<StoreAddr, EcssTmtcError> { pub fn add_pus_tm(&self, pus_tm: &PusTmCreator) -> Result<StoreAddr, EcssTmtcError> {
let mut pg = self.0.write().map_err(|_| EcssTmtcError::StoreLock)?; let mut pg = self.0.write().map_err(|_| StoreError::LockError)?;
let addr = pg.free_element(pus_tm.len_written(), |buf| { let addr = pg.free_element(pus_tm.len_written(), |buf| {
pus_tm pus_tm
.write_to_bytes(buf) .write_to_bytes(buf)