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
6 changed files with 232 additions and 123 deletions
Showing only changes of commit 0109c6855d - Show all commits

View File

@ -1,38 +1,38 @@
use crate::events::EventU32; use crate::events::EventU32;
use crate::pool::SharedPool;
use crate::pus::event_man::{EventRequest, EventRequestWithToken}; use crate::pus::event_man::{EventRequest, EventRequestWithToken};
use crate::pus::verification::{StdVerifReporterWithSender, TcStateToken}; use crate::pus::verification::{StdVerifReporterWithSender, TcStateToken};
use crate::pus::{ use crate::pus::{
EcssTcReceiver, EcssTmSender, PartialPusHandlingError, PusPacketHandlerResult, EcssTcReceiver, EcssTmSender, PartialPusHandlingError, PusPacketHandlerResult,
PusPacketHandlingError, PusServiceBaseWithStore, PusPacketHandlingError,
}; };
use alloc::boxed::Box; use alloc::boxed::Box;
use spacepackets::ecss::event::Subservice; use spacepackets::ecss::event::Subservice;
use spacepackets::ecss::tc::PusTcReader;
use spacepackets::ecss::PusPacket; use spacepackets::ecss::PusPacket;
use std::sync::mpsc::Sender; use std::sync::mpsc::Sender;
pub struct PusService5EventHandler { use super::{EcssTcInMemConverter, PusServiceBase, PusServiceHandler};
psb: PusServiceBaseWithStore,
pub struct PusService5EventHandler<TcInMemConverter: EcssTcInMemConverter> {
pub psb: PusServiceHandler<TcInMemConverter>,
event_request_tx: Sender<EventRequestWithToken>, event_request_tx: Sender<EventRequestWithToken>,
} }
impl PusService5EventHandler { impl<TcInMemConverter: EcssTcInMemConverter> PusService5EventHandler<TcInMemConverter> {
pub fn new( pub fn new(
tc_receiver: Box<dyn EcssTcReceiver>, tc_receiver: Box<dyn EcssTcReceiver>,
shared_tc_store: SharedPool,
tm_sender: Box<dyn EcssTmSender>, tm_sender: Box<dyn EcssTmSender>,
tm_apid: u16, tm_apid: u16,
verification_handler: StdVerifReporterWithSender, verification_handler: StdVerifReporterWithSender,
event_request_tx: Sender<EventRequestWithToken>, event_request_tx: Sender<EventRequestWithToken>,
tc_in_mem_converter: TcInMemConverter,
) -> Self { ) -> Self {
Self { Self {
psb: PusServiceBaseWithStore::new( psb: PusServiceHandler::new(
tc_receiver, tc_receiver,
shared_tc_store,
tm_sender, tm_sender,
tm_apid, tm_apid,
verification_handler, verification_handler,
tc_in_mem_converter,
), ),
event_request_tx, event_request_tx,
} }
@ -44,9 +44,10 @@ impl PusService5EventHandler {
return Ok(PusPacketHandlerResult::Empty); return Ok(PusPacketHandlerResult::Empty);
} }
let ecss_tc_and_token = possible_packet.unwrap(); let ecss_tc_and_token = possible_packet.unwrap();
self.psb let tc = self
.convert_possible_packet_to_tc_buf(&ecss_tc_and_token)?; .psb
let (tc, _) = PusTcReader::new(&self.psb.pus_buf)?; .tc_in_mem_converter
.convert_ecss_tc_in_memory_to_reader(&ecss_tc_and_token)?;
let subservice = tc.subservice(); let subservice = tc.subservice();
let srv = Subservice::try_from(subservice); let srv = Subservice::try_from(subservice);
if srv.is_err() { if srv.is_err() {
@ -65,6 +66,7 @@ impl PusService5EventHandler {
let event_u32 = EventU32::from(u32::from_be_bytes(user_data[0..4].try_into().unwrap())); let event_u32 = EventU32::from(u32::from_be_bytes(user_data[0..4].try_into().unwrap()));
let start_token = self let start_token = self
.psb .psb
.common
.verification_handler .verification_handler
.borrow_mut() .borrow_mut()
.start_success(ecss_tc_and_token.token, Some(&stamp)) .start_success(ecss_tc_and_token.token, Some(&stamp))
@ -98,7 +100,7 @@ impl PusService5EventHandler {
Ok(PusPacketHandlerResult::RequestHandled) Ok(PusPacketHandlerResult::RequestHandled)
}; };
let mut partial_error = None; let mut partial_error = None;
let time_stamp = self.psb.get_current_timestamp(&mut partial_error); let time_stamp = PusServiceBase::get_current_timestamp(&mut partial_error);
match srv.unwrap() { match srv.unwrap() {
Subservice::TmInfoReport Subservice::TmInfoReport
| Subservice::TmLowSeverityReport | Subservice::TmLowSeverityReport

View File

@ -202,12 +202,34 @@ pub enum TcInMemory {
Vec(alloc::vec::Vec<u8>), Vec(alloc::vec::Vec<u8>),
} }
impl From<StoreAddr> for TcInMemory {
fn from(value: StoreAddr) -> Self {
Self::StoreAddr(value)
}
}
#[cfg(feature = "alloc")]
impl From<alloc::vec::Vec<u8>> for TcInMemory {
fn from(value: alloc::vec::Vec<u8>) -> Self {
Self::Vec(value)
}
}
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct EcssTcAndToken { pub struct EcssTcAndToken {
pub tc_in_memory: TcInMemory, pub tc_in_memory: TcInMemory,
pub token: Option<TcStateToken>, pub token: Option<TcStateToken>,
} }
impl EcssTcAndToken {
pub fn new(tc_in_memory: impl Into<TcInMemory>, token: impl Into<TcStateToken>) -> Self {
Self {
tc_in_memory: tc_in_memory.into(),
token: Some(token.into()),
}
}
}
/// Generic abstraction for a telecommand being sent around after is has been accepted. /// Generic abstraction for a telecommand being sent around after is has been accepted.
pub struct AcceptedEcssTcAndToken { pub struct AcceptedEcssTcAndToken {
pub tc_in_memory: TcInMemory, pub tc_in_memory: TcInMemory,
@ -356,6 +378,7 @@ pub mod std_mod {
use alloc::boxed::Box; use alloc::boxed::Box;
use alloc::vec::Vec; use alloc::vec::Vec;
use crossbeam_channel as cb; use crossbeam_channel as cb;
use spacepackets::ecss::tc::PusTcReader;
use spacepackets::ecss::tm::PusTmCreator; use spacepackets::ecss::tm::PusTmCreator;
use spacepackets::ecss::PusError; use spacepackets::ecss::PusError;
use spacepackets::time::cds::TimeProvider; use spacepackets::time::cds::TimeProvider;
@ -367,7 +390,8 @@ pub mod std_mod {
use std::sync::mpsc::TryRecvError; use std::sync::mpsc::TryRecvError;
use thiserror::Error; use thiserror::Error;
use super::AcceptedEcssTcAndToken; use super::verification::VerificationReporterWithSender;
use super::{AcceptedEcssTcAndToken, TcInMemory};
impl From<mpsc::SendError<StoreAddr>> for EcssTmtcError { impl From<mpsc::SendError<StoreAddr>> for EcssTmtcError {
fn from(_: mpsc::SendError<StoreAddr>) -> Self { fn from(_: mpsc::SendError<StoreAddr>) -> Self {
@ -624,6 +648,8 @@ pub mod std_mod {
NotEnoughAppData(String), NotEnoughAppData(String),
#[error("invalid application data")] #[error("invalid application data")]
InvalidAppData(String), InvalidAppData(String),
#[error("invalid format of TC in memory: {0:?}")]
InvalidTcInMemoryFormat(TcInMemory),
#[error("generic ECSS tmtc error: {0}")] #[error("generic ECSS tmtc error: {0}")]
EcssTmtc(#[from] EcssTmtcError), EcssTmtc(#[from] EcssTmtcError),
#[error("invalid verification token")] #[error("invalid verification token")]
@ -660,42 +686,107 @@ pub mod std_mod {
} }
} }
/// Base class for handlers which can handle PUS TC packets. Right now, the verification pub trait EcssTcInMemConverter {
/// reporter is constrained to the [StdVerifReporterWithSender] and the service handler fn convert_ecss_tc_in_memory_to_reader<'a>(
/// relies on TMTC packets being exchanged via a [SharedPool]. &'a mut self,
pub struct PusServiceBaseWithStore { possible_packet: &'a AcceptedEcssTcAndToken,
pub tc_receiver: Box<dyn EcssTcReceiver>, ) -> Result<PusTcReader<'a>, PusPacketHandlingError>;
fn tc_slice_raw(&self) -> &[u8];
}
pub struct EcssTcInVecConverter {
pub pus_tc_raw: Option<Vec<u8>>,
}
impl EcssTcInMemConverter for EcssTcInVecConverter {
fn convert_ecss_tc_in_memory_to_reader<'a>(
&'a mut self,
possible_packet: &'a AcceptedEcssTcAndToken,
) -> Result<PusTcReader<'a>, PusPacketHandlingError> {
match &possible_packet.tc_in_memory {
super::TcInMemory::StoreAddr(_) => {
return Err(PusPacketHandlingError::InvalidTcInMemoryFormat(
possible_packet.tc_in_memory.clone(),
));
}
super::TcInMemory::Vec(vec) => {
self.pus_tc_raw = Some(vec.clone());
}
};
let (tc, _) = PusTcReader::new(self.pus_tc_raw.as_ref().unwrap())?;
Ok(tc)
}
fn tc_slice_raw(&self) -> &[u8] {
if self.pus_tc_raw.is_none() {
return &[];
}
self.pus_tc_raw.as_ref().unwrap()
}
}
pub struct EcssTcInStoreConverter {
pub shared_tc_store: SharedPool, pub shared_tc_store: SharedPool,
pub pus_buf: [u8; 2048],
}
impl EcssTcInStoreConverter {
pub fn new(shared_tc_store: SharedPool) -> Self {
Self {
shared_tc_store,
pus_buf: [0; 2048],
}
}
pub fn copy_tc_to_buf(&mut self, addr: StoreAddr) -> Result<(), PusPacketHandlingError> {
// Keep locked section as short as possible.
let mut tc_pool = self
.shared_tc_store
.write()
.map_err(|_| PusPacketHandlingError::EcssTmtc(EcssTmtcError::StoreLock))?;
let tc_guard = tc_pool.read_with_guard(addr);
let tc_raw = tc_guard.read().unwrap();
self.pus_buf[0..tc_raw.len()].copy_from_slice(tc_raw);
Ok(())
}
}
impl EcssTcInMemConverter for EcssTcInStoreConverter {
fn convert_ecss_tc_in_memory_to_reader<'a>(
&'a mut self,
possible_packet: &'a AcceptedEcssTcAndToken,
) -> Result<PusTcReader<'a>, PusPacketHandlingError> {
Ok(match &possible_packet.tc_in_memory {
super::TcInMemory::StoreAddr(addr) => {
self.copy_tc_to_buf(*addr)?;
PusTcReader::new(&self.pus_buf)?.0
}
super::TcInMemory::Vec(_) => {
return Err(PusPacketHandlingError::InvalidTcInMemoryFormat(
possible_packet.tc_in_memory.clone(),
));
}
})
}
fn tc_slice_raw(&self) -> &[u8] {
self.pus_buf.as_ref()
}
}
pub struct PusServiceBase {
pub tc_receiver: Box<dyn EcssTcReceiver>,
pub tm_sender: Box<dyn EcssTmSender>, pub tm_sender: Box<dyn EcssTmSender>,
pub tm_apid: u16, pub tm_apid: u16,
/// The verification handler is wrapped in a [RefCell] to allow the interior mutability /// The verification handler is wrapped in a [RefCell] to allow the interior mutability
/// pattern. This makes writing methods which are not mutable a lot easier. /// pattern. This makes writing methods which are not mutable a lot easier.
pub verification_handler: RefCell<StdVerifReporterWithSender>, pub verification_handler: RefCell<StdVerifReporterWithSender>,
pub pus_buf: [u8; 2048],
pub pus_size: usize,
}
impl PusServiceBaseWithStore {
pub fn new(
tc_receiver: Box<dyn EcssTcReceiver>,
shared_tc_store: SharedPool,
tm_sender: Box<dyn EcssTmSender>,
tm_apid: u16,
verification_handler: StdVerifReporterWithSender,
) -> Self {
Self {
tc_receiver,
shared_tc_store,
tm_apid,
tm_sender,
verification_handler: RefCell::new(verification_handler),
pus_buf: [0; 2048],
pus_size: 0,
}
} }
impl PusServiceBase {
#[cfg(feature = "std")]
pub fn get_current_timestamp( pub fn get_current_timestamp(
&self,
partial_error: &mut Option<PartialPusHandlingError>, partial_error: &mut Option<PartialPusHandlingError>,
) -> [u8; 7] { ) -> [u8; 7] {
let mut time_stamp: [u8; 7] = [0; 7]; let mut time_stamp: [u8; 7] = [0; 7];
@ -710,42 +801,47 @@ pub mod std_mod {
time_stamp time_stamp
} }
pub fn get_current_timestamp_ignore_error(&self) -> [u8; 7] { #[cfg(feature = "std")]
pub fn get_current_timestamp_ignore_error() -> [u8; 7] {
let mut dummy = None; let mut dummy = None;
self.get_current_timestamp(&mut dummy) Self::get_current_timestamp(&mut dummy)
}
} }
pub fn copy_tc_to_buf(&mut self, addr: StoreAddr) -> Result<(), PusPacketHandlingError> { /// Base class for handlers which can handle PUS TC packets. Right now, the verification
// Keep locked section as short as possible. /// reporter is constrained to the [StdVerifReporterWithSender] and the service handler
let mut tc_pool = self /// relies on TMTC packets being exchanged via a [SharedPool]. Please note that this variant
.shared_tc_store /// of the PUS service base is not optimized for handling packets sent as a `Vec<u8>` and
.write() /// might perform additional copies to the internal buffer as well. The class should
.map_err(|_| PusPacketHandlingError::EcssTmtc(EcssTmtcError::StoreLock))?; /// still behave correctly.
let tc_guard = tc_pool.read_with_guard(addr); pub struct PusServiceHandler<TcInMemConverter: EcssTcInMemConverter> {
let tc_raw = tc_guard.read().unwrap(); pub common: PusServiceBase,
self.pus_buf[0..tc_raw.len()].copy_from_slice(tc_raw); pub tc_in_mem_converter: TcInMemConverter,
Ok(())
} }
pub fn convert_possible_packet_to_tc_buf( impl<TcInMemConverter: EcssTcInMemConverter> PusServiceHandler<TcInMemConverter> {
&mut self, pub fn new(
possible_packet: &AcceptedEcssTcAndToken, tc_receiver: Box<dyn EcssTcReceiver>,
) -> Result<(), PusPacketHandlingError> { tm_sender: Box<dyn EcssTmSender>,
match &possible_packet.tc_in_memory { tm_apid: u16,
super::TcInMemory::StoreAddr(addr) => { verification_handler: VerificationReporterWithSender,
self.copy_tc_to_buf(*addr)?; tc_in_mem_converter: TcInMemConverter,
) -> Self {
Self {
common: PusServiceBase {
tc_receiver,
tm_sender,
tm_apid,
verification_handler: RefCell::new(verification_handler),
},
tc_in_mem_converter,
} }
super::TcInMemory::Vec(vec) => {
self.pus_buf.copy_from_slice(vec);
}
};
Ok(())
} }
pub fn retrieve_and_accept_next_packet( pub fn retrieve_and_accept_next_packet(
&mut self, &mut self,
) -> Result<Option<AcceptedEcssTcAndToken>, PusPacketHandlingError> { ) -> Result<Option<AcceptedEcssTcAndToken>, PusPacketHandlingError> {
match self.tc_receiver.recv_tc() { match self.common.tc_receiver.recv_tc() {
Ok(EcssTcAndToken { Ok(EcssTcAndToken {
tc_in_memory, tc_in_memory,
token, token,

View File

@ -1,15 +1,13 @@
use crate::pool::SharedPool; use crate::pool::SharedPool;
use crate::pus::scheduler::PusScheduler; use crate::pus::scheduler::PusScheduler;
use crate::pus::verification::StdVerifReporterWithSender; use crate::pus::verification::StdVerifReporterWithSender;
use crate::pus::{ use crate::pus::{EcssTcReceiver, EcssTmSender, PusPacketHandlerResult, PusPacketHandlingError};
EcssTcReceiver, EcssTmSender, PusPacketHandlerResult, PusPacketHandlingError,
PusServiceBaseWithStore,
};
use spacepackets::ecss::tc::PusTcReader;
use spacepackets::ecss::{scheduling, PusPacket}; use spacepackets::ecss::{scheduling, PusPacket};
use spacepackets::time::cds::TimeProvider; use spacepackets::time::cds::TimeProvider;
use std::boxed::Box; use std::boxed::Box;
use super::{EcssTcInMemConverter, PusServiceBase, PusServiceHandler};
/// This is a helper class for [std] environments to handle generic PUS 11 (scheduling service) /// This is a helper class for [std] environments to handle generic PUS 11 (scheduling service)
/// packets. This handler is constrained to using the [PusScheduler], but is able to process /// packets. This handler is constrained to using the [PusScheduler], but is able to process
/// the most important PUS requests for a scheduling service. /// the most important PUS requests for a scheduling service.
@ -18,28 +16,31 @@ use std::boxed::Box;
/// telecommands inside the scheduler. The user can retrieve the wrapped scheduler via the /// 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 /// [Self::scheduler] and [Self::scheduler_mut] function and then use the scheduler API to release
/// telecommands when applicable. /// telecommands when applicable.
pub struct PusService11SchedHandler { pub struct PusService11SchedHandler<TcInMemConverter: EcssTcInMemConverter> {
psb: PusServiceBaseWithStore, pub psb: PusServiceHandler<TcInMemConverter>,
shared_tc_store: SharedPool,
scheduler: PusScheduler, scheduler: PusScheduler,
} }
impl PusService11SchedHandler { impl<TcInMemConverter: EcssTcInMemConverter> PusService11SchedHandler<TcInMemConverter> {
pub fn new( pub fn new(
tc_receiver: Box<dyn EcssTcReceiver>, tc_receiver: Box<dyn EcssTcReceiver>,
shared_tc_store: SharedPool,
tm_sender: Box<dyn EcssTmSender>, tm_sender: Box<dyn EcssTmSender>,
tm_apid: u16, tm_apid: u16,
verification_handler: StdVerifReporterWithSender, verification_handler: StdVerifReporterWithSender,
tc_in_mem_converter: TcInMemConverter,
shared_tc_store: SharedPool,
scheduler: PusScheduler, scheduler: PusScheduler,
) -> Self { ) -> Self {
Self { Self {
psb: PusServiceBaseWithStore::new( psb: PusServiceHandler::new(
tc_receiver, tc_receiver,
shared_tc_store,
tm_sender, tm_sender,
tm_apid, tm_apid,
verification_handler, verification_handler,
tc_in_mem_converter,
), ),
shared_tc_store,
scheduler, scheduler,
} }
} }
@ -58,7 +59,10 @@ impl PusService11SchedHandler {
return Ok(PusPacketHandlerResult::Empty); return Ok(PusPacketHandlerResult::Empty);
} }
let ecss_tc_and_token = possible_packet.unwrap(); let ecss_tc_and_token = possible_packet.unwrap();
let (tc, _) = PusTcReader::new(&self.psb.pus_buf)?; let tc = self
.psb
.tc_in_mem_converter
.convert_ecss_tc_in_memory_to_reader(&ecss_tc_and_token)?;
let subservice = tc.subservice(); let subservice = tc.subservice();
let std_service = scheduling::Subservice::try_from(subservice); let std_service = scheduling::Subservice::try_from(subservice);
if std_service.is_err() { if std_service.is_err() {
@ -68,11 +72,12 @@ impl PusService11SchedHandler {
)); ));
} }
let mut partial_error = None; let mut partial_error = None;
let time_stamp = self.psb.get_current_timestamp(&mut partial_error); let time_stamp = PusServiceBase::get_current_timestamp(&mut partial_error);
match std_service.unwrap() { match std_service.unwrap() {
scheduling::Subservice::TcEnableScheduling => { scheduling::Subservice::TcEnableScheduling => {
let start_token = self let start_token = self
.psb .psb
.common
.verification_handler .verification_handler
.get_mut() .get_mut()
.start_success(ecss_tc_and_token.token, Some(&time_stamp)) .start_success(ecss_tc_and_token.token, Some(&time_stamp))
@ -81,6 +86,7 @@ impl PusService11SchedHandler {
self.scheduler.enable(); self.scheduler.enable();
if self.scheduler.is_enabled() { if self.scheduler.is_enabled() {
self.psb self.psb
.common
.verification_handler .verification_handler
.get_mut() .get_mut()
.completion_success(start_token, Some(&time_stamp)) .completion_success(start_token, Some(&time_stamp))
@ -92,6 +98,7 @@ impl PusService11SchedHandler {
scheduling::Subservice::TcDisableScheduling => { scheduling::Subservice::TcDisableScheduling => {
let start_token = self let start_token = self
.psb .psb
.common
.verification_handler .verification_handler
.get_mut() .get_mut()
.start_success(ecss_tc_and_token.token, Some(&time_stamp)) .start_success(ecss_tc_and_token.token, Some(&time_stamp))
@ -100,6 +107,7 @@ impl PusService11SchedHandler {
self.scheduler.disable(); self.scheduler.disable();
if !self.scheduler.is_enabled() { if !self.scheduler.is_enabled() {
self.psb self.psb
.common
.verification_handler .verification_handler
.get_mut() .get_mut()
.completion_success(start_token, Some(&time_stamp)) .completion_success(start_token, Some(&time_stamp))
@ -111,22 +119,20 @@ impl PusService11SchedHandler {
scheduling::Subservice::TcResetScheduling => { scheduling::Subservice::TcResetScheduling => {
let start_token = self let start_token = self
.psb .psb
.common
.verification_handler .verification_handler
.get_mut() .get_mut()
.start_success(ecss_tc_and_token.token, Some(&time_stamp)) .start_success(ecss_tc_and_token.token, Some(&time_stamp))
.expect("Error sending start success"); .expect("Error sending start success");
let mut pool = self let mut pool = self.shared_tc_store.write().expect("Locking pool failed");
.psb
.shared_tc_store
.write()
.expect("Locking pool failed");
self.scheduler self.scheduler
.reset(pool.as_mut()) .reset(pool.as_mut())
.expect("Error resetting TC Pool"); .expect("Error resetting TC Pool");
self.psb self.psb
.common
.verification_handler .verification_handler
.get_mut() .get_mut()
.completion_success(start_token, Some(&time_stamp)) .completion_success(start_token, Some(&time_stamp))
@ -135,21 +141,19 @@ impl PusService11SchedHandler {
scheduling::Subservice::TcInsertActivity => { scheduling::Subservice::TcInsertActivity => {
let start_token = self let start_token = self
.psb .psb
.common
.verification_handler .verification_handler
.get_mut() .get_mut()
.start_success(ecss_tc_and_token.token, Some(&time_stamp)) .start_success(ecss_tc_and_token.token, Some(&time_stamp))
.expect("error sending start success"); .expect("error sending start success");
let mut pool = self let mut pool = self.shared_tc_store.write().expect("locking pool failed");
.psb
.shared_tc_store
.write()
.expect("locking pool failed");
self.scheduler self.scheduler
.insert_wrapped_tc::<TimeProvider>(&tc, pool.as_mut()) .insert_wrapped_tc::<TimeProvider>(&tc, pool.as_mut())
.expect("insertion of activity into pool failed"); .expect("insertion of activity into pool failed");
self.psb self.psb
.common
.verification_handler .verification_handler
.get_mut() .get_mut()
.completion_success(start_token, Some(&time_stamp)) .completion_success(start_token, Some(&time_stamp))
@ -159,7 +163,7 @@ impl PusService11SchedHandler {
// Treat unhandled standard subservices as custom subservices for now. // Treat unhandled standard subservices as custom subservices for now.
return Ok(PusPacketHandlerResult::CustomSubservice( return Ok(PusPacketHandlerResult::CustomSubservice(
tc.subservice(), tc.subservice(),
ecss_tc_and_token.token.into(), ecss_tc_and_token.token,
)); ));
} }
} }

View File

@ -1,36 +1,36 @@
use crate::pool::SharedPool;
use crate::pus::verification::StdVerifReporterWithSender;
use crate::pus::{ use crate::pus::{
EcssTcReceiver, EcssTmSender, PartialPusHandlingError, PusPacketHandlerResult, EcssTcReceiver, EcssTmSender, PartialPusHandlingError, PusPacketHandlerResult,
PusPacketHandlingError, PusServiceBaseWithStore, PusTmWrapper, PusPacketHandlingError, PusTmWrapper,
}; };
use spacepackets::ecss::tc::PusTcReader;
use spacepackets::ecss::tm::{PusTmCreator, PusTmSecondaryHeader}; use spacepackets::ecss::tm::{PusTmCreator, PusTmSecondaryHeader};
use spacepackets::ecss::PusPacket; use spacepackets::ecss::PusPacket;
use spacepackets::SpHeader; use spacepackets::SpHeader;
use std::boxed::Box; use std::boxed::Box;
use super::verification::VerificationReporterWithSender;
use super::{EcssTcInMemConverter, PusServiceBase, PusServiceHandler};
/// This is a helper class for [std] environments to handle generic PUS 17 (test service) packets. /// This is a helper class for [std] environments to handle generic PUS 17 (test service) packets.
/// This handler only processes ping requests and generates a ping reply for them accordingly. /// This handler only processes ping requests and generates a ping reply for them accordingly.
pub struct PusService17TestHandler { pub struct PusService17TestHandler<TcInMemConverter: EcssTcInMemConverter> {
pub psb: PusServiceBaseWithStore, pub psb: PusServiceHandler<TcInMemConverter>,
} }
impl PusService17TestHandler { impl<TcInMemConverter: EcssTcInMemConverter> PusService17TestHandler<TcInMemConverter> {
pub fn new( pub fn new(
tc_receiver: Box<dyn EcssTcReceiver>, tc_receiver: Box<dyn EcssTcReceiver>,
shared_tc_store: SharedPool,
tm_sender: Box<dyn EcssTmSender>, tm_sender: Box<dyn EcssTmSender>,
tm_apid: u16, tm_apid: u16,
verification_handler: StdVerifReporterWithSender, verification_handler: VerificationReporterWithSender,
tc_in_mem_converter: TcInMemConverter,
) -> Self { ) -> Self {
Self { Self {
psb: PusServiceBaseWithStore::new( psb: PusServiceHandler::new(
tc_receiver, tc_receiver,
shared_tc_store,
tm_sender, tm_sender,
tm_apid, tm_apid,
verification_handler, verification_handler,
tc_in_mem_converter,
), ),
} }
} }
@ -41,17 +41,19 @@ impl PusService17TestHandler {
return Ok(PusPacketHandlerResult::Empty); return Ok(PusPacketHandlerResult::Empty);
} }
let ecss_tc_and_token = possible_packet.unwrap(); let ecss_tc_and_token = possible_packet.unwrap();
self.psb let tc = self
.convert_possible_packet_to_tc_buf(&ecss_tc_and_token)?; .psb
let (tc, _) = PusTcReader::new(&self.psb.pus_buf)?; .tc_in_mem_converter
.convert_ecss_tc_in_memory_to_reader(&ecss_tc_and_token)?;
if tc.service() != 17 { if tc.service() != 17 {
return Err(PusPacketHandlingError::WrongService(tc.service())); return Err(PusPacketHandlingError::WrongService(tc.service()));
} }
if tc.subservice() == 1 { if tc.subservice() == 1 {
let mut partial_error = None; let mut partial_error = None;
let time_stamp = self.psb.get_current_timestamp(&mut partial_error); let time_stamp = PusServiceBase::get_current_timestamp(&mut partial_error);
let result = self let result = self
.psb .psb
.common
.verification_handler .verification_handler
.get_mut() .get_mut()
.start_success(ecss_tc_and_token.token, Some(&time_stamp)) .start_success(ecss_tc_and_token.token, Some(&time_stamp))
@ -63,11 +65,12 @@ impl PusService17TestHandler {
None None
}; };
// Sequence count will be handled centrally in TM funnel. // Sequence count will be handled centrally in TM funnel.
let mut reply_header = SpHeader::tm_unseg(self.psb.tm_apid, 0, 0).unwrap(); let mut reply_header = SpHeader::tm_unseg(self.psb.common.tm_apid, 0, 0).unwrap();
let tc_header = PusTmSecondaryHeader::new_simple(17, 2, &time_stamp); let tc_header = PusTmSecondaryHeader::new_simple(17, 2, &time_stamp);
let ping_reply = PusTmCreator::new(&mut reply_header, tc_header, &[], true); let ping_reply = PusTmCreator::new(&mut reply_header, tc_header, &[], true);
let result = self let result = self
.psb .psb
.common
.tm_sender .tm_sender
.send_tm(PusTmWrapper::Direct(ping_reply)) .send_tm(PusTmWrapper::Direct(ping_reply))
.map_err(PartialPusHandlingError::TmSend); .map_err(PartialPusHandlingError::TmSend);
@ -78,6 +81,7 @@ impl PusService17TestHandler {
if let Some(start_token) = start_token { if let Some(start_token) = start_token {
if self if self
.psb .psb
.common
.verification_handler .verification_handler
.get_mut() .get_mut()
.completion_success(start_token, Some(&time_stamp)) .completion_success(start_token, Some(&time_stamp))
@ -94,7 +98,7 @@ impl PusService17TestHandler {
} else { } else {
return Ok(PusPacketHandlerResult::CustomSubservice( return Ok(PusPacketHandlerResult::CustomSubservice(
tc.subservice(), tc.subservice(),
ecss_tc_and_token.token.into(), ecss_tc_and_token.token,
)); ));
} }
Ok(PusPacketHandlerResult::RequestHandled) Ok(PusPacketHandlerResult::RequestHandled)
@ -106,9 +110,11 @@ mod tests {
use crate::pool::{LocalPool, PoolCfg, SharedPool}; use crate::pool::{LocalPool, PoolCfg, SharedPool};
use crate::pus::test::PusService17TestHandler; use crate::pus::test::PusService17TestHandler;
use crate::pus::verification::{ use crate::pus::verification::{
RequestId, StdVerifReporterWithSender, VerificationReporterCfg, RequestId, VerificationReporterCfg, VerificationReporterWithSender,
};
use crate::pus::{
EcssTcAndToken, EcssTcInStoreConverter, MpscTcInStoreReceiver, MpscTmInStoreSender,
}; };
use crate::pus::{MpscTcInStoreReceiver, MpscTmInStoreSender};
use crate::tmtc::tm_helper::SharedTmStore; use crate::tmtc::tm_helper::SharedTmStore;
use spacepackets::ecss::tc::{PusTcCreator, PusTcSecondaryHeader}; use spacepackets::ecss::tc::{PusTcCreator, PusTcSecondaryHeader};
use spacepackets::ecss::tm::PusTmReader; use spacepackets::ecss::tm::PusTmReader;
@ -135,15 +141,16 @@ mod tests {
MpscTmInStoreSender::new(0, "verif_sender", shared_tm_store.clone(), tm_tx.clone()); MpscTmInStoreSender::new(0, "verif_sender", shared_tm_store.clone(), tm_tx.clone());
let verif_cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8).unwrap(); let verif_cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8).unwrap();
let mut verification_handler = let mut verification_handler =
StdVerifReporterWithSender::new(&verif_cfg, Box::new(verif_sender)); VerificationReporterWithSender::new(&verif_cfg, Box::new(verif_sender));
let test_srv_tm_sender = MpscTmInStoreSender::new(0, "TEST_SENDER", shared_tm_store, tm_tx); let test_srv_tm_sender = MpscTmInStoreSender::new(0, "TEST_SENDER", shared_tm_store, tm_tx);
let test_srv_tc_receiver = MpscTcInStoreReceiver::new(0, "TEST_RECEIVER", test_srv_tc_rx); let test_srv_tc_receiver = MpscTcInStoreReceiver::new(0, "TEST_RECEIVER", test_srv_tc_rx);
let in_store_converter = EcssTcInStoreConverter::new(tc_pool_shared.clone());
let mut pus_17_handler = PusService17TestHandler::new( let mut pus_17_handler = PusService17TestHandler::new(
Box::new(test_srv_tc_receiver), Box::new(test_srv_tc_receiver),
tc_pool_shared.clone(),
Box::new(test_srv_tm_sender), Box::new(test_srv_tm_sender),
TEST_APID, TEST_APID,
verification_handler.clone(), verification_handler.clone(),
in_store_converter,
); );
// Create a ping TC, verify acceptance. // Create a ping TC, verify acceptance.
let mut sp_header = SpHeader::tc(TEST_APID, SequenceFlags::Unsegmented, 0, 0).unwrap(); let mut sp_header = SpHeader::tc(TEST_APID, SequenceFlags::Unsegmented, 0, 0).unwrap();
@ -158,7 +165,9 @@ mod tests {
let addr = tc_pool.add(&pus_buf[..tc_size]).unwrap(); let addr = tc_pool.add(&pus_buf[..tc_size]).unwrap();
drop(tc_pool); drop(tc_pool);
// Send accepted TC to test service handler. // Send accepted TC to test service handler.
test_srv_tc_tx.send((addr, token.into())).unwrap(); test_srv_tc_tx
.send(EcssTcAndToken::new(addr, token))
.unwrap();
let result = pus_17_handler.handle_one_tc(); let result = pus_17_handler.handle_one_tc();
assert!(result.is_ok()); assert!(result.is_ok());
// We should see 4 replies in the TM queue now: Acceptance TM, Start TM, ping reply and // We should see 4 replies in the TM queue now: Acceptance TM, Start TM, ping reply and

View File

@ -5,8 +5,7 @@ use satrs_core::pus::verification::{
FailParams, StdVerifReporterWithSender, TcStateAccepted, VerificationToken, FailParams, StdVerifReporterWithSender, TcStateAccepted, VerificationToken,
}; };
use satrs_core::pus::{ use satrs_core::pus::{
EcssTcReceiver, EcssTmSender, PusPacketHandlerResult, PusPacketHandlingError, EcssTcReceiver, EcssTmSender, PusPacketHandlerResult, PusPacketHandlingError, PusServiceHandler,
PusServiceBaseWithStore,
}; };
use satrs_core::spacepackets::ecss::tc::PusTcReader; use satrs_core::spacepackets::ecss::tc::PusTcReader;
use satrs_core::spacepackets::ecss::PusPacket; use satrs_core::spacepackets::ecss::PusPacket;
@ -16,7 +15,7 @@ use std::collections::HashMap;
use std::sync::mpsc::Sender; use std::sync::mpsc::Sender;
pub struct PusService8ActionHandler { pub struct PusService8ActionHandler {
psb: PusServiceBaseWithStore, psb: PusServiceHandler,
request_handlers: HashMap<TargetId, Sender<RequestWithToken>>, request_handlers: HashMap<TargetId, Sender<RequestWithToken>>,
} }
@ -26,11 +25,11 @@ impl PusService8ActionHandler {
shared_tc_pool: SharedPool, shared_tc_pool: SharedPool,
tm_sender: Box<dyn EcssTmSender>, tm_sender: Box<dyn EcssTmSender>,
tm_apid: u16, tm_apid: u16,
verification_handler: StdVerifReporterWithSender, verification_handler: VerificationReporterWithSender,
request_handlers: HashMap<TargetId, Sender<RequestWithToken>>, request_handlers: HashMap<TargetId, Sender<RequestWithToken>>,
) -> Self { ) -> Self {
Self { Self {
psb: PusServiceBaseWithStore::new( psb: PusServiceHandler::new(
tc_receiver, tc_receiver,
shared_tc_pool, shared_tc_pool,
tm_sender, tm_sender,

View File

@ -4,8 +4,7 @@ use satrs_core::hk::{CollectionIntervalFactor, HkRequest};
use satrs_core::pool::SharedPool; use satrs_core::pool::SharedPool;
use satrs_core::pus::verification::{FailParams, StdVerifReporterWithSender}; use satrs_core::pus::verification::{FailParams, StdVerifReporterWithSender};
use satrs_core::pus::{ use satrs_core::pus::{
EcssTcReceiver, EcssTmSender, PusPacketHandlerResult, PusPacketHandlingError, EcssTcReceiver, EcssTmSender, PusPacketHandlerResult, PusPacketHandlingError, PusServiceHandler,
PusServiceBaseWithStore,
}; };
use satrs_core::spacepackets::ecss::tc::PusTcReader; use satrs_core::spacepackets::ecss::tc::PusTcReader;
use satrs_core::spacepackets::ecss::{hk, PusPacket}; use satrs_core::spacepackets::ecss::{hk, PusPacket};
@ -15,7 +14,7 @@ use std::collections::HashMap;
use std::sync::mpsc::Sender; use std::sync::mpsc::Sender;
pub struct PusService3HkHandler { pub struct PusService3HkHandler {
psb: PusServiceBaseWithStore, psb: PusServiceHandler,
request_handlers: HashMap<TargetId, Sender<RequestWithToken>>, request_handlers: HashMap<TargetId, Sender<RequestWithToken>>,
} }
@ -29,7 +28,7 @@ impl PusService3HkHandler {
request_handlers: HashMap<TargetId, Sender<RequestWithToken>>, request_handlers: HashMap<TargetId, Sender<RequestWithToken>>,
) -> Self { ) -> Self {
Self { Self {
psb: PusServiceBaseWithStore::new( psb: PusServiceHandler::new(
tc_receiver, tc_receiver,
shared_tc_pool, shared_tc_pool,
tm_sender, tm_sender,