Implementation of scheduler in pus and tmtc handler #29
@ -13,8 +13,8 @@ categories = ["aerospace", "aerospace::space-protocols", "no-std", "hardware-sup
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
delegate = "0.8"
|
delegate = ">=0.8, <0.10"
|
||||||
paste = "1.0"
|
paste = "1"
|
||||||
embed-doc-image = "0.1"
|
embed-doc-image = "0.1"
|
||||||
|
|
||||||
[dependencies.dyn-clone]
|
[dependencies.dyn-clone]
|
||||||
@ -53,7 +53,7 @@ default-features = false
|
|||||||
optional = true
|
optional = true
|
||||||
|
|
||||||
[dependencies.spacepackets]
|
[dependencies.spacepackets]
|
||||||
version = "0.5.1"
|
version = "0.5.2"
|
||||||
# path = "../spacepackets"
|
# path = "../spacepackets"
|
||||||
# git = "https://egit.irs.uni-stuttgart.de/rust/spacepackets.git"
|
# git = "https://egit.irs.uni-stuttgart.de/rust/spacepackets.git"
|
||||||
# rev = "..."
|
# rev = "..."
|
||||||
|
@ -153,10 +153,10 @@ impl Display for StoreIdError {
|
|||||||
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
StoreIdError::InvalidSubpool(pool) => {
|
StoreIdError::InvalidSubpool(pool) => {
|
||||||
write!(f, "invalid subpool, index: {}", pool)
|
write!(f, "invalid subpool, index: {pool}")
|
||||||
}
|
}
|
||||||
StoreIdError::InvalidPacketIdx(packet_idx) => {
|
StoreIdError::InvalidPacketIdx(packet_idx) => {
|
||||||
write!(f, "invalid packet index: {}", packet_idx)
|
write!(f, "invalid packet index: {packet_idx}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -183,19 +183,19 @@ impl Display for StoreError {
|
|||||||
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
StoreError::DataTooLarge(size) => {
|
StoreError::DataTooLarge(size) => {
|
||||||
write!(f, "data to store with size {} is too large", size)
|
write!(f, "data to store with size {size} is too large")
|
||||||
}
|
}
|
||||||
StoreError::StoreFull(u16) => {
|
StoreError::StoreFull(u16) => {
|
||||||
write!(f, "store is too full. index for full subpool: {}", u16)
|
write!(f, "store is too full. index for full subpool: {u16}")
|
||||||
}
|
}
|
||||||
StoreError::InvalidStoreId(id_e, addr) => {
|
StoreError::InvalidStoreId(id_e, addr) => {
|
||||||
write!(f, "invalid store ID: {}, address: {:?}", id_e, addr)
|
write!(f, "invalid store ID: {id_e}, address: {addr:?}")
|
||||||
}
|
}
|
||||||
StoreError::DataDoesNotExist(addr) => {
|
StoreError::DataDoesNotExist(addr) => {
|
||||||
write!(f, "no data exists at address {:?}", addr)
|
write!(f, "no data exists at address {addr:?}")
|
||||||
}
|
}
|
||||||
StoreError::InternalError(e) => {
|
StoreError::InternalError(e) => {
|
||||||
write!(f, "internal error: {}", e)
|
write!(f, "internal error: {e}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -330,14 +330,12 @@ impl LocalPool {
|
|||||||
fn write(&mut self, addr: &StoreAddr, data: &[u8]) -> Result<(), StoreError> {
|
fn write(&mut self, addr: &StoreAddr, data: &[u8]) -> Result<(), StoreError> {
|
||||||
let packet_pos = self.raw_pos(addr).ok_or_else(|| {
|
let packet_pos = self.raw_pos(addr).ok_or_else(|| {
|
||||||
StoreError::InternalError(format!(
|
StoreError::InternalError(format!(
|
||||||
"write: Error in raw_pos func with address {:?}",
|
"write: Error in raw_pos func with address {addr:?}"
|
||||||
addr
|
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
let subpool = self.pool.get_mut(addr.pool_idx as usize).ok_or_else(|| {
|
let subpool = self.pool.get_mut(addr.pool_idx as usize).ok_or_else(|| {
|
||||||
StoreError::InternalError(format!(
|
StoreError::InternalError(format!(
|
||||||
"write: Error retrieving pool slice with address {:?}",
|
"write: Error retrieving pool slice with address {addr:?}"
|
||||||
addr
|
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
let pool_slice = &mut subpool[packet_pos..packet_pos + data.len()];
|
let pool_slice = &mut subpool[packet_pos..packet_pos + data.len()];
|
||||||
|
@ -522,9 +522,9 @@ impl VerificationReporterCore {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_acceptance_success<'src_data, E>(
|
pub fn send_acceptance_success<E>(
|
||||||
&self,
|
&self,
|
||||||
mut sendable: VerificationSendable<'src_data, TcStateNone, VerifSuccess>,
|
mut sendable: VerificationSendable<'_, TcStateNone, VerifSuccess>,
|
||||||
seq_counter: &(impl SequenceCountProviderCore<u16> + ?Sized),
|
seq_counter: &(impl SequenceCountProviderCore<u16> + ?Sized),
|
||||||
sender: &mut (impl EcssTmSenderCore<Error = E> + ?Sized),
|
sender: &mut (impl EcssTmSenderCore<Error = E> + ?Sized),
|
||||||
) -> Result<VerificationToken<TcStateAccepted>, VerificationOrSendErrorWithToken<E, TcStateNone>>
|
) -> Result<VerificationToken<TcStateAccepted>, VerificationOrSendErrorWithToken<E, TcStateNone>>
|
||||||
@ -535,9 +535,9 @@ impl VerificationReporterCore {
|
|||||||
Ok(sendable.send_success_acceptance_success(Some(seq_counter)))
|
Ok(sendable.send_success_acceptance_success(Some(seq_counter)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_acceptance_failure<'src_data, E>(
|
pub fn send_acceptance_failure<E>(
|
||||||
&self,
|
&self,
|
||||||
mut sendable: VerificationSendable<'src_data, TcStateNone, VerifFailure>,
|
mut sendable: VerificationSendable<'_, TcStateNone, VerifFailure>,
|
||||||
seq_counter: &(impl SequenceCountProviderCore<u16> + ?Sized),
|
seq_counter: &(impl SequenceCountProviderCore<u16> + ?Sized),
|
||||||
sender: &mut (impl EcssTmSenderCore<Error = E> + ?Sized),
|
sender: &mut (impl EcssTmSenderCore<Error = E> + ?Sized),
|
||||||
) -> Result<(), VerificationOrSendErrorWithToken<E, TcStateNone>> {
|
) -> Result<(), VerificationOrSendErrorWithToken<E, TcStateNone>> {
|
||||||
@ -591,9 +591,9 @@ impl VerificationReporterCore {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_start_success<'src_data, E>(
|
pub fn send_start_success<E>(
|
||||||
&self,
|
&self,
|
||||||
mut sendable: VerificationSendable<'src_data, TcStateAccepted, VerifSuccess>,
|
mut sendable: VerificationSendable<'_, TcStateAccepted, VerifSuccess>,
|
||||||
seq_counter: &(impl SequenceCountProviderCore<u16> + ?Sized),
|
seq_counter: &(impl SequenceCountProviderCore<u16> + ?Sized),
|
||||||
sender: &mut (impl EcssTmSenderCore<Error = E> + ?Sized),
|
sender: &mut (impl EcssTmSenderCore<Error = E> + ?Sized),
|
||||||
) -> Result<
|
) -> Result<
|
||||||
@ -630,9 +630,9 @@ impl VerificationReporterCore {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_start_failure<'src_data, E>(
|
pub fn send_start_failure<E>(
|
||||||
&self,
|
&self,
|
||||||
mut sendable: VerificationSendable<'src_data, TcStateAccepted, VerifFailure>,
|
mut sendable: VerificationSendable<'_, TcStateAccepted, VerifFailure>,
|
||||||
seq_counter: &(impl SequenceCountProviderCore<u16> + ?Sized),
|
seq_counter: &(impl SequenceCountProviderCore<u16> + ?Sized),
|
||||||
sender: &mut (impl EcssTmSenderCore<Error = E> + ?Sized),
|
sender: &mut (impl EcssTmSenderCore<Error = E> + ?Sized),
|
||||||
) -> Result<(), VerificationOrSendErrorWithToken<E, TcStateAccepted>> {
|
) -> Result<(), VerificationOrSendErrorWithToken<E, TcStateAccepted>> {
|
||||||
@ -741,9 +741,9 @@ impl VerificationReporterCore {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_step_or_completion_success<'src_data, E>(
|
pub fn send_step_or_completion_success<E>(
|
||||||
&self,
|
&self,
|
||||||
mut sendable: VerificationSendable<'src_data, TcStateStarted, VerifSuccess>,
|
mut sendable: VerificationSendable<'_, TcStateStarted, VerifSuccess>,
|
||||||
seq_counter: &(impl SequenceCountProviderCore<u16> + ?Sized),
|
seq_counter: &(impl SequenceCountProviderCore<u16> + ?Sized),
|
||||||
sender: &mut (impl EcssTmSenderCore<Error = E> + ?Sized),
|
sender: &mut (impl EcssTmSenderCore<Error = E> + ?Sized),
|
||||||
) -> Result<(), VerificationOrSendErrorWithToken<E, TcStateStarted>> {
|
) -> Result<(), VerificationOrSendErrorWithToken<E, TcStateStarted>> {
|
||||||
@ -754,9 +754,9 @@ impl VerificationReporterCore {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_step_or_completion_failure<'src_data, E>(
|
pub fn send_step_or_completion_failure<E>(
|
||||||
&self,
|
&self,
|
||||||
mut sendable: VerificationSendable<'src_data, TcStateStarted, VerifFailure>,
|
mut sendable: VerificationSendable<'_, TcStateStarted, VerifFailure>,
|
||||||
seq_counter: &(impl SequenceCountProviderCore<u16> + ?Sized),
|
seq_counter: &(impl SequenceCountProviderCore<u16> + ?Sized),
|
||||||
sender: &mut (impl EcssTmSenderCore<Error = E> + ?Sized),
|
sender: &mut (impl EcssTmSenderCore<Error = E> + ?Sized),
|
||||||
) -> Result<(), VerificationOrSendErrorWithToken<E, TcStateStarted>> {
|
) -> Result<(), VerificationOrSendErrorWithToken<E, TcStateStarted>> {
|
||||||
|
@ -86,8 +86,11 @@
|
|||||||
//! ```
|
//! ```
|
||||||
use crate::tmtc::{ReceivesCcsdsTc, ReceivesTcCore};
|
use crate::tmtc::{ReceivesCcsdsTc, ReceivesTcCore};
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
|
use core::fmt::{Display, Formatter};
|
||||||
use downcast_rs::Downcast;
|
use downcast_rs::Downcast;
|
||||||
use spacepackets::{ByteConversionError, CcsdsPacket, SizeMissmatch, SpHeader};
|
use spacepackets::{ByteConversionError, CcsdsPacket, SizeMissmatch, SpHeader};
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
use std::error::Error;
|
||||||
|
|
||||||
/// Generic trait for a handler or dispatcher object handling CCSDS packets.
|
/// Generic trait for a handler or dispatcher object handling CCSDS packets.
|
||||||
///
|
///
|
||||||
@ -99,7 +102,7 @@ use spacepackets::{ByteConversionError, CcsdsPacket, SizeMissmatch, SpHeader};
|
|||||||
/// This trait automatically implements the [downcast_rs::Downcast] to allow a more convenient API
|
/// This trait automatically implements the [downcast_rs::Downcast] to allow a more convenient API
|
||||||
/// to cast trait objects back to their concrete type after the handler was passed to the
|
/// to cast trait objects back to their concrete type after the handler was passed to the
|
||||||
/// distributor.
|
/// distributor.
|
||||||
pub trait CcsdsPacketHandler: Downcast + Send {
|
pub trait CcsdsPacketHandler: Downcast {
|
||||||
type Error;
|
type Error;
|
||||||
|
|
||||||
fn valid_apids(&self) -> &'static [u16];
|
fn valid_apids(&self) -> &'static [u16];
|
||||||
@ -114,18 +117,46 @@ pub trait CcsdsPacketHandler: Downcast + Send {
|
|||||||
|
|
||||||
downcast_rs::impl_downcast!(CcsdsPacketHandler assoc Error);
|
downcast_rs::impl_downcast!(CcsdsPacketHandler assoc Error);
|
||||||
|
|
||||||
|
pub trait SendableCcsdsPacketHandler: CcsdsPacketHandler + Send {}
|
||||||
|
|
||||||
|
impl<T: CcsdsPacketHandler + Send> SendableCcsdsPacketHandler for T {}
|
||||||
|
|
||||||
|
downcast_rs::impl_downcast!(SendableCcsdsPacketHandler assoc Error);
|
||||||
|
|
||||||
/// The CCSDS distributor dispatches received CCSDS packets to a user provided packet handler.
|
/// The CCSDS distributor dispatches received CCSDS packets to a user provided packet handler.
|
||||||
|
///
|
||||||
|
/// The passed APID handler is required to be [Send]able to allow more ergonomic usage with
|
||||||
|
/// threads.
|
||||||
pub struct CcsdsDistributor<E> {
|
pub struct CcsdsDistributor<E> {
|
||||||
/// User provided APID handler stored as a generic trait object.
|
/// User provided APID handler stored as a generic trait object.
|
||||||
/// It can be cast back to the original concrete type using the [Self::apid_handler_ref] or
|
/// It can be cast back to the original concrete type using the [Self::apid_handler_ref] or
|
||||||
/// the [Self::apid_handler_mut] method.
|
/// the [Self::apid_handler_mut] method.
|
||||||
pub apid_handler: Box<dyn CcsdsPacketHandler<Error = E>>,
|
pub apid_handler: Box<dyn SendableCcsdsPacketHandler<Error = E>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum CcsdsError<E> {
|
pub enum CcsdsError<E> {
|
||||||
CustomError(E),
|
CustomError(E),
|
||||||
PacketError(ByteConversionError),
|
ByteConversionError(ByteConversionError),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Display> Display for CcsdsError<E> {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::CustomError(e) => write!(f, "{e}"),
|
||||||
|
Self::ByteConversionError(e) => write!(f, "{e}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
impl<E: Error> Error for CcsdsError<E> {
|
||||||
|
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||||
|
match self {
|
||||||
|
Self::CustomError(e) => e.source(),
|
||||||
|
Self::ByteConversionError(e) => e.source(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: 'static> ReceivesCcsdsTc for CcsdsDistributor<E> {
|
impl<E: 'static> ReceivesCcsdsTc for CcsdsDistributor<E> {
|
||||||
@ -141,7 +172,7 @@ impl<E: 'static> ReceivesTcCore for CcsdsDistributor<E> {
|
|||||||
|
|
||||||
fn pass_tc(&mut self, tc_raw: &[u8]) -> Result<(), Self::Error> {
|
fn pass_tc(&mut self, tc_raw: &[u8]) -> Result<(), Self::Error> {
|
||||||
if tc_raw.len() < 7 {
|
if tc_raw.len() < 7 {
|
||||||
return Err(CcsdsError::PacketError(
|
return Err(CcsdsError::ByteConversionError(
|
||||||
ByteConversionError::FromSliceTooSmall(SizeMissmatch {
|
ByteConversionError::FromSliceTooSmall(SizeMissmatch {
|
||||||
found: tc_raw.len(),
|
found: tc_raw.len(),
|
||||||
expected: 7,
|
expected: 7,
|
||||||
@ -149,26 +180,26 @@ impl<E: 'static> ReceivesTcCore for CcsdsDistributor<E> {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
let (sp_header, _) =
|
let (sp_header, _) =
|
||||||
SpHeader::from_be_bytes(tc_raw).map_err(|e| CcsdsError::PacketError(e))?;
|
SpHeader::from_be_bytes(tc_raw).map_err(|e| CcsdsError::ByteConversionError(e))?;
|
||||||
self.dispatch_ccsds(&sp_header, tc_raw)
|
self.dispatch_ccsds(&sp_header, tc_raw)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: 'static> CcsdsDistributor<E> {
|
impl<E: 'static> CcsdsDistributor<E> {
|
||||||
pub fn new(apid_handler: Box<dyn CcsdsPacketHandler<Error = E>>) -> Self {
|
pub fn new(apid_handler: Box<dyn SendableCcsdsPacketHandler<Error = E>>) -> Self {
|
||||||
CcsdsDistributor { apid_handler }
|
CcsdsDistributor { apid_handler }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function can be used to retrieve a reference to the concrete instance of the APID
|
/// This function can be used to retrieve a reference to the concrete instance of the APID
|
||||||
/// handler after it was passed to the distributor. See the
|
/// handler after it was passed to the distributor. See the
|
||||||
/// [module documentation][crate::tmtc::ccsds_distrib] for an fsrc-example.
|
/// [module documentation][crate::tmtc::ccsds_distrib] for an fsrc-example.
|
||||||
pub fn apid_handler_ref<T: CcsdsPacketHandler<Error = E>>(&self) -> Option<&T> {
|
pub fn apid_handler_ref<T: SendableCcsdsPacketHandler<Error = E>>(&self) -> Option<&T> {
|
||||||
self.apid_handler.downcast_ref::<T>()
|
self.apid_handler.downcast_ref::<T>()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function can be used to retrieve a mutable reference to the concrete instance of the
|
/// This function can be used to retrieve a mutable reference to the concrete instance of the
|
||||||
/// APID handler after it was passed to the distributor.
|
/// APID handler after it was passed to the distributor.
|
||||||
pub fn apid_handler_mut<T: CcsdsPacketHandler<Error = E>>(&mut self) -> Option<&mut T> {
|
pub fn apid_handler_mut<T: SendableCcsdsPacketHandler<Error = E>>(&mut self) -> Option<&mut T> {
|
||||||
self.apid_handler.downcast_mut::<T>()
|
self.apid_handler.downcast_mut::<T>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,19 +63,20 @@ impl AddressableId {
|
|||||||
/// This trait is implemented by both the [crate::tmtc::pus_distrib::PusDistributor] and the
|
/// This trait is implemented by both the [crate::tmtc::pus_distrib::PusDistributor] and the
|
||||||
/// [crate::tmtc::ccsds_distrib::CcsdsDistributor] which allows to pass the respective packets in
|
/// [crate::tmtc::ccsds_distrib::CcsdsDistributor] which allows to pass the respective packets in
|
||||||
/// raw byte format into them.
|
/// raw byte format into them.
|
||||||
pub trait ReceivesTcCore: Send {
|
pub trait ReceivesTcCore {
|
||||||
type Error;
|
type Error;
|
||||||
fn pass_tc(&mut self, tc_raw: &[u8]) -> Result<(), Self::Error>;
|
fn pass_tc(&mut self, tc_raw: &[u8]) -> Result<(), Self::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extension trait of [ReceivesTcCore] which allows downcasting by implementing [Downcast]
|
/// Extension trait of [ReceivesTcCore] which allows downcasting by implementing [Downcast] and
|
||||||
|
/// is also sendable.
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
pub trait ReceivesTc: ReceivesTcCore + Downcast {}
|
pub trait ReceivesTc: ReceivesTcCore + Downcast + Send {}
|
||||||
|
|
||||||
/// Blanket implementation to automatically implement [ReceivesTc] when the [alloc] feature
|
/// Blanket implementation to automatically implement [ReceivesTc] when the [alloc] feature
|
||||||
/// is enabled.
|
/// is enabled.
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
impl<T> ReceivesTc for T where T: ReceivesTcCore + 'static {}
|
impl<T> ReceivesTc for T where T: ReceivesTcCore + Send + 'static {}
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
impl_downcast!(ReceivesTc assoc Error);
|
impl_downcast!(ReceivesTc assoc Error);
|
||||||
|
@ -62,12 +62,15 @@
|
|||||||
//! ```
|
//! ```
|
||||||
use crate::tmtc::{ReceivesCcsdsTc, ReceivesEcssPusTc, ReceivesTcCore};
|
use crate::tmtc::{ReceivesCcsdsTc, ReceivesEcssPusTc, ReceivesTcCore};
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
|
use core::fmt::{Display, Formatter};
|
||||||
use downcast_rs::Downcast;
|
use downcast_rs::Downcast;
|
||||||
use spacepackets::ecss::{PusError, PusPacket};
|
use spacepackets::ecss::{PusError, PusPacket};
|
||||||
use spacepackets::tc::PusTc;
|
use spacepackets::tc::PusTc;
|
||||||
use spacepackets::SpHeader;
|
use spacepackets::SpHeader;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
use std::error::Error;
|
||||||
|
|
||||||
pub trait PusServiceProvider: Downcast + Send {
|
pub trait PusServiceProvider: Downcast {
|
||||||
type Error;
|
type Error;
|
||||||
fn handle_pus_tc_packet(
|
fn handle_pus_tc_packet(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -78,12 +81,22 @@ pub trait PusServiceProvider: Downcast + Send {
|
|||||||
}
|
}
|
||||||
downcast_rs::impl_downcast!(PusServiceProvider assoc Error);
|
downcast_rs::impl_downcast!(PusServiceProvider assoc Error);
|
||||||
|
|
||||||
|
pub trait SendablePusServiceProvider: PusServiceProvider + Send {}
|
||||||
|
|
||||||
|
impl<T: Send + PusServiceProvider> SendablePusServiceProvider for T {}
|
||||||
|
|
||||||
|
downcast_rs::impl_downcast!(SendablePusServiceProvider assoc Error);
|
||||||
|
|
||||||
|
/// Generic distributor object which dispatches received packets to a user provided handler.
|
||||||
|
///
|
||||||
|
/// This distributor expects the passed trait object to be [Send]able to allow more ergonomic
|
||||||
|
/// usage with threads.
|
||||||
pub struct PusDistributor<E> {
|
pub struct PusDistributor<E> {
|
||||||
pub service_provider: Box<dyn PusServiceProvider<Error = E>>,
|
pub service_provider: Box<dyn SendablePusServiceProvider<Error = E>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E> PusDistributor<E> {
|
impl<E> PusDistributor<E> {
|
||||||
pub fn new(service_provider: Box<dyn PusServiceProvider<Error = E>>) -> Self {
|
pub fn new(service_provider: Box<dyn SendablePusServiceProvider<Error = E>>) -> Self {
|
||||||
PusDistributor { service_provider }
|
PusDistributor { service_provider }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -94,6 +107,25 @@ pub enum PusDistribError<E> {
|
|||||||
PusError(PusError),
|
PusError(PusError),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<E: Display> Display for PusDistribError<E> {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
||||||
|
match self {
|
||||||
|
PusDistribError::CustomError(e) => write!(f, "{e}"),
|
||||||
|
PusDistribError::PusError(e) => write!(f, "{e}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
impl<E: Error> Error for PusDistribError<E> {
|
||||||
|
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||||
|
match self {
|
||||||
|
Self::CustomError(e) => e.source(),
|
||||||
|
Self::PusError(e) => e.source(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<E: 'static> ReceivesTcCore for PusDistributor<E> {
|
impl<E: 'static> ReceivesTcCore for PusDistributor<E> {
|
||||||
type Error = PusDistribError<E>;
|
type Error = PusDistribError<E>;
|
||||||
fn pass_tc(&mut self, tm_raw: &[u8]) -> Result<(), Self::Error> {
|
fn pass_tc(&mut self, tm_raw: &[u8]) -> Result<(), Self::Error> {
|
||||||
@ -122,11 +154,13 @@ impl<E: 'static> ReceivesEcssPusTc for PusDistributor<E> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<E: 'static> PusDistributor<E> {
|
impl<E: 'static> PusDistributor<E> {
|
||||||
pub fn service_provider_ref<T: PusServiceProvider<Error = E>>(&self) -> Option<&T> {
|
pub fn service_provider_ref<T: SendablePusServiceProvider<Error = E>>(&self) -> Option<&T> {
|
||||||
self.service_provider.downcast_ref::<T>()
|
self.service_provider.downcast_ref::<T>()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn service_provider_mut<T: PusServiceProvider<Error = E>>(&mut self) -> Option<&mut T> {
|
pub fn service_provider_mut<T: SendablePusServiceProvider<Error = E>>(
|
||||||
|
&mut self,
|
||||||
|
) -> Option<&mut T> {
|
||||||
self.service_provider.downcast_mut::<T>()
|
self.service_provider.downcast_mut::<T>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,14 +20,15 @@ fn threaded_usage() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let jh1 = thread::spawn(move || {
|
let jh1 = thread::spawn(move || {
|
||||||
let mut pool_access = shared_clone.write().unwrap();
|
|
||||||
let addr;
|
let addr;
|
||||||
{
|
{
|
||||||
addr = rx.recv().expect("Receiving store address failed");
|
addr = rx.recv().expect("Receiving store address failed");
|
||||||
|
let mut pool_access = shared_clone.write().unwrap();
|
||||||
let pg = PoolGuard::new(pool_access.deref_mut(), addr);
|
let pg = PoolGuard::new(pool_access.deref_mut(), addr);
|
||||||
let read_res = pg.read().expect("Reading failed");
|
let read_res = pg.read().expect("Reading failed");
|
||||||
assert_eq!(read_res, DUMMY_DATA);
|
assert_eq!(read_res, DUMMY_DATA);
|
||||||
}
|
}
|
||||||
|
let pool_access = shared_clone.read().unwrap();
|
||||||
assert!(!pool_access.has_element_at(&addr).expect("Invalid address"));
|
assert!(!pool_access.has_element_at(&addr).expect("Invalid address"));
|
||||||
});
|
});
|
||||||
jh0.join().unwrap();
|
jh0.join().unwrap();
|
||||||
|
@ -14,16 +14,13 @@ fn main() {
|
|||||||
let pus_tc = PusTc::new_simple(&mut sph, 17, 1, None, true);
|
let pus_tc = PusTc::new_simple(&mut sph, 17, 1, None, true);
|
||||||
let client = UdpSocket::bind("127.0.0.1:7302").expect("Connecting to UDP server failed");
|
let client = UdpSocket::bind("127.0.0.1:7302").expect("Connecting to UDP server failed");
|
||||||
let tc_req_id = RequestId::new(&pus_tc);
|
let tc_req_id = RequestId::new(&pus_tc);
|
||||||
println!(
|
println!("Packing and sending PUS ping command TC[17,1] with request ID {tc_req_id}");
|
||||||
"Packing and sending PUS ping command TC[17,1] with request ID {}",
|
|
||||||
tc_req_id
|
|
||||||
);
|
|
||||||
let size = pus_tc
|
let size = pus_tc
|
||||||
.write_to_bytes(&mut buf)
|
.write_to_bytes(&mut buf)
|
||||||
.expect("Creating PUS TC failed");
|
.expect("Creating PUS TC failed");
|
||||||
client
|
client
|
||||||
.send_to(&buf[0..size], addr)
|
.send_to(&buf[0..size], addr)
|
||||||
.unwrap_or_else(|_| panic!("Sending to {:?} failed", addr));
|
.unwrap_or_else(|_| panic!("Sending to {addr:?} failed"));
|
||||||
client
|
client
|
||||||
.set_read_timeout(Some(Duration::from_secs(2)))
|
.set_read_timeout(Some(Duration::from_secs(2)))
|
||||||
.expect("Setting read timeout failed");
|
.expect("Setting read timeout failed");
|
||||||
@ -44,33 +41,21 @@ fn main() {
|
|||||||
}
|
}
|
||||||
let req_id = RequestId::from_bytes(src_data).unwrap();
|
let req_id = RequestId::from_bytes(src_data).unwrap();
|
||||||
if pus_tm.subservice() == 1 {
|
if pus_tm.subservice() == 1 {
|
||||||
println!(
|
println!("Received TM[1,1] acceptance success for request ID {req_id}")
|
||||||
"Received TM[1,1] acceptance success for request ID {}",
|
|
||||||
req_id
|
|
||||||
)
|
|
||||||
} else if pus_tm.subservice() == 2 {
|
} else if pus_tm.subservice() == 2 {
|
||||||
println!(
|
println!("Received TM[1,2] acceptance failure for request ID {req_id}")
|
||||||
"Received TM[1,2] acceptance failure for request ID {}",
|
|
||||||
req_id
|
|
||||||
)
|
|
||||||
} else if pus_tm.subservice() == 3 {
|
} else if pus_tm.subservice() == 3 {
|
||||||
println!("Received TM[1,3] start success for request ID {}", req_id)
|
println!("Received TM[1,3] start success for request ID {req_id}")
|
||||||
} else if pus_tm.subservice() == 4 {
|
} else if pus_tm.subservice() == 4 {
|
||||||
println!("Received TM[1,2] start failure for request ID {}", req_id)
|
println!("Received TM[1,2] start failure for request ID {req_id}")
|
||||||
} else if pus_tm.subservice() == 5 {
|
} else if pus_tm.subservice() == 5 {
|
||||||
println!("Received TM[1,5] step success for request ID {}", req_id)
|
println!("Received TM[1,5] step success for request ID {req_id}")
|
||||||
} else if pus_tm.subservice() == 6 {
|
} else if pus_tm.subservice() == 6 {
|
||||||
println!("Received TM[1,6] step failure for request ID {}", req_id)
|
println!("Received TM[1,6] step failure for request ID {req_id}")
|
||||||
} else if pus_tm.subservice() == 7 {
|
} else if pus_tm.subservice() == 7 {
|
||||||
println!(
|
println!("Received TM[1,7] completion success for request ID {req_id}")
|
||||||
"Received TM[1,7] completion success for request ID {}",
|
|
||||||
req_id
|
|
||||||
)
|
|
||||||
} else if pus_tm.subservice() == 8 {
|
} else if pus_tm.subservice() == 8 {
|
||||||
println!(
|
println!("Received TM[1,8] completion failure for request ID {req_id}");
|
||||||
"Received TM[1,8] completion failure for request ID {}",
|
|
||||||
req_id
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
println!(
|
println!(
|
||||||
|
@ -49,7 +49,7 @@ fn main() {
|
|||||||
let jh0 = thread::spawn(move || {
|
let jh0 = thread::spawn(move || {
|
||||||
let data = r0.recv().unwrap();
|
let data = r0.recv().unwrap();
|
||||||
let raw = data.get_data();
|
let raw = data.get_data();
|
||||||
println!("Received data {:?}", raw);
|
println!("Received data {raw:?}");
|
||||||
});
|
});
|
||||||
let jh1 = thread::spawn(|| {});
|
let jh1 = thread::spawn(|| {});
|
||||||
jh0.join().unwrap();
|
jh0.join().unwrap();
|
||||||
|
@ -181,7 +181,7 @@ impl PusReceiver {
|
|||||||
let sender = self.request_map.get(&addressable_id.target_id).unwrap();
|
let sender = self.request_map.get(&addressable_id.target_id).unwrap();
|
||||||
sender
|
sender
|
||||||
.send(RequestWithToken(Request::HkRequest(request), token))
|
.send(RequestWithToken(Request::HkRequest(request), token))
|
||||||
.unwrap_or_else(|_| panic!("Sending HK request {:?} failed", request));
|
.unwrap_or_else(|_| panic!("Sending HK request {request:?} failed"));
|
||||||
};
|
};
|
||||||
if PusPacket::subservice(pus_tc) == hk::Subservice::TcEnableGeneration as u8 {
|
if PusPacket::subservice(pus_tc) == hk::Subservice::TcEnableGeneration as u8 {
|
||||||
send_request(HkRequest::Enable(addressable_id));
|
send_request(HkRequest::Enable(addressable_id));
|
||||||
|
@ -60,10 +60,10 @@ impl Display for MpscStoreAndSendError {
|
|||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
MpscStoreAndSendError::StoreError(s) => {
|
MpscStoreAndSendError::StoreError(s) => {
|
||||||
write!(f, "store error {}", s)
|
write!(f, "store error {s}")
|
||||||
}
|
}
|
||||||
MpscStoreAndSendError::SendError(s) => {
|
MpscStoreAndSendError::SendError(s) => {
|
||||||
write!(f, "send error {}", s)
|
write!(f, "send error {s}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -245,8 +245,8 @@ fn core_tmtc_loop(
|
|||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
lkoester marked this conversation as resolved
Outdated
|
|||||||
println!("error creating PUS TC from raw data: {}", e);
|
println!("error creating PUS TC from raw data: {e}");
|
||||||
println!("raw data: {:x?}", data);
|
println!("raw data: {data:x?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -266,7 +266,7 @@ fn poll_tc_server(udp_tmtc_server: &mut UdpTmtcServer) -> bool {
|
|||||||
Ok(_) => true,
|
Ok(_) => true,
|
||||||
Err(e) => match e {
|
Err(e) => match e {
|
||||||
ReceiveResult::ReceiverError(e) => match e {
|
ReceiveResult::ReceiverError(e) => match e {
|
||||||
CcsdsError::PacketError(e) => {
|
CcsdsError::ByteConversionError(e) => {
|
||||||
println!("Got packet error: {e:?}");
|
println!("Got packet error: {e:?}");
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
@ -295,7 +295,7 @@ fn core_tm_handling(udp_tmtc_server: &mut UdpTmtcServer, recv_addr: &SocketAddr)
|
|||||||
if buf.len() > 9 {
|
if buf.len() > 9 {
|
||||||
let service = buf[7];
|
let service = buf[7];
|
||||||
let subservice = buf[8];
|
let subservice = buf[8];
|
||||||
println!("Sending PUS TM[{},{}]", service, subservice)
|
println!("Sending PUS TM[{service},{subservice}]")
|
||||||
} else {
|
} else {
|
||||||
println!("Sending PUS TM");
|
println!("Sending PUS TM");
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user
can be deleted