Tricky PUS handler changes #95
@ -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)
|
||||||
|
BIN
satrs-book/src/images/events/event_man_arch.png
Normal file
BIN
satrs-book/src/images/events/event_man_arch.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 116 KiB |
@ -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,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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");
|
||||||
|
1
satrs-example/pyclient/.gitignore
vendored
1
satrs-example/pyclient/.gitignore
vendored
@ -6,3 +6,4 @@ __pycache__
|
|||||||
!/.idea/runConfigurations
|
!/.idea/runConfigurations
|
||||||
|
|
||||||
/seqcnt.txt
|
/seqcnt.txt
|
||||||
|
/.tmtc-history.txt
|
||||||
|
@ -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))
|
||||||
|
@ -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():
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
||||||
|
@ -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 };
|
||||||
|
@ -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) => {
|
||||||
|
@ -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) => {
|
||||||
|
@ -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) => {
|
||||||
|
@ -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,
|
||||||
|
@ -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) => {
|
||||||
|
@ -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(
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user