Tricky PUS handler changes #95

Merged
muellerr merged 9 commits from tricky-pus-abstraction-changes into main 2024-01-31 14:35:09 +01:00
9 changed files with 163 additions and 112 deletions
Showing only changes of commit 7cbe4f1170 - Show all commits

View File

@ -43,15 +43,16 @@ impl PusService5EventHandler {
if possible_packet.is_none() {
return Ok(PusPacketHandlerResult::Empty);
}
let (addr, token) = possible_packet.unwrap();
self.psb.copy_tc_to_buf(addr)?;
let ecss_tc_and_token = possible_packet.unwrap();
self.psb
.convert_possible_packet_to_tc_buf(&ecss_tc_and_token)?;
let (tc, _) = PusTcReader::new(&self.psb.pus_buf)?;
let subservice = tc.subservice();
let srv = Subservice::try_from(subservice);
if srv.is_err() {
return Ok(PusPacketHandlerResult::CustomSubservice(
tc.subservice(),
token,
ecss_tc_and_token.token,
));
}
let handle_enable_disable_request = |enable: bool, stamp: [u8; 7]| {
@ -66,10 +67,10 @@ impl PusService5EventHandler {
.psb
.verification_handler
.borrow_mut()
.start_success(token, Some(&stamp))
.start_success(ecss_tc_and_token.token, Some(&stamp))
.map_err(|_| PartialPusHandlingError::Verification);
let partial_error = start_token.clone().err();
let mut token: TcStateToken = token.into();
let mut token: TcStateToken = ecss_tc_and_token.token.into();
if let Ok(start_token) = start_token {
token = start_token.into();
}
@ -113,7 +114,8 @@ impl PusService5EventHandler {
}
Subservice::TcReportDisabledList | Subservice::TmDisabledEventsReport => {
return Ok(PusPacketHandlerResult::SubserviceNotImplemented(
subservice, token,
subservice,
ecss_tc_and_token.token,
));
}
}

View File

@ -55,12 +55,6 @@ impl<'tm> From<PusTmCreator<'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 {
@ -201,17 +195,48 @@ pub trait EcssTcSenderCore: EcssChannel {
}
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum TcInMemory {
StoreAddr(StoreAddr),
#[cfg(feature = "alloc")]
Vec(alloc::vec::Vec<u8>),
}
pub struct ReceivedTcWrapper {
pub store_addr: TcInMemory,
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EcssTcAndToken {
pub tc_in_memory: TcInMemory,
pub token: Option<TcStateToken>,
}
/// Generic abstraction for a telecommand being sent around after is has been accepted.
pub struct AcceptedEcssTcAndToken {
pub tc_in_memory: TcInMemory,
pub token: VerificationToken<TcStateAccepted>,
}
impl From<AcceptedEcssTcAndToken> for EcssTcAndToken {
fn from(value: AcceptedEcssTcAndToken) -> Self {
EcssTcAndToken {
tc_in_memory: value.tc_in_memory,
token: Some(value.token.into()),
}
}
}
impl TryFrom<EcssTcAndToken> for AcceptedEcssTcAndToken {
type Error = ();
fn try_from(value: EcssTcAndToken) -> Result<Self, Self::Error> {
if let Some(TcStateToken::Accepted(token)) = value.token {
return Ok(AcceptedEcssTcAndToken {
tc_in_memory: value.tc_in_memory,
token,
});
}
Err(())
}
}
#[derive(Debug, Clone)]
pub enum TryRecvTmtcError {
Error(EcssTmtcError),
@ -238,7 +263,7 @@ impl From<StoreError> for TryRecvTmtcError {
/// Generic trait for a user supplied receiver object.
pub trait EcssTcReceiverCore: EcssChannel {
fn recv_tc(&self) -> Result<ReceivedTcWrapper, TryRecvTmtcError>;
fn recv_tc(&self) -> Result<EcssTcAndToken, TryRecvTmtcError>;
}
/// Generic trait for objects which can receive ECSS PUS telecommands. This trait is
@ -322,9 +347,9 @@ pub mod std_mod {
StdVerifReporterWithSender, TcStateAccepted, VerificationToken,
};
use crate::pus::{
EcssChannel, EcssTcReceiver, EcssTcReceiverCore, EcssTmSender, EcssTmSenderCore,
EcssTmtcError, GenericRecvError, GenericSendError, PusTmWrapper, ReceivedTcWrapper,
TcAddrWithToken, TryRecvTmtcError,
EcssChannel, EcssTcAndToken, EcssTcReceiver, EcssTcReceiverCore, EcssTmSender,
EcssTmSenderCore, EcssTmtcError, GenericRecvError, GenericSendError, PusTmWrapper,
TryRecvTmtcError,
};
use crate::tmtc::tm_helper::SharedTmStore;
use crate::ChannelId;
@ -342,7 +367,7 @@ pub mod std_mod {
use std::sync::mpsc::TryRecvError;
use thiserror::Error;
use super::TcInMemory;
use super::AcceptedEcssTcAndToken;
impl From<mpsc::SendError<StoreAddr>> for EcssTmtcError {
fn from(_: mpsc::SendError<StoreAddr>) -> Self {
@ -423,7 +448,7 @@ pub mod std_mod {
pub struct MpscTcInStoreReceiver {
id: ChannelId,
name: &'static str,
receiver: mpsc::Receiver<TcAddrWithToken>,
receiver: mpsc::Receiver<EcssTcAndToken>,
}
impl EcssChannel for MpscTcInStoreReceiver {
@ -437,16 +462,12 @@ pub mod std_mod {
}
impl EcssTcReceiverCore for MpscTcInStoreReceiver {
fn recv_tc(&self) -> Result<ReceivedTcWrapper, TryRecvTmtcError> {
let (store_addr, token) = self.receiver.try_recv().map_err(|e| match e {
fn recv_tc(&self) -> Result<EcssTcAndToken, TryRecvTmtcError> {
self.receiver.try_recv().map_err(|e| match e {
TryRecvError::Empty => TryRecvTmtcError::Empty,
TryRecvError::Disconnected => {
TryRecvTmtcError::Error(EcssTmtcError::from(GenericRecvError::TxDisconnected))
}
})?;
Ok(ReceivedTcWrapper {
store_addr,
token: Some(token),
})
}
}
@ -455,7 +476,7 @@ pub mod std_mod {
pub fn new(
id: ChannelId,
name: &'static str,
receiver: mpsc::Receiver<TcAddrWithToken>,
receiver: mpsc::Receiver<EcssTcAndToken>,
) -> Self {
Self { id, name, receiver }
}
@ -557,14 +578,14 @@ pub mod std_mod {
pub struct CrossbeamTcInStoreReceiver {
id: ChannelId,
name: &'static str,
receiver: cb::Receiver<TcAddrWithToken>,
receiver: cb::Receiver<EcssTcAndToken>,
}
impl CrossbeamTcInStoreReceiver {
pub fn new(
id: ChannelId,
name: &'static str,
receiver: cb::Receiver<TcAddrWithToken>,
receiver: cb::Receiver<EcssTcAndToken>,
) -> Self {
Self { id, name, receiver }
}
@ -581,16 +602,12 @@ pub mod std_mod {
}
impl EcssTcReceiverCore for CrossbeamTcInStoreReceiver {
fn recv_tc(&self) -> Result<ReceivedTcWrapper, TryRecvTmtcError> {
let (store_addr, token) = self.receiver.try_recv().map_err(|e| match e {
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::Error(EcssTmtcError::from(GenericRecvError::TxDisconnected))
}
})?;
Ok(ReceivedTcWrapper {
store_addr,
token: Some(token),
})
}
}
@ -710,26 +727,38 @@ pub mod std_mod {
Ok(())
}
pub fn retrieve_next_packet(
pub fn convert_possible_packet_to_tc_buf(
&mut self,
handle_acceptance: bool,
) -> Result<Option<ReceivedTcWrapper>,PusPacketHandlingError>
{
possible_packet: &AcceptedEcssTcAndToken,
) -> Result<(), PusPacketHandlingError> {
match &possible_packet.tc_in_memory {
super::TcInMemory::StoreAddr(addr) => {
self.copy_tc_to_buf(*addr)?;
}
super::TcInMemory::Vec(vec) => {
self.pus_buf.copy_from_slice(vec);
}
};
Ok(())
}
pub fn retrieve_and_accept_next_packet(
&mut self,
) -> Result<Option<AcceptedEcssTcAndToken>, PusPacketHandlingError> {
match self.tc_receiver.recv_tc() {
Ok(ReceivedTcWrapper { store_addr, token }) => {
let mut passed_token = token;
if handle_acceptance {
if token.is_none() {
return Err(PusPacketHandlingError::InvalidVerificationToken);
}
let token = token.unwrap();
let accepted_token = VerificationToken::<TcStateAccepted>::try_from(token)
.map_err(|_| PusPacketHandlingError::InvalidVerificationToken)?;
passed_token = Some(accepted_token.into());
Ok(EcssTcAndToken {
tc_in_memory,
token,
}) => {
if token.is_none() {
return Err(PusPacketHandlingError::InvalidVerificationToken);
}
Ok(Some(ReceivedTcWrapper {
store_addr,
token: passed_token
let token = token.unwrap();
let accepted_token = VerificationToken::<TcStateAccepted>::try_from(token)
.map_err(|_| PusPacketHandlingError::InvalidVerificationToken)?;
Ok(Some(AcceptedEcssTcAndToken {
tc_in_memory,
token: accepted_token,
}))
}
Err(e) => match e {

View File

@ -57,15 +57,14 @@ impl PusService11SchedHandler {
if possible_packet.is_none() {
return Ok(PusPacketHandlerResult::Empty);
}
let (addr, token) = possible_packet.unwrap();
self.psb.copy_tc_to_buf(addr)?;
let ecss_tc_and_token = possible_packet.unwrap();
let (tc, _) = PusTcReader::new(&self.psb.pus_buf)?;
let subservice = tc.subservice();
let std_service = scheduling::Subservice::try_from(subservice);
if std_service.is_err() {
return Ok(PusPacketHandlerResult::CustomSubservice(
tc.subservice(),
token,
ecss_tc_and_token.token,
));
}
let mut partial_error = None;
@ -76,7 +75,7 @@ impl PusService11SchedHandler {
.psb
.verification_handler
.get_mut()
.start_success(token, Some(&time_stamp))
.start_success(ecss_tc_and_token.token, Some(&time_stamp))
.expect("Error sending start success");
self.scheduler.enable();
@ -95,7 +94,7 @@ impl PusService11SchedHandler {
.psb
.verification_handler
.get_mut()
.start_success(token, Some(&time_stamp))
.start_success(ecss_tc_and_token.token, Some(&time_stamp))
.expect("Error sending start success");
self.scheduler.disable();
@ -114,7 +113,7 @@ impl PusService11SchedHandler {
.psb
.verification_handler
.get_mut()
.start_success(token, Some(&time_stamp))
.start_success(ecss_tc_and_token.token, Some(&time_stamp))
.expect("Error sending start success");
let mut pool = self
@ -138,7 +137,7 @@ impl PusService11SchedHandler {
.psb
.verification_handler
.get_mut()
.start_success(token, Some(&time_stamp))
.start_success(ecss_tc_and_token.token, Some(&time_stamp))
.expect("error sending start success");
let mut pool = self
@ -157,9 +156,10 @@ impl PusService11SchedHandler {
.expect("sending completion success failed");
}
_ => {
// Treat unhandled standard subservices as custom subservices for now.
return Ok(PusPacketHandlerResult::CustomSubservice(
tc.subservice(),
token,
ecss_tc_and_token.token.into(),
));
}
}
@ -168,9 +168,6 @@ impl PusService11SchedHandler {
partial_error,
));
}
Ok(PusPacketHandlerResult::CustomSubservice(
tc.subservice(),
token,
))
Ok(PusPacketHandlerResult::RequestHandled)
}
}

View File

@ -40,8 +40,9 @@ impl PusService17TestHandler {
if possible_packet.is_none() {
return Ok(PusPacketHandlerResult::Empty);
}
let (addr, token) = possible_packet.unwrap();
self.psb.copy_tc_to_buf(addr)?;
let ecss_tc_and_token = possible_packet.unwrap();
self.psb
.convert_possible_packet_to_tc_buf(&ecss_tc_and_token)?;
let (tc, _) = PusTcReader::new(&self.psb.pus_buf)?;
if tc.service() != 17 {
return Err(PusPacketHandlingError::WrongService(tc.service()));
@ -53,7 +54,7 @@ impl PusService17TestHandler {
.psb
.verification_handler
.get_mut()
.start_success(token, Some(&time_stamp))
.start_success(ecss_tc_and_token.token, Some(&time_stamp))
.map_err(|_| PartialPusHandlingError::Verification);
let start_token = if let Ok(result) = result {
Some(result)
@ -90,12 +91,13 @@ impl PusService17TestHandler {
partial_error,
));
};
return Ok(PusPacketHandlerResult::RequestHandled);
} else {
return Ok(PusPacketHandlerResult::CustomSubservice(
tc.subservice(),
ecss_tc_and_token.token.into(),
));
}
Ok(PusPacketHandlerResult::CustomSubservice(
tc.subservice(),
token,
))
Ok(PusPacketHandlerResult::RequestHandled)
}
}

View File

@ -103,15 +103,16 @@ impl PusService8ActionHandler {
if possible_packet.is_none() {
return Ok(PusPacketHandlerResult::Empty);
}
let (addr, token) = possible_packet.unwrap();
self.psb.copy_tc_to_buf(addr)?;
let ecss_tc_and_token = possible_packet.unwrap();
self.psb
.convert_possible_packet_to_tc_buf(&ecss_tc_and_token)?;
let (tc, _) = PusTcReader::new(&self.psb.pus_buf).unwrap();
let subservice = tc.subservice();
let mut partial_error = None;
let time_stamp = self.psb.get_current_timestamp(&mut partial_error);
match subservice {
128 => {
self.handle_action_request_with_id(token, &tc, &time_stamp)?;
self.handle_action_request_with_id(ecss_tc_and_token.token, &tc, &time_stamp)?;
}
_ => {
let fail_data = [subservice];
@ -119,7 +120,7 @@ impl PusService8ActionHandler {
.verification_handler
.get_mut()
.start_failure(
token,
ecss_tc_and_token.token,
FailParams::new(
Some(&time_stamp),
&tmtc_err::INVALID_PUS_SUBSERVICE,

View File

@ -45,8 +45,9 @@ impl PusService3HkHandler {
if possible_packet.is_none() {
return Ok(PusPacketHandlerResult::Empty);
}
let (addr, token) = possible_packet.unwrap();
self.psb.copy_tc_to_buf(addr)?;
let ecss_tc_and_token = possible_packet.unwrap();
self.psb
.convert_possible_packet_to_tc_buf(&ecss_tc_and_token)?;
let (tc, _) = PusTcReader::new(&self.psb.pus_buf).unwrap();
let subservice = tc.subservice();
let mut partial_error = None;
@ -57,7 +58,7 @@ impl PusService3HkHandler {
.verification_handler
.borrow_mut()
.start_failure(
token,
ecss_tc_and_token.token,
FailParams::new(Some(&time_stamp), &tmtc_err::NOT_ENOUGH_APP_DATA, None),
)
.expect("Sending start failure TM failed");
@ -74,7 +75,10 @@ impl PusService3HkHandler {
self.psb
.verification_handler
.borrow_mut()
.start_failure(token, FailParams::new(Some(&time_stamp), err, None))
.start_failure(
ecss_tc_and_token.token,
FailParams::new(Some(&time_stamp), err, None),
)
.expect("Sending start failure TM failed");
return Err(PusPacketHandlingError::NotEnoughAppData(
"Expected at least 8 bytes of app data".into(),
@ -89,7 +93,7 @@ impl PusService3HkHandler {
.verification_handler
.borrow_mut()
.start_failure(
token,
ecss_tc_and_token.token,
FailParams::new(Some(&time_stamp), &hk_err::UNKNOWN_TARGET_ID, None),
)
.expect("Sending start failure TM failed");
@ -104,7 +108,11 @@ impl PusService3HkHandler {
.get(&addressable_id.target_id)
.unwrap();
sender
.send(RequestWithToken::new(target, Request::Hk(request), token))
.send(RequestWithToken::new(
target,
Request::Hk(request),
ecss_tc_and_token.token,
))
.unwrap_or_else(|_| panic!("Sending HK request {request:?} failed"));
};
if subservice == hk::Subservice::TcEnableHkGeneration as u8 {
@ -128,7 +136,7 @@ impl PusService3HkHandler {
.verification_handler
.borrow_mut()
.start_failure(
token,
ecss_tc_and_token.token,
FailParams::new(
Some(&time_stamp),
&hk_err::COLLECTION_INTERVAL_MISSING,

View File

@ -1,8 +1,7 @@
use crate::tmtc::MpscStoreAndSendError;
use log::warn;
use satrs_core::pool::StoreAddr;
use satrs_core::pus::verification::{FailParams, StdVerifReporterWithSender};
use satrs_core::pus::{PusPacketHandlerResult, TcAddrWithToken};
use satrs_core::pus::{EcssTcAndToken, PusPacketHandlerResult, TcInMemory};
use satrs_core::spacepackets::ecss::tc::PusTcReader;
use satrs_core::spacepackets::ecss::PusServiceId;
use satrs_core::spacepackets::time::cds::TimeProvider;
@ -17,11 +16,11 @@ pub mod scheduler;
pub mod test;
pub struct PusTcMpscRouter {
pub test_service_receiver: Sender<TcAddrWithToken>,
pub event_service_receiver: Sender<TcAddrWithToken>,
pub sched_service_receiver: Sender<TcAddrWithToken>,
pub hk_service_receiver: Sender<TcAddrWithToken>,
pub action_service_receiver: Sender<TcAddrWithToken>,
pub test_service_receiver: Sender<EcssTcAndToken>,
pub event_service_receiver: Sender<EcssTcAndToken>,
pub sched_service_receiver: Sender<EcssTcAndToken>,
pub hk_service_receiver: Sender<EcssTcAndToken>,
pub action_service_receiver: Sender<EcssTcAndToken>,
}
pub struct PusReceiver {
@ -70,7 +69,7 @@ impl PusReceiver {
impl PusReceiver {
pub fn handle_tc_packet(
&mut self,
store_addr: StoreAddr,
tc_in_memory: TcInMemory,
service: u8,
pus_tc: &PusTcReader,
) -> Result<PusPacketHandlerResult, MpscStoreAndSendError> {
@ -84,22 +83,33 @@ impl PusReceiver {
match service {
Ok(standard_service) => match standard_service {
PusServiceId::Test => {
self.pus_router
.test_service_receiver
.send((store_addr, accepted_token.into()))?;
self.pus_router.test_service_receiver.send(EcssTcAndToken {
tc_in_memory,
token: Some(accepted_token.into()),
})?
}
PusServiceId::Housekeeping => {
self.pus_router.hk_service_receiver.send(EcssTcAndToken {
tc_in_memory,
token: Some(accepted_token.into()),
})?
}
PusServiceId::Event => {
self.pus_router
.event_service_receiver
.send(EcssTcAndToken {
tc_in_memory,
token: Some(accepted_token.into()),
})?
}
PusServiceId::Scheduling => {
self.pus_router
.sched_service_receiver
.send(EcssTcAndToken {
tc_in_memory,
token: Some(accepted_token.into()),
})?
}
PusServiceId::Housekeeping => self
.pus_router
.hk_service_receiver
.send((store_addr, accepted_token.into()))?,
PusServiceId::Event => self
.pus_router
.event_service_receiver
.send((store_addr, accepted_token.into()))?,
PusServiceId::Scheduling => self
.pus_router
.sched_service_receiver
.send((store_addr, accepted_token.into()))?,
_ => {
let result = self.verif_reporter.start_failure(
accepted_token,

View File

@ -52,7 +52,7 @@ impl Service17CustomWrapper {
let start_token = psb_mut
.verification_handler
.get_mut()
.start_success(token, Some(&stamp_buf))
.start_success(token.into(), Some(&stamp_buf))
.expect("Error sending start success");
psb_mut
.verification_handler

View File

@ -1,12 +1,11 @@
use log::warn;
use satrs_core::pus::ReceivesEcssPusTc;
use satrs_core::pus::{EcssTcAndToken, ReceivesEcssPusTc};
use satrs_core::spacepackets::SpHeader;
use std::sync::mpsc::{Receiver, SendError, Sender, TryRecvError};
use thiserror::Error;
use crate::pus::PusReceiver;
use satrs_core::pool::{SharedPool, StoreAddr, StoreError};
use satrs_core::pus::TcAddrWithToken;
use satrs_core::spacepackets::ecss::tc::PusTcReader;
use satrs_core::spacepackets::ecss::PusPacket;
use satrs_core::tmtc::tm_helper::SharedTmStore;
@ -35,7 +34,7 @@ pub enum MpscStoreAndSendError {
#[error("Store error: {0}")]
Store(#[from] StoreError),
#[error("TC send error: {0}")]
TcSend(#[from] SendError<TcAddrWithToken>),
TcSend(#[from] SendError<EcssTcAndToken>),
#[error("TMTC send error: {0}")]
TmTcSend(#[from] SendError<StoreAddr>),
}
@ -103,7 +102,6 @@ impl TmtcTask {
}
pub fn periodic_operation(&mut self) {
//while self.poll_tc() {}
self.poll_tc();
}
@ -123,7 +121,11 @@ impl TmtcTask {
match PusTcReader::new(&self.tc_buf) {
Ok((pus_tc, _)) => {
self.pus_receiver
.handle_tc_packet(addr, pus_tc.service(), &pus_tc)
.handle_tc_packet(
satrs_core::pus::TcInMemory::StoreAddr(addr),
pus_tc.service(),
&pus_tc,
)
.ok();
true
}