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
19 changed files with 582 additions and 406 deletions

View File

@ -13,4 +13,4 @@ event components recommended by this framework do not really need this service.
The following images shows how the flow of events could look like in a system where components The following images shows how the flow of events could look like in a system where components
can generate events, and where other system components might be interested in those events: can generate events, and where other system components might be interested in those events:
![Event flow](../../images/events/event_man_arch.png) ![Event flow](images/events/event_man_arch.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

View File

@ -1,67 +1,60 @@
use crate::events::EventU32; use crate::events::EventU32;
use crate::pool::{SharedPool, StoreAddr};
use crate::pus::event_man::{EventRequest, EventRequestWithToken}; use crate::pus::event_man::{EventRequest, EventRequestWithToken};
use crate::pus::verification::{ use crate::pus::verification::TcStateToken;
StdVerifReporterWithSender, TcStateAccepted, TcStateToken, VerificationToken,
};
use crate::pus::{ use crate::pus::{
EcssTcReceiver, EcssTmSender, PartialPusHandlingError, PusPacketHandlerResult, EcssTcReceiver, EcssTmSender, PartialPusHandlingError, PusPacketHandlerResult,
PusPacketHandlingError, PusServiceBase, PusServiceHandler, 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::verification::VerificationReporterWithSender;
psb: PusServiceBase, use super::{EcssTcInMemConverter, PusServiceBase, PusServiceHandler};
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: VerificationReporterWithSender,
tc_in_mem_converter: TcInMemConverter,
event_request_tx: Sender<EventRequestWithToken>, event_request_tx: Sender<EventRequestWithToken>,
) -> Self { ) -> Self {
Self { Self {
psb: PusServiceBase::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,
} }
} }
}
impl PusServiceHandler for PusService5EventHandler { pub fn handle_one_tc(&mut self) -> Result<PusPacketHandlerResult, PusPacketHandlingError> {
fn psb_mut(&mut self) -> &mut PusServiceBase { let possible_packet = self.psb.retrieve_and_accept_next_packet()?;
&mut self.psb if possible_packet.is_none() {
return Ok(PusPacketHandlerResult::Empty);
} }
fn psb(&self) -> &PusServiceBase { let ecss_tc_and_token = possible_packet.unwrap();
&self.psb let tc = self
} .psb
.tc_in_mem_converter
fn handle_one_tc( .convert_ecss_tc_in_memory_to_reader(&ecss_tc_and_token)?;
&mut self,
addr: StoreAddr,
token: VerificationToken<TcStateAccepted>,
) -> Result<PusPacketHandlerResult, PusPacketHandlingError> {
self.copy_tc_to_buf(addr)?;
let (tc, _) = PusTcReader::new(&self.psb.pus_buf)?;
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() {
return Ok(PusPacketHandlerResult::CustomSubservice( return Ok(PusPacketHandlerResult::CustomSubservice(
tc.subservice(), tc.subservice(),
token, ecss_tc_and_token.token,
)); ));
} }
let handle_enable_disable_request = |enable: bool, stamp: [u8; 7]| { let handle_enable_disable_request = |enable: bool, stamp: [u8; 7]| {
@ -74,12 +67,13 @@ impl PusServiceHandler for 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(token, Some(&stamp)) .start_success(ecss_tc_and_token.token, Some(&stamp))
.map_err(|_| PartialPusHandlingError::Verification); .map_err(|_| PartialPusHandlingError::Verification);
let partial_error = start_token.clone().err(); 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 { if let Ok(start_token) = start_token {
token = start_token.into(); token = start_token.into();
} }
@ -107,7 +101,7 @@ impl PusServiceHandler for 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
@ -123,7 +117,8 @@ impl PusServiceHandler for PusService5EventHandler {
} }
Subservice::TcReportDisabledList | Subservice::TmDisabledEventsReport => { Subservice::TcReportDisabledList | Subservice::TmDisabledEventsReport => {
return Ok(PusPacketHandlerResult::SubserviceNotImplemented( 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. /// Generic error type for sending something via a message queue.
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub enum GenericSendError { pub enum GenericSendError {
@ -200,11 +194,71 @@ pub trait EcssTcSenderCore: EcssChannel {
fn send_tc(&self, tc: PusTcCreator, token: Option<TcStateToken>) -> Result<(), EcssTmtcError>; fn send_tc(&self, tc: PusTcCreator, token: Option<TcStateToken>) -> Result<(), EcssTmtcError>;
} }
pub struct ReceivedTcWrapper { #[non_exhaustive]
pub store_addr: StoreAddr, #[derive(Debug, Clone, PartialEq, Eq)]
pub enum TcInMemory {
StoreAddr(StoreAddr),
#[cfg(feature = "alloc")]
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)]
pub struct EcssTcAndToken {
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.
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)] #[derive(Debug, Clone)]
pub enum TryRecvTmtcError { pub enum TryRecvTmtcError {
Error(EcssTmtcError), Error(EcssTmtcError),
@ -231,7 +285,7 @@ impl From<StoreError> for TryRecvTmtcError {
/// Generic trait for a user supplied receiver object. /// Generic trait for a user supplied receiver object.
pub trait EcssTcReceiverCore: EcssChannel { 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 /// Generic trait for objects which can receive ECSS PUS telecommands. This trait is
@ -315,15 +369,16 @@ pub mod std_mod {
StdVerifReporterWithSender, TcStateAccepted, VerificationToken, StdVerifReporterWithSender, TcStateAccepted, VerificationToken,
}; };
use crate::pus::{ use crate::pus::{
EcssChannel, EcssTcReceiver, EcssTcReceiverCore, EcssTmSender, EcssTmSenderCore, EcssChannel, EcssTcAndToken, EcssTcReceiver, EcssTcReceiverCore, EcssTmSender,
EcssTmtcError, GenericRecvError, GenericSendError, PusTmWrapper, ReceivedTcWrapper, EcssTmSenderCore, EcssTmtcError, GenericRecvError, GenericSendError, PusTmWrapper,
TcAddrWithToken, TryRecvTmtcError, TryRecvTmtcError,
}; };
use crate::tmtc::tm_helper::SharedTmStore; use crate::tmtc::tm_helper::SharedTmStore;
use crate::ChannelId; use crate::ChannelId;
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;
@ -335,6 +390,9 @@ pub mod std_mod {
use std::sync::mpsc::TryRecvError; use std::sync::mpsc::TryRecvError;
use thiserror::Error; use thiserror::Error;
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 {
Self::Send(GenericSendError::RxDisconnected) Self::Send(GenericSendError::RxDisconnected)
@ -414,7 +472,7 @@ pub mod std_mod {
pub struct MpscTcInStoreReceiver { pub struct MpscTcInStoreReceiver {
id: ChannelId, id: ChannelId,
name: &'static str, name: &'static str,
receiver: mpsc::Receiver<TcAddrWithToken>, receiver: mpsc::Receiver<EcssTcAndToken>,
} }
impl EcssChannel for MpscTcInStoreReceiver { impl EcssChannel for MpscTcInStoreReceiver {
@ -428,16 +486,12 @@ pub mod std_mod {
} }
impl EcssTcReceiverCore for MpscTcInStoreReceiver { impl EcssTcReceiverCore for MpscTcInStoreReceiver {
fn recv_tc(&self) -> Result<ReceivedTcWrapper, TryRecvTmtcError> { fn recv_tc(&self) -> Result<EcssTcAndToken, TryRecvTmtcError> {
let (store_addr, token) = 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::Error(EcssTmtcError::from(GenericRecvError::TxDisconnected)) TryRecvTmtcError::Error(EcssTmtcError::from(GenericRecvError::TxDisconnected))
} }
})?;
Ok(ReceivedTcWrapper {
store_addr,
token: Some(token),
}) })
} }
} }
@ -446,7 +500,7 @@ pub mod std_mod {
pub fn new( pub fn new(
id: ChannelId, id: ChannelId,
name: &'static str, name: &'static str,
receiver: mpsc::Receiver<TcAddrWithToken>, receiver: mpsc::Receiver<EcssTcAndToken>,
) -> Self { ) -> Self {
Self { id, name, receiver } Self { id, name, receiver }
} }
@ -548,14 +602,14 @@ pub mod std_mod {
pub struct CrossbeamTcInStoreReceiver { pub struct CrossbeamTcInStoreReceiver {
id: ChannelId, id: ChannelId,
name: &'static str, name: &'static str,
receiver: cb::Receiver<TcAddrWithToken>, receiver: cb::Receiver<EcssTcAndToken>,
} }
impl CrossbeamTcInStoreReceiver { impl CrossbeamTcInStoreReceiver {
pub fn new( pub fn new(
id: ChannelId, id: ChannelId,
name: &'static str, name: &'static str,
receiver: cb::Receiver<TcAddrWithToken>, receiver: cb::Receiver<EcssTcAndToken>,
) -> Self { ) -> Self {
Self { id, name, receiver } Self { id, name, receiver }
} }
@ -572,16 +626,12 @@ pub mod std_mod {
} }
impl EcssTcReceiverCore for CrossbeamTcInStoreReceiver { impl EcssTcReceiverCore for CrossbeamTcInStoreReceiver {
fn recv_tc(&self) -> Result<ReceivedTcWrapper, TryRecvTmtcError> { fn recv_tc(&self) -> Result<EcssTcAndToken, TryRecvTmtcError> {
let (store_addr, token) = 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 => { cb::TryRecvError::Disconnected => {
TryRecvTmtcError::Error(EcssTmtcError::from(GenericRecvError::TxDisconnected)) TryRecvTmtcError::Error(EcssTmtcError::from(GenericRecvError::TxDisconnected))
} }
})?;
Ok(ReceivedTcWrapper {
store_addr,
token: Some(token),
}) })
} }
} }
@ -596,8 +646,12 @@ pub mod std_mod {
InvalidSubservice(u8), InvalidSubservice(u8),
#[error("not enough application data available: {0}")] #[error("not enough application data available: {0}")]
NotEnoughAppData(String), NotEnoughAppData(String),
#[error("PUS packet too large, does not fit in buffer: {0}")]
PusPacketTooLarge(usize),
#[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")]
@ -634,42 +688,118 @@ 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 cache_ecss_tc_in_memory<'a>(
/// relies on TMTC packets being exchanged via a [SharedPool]. &'a mut self,
possible_packet: &'a AcceptedEcssTcAndToken,
) -> Result<(), PusPacketHandlingError>;
fn tc_slice_raw(&self) -> &[u8];
fn convert_ecss_tc_in_memory_to_reader<'a>(
&'a mut self,
possible_packet: &'a AcceptedEcssTcAndToken,
) -> Result<PusTcReader<'a>, PusPacketHandlingError> {
self.cache_ecss_tc_in_memory(possible_packet)?;
Ok(PusTcReader::new(self.tc_slice_raw())?.0)
}
}
pub struct EcssTcInVecConverter {
pub pus_tc_raw: Option<Vec<u8>>,
}
impl EcssTcInMemConverter for EcssTcInVecConverter {
fn cache_ecss_tc_in_memory<'a>(
&'a mut self,
possible_packet: &'a AcceptedEcssTcAndToken,
) -> Result<(), PusPacketHandlingError> {
self.pus_tc_raw = None;
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());
}
};
Ok(())
}
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 pus_buf: Vec<u8>,
}
impl EcssTcInStoreConverter {
pub fn new(shared_tc_store: SharedPool, max_expected_tc_size: usize) -> Self {
Self {
shared_tc_store,
pus_buf: alloc::vec![0; max_expected_tc_size],
}
}
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();
if tc_raw.len() > self.pus_buf.len() {
return Err(PusPacketHandlingError::PusPacketTooLarge(tc_raw.len()));
}
self.pus_buf[0..tc_raw.len()].copy_from_slice(tc_raw);
Ok(())
}
}
impl EcssTcInMemConverter for EcssTcInStoreConverter {
fn cache_ecss_tc_in_memory<'a>(
&'a mut self,
possible_packet: &'a AcceptedEcssTcAndToken,
) -> Result<(), PusPacketHandlingError> {
match &possible_packet.tc_in_memory {
super::TcInMemory::StoreAddr(addr) => {
self.copy_tc_to_buf(*addr)?;
}
super::TcInMemory::Vec(_) => {
return Err(PusPacketHandlingError::InvalidTcInMemoryFormat(
possible_packet.tc_in_memory.clone(),
));
}
};
Ok(())
}
fn tc_slice_raw(&self) -> &[u8] {
self.pus_buf.as_ref()
}
}
pub struct PusServiceBase { pub struct PusServiceBase {
pub tc_receiver: Box<dyn EcssTcReceiver>, pub tc_receiver: Box<dyn EcssTcReceiver>,
pub shared_tc_store: SharedPool,
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 PusServiceBase { impl PusServiceBase {
pub fn new( #[cfg(feature = "std")]
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,
}
}
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];
@ -684,48 +814,65 @@ 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 trait PusServiceHandler { /// Base class for handlers which can handle PUS TC packets. Right now, the verification
fn psb_mut(&mut self) -> &mut PusServiceBase; /// reporter is constrained to the [StdVerifReporterWithSender] and the service handler
fn psb(&self) -> &PusServiceBase; /// relies on TMTC packets being exchanged via a [SharedPool]. Please note that this variant
fn handle_one_tc( /// of the PUS service base is not optimized for handling packets sent as a `Vec<u8>` and
/// might perform additional copies to the internal buffer as well. The class should
/// still behave correctly.
pub struct PusServiceHandler<TcInMemConverter: EcssTcInMemConverter> {
pub common: PusServiceBase,
pub tc_in_mem_converter: TcInMemConverter,
}
impl<TcInMemConverter: EcssTcInMemConverter> PusServiceHandler<TcInMemConverter> {
pub fn new(
tc_receiver: Box<dyn EcssTcReceiver>,
tm_sender: Box<dyn EcssTmSender>,
tm_apid: u16,
verification_handler: VerificationReporterWithSender,
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,
}
}
pub fn retrieve_and_accept_next_packet(
&mut self, &mut self,
addr: StoreAddr, ) -> Result<Option<AcceptedEcssTcAndToken>, PusPacketHandlingError> {
token: VerificationToken<TcStateAccepted>, match self.common.tc_receiver.recv_tc() {
) -> Result<PusPacketHandlerResult, PusPacketHandlingError>; Ok(EcssTcAndToken {
tc_in_memory,
fn copy_tc_to_buf(&mut self, addr: StoreAddr) -> Result<(), PusPacketHandlingError> { token,
// Keep locked section as short as possible. }) => {
let psb_mut = self.psb_mut();
let mut tc_pool = psb_mut
.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();
psb_mut.pus_buf[0..tc_raw.len()].copy_from_slice(tc_raw);
Ok(())
}
fn handle_next_packet(&mut self) -> Result<PusPacketHandlerResult, PusPacketHandlingError> {
match self.psb().tc_receiver.recv_tc() {
Ok(ReceivedTcWrapper { store_addr, token }) => {
if token.is_none() { if token.is_none() {
return Err(PusPacketHandlingError::InvalidVerificationToken); return Err(PusPacketHandlingError::InvalidVerificationToken);
} }
let token = token.unwrap(); let token = token.unwrap();
let accepted_token = VerificationToken::<TcStateAccepted>::try_from(token) let accepted_token = VerificationToken::<TcStateAccepted>::try_from(token)
.map_err(|_| PusPacketHandlingError::InvalidVerificationToken)?; .map_err(|_| PusPacketHandlingError::InvalidVerificationToken)?;
self.handle_one_tc(store_addr, accepted_token) Ok(Some(AcceptedEcssTcAndToken {
tc_in_memory,
token: accepted_token,
}))
} }
Err(e) => match e { Err(e) => match e {
TryRecvTmtcError::Error(e) => Err(PusPacketHandlingError::EcssTmtc(e)), TryRecvTmtcError::Error(e) => Err(PusPacketHandlingError::EcssTmtc(e)),
TryRecvTmtcError::Empty => Ok(PusPacketHandlerResult::Empty), TryRecvTmtcError::Empty => Ok(None),
}, },
} }
} }

View File

@ -1,15 +1,13 @@
use crate::pool::{SharedPool, StoreAddr}; use crate::pool::SharedPool;
use crate::pus::scheduler::PusScheduler; use crate::pus::scheduler::PusScheduler;
use crate::pus::verification::{StdVerifReporterWithSender, TcStateAccepted, VerificationToken}; use crate::pus::{EcssTcReceiver, EcssTmSender, PusPacketHandlerResult, PusPacketHandlingError};
use crate::pus::{
EcssTcReceiver, EcssTmSender, PusPacketHandlerResult, PusPacketHandlingError, PusServiceBase,
PusServiceHandler,
};
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::verification::VerificationReporterWithSender;
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: PusServiceBase, 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: VerificationReporterWithSender,
tc_in_mem_converter: TcInMemConverter,
shared_tc_store: SharedPool,
scheduler: PusScheduler, scheduler: PusScheduler,
) -> Self { ) -> Self {
Self { Self {
psb: PusServiceBase::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,
} }
} }
@ -51,45 +52,41 @@ impl PusService11SchedHandler {
pub fn scheduler(&self) -> &PusScheduler { pub fn scheduler(&self) -> &PusScheduler {
&self.scheduler &self.scheduler
} }
}
impl PusServiceHandler for PusService11SchedHandler { pub fn handle_one_tc(&mut self) -> Result<PusPacketHandlerResult, PusPacketHandlingError> {
fn psb_mut(&mut self) -> &mut PusServiceBase { let possible_packet = self.psb.retrieve_and_accept_next_packet()?;
&mut self.psb if possible_packet.is_none() {
return Ok(PusPacketHandlerResult::Empty);
} }
fn psb(&self) -> &PusServiceBase { let ecss_tc_and_token = possible_packet.unwrap();
&self.psb let tc = self
} .psb
.tc_in_mem_converter
fn handle_one_tc( .convert_ecss_tc_in_memory_to_reader(&ecss_tc_and_token)?;
&mut self,
addr: StoreAddr,
token: VerificationToken<TcStateAccepted>,
) -> Result<PusPacketHandlerResult, PusPacketHandlingError> {
self.copy_tc_to_buf(addr)?;
let (tc, _) = PusTcReader::new(&self.psb.pus_buf)?;
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() {
return Ok(PusPacketHandlerResult::CustomSubservice( return Ok(PusPacketHandlerResult::CustomSubservice(
tc.subservice(), tc.subservice(),
token, ecss_tc_and_token.token,
)); ));
} }
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(token, Some(&time_stamp)) .start_success(ecss_tc_and_token.token, Some(&time_stamp))
.expect("Error sending start success"); .expect("Error sending start success");
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))
@ -101,14 +98,16 @@ impl PusServiceHandler for 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(token, Some(&time_stamp)) .start_success(ecss_tc_and_token.token, Some(&time_stamp))
.expect("Error sending start success"); .expect("Error sending start success");
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))
@ -120,22 +119,20 @@ impl PusServiceHandler for 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(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))
@ -144,30 +141,29 @@ impl PusServiceHandler for 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(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))
.expect("sending completion success failed"); .expect("sending completion success failed");
} }
_ => { _ => {
// Treat unhandled standard subservices as custom subservices for now.
return Ok(PusPacketHandlerResult::CustomSubservice( return Ok(PusPacketHandlerResult::CustomSubservice(
tc.subservice(), tc.subservice(),
token, ecss_tc_and_token.token,
)); ));
} }
} }
@ -176,9 +172,6 @@ impl PusServiceHandler for PusService11SchedHandler {
partial_error, partial_error,
)); ));
} }
Ok(PusPacketHandlerResult::CustomSubservice( Ok(PusPacketHandlerResult::RequestHandled)
tc.subservice(),
token,
))
} }
} }

View File

@ -1,67 +1,62 @@
use crate::pool::{SharedPool, StoreAddr};
use crate::pus::verification::{StdVerifReporterWithSender, TcStateAccepted, VerificationToken};
use crate::pus::{ use crate::pus::{
EcssTcReceiver, EcssTmSender, PartialPusHandlingError, PusPacketHandlerResult, EcssTcReceiver, EcssTmSender, PartialPusHandlingError, PusPacketHandlerResult,
PusPacketHandlingError, PusServiceBase, PusServiceHandler, 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> {
psb: PusServiceBase, 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: PusServiceBase::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,
), ),
} }
} }
}
impl PusServiceHandler for PusService17TestHandler { pub fn handle_one_tc(&mut self) -> Result<PusPacketHandlerResult, PusPacketHandlingError> {
fn psb_mut(&mut self) -> &mut PusServiceBase { let possible_packet = self.psb.retrieve_and_accept_next_packet()?;
&mut self.psb if possible_packet.is_none() {
return Ok(PusPacketHandlerResult::Empty);
} }
fn psb(&self) -> &PusServiceBase { let ecss_tc_and_token = possible_packet.unwrap();
&self.psb let tc = self
} .psb
.tc_in_mem_converter
fn handle_one_tc( .convert_ecss_tc_in_memory_to_reader(&ecss_tc_and_token)?;
&mut self,
addr: StoreAddr,
token: VerificationToken<TcStateAccepted>,
) -> Result<PusPacketHandlerResult, PusPacketHandlingError> {
self.copy_tc_to_buf(addr)?;
let (tc, _) = PusTcReader::new(&self.psb.pus_buf)?;
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(token, Some(&time_stamp)) .start_success(ecss_tc_and_token.token, Some(&time_stamp))
.map_err(|_| PartialPusHandlingError::Verification); .map_err(|_| PartialPusHandlingError::Verification);
let start_token = if let Ok(result) = result { let start_token = if let Ok(result) = result {
Some(result) Some(result)
@ -70,11 +65,12 @@ impl PusServiceHandler for 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);
@ -85,6 +81,7 @@ impl PusServiceHandler for 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))
@ -98,12 +95,13 @@ impl PusServiceHandler for PusService17TestHandler {
partial_error, partial_error,
)); ));
}; };
return Ok(PusPacketHandlerResult::RequestHandled); } else {
} return Ok(PusPacketHandlerResult::CustomSubservice(
Ok(PusPacketHandlerResult::CustomSubservice(
tc.subservice(), tc.subservice(),
token, ecss_tc_and_token.token,
)) ));
}
Ok(PusPacketHandlerResult::RequestHandled)
} }
} }
@ -112,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, PusServiceHandler};
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;
@ -141,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(), 2048);
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();
@ -164,8 +165,10 @@ 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
let result = pus_17_handler.handle_next_packet(); .send(EcssTcAndToken::new(addr, token))
.unwrap();
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
// Completion TM // Completion TM
@ -174,7 +177,7 @@ mod tests {
let mut tm_addr = next_msg.unwrap(); let mut tm_addr = next_msg.unwrap();
let tm_pool = tm_pool_shared.read().unwrap(); let tm_pool = tm_pool_shared.read().unwrap();
let tm_raw = tm_pool.read(&tm_addr).unwrap(); let tm_raw = tm_pool.read(&tm_addr).unwrap();
let (tm, _) = PusTmReader::new(&tm_raw, 0).unwrap(); let (tm, _) = PusTmReader::new(tm_raw, 0).unwrap();
assert_eq!(tm.service(), 1); assert_eq!(tm.service(), 1);
assert_eq!(tm.subservice(), 1); assert_eq!(tm.subservice(), 1);
let req_id = RequestId::from_bytes(tm.user_data()).expect("generating request ID failed"); let req_id = RequestId::from_bytes(tm.user_data()).expect("generating request ID failed");
@ -186,7 +189,7 @@ mod tests {
tm_addr = next_msg.unwrap(); tm_addr = next_msg.unwrap();
let tm_raw = tm_pool.read(&tm_addr).unwrap(); let tm_raw = tm_pool.read(&tm_addr).unwrap();
// Is generated with CDS short timestamp. // Is generated with CDS short timestamp.
let (tm, _) = PusTmReader::new(&tm_raw, 7).unwrap(); let (tm, _) = PusTmReader::new(tm_raw, 7).unwrap();
assert_eq!(tm.service(), 1); assert_eq!(tm.service(), 1);
assert_eq!(tm.subservice(), 3); assert_eq!(tm.subservice(), 3);
let req_id = RequestId::from_bytes(tm.user_data()).expect("generating request ID failed"); let req_id = RequestId::from_bytes(tm.user_data()).expect("generating request ID failed");
@ -198,7 +201,7 @@ mod tests {
tm_addr = next_msg.unwrap(); tm_addr = next_msg.unwrap();
let tm_raw = tm_pool.read(&tm_addr).unwrap(); let tm_raw = tm_pool.read(&tm_addr).unwrap();
// Is generated with CDS short timestamp. // Is generated with CDS short timestamp.
let (tm, _) = PusTmReader::new(&tm_raw, 7).unwrap(); let (tm, _) = PusTmReader::new(tm_raw, 7).unwrap();
assert_eq!(tm.service(), 17); assert_eq!(tm.service(), 17);
assert_eq!(tm.subservice(), 2); assert_eq!(tm.subservice(), 2);
assert!(tm.user_data().is_empty()); assert!(tm.user_data().is_empty());
@ -209,7 +212,7 @@ mod tests {
tm_addr = next_msg.unwrap(); tm_addr = next_msg.unwrap();
let tm_raw = tm_pool.read(&tm_addr).unwrap(); let tm_raw = tm_pool.read(&tm_addr).unwrap();
// Is generated with CDS short timestamp. // Is generated with CDS short timestamp.
let (tm, _) = PusTmReader::new(&tm_raw, 7).unwrap(); let (tm, _) = PusTmReader::new(tm_raw, 7).unwrap();
assert_eq!(tm.service(), 1); assert_eq!(tm.service(), 1);
assert_eq!(tm.subservice(), 7); assert_eq!(tm.subservice(), 7);
let req_id = RequestId::from_bytes(tm.user_data()).expect("generating request ID failed"); let req_id = RequestId::from_bytes(tm.user_data()).expect("generating request ID failed");

View File

@ -6,3 +6,4 @@ __pycache__
!/.idea/runConfigurations !/.idea/runConfigurations
/seqcnt.txt /seqcnt.txt
/.tmtc-history.txt

View File

@ -44,10 +44,6 @@ class AcsHkIds(enum.IntEnum):
MGM_SET = 1 MGM_SET = 1
class HkOpCodes:
GENERATE_ONE_SHOT = ["0", "oneshot"]
def make_addressable_id(target_id: int, unique_id: int) -> bytes: def make_addressable_id(target_id: int, unique_id: int) -> bytes:
byte_string = bytearray(struct.pack("!I", target_id)) byte_string = bytearray(struct.pack("!I", target_id))
byte_string.extend(struct.pack("!I", unique_id)) byte_string.extend(struct.pack("!I", unique_id))

View File

@ -4,6 +4,8 @@ import logging
import sys import sys
import time import time
from typing import Optional from typing import Optional
from prompt_toolkit.history import History
from prompt_toolkit.history import FileHistory
import tmtccmd import tmtccmd
from spacepackets.ecss import PusTelemetry, PusVerificator from spacepackets.ecss import PusTelemetry, PusVerificator
@ -11,16 +13,16 @@ from spacepackets.ecss.pus_17_test import Service17Tm
from spacepackets.ecss.pus_1_verification import UnpackParams, Service1Tm from spacepackets.ecss.pus_1_verification import UnpackParams, Service1Tm
from spacepackets.ccsds.time import CdsShortTimestamp from spacepackets.ccsds.time import CdsShortTimestamp
from tmtccmd import CcsdsTmtcBackend, TcHandlerBase, ProcedureParamsWrapper from tmtccmd import TcHandlerBase, ProcedureParamsWrapper
from tmtccmd.core.base import BackendRequest from tmtccmd.core.base import BackendRequest
from tmtccmd.pus import VerificationWrapper from tmtccmd.pus import VerificationWrapper
from tmtccmd.tmtc import CcsdsTmHandler, SpecificApidHandlerBase from tmtccmd.tmtc import CcsdsTmHandler, SpecificApidHandlerBase
from tmtccmd.com import ComInterface from tmtccmd.com import ComInterface
from tmtccmd.config import ( from tmtccmd.config import (
CmdTreeNode,
default_json_path, default_json_path,
SetupParams, SetupParams,
HookBase, HookBase,
TmtcDefinitionWrapper,
params_to_procedure_conversion, params_to_procedure_conversion,
) )
from tmtccmd.config import PreArgsParsingWrapper, SetupWrapper from tmtccmd.config import PreArgsParsingWrapper, SetupWrapper
@ -39,12 +41,11 @@ from tmtccmd.tmtc import (
DefaultPusQueueHelper, DefaultPusQueueHelper,
QueueWrapper, QueueWrapper,
) )
from tmtccmd.util import FileSeqCountProvider, PusFileSeqCountProvider from spacepackets.seqcount import FileSeqCountProvider, PusFileSeqCountProvider
from tmtccmd.util.obj_id import ObjectIdDictT from tmtccmd.util.obj_id import ObjectIdDictT
import pus_tc import pus_tc
import tc_definitions
from common import EXAMPLE_PUS_APID, TM_PACKET_IDS, EventU32 from common import EXAMPLE_PUS_APID, TM_PACKET_IDS, EventU32
_LOGGER = logging.getLogger() _LOGGER = logging.getLogger()
@ -54,25 +55,29 @@ class SatRsConfigHook(HookBase):
def __init__(self, json_cfg_path: str): def __init__(self, json_cfg_path: str):
super().__init__(json_cfg_path=json_cfg_path) super().__init__(json_cfg_path=json_cfg_path)
def assign_communication_interface(self, com_if_key: str) -> Optional[ComInterface]: def get_communication_interface(self, com_if_key: str) -> Optional[ComInterface]:
from tmtccmd.config.com import ( from tmtccmd.config.com import (
create_com_interface_default, create_com_interface_default,
create_com_interface_cfg_default, create_com_interface_cfg_default,
) )
assert self.cfg_path is not None
cfg = create_com_interface_cfg_default( cfg = create_com_interface_cfg_default(
com_if_key=com_if_key, com_if_key=com_if_key,
json_cfg_path=self.cfg_path, json_cfg_path=self.cfg_path,
space_packet_ids=TM_PACKET_IDS, space_packet_ids=TM_PACKET_IDS,
) )
assert cfg is not None
return create_com_interface_default(cfg) return create_com_interface_default(cfg)
def get_tmtc_definitions(self) -> TmtcDefinitionWrapper: def get_command_definitions(self) -> CmdTreeNode:
return tc_definitions.tc_definitions() """This function should return the root node of the command definition tree."""
return pus_tc.create_cmd_definition_tree()
def perform_mode_operation(self, tmtc_backend: CcsdsTmtcBackend, mode: int): def get_cmd_history(self) -> Optional[History]:
_LOGGER.info("Mode operation hook was called") """Optionlly return a history class for the past command paths which will be used
pass when prompting a command path from the user in CLI mode."""
return FileHistory(".tmtc-history.txt")
def get_object_ids(self) -> ObjectIdDictT: def get_object_ids(self) -> ObjectIdDictT:
from tmtccmd.config.objects import get_core_object_ids from tmtccmd.config.objects import get_core_object_ids
@ -94,15 +99,12 @@ class PusHandler(SpecificApidHandlerBase):
def handle_tm(self, packet: bytes, _user_args: any): def handle_tm(self, packet: bytes, _user_args: any):
try: try:
tm_packet = PusTelemetry.unpack( pus_tm = PusTelemetry.unpack(packet, time_reader=CdsShortTimestamp.empty())
packet, time_reader=CdsShortTimestamp.empty()
)
except ValueError as e: except ValueError as e:
_LOGGER.warning("Could not generate PUS TM object from raw data") _LOGGER.warning("Could not generate PUS TM object from raw data")
_LOGGER.warning(f"Raw Packet: [{packet.hex(sep=',')}], REPR: {packet!r}") _LOGGER.warning(f"Raw Packet: [{packet.hex(sep=',')}], REPR: {packet!r}")
raise e raise e
service = tm_packet.service service = pus_tm.service
dedicated_handler = False
if service == 1: if service == 1:
tm_packet = Service1Tm.unpack( tm_packet = Service1Tm.unpack(
data=packet, params=UnpackParams(CdsShortTimestamp.empty(), 1, 2) data=packet, params=UnpackParams(CdsShortTimestamp.empty(), 1, 2)
@ -119,8 +121,7 @@ class PusHandler(SpecificApidHandlerBase):
else: else:
self.verif_wrapper.log_to_console(tm_packet, res) self.verif_wrapper.log_to_console(tm_packet, res)
self.verif_wrapper.log_to_file(tm_packet, res) self.verif_wrapper.log_to_file(tm_packet, res)
dedicated_handler = True elif service == 3:
if service == 3:
_LOGGER.info("No handling for HK packets implemented") _LOGGER.info("No handling for HK packets implemented")
_LOGGER.info(f"Raw packet: 0x[{packet.hex(sep=',')}]") _LOGGER.info(f"Raw packet: 0x[{packet.hex(sep=',')}]")
pus_tm = PusTelemetry.unpack(packet, time_reader=CdsShortTimestamp.empty()) pus_tm = PusTelemetry.unpack(packet, time_reader=CdsShortTimestamp.empty())
@ -129,8 +130,7 @@ class PusHandler(SpecificApidHandlerBase):
raise ValueError("No addressable ID in HK packet") raise ValueError("No addressable ID in HK packet")
json_str = pus_tm.source_data[8:] json_str = pus_tm.source_data[8:]
_LOGGER.info(json_str) _LOGGER.info(json_str)
dedicated_handler = True elif service == 5:
if service == 5:
tm_packet = PusTelemetry.unpack( tm_packet = PusTelemetry.unpack(
packet, time_reader=CdsShortTimestamp.empty() packet, time_reader=CdsShortTimestamp.empty()
) )
@ -139,11 +139,10 @@ class PusHandler(SpecificApidHandlerBase):
_LOGGER.info(f"Received event packet. Event: {event_u32}") _LOGGER.info(f"Received event packet. Event: {event_u32}")
if event_u32.group_id == 0 and event_u32.unique_id == 0: if event_u32.group_id == 0 and event_u32.unique_id == 0:
_LOGGER.info("Received test event") _LOGGER.info("Received test event")
if service == 17: elif service == 17:
tm_packet = Service17Tm.unpack( tm_packet = Service17Tm.unpack(
packet, time_reader=CdsShortTimestamp.empty() packet, time_reader=CdsShortTimestamp.empty()
) )
dedicated_handler = True
if tm_packet.subservice == 2: if tm_packet.subservice == 2:
self.file_logger.info("Received Ping Reply TM[17,2]") self.file_logger.info("Received Ping Reply TM[17,2]")
_LOGGER.info("Received Ping Reply TM[17,2]") _LOGGER.info("Received Ping Reply TM[17,2]")
@ -154,17 +153,14 @@ class PusHandler(SpecificApidHandlerBase):
_LOGGER.info( _LOGGER.info(
f"Received Test Packet with unknown subservice {tm_packet.subservice}" f"Received Test Packet with unknown subservice {tm_packet.subservice}"
) )
if tm_packet is None: else:
_LOGGER.info( _LOGGER.info(
f"The service {service} is not implemented in Telemetry Factory" f"The service {service} is not implemented in Telemetry Factory"
) )
tm_packet = PusTelemetry.unpack( tm_packet = PusTelemetry.unpack(
packet, time_reader=CdsShortTimestamp.empty() packet, time_reader=CdsShortTimestamp.empty()
) )
self.raw_logger.log_tm(tm_packet) self.raw_logger.log_tm(pus_tm)
if not dedicated_handler and tm_packet is not None:
pass
# self.printer.handle_long_tm_print(packet_if=tm_packet, info_if=tm_packet)
class TcHandler(TcHandlerBase): class TcHandler(TcHandlerBase):
@ -196,22 +192,18 @@ class TcHandler(TcHandlerBase):
log_entry = entry_helper.to_log_entry() log_entry = entry_helper.to_log_entry()
_LOGGER.info(log_entry.log_str) _LOGGER.info(log_entry.log_str)
def queue_finished_cb(self, helper: ProcedureWrapper): def queue_finished_cb(self, info: ProcedureWrapper):
if helper.proc_type == TcProcedureType.DEFAULT: if info.proc_type == TcProcedureType.DEFAULT:
def_proc = helper.to_def_procedure() def_proc = info.to_def_procedure()
_LOGGER.info( _LOGGER.info(f"Queue handling finished for command {def_proc.cmd_path}")
f"Queue handling finished for service {def_proc.service} and "
f"op code {def_proc.op_code}"
)
def feed_cb(self, helper: ProcedureWrapper, wrapper: FeedWrapper): def feed_cb(self, info: ProcedureWrapper, wrapper: FeedWrapper):
q = self.queue_helper q = self.queue_helper
q.queue_wrapper = wrapper.queue_wrapper q.queue_wrapper = wrapper.queue_wrapper
if helper.proc_type == TcProcedureType.DEFAULT: if info.proc_type == TcProcedureType.DEFAULT:
def_proc = helper.to_def_procedure() def_proc = info.to_def_procedure()
service = def_proc.service assert def_proc.cmd_path is not None
op_code = def_proc.op_code pus_tc.pack_pus_telecommands(q, def_proc.cmd_path)
pus_tc.pack_pus_telecommands(q, service, op_code)
def main(): def main():

View File

@ -1,33 +1,66 @@
import datetime import datetime
import logging
from spacepackets.ccsds import CdsShortTimestamp from spacepackets.ccsds import CdsShortTimestamp
from spacepackets.ecss import PusTelecommand from spacepackets.ecss import PusTelecommand
from tmtccmd.config import CoreServiceList from tmtccmd.config import CmdTreeNode
from tmtccmd.tmtc import DefaultPusQueueHelper from tmtccmd.tmtc import DefaultPusQueueHelper
from tmtccmd.pus.s11_tc_sched import create_time_tagged_cmd from tmtccmd.pus.s11_tc_sched import create_time_tagged_cmd
from tmtccmd.pus.tc.s3_fsfw_hk import create_request_one_hk_command from tmtccmd.pus.tc.s3_fsfw_hk import create_request_one_hk_command
from common import ( from common import (
EXAMPLE_PUS_APID, EXAMPLE_PUS_APID,
HkOpCodes,
make_addressable_id, make_addressable_id,
RequestTargetId, RequestTargetId,
AcsHkIds, AcsHkIds,
) )
_LOGGER = logging.getLogger(__name__)
def pack_pus_telecommands(q: DefaultPusQueueHelper, service: str, op_code: str):
if ( def create_cmd_definition_tree() -> CmdTreeNode:
service == CoreServiceList.SERVICE_17
or service == CoreServiceList.SERVICE_17_ALT root_node = CmdTreeNode.root_node()
):
if op_code == "ping": test_node = CmdTreeNode("test", "Test Node")
test_node.add_child(CmdTreeNode("ping", "Send PUS ping TC"))
test_node.add_child(CmdTreeNode("trigger_event", "Send PUS test to trigger event"))
root_node.add_child(test_node)
scheduler_node = CmdTreeNode("scheduler", "Scheduler Node")
scheduler_node.add_child(
CmdTreeNode(
"schedule_ping_10_secs_ahead", "Schedule Ping to execute in 10 seconds"
)
)
root_node.add_child(scheduler_node)
acs_node = CmdTreeNode("acs", "ACS Subsystem Node")
mgm_node = CmdTreeNode("mgms", "MGM devices node")
mgm_node.add_child(CmdTreeNode("one_shot_hk", "Request one shot HK"))
acs_node.add_child(mgm_node)
root_node.add_child(acs_node)
return root_node
def pack_pus_telecommands(q: DefaultPusQueueHelper, cmd_path: str):
# It should always be at least the root path "/", so we split of the empty portion left of it.
cmd_path_list = cmd_path.split("/")[1:]
if len(cmd_path_list) == 0:
_LOGGER.warning("empty command path")
return
if cmd_path_list[0] == "test":
assert len(cmd_path_list) >= 2
if cmd_path_list[1] == "ping":
q.add_log_cmd("Sending PUS ping telecommand") q.add_log_cmd("Sending PUS ping telecommand")
return q.add_pus_tc(PusTelecommand(service=17, subservice=1)) return q.add_pus_tc(PusTelecommand(service=17, subservice=1))
elif op_code == "trigger_event": elif cmd_path_list[1] == "trigger_event":
q.add_log_cmd("Triggering test event") q.add_log_cmd("Triggering test event")
return q.add_pus_tc(PusTelecommand(service=17, subservice=128)) return q.add_pus_tc(PusTelecommand(service=17, subservice=128))
if service == CoreServiceList.SERVICE_11: if cmd_path_list[0] == "scheduler":
assert len(cmd_path_list) >= 2
if cmd_path_list[1] == "schedule_ping_10_secs_ahead":
q.add_log_cmd("Sending PUS scheduled TC telecommand") q.add_log_cmd("Sending PUS scheduled TC telecommand")
crt_time = CdsShortTimestamp.from_now() crt_time = CdsShortTimestamp.from_now()
time_stamp = crt_time + datetime.timedelta(seconds=10) time_stamp = crt_time + datetime.timedelta(seconds=10)
@ -39,12 +72,14 @@ def pack_pus_telecommands(q: DefaultPusQueueHelper, service: str, op_code: str):
apid=EXAMPLE_PUS_APID, apid=EXAMPLE_PUS_APID,
) )
) )
if service == CoreServiceList.SERVICE_3: if cmd_path_list[0] == "acs":
if op_code in HkOpCodes.GENERATE_ONE_SHOT: assert len(cmd_path_list) >= 2
if cmd_path_list[1] == "mgm":
assert len(cmd_path_list) >= 3
if cmd_path_list[2] == "one_shot_hk":
q.add_log_cmd("Sending HK one shot request") q.add_log_cmd("Sending HK one shot request")
q.add_pus_tc( q.add_pus_tc(
create_request_one_hk_command( create_request_one_hk_command(
make_addressable_id(RequestTargetId.ACS, AcsHkIds.MGM_SET) make_addressable_id(RequestTargetId.ACS, AcsHkIds.MGM_SET)
) )
) )
pass

View File

@ -1,2 +1,2 @@
tmtccmd == 7.0.0 tmtccmd == 8.0.0rc1
# -e git+https://github.com/robamu-org/tmtccmd@97e5e51101a08b21472b3ddecc2063359f7e307a#egg=tmtccmd # -e git+https://github.com/robamu-org/tmtccmd@97e5e51101a08b21472b3ddecc2063359f7e307a#egg=tmtccmd

View File

@ -42,7 +42,7 @@ use satrs_core::pus::test::PusService17TestHandler;
use satrs_core::pus::verification::{ use satrs_core::pus::verification::{
TcStateStarted, VerificationReporterCfg, VerificationReporterWithSender, VerificationToken, TcStateStarted, VerificationReporterCfg, VerificationReporterWithSender, VerificationToken,
}; };
use satrs_core::pus::{MpscTcInStoreReceiver, MpscTmInStoreSender}; use satrs_core::pus::{EcssTcInStoreConverter, MpscTcInStoreReceiver, MpscTmInStoreSender};
use satrs_core::seq_count::{CcsdsSimpleSeqCountProvider, SequenceCountProviderCore}; use satrs_core::seq_count::{CcsdsSimpleSeqCountProvider, SequenceCountProviderCore};
use satrs_core::spacepackets::ecss::tm::{PusTmCreator, PusTmZeroCopyWriter}; use satrs_core::spacepackets::ecss::tm::{PusTmCreator, PusTmZeroCopyWriter};
use satrs_core::spacepackets::{ use satrs_core::spacepackets::{
@ -179,10 +179,10 @@ fn main() {
); );
let pus17_handler = PusService17TestHandler::new( let pus17_handler = PusService17TestHandler::new(
Box::new(test_srv_receiver), Box::new(test_srv_receiver),
tc_store.pool.clone(),
Box::new(test_srv_tm_sender), Box::new(test_srv_tm_sender),
PUS_APID, PUS_APID,
verif_reporter.clone(), verif_reporter.clone(),
EcssTcInStoreConverter::new(tc_store.pool.clone(), 2048),
); );
let mut pus_17_wrapper = Service17CustomWrapper { let mut pus_17_wrapper = Service17CustomWrapper {
pus17_handler, pus17_handler,
@ -204,10 +204,11 @@ fn main() {
.expect("Creating PUS Scheduler failed"); .expect("Creating PUS Scheduler failed");
let pus_11_handler = PusService11SchedHandler::new( let pus_11_handler = PusService11SchedHandler::new(
Box::new(sched_srv_receiver), Box::new(sched_srv_receiver),
tc_store.pool.clone(),
Box::new(sched_srv_tm_sender), Box::new(sched_srv_tm_sender),
PUS_APID, PUS_APID,
verif_reporter.clone(), verif_reporter.clone(),
EcssTcInStoreConverter::new(tc_store.pool.clone(), 2048),
tc_store.pool.clone(),
scheduler, scheduler,
); );
let mut pus_11_wrapper = Pus11Wrapper { let mut pus_11_wrapper = Pus11Wrapper {
@ -228,10 +229,10 @@ fn main() {
); );
let pus_5_handler = PusService5EventHandler::new( let pus_5_handler = PusService5EventHandler::new(
Box::new(event_srv_receiver), Box::new(event_srv_receiver),
tc_store.pool.clone(),
Box::new(event_srv_tm_sender), Box::new(event_srv_tm_sender),
PUS_APID, PUS_APID,
verif_reporter.clone(), verif_reporter.clone(),
EcssTcInStoreConverter::new(tc_store.pool.clone(), 2048),
event_request_tx, event_request_tx,
); );
let mut pus_5_wrapper = Pus5Wrapper { pus_5_handler }; let mut pus_5_wrapper = Pus5Wrapper { pus_5_handler };
@ -249,10 +250,10 @@ fn main() {
); );
let pus_8_handler = PusService8ActionHandler::new( let pus_8_handler = PusService8ActionHandler::new(
Box::new(action_srv_receiver), Box::new(action_srv_receiver),
tc_store.pool.clone(),
Box::new(action_srv_tm_sender), Box::new(action_srv_tm_sender),
PUS_APID, PUS_APID,
verif_reporter.clone(), verif_reporter.clone(),
EcssTcInStoreConverter::new(tc_store.pool.clone(), 2048),
request_map.clone(), request_map.clone(),
); );
let mut pus_8_wrapper = Pus8Wrapper { pus_8_handler }; let mut pus_8_wrapper = Pus8Wrapper { pus_8_handler };
@ -267,10 +268,10 @@ fn main() {
MpscTcInStoreReceiver::new(TcReceiverId::PusHk as ChannelId, "PUS_8_TC_RECV", pus_hk_rx); MpscTcInStoreReceiver::new(TcReceiverId::PusHk as ChannelId, "PUS_8_TC_RECV", pus_hk_rx);
let pus_3_handler = PusService3HkHandler::new( let pus_3_handler = PusService3HkHandler::new(
Box::new(hk_srv_receiver), Box::new(hk_srv_receiver),
tc_store.pool.clone(),
Box::new(hk_srv_tm_sender), Box::new(hk_srv_tm_sender),
PUS_APID, PUS_APID,
verif_reporter.clone(), verif_reporter.clone(),
EcssTcInStoreConverter::new(tc_store.pool.clone(), 2048),
request_map, request_map,
); );
let mut pus_3_wrapper = Pus3Wrapper { pus_3_handler }; let mut pus_3_wrapper = Pus3Wrapper { pus_3_handler };

View File

@ -1,12 +1,11 @@
use crate::requests::{ActionRequest, Request, RequestWithToken}; use crate::requests::{ActionRequest, Request, RequestWithToken};
use log::{error, warn}; use log::{error, warn};
use satrs_core::pool::{SharedPool, StoreAddr};
use satrs_core::pus::verification::{ use satrs_core::pus::verification::{
FailParams, StdVerifReporterWithSender, TcStateAccepted, VerificationToken, FailParams, TcStateAccepted, VerificationReporterWithSender, VerificationToken,
}; };
use satrs_core::pus::{ use satrs_core::pus::{
EcssTcReceiver, EcssTmSender, PusPacketHandlerResult, PusPacketHandlingError, PusServiceBase, EcssTcInMemConverter, EcssTcInStoreConverter, EcssTcReceiver, EcssTmSender,
PusServiceHandler, PusPacketHandlerResult, PusPacketHandlingError, PusServiceBase, PusServiceHandler,
}; };
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;
@ -14,34 +13,32 @@ use satrs_example::{tmtc_err, TargetIdWithApid};
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::mpsc::Sender; use std::sync::mpsc::Sender;
pub struct PusService8ActionHandler { pub struct PusService8ActionHandler<TcInMemConverter: EcssTcInMemConverter> {
psb: PusServiceBase, psb: PusServiceHandler<TcInMemConverter>,
request_handlers: HashMap<TargetIdWithApid, Sender<RequestWithToken>>, request_handlers: HashMap<TargetIdWithApid, Sender<RequestWithToken>>,
} }
impl PusService8ActionHandler { impl<TcInMemConverter: EcssTcInMemConverter> PusService8ActionHandler<TcInMemConverter> {
pub fn new( pub fn new(
tc_receiver: Box<dyn EcssTcReceiver>, tc_receiver: Box<dyn EcssTcReceiver>,
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,
tc_in_mem_converter: TcInMemConverter,
request_handlers: HashMap<TargetIdWithApid, Sender<RequestWithToken>>, request_handlers: HashMap<TargetIdWithApid, Sender<RequestWithToken>>,
) -> Self { ) -> Self {
Self { Self {
psb: PusServiceBase::new( psb: PusServiceHandler::new(
tc_receiver, tc_receiver,
shared_tc_pool,
tm_sender, tm_sender,
tm_apid, tm_apid,
verification_handler, verification_handler,
tc_in_mem_converter,
), ),
request_handlers, request_handlers,
} }
} }
}
impl PusService8ActionHandler {
fn handle_action_request_with_id( fn handle_action_request_with_id(
&self, &self,
token: VerificationToken<TcStateAccepted>, token: VerificationToken<TcStateAccepted>,
@ -50,7 +47,8 @@ impl PusService8ActionHandler {
) -> Result<(), PusPacketHandlingError> { ) -> Result<(), PusPacketHandlingError> {
let user_data = tc.user_data(); let user_data = tc.user_data();
if user_data.len() < 8 { if user_data.len() < 8 {
self.psb() self.psb
.common
.verification_handler .verification_handler
.borrow_mut() .borrow_mut()
.start_failure( .start_failure(
@ -79,7 +77,8 @@ impl PusService8ActionHandler {
} else { } else {
let mut fail_data: [u8; 4] = [0; 4]; let mut fail_data: [u8; 4] = [0; 4];
fail_data.copy_from_slice(&target_id.target.to_be_bytes()); fail_data.copy_from_slice(&target_id.target.to_be_bytes());
self.psb() self.psb
.common
.verification_handler .verification_handler
.borrow_mut() .borrow_mut()
.start_failure( .start_failure(
@ -97,37 +96,32 @@ impl PusService8ActionHandler {
} }
Ok(()) Ok(())
} }
}
impl PusServiceHandler for PusService8ActionHandler { fn handle_one_tc(&mut self) -> Result<PusPacketHandlerResult, PusPacketHandlingError> {
fn psb_mut(&mut self) -> &mut PusServiceBase { let possible_packet = self.psb.retrieve_and_accept_next_packet()?;
&mut self.psb if possible_packet.is_none() {
return Ok(PusPacketHandlerResult::Empty);
} }
fn psb(&self) -> &PusServiceBase { let ecss_tc_and_token = possible_packet.unwrap();
&self.psb self.psb
} .tc_in_mem_converter
.cache_ecss_tc_in_memory(&ecss_tc_and_token)?;
fn handle_one_tc( let tc = PusTcReader::new(self.psb.tc_in_mem_converter.tc_slice_raw())?.0;
&mut self,
addr: StoreAddr,
token: VerificationToken<TcStateAccepted>,
) -> Result<PusPacketHandlerResult, PusPacketHandlingError> {
self.copy_tc_to_buf(addr)?;
let (tc, _) = PusTcReader::new(&self.psb().pus_buf).unwrap();
let subservice = tc.subservice(); let subservice = tc.subservice();
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 subservice { match subservice {
128 => { 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]; let fail_data = [subservice];
self.psb_mut() self.psb
.common
.verification_handler .verification_handler
.get_mut() .get_mut()
.start_failure( .start_failure(
token, ecss_tc_and_token.token,
FailParams::new( FailParams::new(
Some(&time_stamp), Some(&time_stamp),
&tmtc_err::INVALID_PUS_SUBSERVICE, &tmtc_err::INVALID_PUS_SUBSERVICE,
@ -148,12 +142,12 @@ impl PusServiceHandler for PusService8ActionHandler {
} }
pub struct Pus8Wrapper { pub struct Pus8Wrapper {
pub(crate) pus_8_handler: PusService8ActionHandler, pub(crate) pus_8_handler: PusService8ActionHandler<EcssTcInStoreConverter>,
} }
impl Pus8Wrapper { impl Pus8Wrapper {
pub fn handle_next_packet(&mut self) -> bool { pub fn handle_next_packet(&mut self) -> bool {
match self.pus_8_handler.handle_next_packet() { match self.pus_8_handler.handle_one_tc() {
Ok(result) => match result { Ok(result) => match result {
PusPacketHandlerResult::RequestHandled => {} PusPacketHandlerResult::RequestHandled => {}
PusPacketHandlerResult::RequestHandledPartialSuccess(e) => { PusPacketHandlerResult::RequestHandledPartialSuccess(e) => {

View File

@ -1,14 +1,14 @@
use log::{error, warn}; use log::{error, warn};
use satrs_core::pus::event_srv::PusService5EventHandler; use satrs_core::pus::event_srv::PusService5EventHandler;
use satrs_core::pus::{PusPacketHandlerResult, PusServiceHandler}; use satrs_core::pus::{EcssTcInStoreConverter, PusPacketHandlerResult};
pub struct Pus5Wrapper { pub struct Pus5Wrapper {
pub pus_5_handler: PusService5EventHandler, pub pus_5_handler: PusService5EventHandler<EcssTcInStoreConverter>,
} }
impl Pus5Wrapper { impl Pus5Wrapper {
pub fn handle_next_packet(&mut self) -> bool { pub fn handle_next_packet(&mut self) -> bool {
match self.pus_5_handler.handle_next_packet() { match self.pus_5_handler.handle_one_tc() {
Ok(result) => match result { Ok(result) => match result {
PusPacketHandlerResult::RequestHandled => {} PusPacketHandlerResult::RequestHandled => {}
PusPacketHandlerResult::RequestHandledPartialSuccess(e) => { PusPacketHandlerResult::RequestHandledPartialSuccess(e) => {

View File

@ -1,72 +1,63 @@
use crate::requests::{Request, RequestWithToken}; use crate::requests::{Request, RequestWithToken};
use log::{error, warn}; use log::{error, warn};
use satrs_core::hk::{CollectionIntervalFactor, HkRequest}; use satrs_core::hk::{CollectionIntervalFactor, HkRequest};
use satrs_core::pool::{SharedPool, StoreAddr}; use satrs_core::pus::verification::{FailParams, StdVerifReporterWithSender};
use satrs_core::pus::verification::{
FailParams, StdVerifReporterWithSender, TcStateAccepted, VerificationToken,
};
use satrs_core::pus::{ use satrs_core::pus::{
EcssTcReceiver, EcssTmSender, PusPacketHandlerResult, PusPacketHandlingError, PusServiceBase, EcssTcInMemConverter, EcssTcInStoreConverter, EcssTcReceiver, EcssTmSender,
PusServiceHandler, PusPacketHandlerResult, PusPacketHandlingError, PusServiceBase, PusServiceHandler,
}; };
use satrs_core::spacepackets::ecss::tc::PusTcReader;
use satrs_core::spacepackets::ecss::{hk, PusPacket}; use satrs_core::spacepackets::ecss::{hk, PusPacket};
use satrs_example::{hk_err, tmtc_err, TargetIdWithApid}; use satrs_example::{hk_err, tmtc_err, TargetIdWithApid};
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::mpsc::Sender; use std::sync::mpsc::Sender;
pub struct PusService3HkHandler { pub struct PusService3HkHandler<TcInMemConverter: EcssTcInMemConverter> {
psb: PusServiceBase, psb: PusServiceHandler<TcInMemConverter>,
request_handlers: HashMap<TargetIdWithApid, Sender<RequestWithToken>>, request_handlers: HashMap<TargetIdWithApid, Sender<RequestWithToken>>,
} }
impl PusService3HkHandler { impl<TcInMemConverter: EcssTcInMemConverter> PusService3HkHandler<TcInMemConverter> {
pub fn new( pub fn new(
tc_receiver: Box<dyn EcssTcReceiver>, tc_receiver: Box<dyn EcssTcReceiver>,
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: StdVerifReporterWithSender,
tc_in_mem_converter: TcInMemConverter,
request_handlers: HashMap<TargetIdWithApid, Sender<RequestWithToken>>, request_handlers: HashMap<TargetIdWithApid, Sender<RequestWithToken>>,
) -> Self { ) -> Self {
Self { Self {
psb: PusServiceBase::new( psb: PusServiceHandler::new(
tc_receiver, tc_receiver,
shared_tc_pool,
tm_sender, tm_sender,
tm_apid, tm_apid,
verification_handler, verification_handler,
tc_in_mem_converter,
), ),
request_handlers, request_handlers,
} }
} }
}
impl PusServiceHandler for PusService3HkHandler { fn handle_one_tc(&mut self) -> Result<PusPacketHandlerResult, PusPacketHandlingError> {
fn psb_mut(&mut self) -> &mut PusServiceBase { let possible_packet = self.psb.retrieve_and_accept_next_packet()?;
&mut self.psb if possible_packet.is_none() {
return Ok(PusPacketHandlerResult::Empty);
} }
fn psb(&self) -> &PusServiceBase { let ecss_tc_and_token = possible_packet.unwrap();
&self.psb let tc = self
} .psb
.tc_in_mem_converter
fn handle_one_tc( .convert_ecss_tc_in_memory_to_reader(&ecss_tc_and_token)?;
&mut self,
addr: StoreAddr,
token: VerificationToken<TcStateAccepted>,
) -> Result<PusPacketHandlerResult, PusPacketHandlingError> {
self.copy_tc_to_buf(addr)?;
let (tc, _) = PusTcReader::new(&self.psb().pus_buf).unwrap();
let subservice = tc.subservice(); let subservice = tc.subservice();
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 user_data = tc.user_data(); let user_data = tc.user_data();
if user_data.is_empty() { if user_data.is_empty() {
self.psb self.psb
.common
.verification_handler .verification_handler
.borrow_mut() .borrow_mut()
.start_failure( .start_failure(
token, ecss_tc_and_token.token,
FailParams::new(Some(&time_stamp), &tmtc_err::NOT_ENOUGH_APP_DATA, None), FailParams::new(Some(&time_stamp), &tmtc_err::NOT_ENOUGH_APP_DATA, None),
) )
.expect("Sending start failure TM failed"); .expect("Sending start failure TM failed");
@ -81,9 +72,13 @@ impl PusServiceHandler for PusService3HkHandler {
&hk_err::UNIQUE_ID_MISSING &hk_err::UNIQUE_ID_MISSING
}; };
self.psb self.psb
.common
.verification_handler .verification_handler
.borrow_mut() .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"); .expect("Sending start failure TM failed");
return Err(PusPacketHandlingError::NotEnoughAppData( return Err(PusPacketHandlingError::NotEnoughAppData(
"Expected at least 8 bytes of app data".into(), "Expected at least 8 bytes of app data".into(),
@ -93,10 +88,11 @@ impl PusServiceHandler for PusService3HkHandler {
let unique_id = u32::from_be_bytes(tc.user_data()[0..4].try_into().unwrap()); let unique_id = u32::from_be_bytes(tc.user_data()[0..4].try_into().unwrap());
if !self.request_handlers.contains_key(&target_id) { if !self.request_handlers.contains_key(&target_id) {
self.psb self.psb
.common
.verification_handler .verification_handler
.borrow_mut() .borrow_mut()
.start_failure( .start_failure(
token, ecss_tc_and_token.token,
FailParams::new(Some(&time_stamp), &hk_err::UNKNOWN_TARGET_ID, None), FailParams::new(Some(&time_stamp), &hk_err::UNKNOWN_TARGET_ID, None),
) )
.expect("Sending start failure TM failed"); .expect("Sending start failure TM failed");
@ -107,7 +103,11 @@ impl PusServiceHandler for PusService3HkHandler {
let send_request = |target: TargetIdWithApid, request: HkRequest| { let send_request = |target: TargetIdWithApid, request: HkRequest| {
let sender = self.request_handlers.get(&target).unwrap(); let sender = self.request_handlers.get(&target).unwrap();
sender 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")); .unwrap_or_else(|_| panic!("Sending HK request {request:?} failed"));
}; };
if subservice == hk::Subservice::TcEnableHkGeneration as u8 { if subservice == hk::Subservice::TcEnableHkGeneration as u8 {
@ -119,10 +119,11 @@ impl PusServiceHandler for PusService3HkHandler {
} else if subservice == hk::Subservice::TcModifyHkCollectionInterval as u8 { } else if subservice == hk::Subservice::TcModifyHkCollectionInterval as u8 {
if user_data.len() < 12 { if user_data.len() < 12 {
self.psb self.psb
.common
.verification_handler .verification_handler
.borrow_mut() .borrow_mut()
.start_failure( .start_failure(
token, ecss_tc_and_token.token,
FailParams::new( FailParams::new(
Some(&time_stamp), Some(&time_stamp),
&hk_err::COLLECTION_INTERVAL_MISSING, &hk_err::COLLECTION_INTERVAL_MISSING,
@ -147,12 +148,12 @@ impl PusServiceHandler for PusService3HkHandler {
} }
pub struct Pus3Wrapper { pub struct Pus3Wrapper {
pub(crate) pus_3_handler: PusService3HkHandler, pub(crate) pus_3_handler: PusService3HkHandler<EcssTcInStoreConverter>,
} }
impl Pus3Wrapper { impl Pus3Wrapper {
pub fn handle_next_packet(&mut self) -> bool { pub fn handle_next_packet(&mut self) -> bool {
match self.pus_3_handler.handle_next_packet() { match self.pus_3_handler.handle_one_tc() {
Ok(result) => match result { Ok(result) => match result {
PusPacketHandlerResult::RequestHandled => {} PusPacketHandlerResult::RequestHandled => {}
PusPacketHandlerResult::RequestHandledPartialSuccess(e) => { PusPacketHandlerResult::RequestHandledPartialSuccess(e) => {

View File

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

View File

@ -2,10 +2,10 @@ use crate::tmtc::PusTcSource;
use log::{error, info, warn}; use log::{error, info, warn};
use satrs_core::pus::scheduler::TcInfo; use satrs_core::pus::scheduler::TcInfo;
use satrs_core::pus::scheduler_srv::PusService11SchedHandler; use satrs_core::pus::scheduler_srv::PusService11SchedHandler;
use satrs_core::pus::{PusPacketHandlerResult, PusServiceHandler}; use satrs_core::pus::{EcssTcInStoreConverter, PusPacketHandlerResult};
pub struct Pus11Wrapper { pub struct Pus11Wrapper {
pub pus_11_handler: PusService11SchedHandler, pub pus_11_handler: PusService11SchedHandler<EcssTcInStoreConverter>,
pub tc_source_wrapper: PusTcSource, pub tc_source_wrapper: PusTcSource,
} }
@ -44,7 +44,7 @@ impl Pus11Wrapper {
} }
pub fn handle_next_packet(&mut self) -> bool { pub fn handle_next_packet(&mut self) -> bool {
match self.pus_11_handler.handle_next_packet() { match self.pus_11_handler.handle_one_tc() {
Ok(result) => match result { Ok(result) => match result {
PusPacketHandlerResult::RequestHandled => {} PusPacketHandlerResult::RequestHandled => {}
PusPacketHandlerResult::RequestHandledPartialSuccess(e) => { PusPacketHandlerResult::RequestHandledPartialSuccess(e) => {

View File

@ -1,24 +1,24 @@
use log::{info, warn}; use log::{info, warn};
use satrs_core::events::EventU32;
use satrs_core::params::Params; use satrs_core::params::Params;
use satrs_core::pus::test::PusService17TestHandler; use satrs_core::pus::test::PusService17TestHandler;
use satrs_core::pus::verification::FailParams; use satrs_core::pus::verification::FailParams;
use satrs_core::pus::{PusPacketHandlerResult, PusServiceHandler}; use satrs_core::pus::{EcssTcInMemConverter, PusPacketHandlerResult};
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;
use satrs_core::spacepackets::time::cds::TimeProvider; use satrs_core::spacepackets::time::cds::TimeProvider;
use satrs_core::spacepackets::time::TimeWriter; use satrs_core::spacepackets::time::TimeWriter;
use satrs_core::{events::EventU32, pus::EcssTcInStoreConverter};
use satrs_example::{tmtc_err, TEST_EVENT}; use satrs_example::{tmtc_err, TEST_EVENT};
use std::sync::mpsc::Sender; use std::sync::mpsc::Sender;
pub struct Service17CustomWrapper { pub struct Service17CustomWrapper {
pub pus17_handler: PusService17TestHandler, pub pus17_handler: PusService17TestHandler<EcssTcInStoreConverter>,
pub test_srv_event_sender: Sender<(EventU32, Option<Params>)>, pub test_srv_event_sender: Sender<(EventU32, Option<Params>)>,
} }
impl Service17CustomWrapper { impl Service17CustomWrapper {
pub fn handle_next_packet(&mut self) -> bool { pub fn handle_next_packet(&mut self) -> bool {
let res = self.pus17_handler.handle_next_packet(); let res = self.pus17_handler.handle_one_tc();
if res.is_err() { if res.is_err() {
warn!("PUS17 handler failed with error {:?}", res.unwrap_err()); warn!("PUS17 handler failed with error {:?}", res.unwrap_err());
return true; return true;
@ -38,9 +38,9 @@ impl Service17CustomWrapper {
warn!("PUS17: Subservice {subservice} not implemented") warn!("PUS17: Subservice {subservice} not implemented")
} }
PusPacketHandlerResult::CustomSubservice(subservice, token) => { PusPacketHandlerResult::CustomSubservice(subservice, token) => {
let psb_mut = self.pus17_handler.psb_mut(); let (tc, _) =
let buf = psb_mut.pus_buf; PusTcReader::new(self.pus17_handler.psb.tc_in_mem_converter.tc_slice_raw())
let (tc, _) = PusTcReader::new(&buf).unwrap(); .unwrap();
let time_stamper = TimeProvider::from_now_with_u16_days().unwrap(); let time_stamper = TimeProvider::from_now_with_u16_days().unwrap();
let mut stamp_buf: [u8; 7] = [0; 7]; let mut stamp_buf: [u8; 7] = [0; 7];
time_stamper.write_to_bytes(&mut stamp_buf).unwrap(); time_stamper.write_to_bytes(&mut stamp_buf).unwrap();
@ -49,12 +49,17 @@ impl Service17CustomWrapper {
self.test_srv_event_sender self.test_srv_event_sender
.send((TEST_EVENT.into(), None)) .send((TEST_EVENT.into(), None))
.expect("Sending test event failed"); .expect("Sending test event failed");
let start_token = psb_mut let start_token = self
.pus17_handler
.psb
.common
.verification_handler .verification_handler
.get_mut() .get_mut()
.start_success(token, Some(&stamp_buf)) .start_success(token, Some(&stamp_buf))
.expect("Error sending start success"); .expect("Error sending start success");
psb_mut self.pus17_handler
.psb
.common
.verification_handler .verification_handler
.get_mut() .get_mut()
.completion_success(start_token, Some(&stamp_buf)) .completion_success(start_token, Some(&stamp_buf))
@ -62,7 +67,8 @@ impl Service17CustomWrapper {
} else { } else {
let fail_data = [tc.subservice()]; let fail_data = [tc.subservice()];
self.pus17_handler self.pus17_handler
.psb_mut() .psb
.common
.verification_handler .verification_handler
.get_mut() .get_mut()
.start_failure( .start_failure(

View File

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