diff --git a/satrs-example/Cargo.toml b/satrs-example/Cargo.toml index 4814001..27ffee9 100644 --- a/satrs-example/Cargo.toml +++ b/satrs-example/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "satrs-example" -version = "0.1.0" +version = "0.1.1" edition = "2021" authors = ["Robin Mueller "] default-run = "satrs-example" @@ -20,12 +20,12 @@ thiserror = "1" derive-new = "0.5" [dependencies.satrs] -# version = "0.1.1" +# version = "0.2.0-rc.0" path = "../satrs" [dependencies.satrs-mib] -# version = "0.1.0" -path = "../satrs-mib" +version = "0.1.1" +# path = "../satrs-mib" [features] dyn_tmtc = [] diff --git a/satrs-example/src/acs.rs b/satrs-example/src/acs.rs index 5c400f7..4fbea90 100644 --- a/satrs-example/src/acs.rs +++ b/satrs-example/src/acs.rs @@ -1,7 +1,7 @@ use std::sync::mpsc::{self, TryRecvError}; use log::{info, warn}; -use satrs::pus::verification::{VerificationReporterWithSender, VerificationReportingProvider}; +use satrs::pus::verification::VerificationReportingProvider; use satrs::pus::{EcssTmSender, PusTmWrapper}; use satrs::request::TargetAndApidId; use satrs::spacepackets::ecss::hk::Subservice as HkSubservice; @@ -21,19 +21,19 @@ use crate::{ update_time, }; -pub struct AcsTask { +pub struct AcsTask { timestamp: [u8; 7], time_provider: TimeProvider, - verif_reporter: VerificationReporterWithSender, + verif_reporter: VerificationReporter, tm_sender: Box, request_rx: mpsc::Receiver, } -impl AcsTask { +impl AcsTask { pub fn new( tm_sender: impl EcssTmSender, request_rx: mpsc::Receiver, - verif_reporter: VerificationReporterWithSender, + verif_reporter: VerificationReporter, ) -> Self { Self { timestamp: [0; 7], diff --git a/satrs-example/src/events.rs b/satrs-example/src/events.rs index 46ba6bb..a6a0d86 100644 --- a/satrs-example/src/events.rs +++ b/satrs-example/src/events.rs @@ -1,21 +1,17 @@ -use std::sync::mpsc::{self, SendError}; +use std::sync::mpsc::{self}; use satrs::{ event_man::{ - EventManager, EventManagerWithMpscQueue, MpscEventReceiver, MpscEventU32SendProvider, - SendEventProvider, + EventManagerWithBoundedMpsc, EventSendProvider, EventU32SenderMpscBounded, + MpscEventReceiver, }, events::EventU32, params::Params, pus::{ event_man::{ - DefaultPusMgmtBackendProvider, EventReporter, EventRequest, EventRequestWithToken, - PusEventDispatcher, - }, - verification::{ - TcStateStarted, VerificationReporterWithSender, VerificationReportingProvider, - VerificationToken, + DefaultPusEventU32Dispatcher, EventReporter, EventRequest, EventRequestWithToken, }, + verification::{TcStateStarted, VerificationReportingProvider, VerificationToken}, EcssTmSender, }, spacepackets::time::cds::{self, TimeProvider}, @@ -24,38 +20,37 @@ use satrs_example::config::PUS_APID; use crate::update_time; -pub type MpscEventManager = EventManager)>>; - -pub struct PusEventHandler { +pub struct PusEventHandler { event_request_rx: mpsc::Receiver, - pus_event_dispatcher: PusEventDispatcher<(), EventU32>, + pus_event_dispatcher: DefaultPusEventU32Dispatcher<()>, pus_event_man_rx: mpsc::Receiver<(EventU32, Option)>, tm_sender: Box, time_provider: TimeProvider, timestamp: [u8; 7], - verif_handler: VerificationReporterWithSender, + verif_handler: VerificationReporter, } /* */ -impl PusEventHandler { +impl PusEventHandler { pub fn new( - verif_handler: VerificationReporterWithSender, - event_manager: &mut MpscEventManager, + verif_handler: VerificationReporter, + event_manager: &mut EventManagerWithBoundedMpsc, event_request_rx: mpsc::Receiver, tm_sender: impl EcssTmSender, ) -> Self { - let (pus_event_man_tx, pus_event_man_rx) = mpsc::channel(); + let event_queue_cap = 30; + let (pus_event_man_tx, pus_event_man_rx) = mpsc::sync_channel(event_queue_cap); // All events sent to the manager are routed to the PUS event manager, which generates PUS event // telemetry for each event. let event_reporter = EventReporter::new(PUS_APID, 128).unwrap(); - let pus_tm_backend = DefaultPusMgmtBackendProvider::::default(); let pus_event_dispatcher = - PusEventDispatcher::new(event_reporter, Box::new(pus_tm_backend)); - let pus_event_man_send_provider = MpscEventU32SendProvider::new(1, pus_event_man_tx); + DefaultPusEventU32Dispatcher::new_with_default_backend(event_reporter); + let pus_event_man_send_provider = + EventU32SenderMpscBounded::new(1, pus_event_man_tx, event_queue_cap); - event_manager.subscribe_all(pus_event_man_send_provider.id()); + event_manager.subscribe_all(pus_event_man_send_provider.channel_id()); event_manager.add_sender(pus_event_man_send_provider); Self { @@ -117,7 +112,7 @@ impl PusEventHandler { } pub struct EventManagerWrapper { - event_manager: MpscEventManager, + event_manager: EventManagerWithBoundedMpsc, event_sender: mpsc::Sender<(EventU32, Option)>, } @@ -128,7 +123,7 @@ impl EventManagerWrapper { let (event_sender, event_man_rx) = mpsc::channel(); let event_recv = MpscEventReceiver::::new(event_man_rx); Self { - event_manager: EventManagerWithMpscQueue::new(Box::new(event_recv)), + event_manager: EventManagerWithBoundedMpsc::new(event_recv), event_sender, } } @@ -137,7 +132,7 @@ impl EventManagerWrapper { self.event_sender.clone() } - pub fn event_manager(&mut self) -> &mut MpscEventManager { + pub fn event_manager(&mut self) -> &mut EventManagerWithBoundedMpsc { &mut self.event_manager } @@ -149,15 +144,15 @@ impl EventManagerWrapper { } } -pub struct EventHandler { +pub struct EventHandler { pub event_man_wrapper: EventManagerWrapper, - pub pus_event_handler: PusEventHandler, + pub pus_event_handler: PusEventHandler, } -impl EventHandler { +impl EventHandler { pub fn new( tm_sender: impl EcssTmSender, - verif_handler: VerificationReporterWithSender, + verif_handler: VerificationReporter, event_request_rx: mpsc::Receiver, ) -> Self { let mut event_man_wrapper = EventManagerWrapper::new(); @@ -178,7 +173,7 @@ impl EventHandler { } #[allow(dead_code)] - pub fn event_manager(&mut self) -> &mut MpscEventManager { + pub fn event_manager(&mut self) -> &mut EventManagerWithBoundedMpsc { self.event_man_wrapper.event_manager() } diff --git a/satrs-example/src/main.rs b/satrs-example/src/main.rs index 76f2ffd..9844424 100644 --- a/satrs-example/src/main.rs +++ b/satrs-example/src/main.rs @@ -44,7 +44,7 @@ use crate::tmtc::{ use crate::udp::{StaticUdpTmHandler, UdpTmtcServer}; use satrs::pus::event_man::EventRequestWithToken; use satrs::pus::verification::{VerificationReporterCfg, VerificationReporterWithSender}; -use satrs::pus::{EcssTmSender, MpscTmAsVecSender, MpscTmInSharedPoolSender}; +use satrs::pus::{EcssTmSender, TmAsVecSenderWithId, TmInSharedPoolSenderWithId}; use satrs::spacepackets::{time::cds::TimeProvider, time::TimeWriter}; use satrs::tmtc::CcsdsDistributor; use satrs::ChannelId; @@ -54,11 +54,13 @@ use std::sync::{Arc, RwLock}; use std::thread; use std::time::Duration; -fn create_verification_reporter(verif_sender: impl EcssTmSender) -> VerificationReporterWithSender { +fn create_verification_reporter( + verif_sender: Sender, +) -> VerificationReporterWithSender { let verif_cfg = VerificationReporterCfg::new(PUS_APID, 1, 2, 8).unwrap(); // Every software component which needs to generate verification telemetry, gets a cloned // verification reporter. - VerificationReporterWithSender::new(&verif_cfg, Box::new(verif_sender)) + VerificationReporterWithSender::new(&verif_cfg, verif_sender) } #[allow(dead_code)] @@ -68,13 +70,13 @@ fn static_tmtc_pool_main() { let shared_tc_pool = SharedTcPool { pool: Arc::new(RwLock::new(tc_pool)), }; - let (tc_source_tx, tc_source_rx) = channel(); - let (tm_funnel_tx, tm_funnel_rx) = channel(); - let (tm_server_tx, tm_server_rx) = channel(); + let (tc_source_tx, tc_source_rx) = mpsc::sync_channel(50); + let (tm_funnel_tx, tm_funnel_rx) = mpsc::sync_channel(50); + let (tm_server_tx, tm_server_rx) = mpsc::sync_channel(50); // Every software component which needs to generate verification telemetry, receives a cloned // verification reporter. - let verif_reporter = create_verification_reporter(MpscTmInSharedPoolSender::new( + let verif_reporter = create_verification_reporter(TmInSharedPoolSenderWithId::new( TmSenderId::PusVerification as ChannelId, "verif_sender", shared_tm_pool.clone(), @@ -102,7 +104,7 @@ fn static_tmtc_pool_main() { // The event task is the core handler to perform the event routing and TM handling as specified // in the sat-rs documentation. let mut event_handler = EventHandler::new( - MpscTmInSharedPoolSender::new( + TmInSharedPoolSenderWithId::new( TmSenderId::AllEvents as ChannelId, "ALL_EVENTS_TX", shared_tm_pool.clone(), @@ -202,7 +204,7 @@ fn static_tmtc_pool_main() { .expect("tcp server creation failed"); let mut acs_task = AcsTask::new( - MpscTmInSharedPoolSender::new( + TmInSharedPoolSenderWithId::new( TmSenderId::AcsSubsystem as ChannelId, "ACS_TASK_SENDER", shared_tm_pool.clone(), @@ -303,7 +305,7 @@ fn dyn_tmtc_pool_main() { let (tm_server_tx, tm_server_rx) = channel(); // Every software component which needs to generate verification telemetry, gets a cloned // verification reporter. - let verif_reporter = create_verification_reporter(MpscTmAsVecSender::new( + let verif_reporter = create_verification_reporter(TmAsVecSenderWithId::new( TmSenderId::PusVerification as ChannelId, "verif_sender", tm_funnel_tx.clone(), @@ -324,7 +326,7 @@ fn dyn_tmtc_pool_main() { // The event task is the core handler to perform the event routing and TM handling as specified // in the sat-rs documentation. let mut event_handler = EventHandler::new( - MpscTmAsVecSender::new( + TmAsVecSenderWithId::new( TmSenderId::AllEvents as ChannelId, "ALL_EVENTS_TX", tm_funnel_tx.clone(), @@ -415,7 +417,7 @@ fn dyn_tmtc_pool_main() { .expect("tcp server creation failed"); let mut acs_task = AcsTask::new( - MpscTmAsVecSender::new( + TmAsVecSenderWithId::new( TmSenderId::AcsSubsystem as ChannelId, "ACS_TASK_SENDER", tm_funnel_tx.clone(), diff --git a/satrs-example/src/pus/action.rs b/satrs-example/src/pus/action.rs index 653fe80..ef23786 100644 --- a/satrs-example/src/pus/action.rs +++ b/satrs-example/src/pus/action.rs @@ -2,14 +2,17 @@ use log::{error, warn}; use satrs::action::ActionRequest; use satrs::pool::{SharedStaticMemoryPool, StoreAddr}; use satrs::pus::action::{PusActionToRequestConverter, PusService8ActionHandler}; +use satrs::pus::verification::std_mod::{ + VerificationReporterWithSharedPoolMpscBoundedSender, VerificationReporterWithVecMpscSender, +}; use satrs::pus::verification::{ - FailParams, TcStateAccepted, VerificationReporterWithSender, VerificationReportingProvider, - VerificationToken, + FailParams, TcStateAccepted, VerificationReportingProvider, VerificationToken, }; use satrs::pus::{ EcssTcAndToken, EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter, - MpscTcReceiver, MpscTmAsVecSender, MpscTmInSharedPoolSender, PusPacketHandlerResult, - PusPacketHandlingError, PusServiceHelper, + EcssTcReceiverCore, EcssTmSenderCore, MpscTcReceiver, PusPacketHandlerResult, + PusPacketHandlingError, PusServiceHelper, TmAsVecSenderWithId, TmAsVecSenderWithMpsc, + TmInSharedPoolSenderWithBoundedMpsc, TmInSharedPoolSenderWithId, }; use satrs::request::TargetAndApidId; use satrs::spacepackets::ecss::tc::PusTcReader; @@ -74,13 +77,18 @@ impl PusActionToRequestConverter for ExampleActionRequestConverter { pub fn create_action_service_static( shared_tm_store: SharedTmPool, - tm_funnel_tx: mpsc::Sender, - verif_reporter: VerificationReporterWithSender, + tm_funnel_tx: mpsc::SyncSender, + verif_reporter: VerificationReporterWithSharedPoolMpscBoundedSender, tc_pool: SharedStaticMemoryPool, pus_action_rx: mpsc::Receiver, action_router: GenericRequestRouter, -) -> Pus8Wrapper { - let action_srv_tm_sender = MpscTmInSharedPoolSender::new( +) -> Pus8Wrapper< + MpscTcReceiver, + TmInSharedPoolSenderWithBoundedMpsc, + EcssTcInSharedStoreConverter, + VerificationReporterWithSharedPoolMpscBoundedSender, +> { + let action_srv_tm_sender = TmInSharedPoolSenderWithId::new( TmSenderId::PusAction as ChannelId, "PUS_8_TM_SENDER", shared_tm_store.clone(), @@ -93,8 +101,8 @@ pub fn create_action_service_static( ); let pus_8_handler = PusService8ActionHandler::new( PusServiceHelper::new( - Box::new(action_srv_receiver), - Box::new(action_srv_tm_sender), + action_srv_receiver, + action_srv_tm_sender, PUS_APID, verif_reporter.clone(), EcssTcInSharedStoreConverter::new(tc_pool.clone(), 2048), @@ -108,11 +116,16 @@ pub fn create_action_service_static( pub fn create_action_service_dynamic( tm_funnel_tx: mpsc::Sender>, - verif_reporter: VerificationReporterWithSender, + verif_reporter: VerificationReporterWithVecMpscSender, pus_action_rx: mpsc::Receiver, action_router: GenericRequestRouter, -) -> Pus8Wrapper { - let action_srv_tm_sender = MpscTmAsVecSender::new( +) -> Pus8Wrapper< + MpscTcReceiver, + TmAsVecSenderWithMpsc, + EcssTcInVecConverter, + VerificationReporterWithVecMpscSender, +> { + let action_srv_tm_sender = TmAsVecSenderWithId::new( TmSenderId::PusAction as ChannelId, "PUS_8_TM_SENDER", tm_funnel_tx.clone(), @@ -124,8 +137,8 @@ pub fn create_action_service_dynamic( ); let pus_8_handler = PusService8ActionHandler::new( PusServiceHelper::new( - Box::new(action_srv_receiver), - Box::new(action_srv_tm_sender), + action_srv_receiver, + action_srv_tm_sender, PUS_APID, verif_reporter.clone(), EcssTcInVecConverter::default(), @@ -137,17 +150,30 @@ pub fn create_action_service_dynamic( Pus8Wrapper { pus_8_handler } } -pub struct Pus8Wrapper { +pub struct Pus8Wrapper< + TcReceiver: EcssTcReceiverCore, + TmSender: EcssTmSenderCore, + TcInMemConverter: EcssTcInMemConverter, + VerificationReporter: VerificationReportingProvider, +> { pub(crate) pus_8_handler: PusService8ActionHandler< + TcReceiver, + TmSender, TcInMemConverter, - VerificationReporterWithSender, + VerificationReporter, ExampleActionRequestConverter, GenericRequestRouter, GenericRoutingErrorHandler<8>, >, } -impl Pus8Wrapper { +impl< + TcReceiver: EcssTcReceiverCore, + TmSender: EcssTmSenderCore, + TcInMemConverter: EcssTcInMemConverter, + VerificationReporter: VerificationReportingProvider, + > Pus8Wrapper +{ pub fn handle_next_packet(&mut self) -> bool { match self.pus_8_handler.handle_one_tc() { Ok(result) => match result { diff --git a/satrs-example/src/pus/event.rs b/satrs-example/src/pus/event.rs index 8256658..1d16f5c 100644 --- a/satrs-example/src/pus/event.rs +++ b/satrs-example/src/pus/event.rs @@ -4,11 +4,15 @@ use log::{error, warn}; use satrs::pool::{SharedStaticMemoryPool, StoreAddr}; use satrs::pus::event_man::EventRequestWithToken; use satrs::pus::event_srv::PusService5EventHandler; -use satrs::pus::verification::VerificationReporterWithSender; +use satrs::pus::verification::std_mod::{ + VerificationReporterWithSharedPoolMpscBoundedSender, VerificationReporterWithVecMpscSender, +}; +use satrs::pus::verification::VerificationReportingProvider; use satrs::pus::{ EcssTcAndToken, EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter, - MpscTcReceiver, MpscTmAsVecSender, MpscTmInSharedPoolSender, PusPacketHandlerResult, - PusServiceHelper, + EcssTcReceiverCore, EcssTmSenderCore, MpscTcReceiver, PusPacketHandlerResult, PusServiceHelper, + TmAsVecSenderWithId, TmAsVecSenderWithMpsc, TmInSharedPoolSenderWithBoundedMpsc, + TmInSharedPoolSenderWithId, }; use satrs::tmtc::tm_helper::SharedTmPool; use satrs::ChannelId; @@ -16,13 +20,18 @@ use satrs_example::config::{TcReceiverId, TmSenderId, PUS_APID}; pub fn create_event_service_static( shared_tm_store: SharedTmPool, - tm_funnel_tx: mpsc::Sender, - verif_reporter: VerificationReporterWithSender, + tm_funnel_tx: mpsc::SyncSender, + verif_reporter: VerificationReporterWithSharedPoolMpscBoundedSender, tc_pool: SharedStaticMemoryPool, pus_event_rx: mpsc::Receiver, event_request_tx: mpsc::Sender, -) -> Pus5Wrapper { - let event_srv_tm_sender = MpscTmInSharedPoolSender::new( +) -> Pus5Wrapper< + MpscTcReceiver, + TmInSharedPoolSenderWithBoundedMpsc, + EcssTcInSharedStoreConverter, + VerificationReporterWithSharedPoolMpscBoundedSender, +> { + let event_srv_tm_sender = TmInSharedPoolSenderWithId::new( TmSenderId::PusEvent as ChannelId, "PUS_5_TM_SENDER", shared_tm_store.clone(), @@ -35,8 +44,8 @@ pub fn create_event_service_static( ); let pus_5_handler = PusService5EventHandler::new( PusServiceHelper::new( - Box::new(event_srv_receiver), - Box::new(event_srv_tm_sender), + event_srv_receiver, + event_srv_tm_sender, PUS_APID, verif_reporter.clone(), EcssTcInSharedStoreConverter::new(tc_pool.clone(), 2048), @@ -48,11 +57,16 @@ pub fn create_event_service_static( pub fn create_event_service_dynamic( tm_funnel_tx: mpsc::Sender>, - verif_reporter: VerificationReporterWithSender, + verif_reporter: VerificationReporterWithVecMpscSender, pus_event_rx: mpsc::Receiver, event_request_tx: mpsc::Sender, -) -> Pus5Wrapper { - let event_srv_tm_sender = MpscTmAsVecSender::new( +) -> Pus5Wrapper< + MpscTcReceiver, + TmAsVecSenderWithMpsc, + EcssTcInVecConverter, + VerificationReporterWithVecMpscSender, +> { + let event_srv_tm_sender = TmAsVecSenderWithId::new( TmSenderId::PusEvent as ChannelId, "PUS_5_TM_SENDER", tm_funnel_tx, @@ -64,8 +78,8 @@ pub fn create_event_service_dynamic( ); let pus_5_handler = PusService5EventHandler::new( PusServiceHelper::new( - Box::new(event_srv_receiver), - Box::new(event_srv_tm_sender), + event_srv_receiver, + event_srv_tm_sender, PUS_APID, verif_reporter.clone(), EcssTcInVecConverter::default(), @@ -75,11 +89,23 @@ pub fn create_event_service_dynamic( Pus5Wrapper { pus_5_handler } } -pub struct Pus5Wrapper { - pub pus_5_handler: PusService5EventHandler, +pub struct Pus5Wrapper< + TcReceiver: EcssTcReceiverCore, + TmSender: EcssTmSenderCore, + TcInMemConverter: EcssTcInMemConverter, + VerificationReporter: VerificationReportingProvider, +> { + pub pus_5_handler: + PusService5EventHandler, } -impl Pus5Wrapper { +impl< + TcReceiver: EcssTcReceiverCore, + TmSender: EcssTmSenderCore, + TcInMemConverter: EcssTcInMemConverter, + VerificationReporter: VerificationReportingProvider, + > Pus5Wrapper +{ pub fn handle_next_packet(&mut self) -> bool { match self.pus_5_handler.handle_one_tc() { Ok(result) => match result { diff --git a/satrs-example/src/pus/hk.rs b/satrs-example/src/pus/hk.rs index 035bb86..48a54be 100644 --- a/satrs-example/src/pus/hk.rs +++ b/satrs-example/src/pus/hk.rs @@ -2,14 +2,17 @@ use log::{error, warn}; use satrs::hk::{CollectionIntervalFactor, HkRequest}; use satrs::pool::{SharedStaticMemoryPool, StoreAddr}; use satrs::pus::hk::{PusHkToRequestConverter, PusService3HkHandler}; +use satrs::pus::verification::std_mod::{ + VerificationReporterWithSharedPoolMpscBoundedSender, VerificationReporterWithVecMpscSender, +}; use satrs::pus::verification::{ - FailParams, TcStateAccepted, VerificationReporterWithSender, VerificationReportingProvider, - VerificationToken, + FailParams, TcStateAccepted, VerificationReportingProvider, VerificationToken, }; use satrs::pus::{ EcssTcAndToken, EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter, - MpscTcReceiver, MpscTmAsVecSender, MpscTmInSharedPoolSender, PusPacketHandlerResult, - PusPacketHandlingError, PusServiceHelper, + EcssTcReceiverCore, EcssTmSenderCore, MpscTcReceiver, PusPacketHandlerResult, + PusPacketHandlingError, PusServiceHelper, TmAsVecSenderWithId, TmAsVecSenderWithMpsc, + TmInSharedPoolSenderWithBoundedMpsc, TmInSharedPoolSenderWithId, }; use satrs::request::TargetAndApidId; use satrs::spacepackets::ecss::tc::PusTcReader; @@ -143,13 +146,18 @@ impl PusHkToRequestConverter for ExampleHkRequestConverter { pub fn create_hk_service_static( shared_tm_store: SharedTmPool, - tm_funnel_tx: mpsc::Sender, - verif_reporter: VerificationReporterWithSender, + tm_funnel_tx: mpsc::SyncSender, + verif_reporter: VerificationReporterWithSharedPoolMpscBoundedSender, tc_pool: SharedStaticMemoryPool, pus_hk_rx: mpsc::Receiver, request_router: GenericRequestRouter, -) -> Pus3Wrapper { - let hk_srv_tm_sender = MpscTmInSharedPoolSender::new( +) -> Pus3Wrapper< + MpscTcReceiver, + TmInSharedPoolSenderWithBoundedMpsc, + EcssTcInSharedStoreConverter, + VerificationReporterWithSharedPoolMpscBoundedSender, +> { + let hk_srv_tm_sender = TmInSharedPoolSenderWithId::new( TmSenderId::PusHk as ChannelId, "PUS_3_TM_SENDER", shared_tm_store.clone(), @@ -159,8 +167,8 @@ pub fn create_hk_service_static( MpscTcReceiver::new(TcReceiverId::PusHk as ChannelId, "PUS_8_TC_RECV", pus_hk_rx); let pus_3_handler = PusService3HkHandler::new( PusServiceHelper::new( - Box::new(hk_srv_receiver), - Box::new(hk_srv_tm_sender), + hk_srv_receiver, + hk_srv_tm_sender, PUS_APID, verif_reporter.clone(), EcssTcInSharedStoreConverter::new(tc_pool, 2048), @@ -174,11 +182,16 @@ pub fn create_hk_service_static( pub fn create_hk_service_dynamic( tm_funnel_tx: mpsc::Sender>, - verif_reporter: VerificationReporterWithSender, + verif_reporter: VerificationReporterWithVecMpscSender, pus_hk_rx: mpsc::Receiver, request_router: GenericRequestRouter, -) -> Pus3Wrapper { - let hk_srv_tm_sender = MpscTmAsVecSender::new( +) -> Pus3Wrapper< + MpscTcReceiver, + TmAsVecSenderWithMpsc, + EcssTcInVecConverter, + VerificationReporterWithVecMpscSender, +> { + let hk_srv_tm_sender = TmAsVecSenderWithId::new( TmSenderId::PusHk as ChannelId, "PUS_3_TM_SENDER", tm_funnel_tx.clone(), @@ -187,8 +200,8 @@ pub fn create_hk_service_dynamic( MpscTcReceiver::new(TcReceiverId::PusHk as ChannelId, "PUS_8_TC_RECV", pus_hk_rx); let pus_3_handler = PusService3HkHandler::new( PusServiceHelper::new( - Box::new(hk_srv_receiver), - Box::new(hk_srv_tm_sender), + hk_srv_receiver, + hk_srv_tm_sender, PUS_APID, verif_reporter.clone(), EcssTcInVecConverter::default(), @@ -200,17 +213,30 @@ pub fn create_hk_service_dynamic( Pus3Wrapper { pus_3_handler } } -pub struct Pus3Wrapper { +pub struct Pus3Wrapper< + TcReceiver: EcssTcReceiverCore, + TmSender: EcssTmSenderCore, + TcInMemConverter: EcssTcInMemConverter, + VerificationReporter: VerificationReportingProvider, +> { pub(crate) pus_3_handler: PusService3HkHandler< + TcReceiver, + TmSender, TcInMemConverter, - VerificationReporterWithSender, + VerificationReporter, ExampleHkRequestConverter, GenericRequestRouter, GenericRoutingErrorHandler<3>, >, } -impl Pus3Wrapper { +impl< + TcReceiver: EcssTcReceiverCore, + TmSender: EcssTmSenderCore, + TcInMemConverter: EcssTcInMemConverter, + VerificationReporter: VerificationReportingProvider, + > Pus3Wrapper +{ pub fn handle_next_packet(&mut self) -> bool { match self.pus_3_handler.handle_one_tc() { Ok(result) => match result { diff --git a/satrs-example/src/pus/mod.rs b/satrs-example/src/pus/mod.rs index b903cb4..2b6c3ed 100644 --- a/satrs-example/src/pus/mod.rs +++ b/satrs-example/src/pus/mod.rs @@ -1,8 +1,6 @@ use crate::tmtc::MpscStoreAndSendError; use log::warn; -use satrs::pus::verification::{ - FailParams, StdVerifReporterWithSender, VerificationReportingProvider, -}; +use satrs::pus::verification::{FailParams, VerificationReportingProvider}; use satrs::pus::{ EcssTcAndToken, GenericRoutingError, PusPacketHandlerResult, PusRoutingErrorHandler, TcInMemory, }; @@ -28,8 +26,8 @@ pub struct PusTcMpscRouter { pub action_service_receiver: Sender, } -pub struct PusReceiver { - pub verif_reporter: StdVerifReporterWithSender, +pub struct PusReceiver { + pub verif_reporter: VerificationReporter, pub pus_router: PusTcMpscRouter, stamp_helper: TimeStampHelper, } @@ -61,8 +59,8 @@ impl TimeStampHelper { } } -impl PusReceiver { - pub fn new(verif_reporter: StdVerifReporterWithSender, pus_router: PusTcMpscRouter) -> Self { +impl PusReceiver { + pub fn new(verif_reporter: VerificationReporter, pus_router: PusTcMpscRouter) -> Self { Self { verif_reporter, pus_router, @@ -71,7 +69,7 @@ impl PusReceiver { } } -impl PusReceiver { +impl PusReceiver { pub fn handle_tc_packet( &mut self, tc_in_memory: TcInMemory, diff --git a/satrs-example/src/pus/scheduler.rs b/satrs-example/src/pus/scheduler.rs index 8b5ec47..c5d2c06 100644 --- a/satrs-example/src/pus/scheduler.rs +++ b/satrs-example/src/pus/scheduler.rs @@ -5,11 +5,15 @@ use log::{error, info, warn}; use satrs::pool::{PoolProvider, StaticMemoryPool, StoreAddr}; use satrs::pus::scheduler::{PusScheduler, TcInfo}; use satrs::pus::scheduler_srv::PusService11SchedHandler; -use satrs::pus::verification::VerificationReporterWithSender; +use satrs::pus::verification::std_mod::{ + VerificationReporterWithSharedPoolMpscBoundedSender, VerificationReporterWithVecMpscSender, +}; +use satrs::pus::verification::VerificationReportingProvider; use satrs::pus::{ EcssTcAndToken, EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter, - MpscTcReceiver, MpscTmAsVecSender, MpscTmInSharedPoolSender, PusPacketHandlerResult, - PusServiceHelper, + EcssTcReceiverCore, EcssTmSenderCore, MpscTcReceiver, PusPacketHandlerResult, PusServiceHelper, + TmAsVecSenderWithId, TmAsVecSenderWithMpsc, TmInSharedPoolSenderWithBoundedMpsc, + TmInSharedPoolSenderWithId, }; use satrs::tmtc::tm_helper::SharedTmPool; use satrs::ChannelId; @@ -51,15 +55,31 @@ impl TcReleaser for mpsc::Sender> { } } -pub struct Pus11Wrapper { - pub pus_11_handler: - PusService11SchedHandler, +pub struct Pus11Wrapper< + TcReceiver: EcssTcReceiverCore, + TmSender: EcssTmSenderCore, + TcInMemConverter: EcssTcInMemConverter, + VerificationReporter: VerificationReportingProvider, +> { + pub pus_11_handler: PusService11SchedHandler< + TcReceiver, + TmSender, + TcInMemConverter, + VerificationReporter, + PusScheduler, + >, pub sched_tc_pool: StaticMemoryPool, pub releaser_buf: [u8; 4096], pub tc_releaser: Box, } -impl Pus11Wrapper { +impl< + TcReceiver: EcssTcReceiverCore, + TmSender: EcssTmSenderCore, + TcInMemConverter: EcssTcInMemConverter, + VerificationReporter: VerificationReportingProvider, + > Pus11Wrapper +{ pub fn release_tcs(&mut self) { let releaser = |enabled: bool, info: &TcInfo, tc: &[u8]| -> bool { self.tc_releaser.release(enabled, info, tc) @@ -110,13 +130,18 @@ impl Pus11Wrapper { pub fn create_scheduler_service_static( shared_tm_store: SharedTmPool, - tm_funnel_tx: mpsc::Sender, - verif_reporter: VerificationReporterWithSender, + tm_funnel_tx: mpsc::SyncSender, + verif_reporter: VerificationReporterWithSharedPoolMpscBoundedSender, tc_releaser: PusTcSourceProviderSharedPool, pus_sched_rx: mpsc::Receiver, sched_tc_pool: StaticMemoryPool, -) -> Pus11Wrapper { - let sched_srv_tm_sender = MpscTmInSharedPoolSender::new( +) -> Pus11Wrapper< + MpscTcReceiver, + TmInSharedPoolSenderWithBoundedMpsc, + EcssTcInSharedStoreConverter, + VerificationReporterWithSharedPoolMpscBoundedSender, +> { + let sched_srv_tm_sender = TmInSharedPoolSenderWithId::new( TmSenderId::PusSched as ChannelId, "PUS_11_TM_SENDER", shared_tm_store.clone(), @@ -131,8 +156,8 @@ pub fn create_scheduler_service_static( .expect("Creating PUS Scheduler failed"); let pus_11_handler = PusService11SchedHandler::new( PusServiceHelper::new( - Box::new(sched_srv_receiver), - Box::new(sched_srv_tm_sender), + sched_srv_receiver, + sched_srv_tm_sender, PUS_APID, verif_reporter.clone(), EcssTcInSharedStoreConverter::new(tc_releaser.clone_backing_pool(), 2048), @@ -149,12 +174,17 @@ pub fn create_scheduler_service_static( pub fn create_scheduler_service_dynamic( tm_funnel_tx: mpsc::Sender>, - verif_reporter: VerificationReporterWithSender, + verif_reporter: VerificationReporterWithVecMpscSender, tc_source_sender: mpsc::Sender>, pus_sched_rx: mpsc::Receiver, sched_tc_pool: StaticMemoryPool, -) -> Pus11Wrapper { - let sched_srv_tm_sender = MpscTmAsVecSender::new( +) -> Pus11Wrapper< + MpscTcReceiver, + TmAsVecSenderWithMpsc, + EcssTcInVecConverter, + VerificationReporterWithVecMpscSender, +> { + let sched_srv_tm_sender = TmAsVecSenderWithId::new( TmSenderId::PusSched as ChannelId, "PUS_11_TM_SENDER", tm_funnel_tx, @@ -168,8 +198,8 @@ pub fn create_scheduler_service_dynamic( .expect("Creating PUS Scheduler failed"); let pus_11_handler = PusService11SchedHandler::new( PusServiceHelper::new( - Box::new(sched_srv_receiver), - Box::new(sched_srv_tm_sender), + sched_srv_receiver, + sched_srv_tm_sender, PUS_APID, verif_reporter.clone(), EcssTcInVecConverter::default(), diff --git a/satrs-example/src/pus/stack.rs b/satrs-example/src/pus/stack.rs index 98718be..ed06e08 100644 --- a/satrs-example/src/pus/stack.rs +++ b/satrs-example/src/pus/stack.rs @@ -1,25 +1,44 @@ -use satrs::pus::EcssTcInMemConverter; +use satrs::pus::{ + verification::VerificationReportingProvider, EcssTcInMemConverter, EcssTcReceiverCore, + EcssTmSenderCore, +}; use super::{ action::Pus8Wrapper, event::Pus5Wrapper, hk::Pus3Wrapper, scheduler::Pus11Wrapper, test::Service17CustomWrapper, }; -pub struct PusStack { - event_srv: Pus5Wrapper, - hk_srv: Pus3Wrapper, - action_srv: Pus8Wrapper, - schedule_srv: Pus11Wrapper, - test_srv: Service17CustomWrapper, +pub struct PusStack< + TcReceiver: EcssTcReceiverCore, + TmSender: EcssTmSenderCore, + TcInMemConverter: EcssTcInMemConverter, + VerificationReporter: VerificationReportingProvider, +> { + event_srv: Pus5Wrapper, + hk_srv: Pus3Wrapper, + action_srv: Pus8Wrapper, + schedule_srv: Pus11Wrapper, + test_srv: Service17CustomWrapper, } -impl PusStack { +impl< + TcReceiver: EcssTcReceiverCore, + TmSender: EcssTmSenderCore, + TcInMemConverter: EcssTcInMemConverter, + VerificationReporter: VerificationReportingProvider, + > PusStack +{ pub fn new( - hk_srv: Pus3Wrapper, - event_srv: Pus5Wrapper, - action_srv: Pus8Wrapper, - schedule_srv: Pus11Wrapper, - test_srv: Service17CustomWrapper, + hk_srv: Pus3Wrapper, + event_srv: Pus5Wrapper, + action_srv: Pus8Wrapper, + schedule_srv: Pus11Wrapper, + test_srv: Service17CustomWrapper< + TcReceiver, + TmSender, + TcInMemConverter, + VerificationReporter, + >, ) -> Self { Self { event_srv, diff --git a/satrs-example/src/pus/test.rs b/satrs-example/src/pus/test.rs index fe52af7..17822a3 100644 --- a/satrs-example/src/pus/test.rs +++ b/satrs-example/src/pus/test.rs @@ -2,12 +2,15 @@ use log::{info, warn}; use satrs::params::Params; use satrs::pool::{SharedStaticMemoryPool, StoreAddr}; use satrs::pus::test::PusService17TestHandler; +use satrs::pus::verification::{FailParams, VerificationReportingProvider}; use satrs::pus::verification::{ - FailParams, VerificationReporterWithSender, VerificationReportingProvider, + VerificationReporterWithSharedPoolMpscBoundedSender, VerificationReporterWithVecMpscSender, }; use satrs::pus::{ - EcssTcAndToken, EcssTcInMemConverter, EcssTcInVecConverter, MpscTcReceiver, MpscTmAsVecSender, - MpscTmInSharedPoolSender, PusPacketHandlerResult, PusServiceHelper, + EcssTcAndToken, EcssTcInMemConverter, EcssTcInVecConverter, EcssTcReceiverCore, + EcssTmSenderCore, MpscTcReceiver, PusPacketHandlerResult, PusServiceHelper, + TmAsVecSenderWithId, TmAsVecSenderWithMpsc, TmInSharedPoolSenderWithBoundedMpsc, + TmInSharedPoolSenderWithId, }; use satrs::spacepackets::ecss::tc::PusTcReader; use satrs::spacepackets::ecss::PusPacket; @@ -21,13 +24,18 @@ use std::sync::mpsc::{self, Sender}; pub fn create_test_service_static( shared_tm_store: SharedTmPool, - tm_funnel_tx: mpsc::Sender, - verif_reporter: VerificationReporterWithSender, + tm_funnel_tx: mpsc::SyncSender, + verif_reporter: VerificationReporterWithSharedPoolMpscBoundedSender, tc_pool: SharedStaticMemoryPool, event_sender: mpsc::Sender<(EventU32, Option)>, pus_test_rx: mpsc::Receiver, -) -> Service17CustomWrapper { - let test_srv_tm_sender = MpscTmInSharedPoolSender::new( +) -> Service17CustomWrapper< + MpscTcReceiver, + TmInSharedPoolSenderWithBoundedMpsc, + EcssTcInSharedStoreConverter, + VerificationReporterWithSharedPoolMpscBoundedSender, +> { + let test_srv_tm_sender = TmInSharedPoolSenderWithId::new( TmSenderId::PusTest as ChannelId, "PUS_17_TM_SENDER", shared_tm_store.clone(), @@ -39,8 +47,8 @@ pub fn create_test_service_static( pus_test_rx, ); let pus17_handler = PusService17TestHandler::new(PusServiceHelper::new( - Box::new(test_srv_receiver), - Box::new(test_srv_tm_sender), + test_srv_receiver, + test_srv_tm_sender, PUS_APID, verif_reporter.clone(), EcssTcInSharedStoreConverter::new(tc_pool, 2048), @@ -53,11 +61,16 @@ pub fn create_test_service_static( pub fn create_test_service_dynamic( tm_funnel_tx: mpsc::Sender>, - verif_reporter: VerificationReporterWithSender, + verif_reporter: VerificationReporterWithVecMpscSender, event_sender: mpsc::Sender<(EventU32, Option)>, pus_test_rx: mpsc::Receiver, -) -> Service17CustomWrapper { - let test_srv_tm_sender = MpscTmAsVecSender::new( +) -> Service17CustomWrapper< + MpscTcReceiver, + TmAsVecSenderWithMpsc, + EcssTcInVecConverter, + VerificationReporterWithVecMpscSender, +> { + let test_srv_tm_sender = TmAsVecSenderWithId::new( TmSenderId::PusTest as ChannelId, "PUS_17_TM_SENDER", tm_funnel_tx.clone(), @@ -68,8 +81,8 @@ pub fn create_test_service_dynamic( pus_test_rx, ); let pus17_handler = PusService17TestHandler::new(PusServiceHelper::new( - Box::new(test_srv_receiver), - Box::new(test_srv_tm_sender), + test_srv_receiver, + test_srv_tm_sender, PUS_APID, verif_reporter.clone(), EcssTcInVecConverter::default(), @@ -80,12 +93,24 @@ pub fn create_test_service_dynamic( } } -pub struct Service17CustomWrapper { - pub pus17_handler: PusService17TestHandler, +pub struct Service17CustomWrapper< + TcReceiver: EcssTcReceiverCore, + TmSender: EcssTmSenderCore, + TcInMemConverter: EcssTcInMemConverter, + VerificationReporter: VerificationReportingProvider, +> { + pub pus17_handler: + PusService17TestHandler, pub test_srv_event_sender: Sender<(EventU32, Option)>, } -impl Service17CustomWrapper { +impl< + TcReceiver: EcssTcReceiverCore, + TmSender: EcssTmSenderCore, + TcInMemConverter: EcssTcInMemConverter, + VerificationReporter: VerificationReportingProvider, + > Service17CustomWrapper +{ pub fn handle_next_packet(&mut self) -> bool { let res = self.pus17_handler.handle_one_tc(); if res.is_err() { diff --git a/satrs-example/src/tm_funnel.rs b/satrs-example/src/tm_funnel.rs index af35045..8b6285f 100644 --- a/satrs-example/src/tm_funnel.rs +++ b/satrs-example/src/tm_funnel.rs @@ -1,6 +1,6 @@ use std::{ collections::HashMap, - sync::mpsc::{Receiver, Sender}, + sync::mpsc::{self}, }; use log::info; @@ -77,16 +77,16 @@ impl TmFunnelCommon { pub struct TmFunnelStatic { common: TmFunnelCommon, shared_tm_store: SharedTmPool, - tm_funnel_rx: Receiver, - tm_server_tx: Sender, + tm_funnel_rx: mpsc::Receiver, + tm_server_tx: mpsc::SyncSender, } impl TmFunnelStatic { pub fn new( shared_tm_store: SharedTmPool, sync_tm_tcp_source: SyncTcpTmSource, - tm_funnel_rx: Receiver, - tm_server_tx: Sender, + tm_funnel_rx: mpsc::Receiver, + tm_server_tx: mpsc::SyncSender, ) -> Self { Self { common: TmFunnelCommon::new(sync_tm_tcp_source), @@ -123,15 +123,15 @@ impl TmFunnelStatic { pub struct TmFunnelDynamic { common: TmFunnelCommon, - tm_funnel_rx: Receiver>, - tm_server_tx: Sender>, + tm_funnel_rx: mpsc::Receiver>, + tm_server_tx: mpsc::Sender>, } impl TmFunnelDynamic { pub fn new( sync_tm_tcp_source: SyncTcpTmSource, - tm_funnel_rx: Receiver>, - tm_server_tx: Sender>, + tm_funnel_rx: mpsc::Receiver>, + tm_server_tx: mpsc::Sender>, ) -> Self { Self { common: TmFunnelCommon::new(sync_tm_tcp_source), diff --git a/satrs-example/src/tmtc.rs b/satrs-example/src/tmtc.rs index f615f23..0a43504 100644 --- a/satrs-example/src/tmtc.rs +++ b/satrs-example/src/tmtc.rs @@ -1,7 +1,10 @@ use log::warn; +use satrs::pus::verification::std_mod::{ + VerificationReporterWithSharedPoolMpscBoundedSender, VerificationReporterWithVecMpscSender, +}; use satrs::pus::{EcssTcAndToken, ReceivesEcssPusTc}; use satrs::spacepackets::SpHeader; -use std::sync::mpsc::{self, Receiver, SendError, Sender, TryRecvError}; +use std::sync::mpsc::{self, Receiver, SendError, Sender, SyncSender, TryRecvError}; use thiserror::Error; use crate::pus::PusReceiver; @@ -37,7 +40,7 @@ impl SharedTcPool { #[derive(Clone)] pub struct PusTcSourceProviderSharedPool { - pub tc_source: Sender, + pub tc_source: SyncSender, pub shared_pool: SharedTcPool, } @@ -97,14 +100,14 @@ pub struct TcSourceTaskStatic { shared_tc_pool: SharedTcPool, tc_receiver: Receiver, tc_buf: [u8; 4096], - pus_receiver: PusReceiver, + pus_receiver: PusReceiver, } impl TcSourceTaskStatic { pub fn new( shared_tc_pool: SharedTcPool, tc_receiver: Receiver, - pus_receiver: PusReceiver, + pus_receiver: PusReceiver, ) -> Self { Self { shared_tc_pool, @@ -161,11 +164,14 @@ impl TcSourceTaskStatic { // TC source components where the heap is the backing memory of the received telecommands. pub struct TcSourceTaskDynamic { pub tc_receiver: Receiver>, - pus_receiver: PusReceiver, + pus_receiver: PusReceiver, } impl TcSourceTaskDynamic { - pub fn new(tc_receiver: Receiver>, pus_receiver: PusReceiver) -> Self { + pub fn new( + tc_receiver: Receiver>, + pus_receiver: PusReceiver, + ) -> Self { Self { tc_receiver, pus_receiver, diff --git a/satrs/CHANGELOG.md b/satrs/CHANGELOG.md index 156e328..b640167 100644 --- a/satrs/CHANGELOG.md +++ b/satrs/CHANGELOG.md @@ -8,7 +8,23 @@ and this project adheres to [Semantic Versioning](http://semver.org/). # [unreleased] -# [v0.2.0] +## Changed + +- Refactored `EventManager` to heavily use generics instead of trait objects. + - `SendEventProvider` -> `EventSendProvider`. `id` trait method renamed to `channel_id`. + - `ListenerTable` -> `ListenerMapProvider` + - `SenderTable` -> `SenderMapProvider` + - There is an `EventManagerWithMpsc` and a `EventManagerWithBoundedMpsc` helper type now. +- Refactored ECSS TM sender abstractions to be generic over different message queue backends. +- Refactored Verification Reporter abstractions and implementation to be generic over the sender + instead of using trait objects. + +## Fixed + +- Update deprecated API for `PusScheduler::insert_wrapped_tc_cds_short` + and `PusScheduler::insert_wrapped_tc_cds_long`. + +# [v0.2.0-rc.0] 2024-02-21 ## Added diff --git a/satrs/Cargo.toml b/satrs/Cargo.toml index 021c593..5e3b27d 100644 --- a/satrs/Cargo.toml +++ b/satrs/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "satrs" -version = "0.1.1" +version = "0.2.0-rc.0" edition = "2021" rust-version = "1.61" authors = ["Robin Mueller "] diff --git a/satrs/src/action.rs b/satrs/src/action.rs index e073fea..7caeaa6 100644 --- a/satrs/src/action.rs +++ b/satrs/src/action.rs @@ -40,3 +40,24 @@ impl TargetedActionRequest { } } } + +/// A reply to an action request. +#[non_exhaustive] +#[derive(Clone, Eq, PartialEq, Debug)] +pub enum ActionReply { + CompletionFailed(ActionId), + StepFailed { + id: ActionId, + step: u32, + }, + Completed(ActionId), + #[cfg(feature = "alloc")] + CompletedStringId(alloc::string::String), + #[cfg(feature = "alloc")] + CompletionFailedStringId(alloc::string::String), + #[cfg(feature = "alloc")] + StepFailedStringId { + id: alloc::string::String, + step: u32, + }, +} diff --git a/satrs/src/cfdp/filestore.rs b/satrs/src/cfdp/filestore.rs index 48ebd88..528d1b8 100644 --- a/satrs/src/cfdp/filestore.rs +++ b/satrs/src/cfdp/filestore.rs @@ -7,7 +7,7 @@ use spacepackets::ByteConversionError; use std::error::Error; use std::path::Path; #[cfg(feature = "std")] -pub use stdmod::*; +pub use std_mod::*; pub const CRC_32: Crc = Crc::::new(&CRC_32_CKSUM); @@ -148,12 +148,11 @@ pub trait VirtualFilestore { } #[cfg(feature = "std")] -pub mod stdmod { +pub mod std_mod { use super::*; use std::{ fs::{self, File, OpenOptions}, io::{BufReader, Read, Seek, SeekFrom, Write}, - path::Path, }; #[derive(Default)] diff --git a/satrs/src/event_man.rs b/satrs/src/event_man.rs index 8cb549f..304f9a1 100644 --- a/satrs/src/event_man.rs +++ b/satrs/src/event_man.rs @@ -10,27 +10,27 @@ //! [sat-rs book chapter](https://absatsw.irs.uni-stuttgart.de/projects/sat-rs/book/events.html) //! about events first: //! -//! The event manager has a listener table abstracted by the [ListenerTable], which maps +//! The event manager has a listener table abstracted by the [ListenerMapProvider], which maps //! listener groups identified by [ListenerKey]s to a [sender ID][ChannelId]. -//! It also contains a sender table abstracted by the [SenderTable] which maps these sender IDs -//! to a concrete [SendEventProvider]s. A simple approach would be to use one send event provider +//! It also contains a sender table abstracted by the [SenderMapProvider] which maps these sender +//! IDs to concrete [EventSendProvider]s. A simple approach would be to use one send event provider //! for each OBSW thread and then subscribe for all interesting events for a particular thread //! using the send event provider ID. //! //! This can be done with the [EventManager] like this: //! -//! 1. Provide a concrete [EventReceiver] implementation. This abstraction allow to use different +//! 1. Provide a concrete [EventReceiveProvider] implementation. This abstraction allow to use different //! message queue backends. A straightforward implementation where dynamic memory allocation is //! not a big concern could use [std::sync::mpsc::channel] to do this and is provided in //! form of the [MpscEventReceiver]. //! 2. To set up event creators, create channel pairs using some message queue implementation. //! Each event creator gets a (cloned) sender component which allows it to send events to the //! manager. -//! 3. The event manager receives the receiver component as part of a [EventReceiver] +//! 3. The event manager receives the receiver component as part of a [EventReceiveProvider] //! implementation so all events are routed to the manager. -//! 4. Create the [send event providers][SendEventProvider]s which allow routing events to -//! subscribers. You can now use their [sender IDs][SendEventProvider::id] to subscribe for -//! event groups, for example by using the [EventManager::subscribe_single] method. +//! 4. Create the [send event providers][EventSendProvider]s which allow routing events to +//! subscribers. You can now use their [sender IDs][EventSendProvider::channel_id] to subscribe +//! for event groups, for example by using the [EventManager::subscribe_single] method. //! 5. Add the send provider as well using the [EventManager::add_sender] call so the event //! manager can route listener groups to a the send provider. //! @@ -41,24 +41,22 @@ //! //! # Examples //! -//! You can check [integration test](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/satrs-core/tests/pus_events.rs) +//! You can check [integration test](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/satrs/tests/pus_events.rs) //! for a concrete example using multi-threading where events are routed to //! different threads. use crate::events::{EventU16, EventU32, GenericEvent, LargestEventRaw, LargestGroupIdRaw}; use crate::params::{Params, ParamsHeapless}; -#[cfg(feature = "alloc")] -use alloc::boxed::Box; -#[cfg(feature = "alloc")] -use alloc::vec; -#[cfg(feature = "alloc")] -use alloc::vec::Vec; +use crate::queue::GenericSendError; +use core::marker::PhantomData; use core::slice::Iter; -#[cfg(feature = "alloc")] -use hashbrown::HashMap; use crate::ChannelId; + +#[cfg(feature = "alloc")] +pub use alloc_mod::*; + #[cfg(feature = "std")] -pub use stdmod::*; +pub use std_mod::*; #[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)] pub enum ListenerKey { @@ -75,108 +73,110 @@ pub type EventWithAuxData = (Event, Option); pub type EventU32WithAuxData = EventWithAuxData; pub type EventU16WithAuxData = EventWithAuxData; -pub trait SendEventProvider { - type Error; +pub trait EventSendProvider { + fn channel_id(&self) -> ChannelId; - fn id(&self) -> ChannelId; - fn send_no_data(&self, event: Provider) -> Result<(), Self::Error> { + fn send_no_data(&self, event: EV) -> Result<(), GenericSendError> { self.send(event, None) } - fn send(&self, event: Provider, aux_data: Option) -> Result<(), Self::Error>; + + fn send(&self, event: EV, aux_data: Option) -> Result<(), GenericSendError>; } /// Generic abstraction for an event receiver. -pub trait EventReceiver { - /// This function has to be provided by any event receiver. A receive call may or may not return - /// an event. - /// - /// To allow returning arbitrary additional auxiliary data, a mutable slice is passed to the - /// [Self::receive] call as well. Receivers can write data to this slice, but care must be taken - /// to avoid panics due to size missmatches or out of bound writes. - fn receive(&self) -> Option<(Event, Option)>; +pub trait EventReceiveProvider { + /// This function has to be provided by any event receiver. A call may or may not return + /// an event and optional auxiliary data. + fn try_recv_event(&self) -> Option<(Event, Option)>; } -pub trait ListenerTable { - fn get_listeners(&self) -> Vec; +pub trait ListenerMapProvider { + #[cfg(feature = "alloc")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] + fn get_listeners(&self) -> alloc::vec::Vec; fn contains_listener(&self, key: &ListenerKey) -> bool; fn get_listener_ids(&self, key: &ListenerKey) -> Option>; fn add_listener(&mut self, key: ListenerKey, sender_id: ChannelId) -> bool; fn remove_duplicates(&mut self, key: &ListenerKey); } -pub trait SenderTable { +pub trait SenderMapProvider< + SP: EventSendProvider, + EV: GenericEvent = EventU32, + AUX = Params, +> +{ fn contains_send_event_provider(&self, id: &ChannelId) -> bool; - fn get_send_event_provider( - &self, - id: &ChannelId, - ) -> Option<&dyn SendEventProvider>; - fn add_send_event_provider( - &mut self, - send_provider: Box< - dyn SendEventProvider, - >, - ) -> bool; + + fn get_send_event_provider(&self, id: &ChannelId) -> Option<&SP>; + fn add_send_event_provider(&mut self, send_provider: SP) -> bool; } /// Generic event manager implementation. /// /// # Generics /// -/// * `SendProviderError`: [SendEventProvider] error type -/// * `Event`: Concrete event provider, currently either [EventU32] or [EventU16] -/// * `AuxDataProvider`: Concrete auxiliary data provider, currently either [Params] or -/// [ParamsHeapless] -pub struct EventManager -{ - listener_table: Box, - sender_table: Box>, - event_receiver: Box>, +/// * `ERP`: [EventReceiveProvider] used to receive all events. +/// * `SMP`: [SenderMapProvider] which maps channel IDs to send providers. +/// * `LTR`: [ListenerMapProvider] which maps listener keys to channel IDs. +/// * `SP`: [EventSendProvider] contained within the sender map which sends the events. +/// * `EV`: The event type. This type must implement the [GenericEvent]. Currently only [EventU32] +/// and [EventU16] are supported. +/// * `AUX`: Auxiliary data which is sent with the event to provide optional context information +pub struct EventManager< + ERP: EventReceiveProvider, + SMP: SenderMapProvider, + LTR: ListenerMapProvider, + SP: EventSendProvider, + EV: GenericEvent = EventU32, + AUX = Params, +> { + event_receiver: ERP, + sender_map: SMP, + listener_map: LTR, + phantom: core::marker::PhantomData<(SP, EV, AUX)>, } -/// Safety: It is safe to implement [Send] because all fields in the [EventManager] are [Send] -/// as well -#[cfg(feature = "std")] -unsafe impl Send - for EventManager -{ -} - -#[cfg(feature = "std")] -pub type EventManagerWithMpscQueue = EventManager< - std::sync::mpsc::SendError<(Event, Option)>, - Event, - AuxDataProvider, ->; - #[derive(Debug)] -pub enum EventRoutingResult { +pub enum EventRoutingResult { /// No event was received Empty, - /// An event was received and routed. - /// The first tuple entry will contain the number of recipients. - Handled(u32, Event, Option), + /// An event was received and routed to listeners. + Handled { + num_recipients: u32, + event: EV, + aux_data: Option, + }, } #[derive(Debug)] -pub enum EventRoutingError { - SendError(E), +pub enum EventRoutingError { + Send(GenericSendError), NoSendersForKey(ListenerKey), NoSenderForId(ChannelId), } #[derive(Debug)] -pub struct EventRoutingErrorsWithResult { - pub result: EventRoutingResult, - pub errors: [Option>; 3], +pub struct EventRoutingErrorsWithResult { + pub result: EventRoutingResult, + pub errors: [Option; 3], } -impl EventManager { +impl< + ER: EventReceiveProvider, + S: SenderMapProvider, + L: ListenerMapProvider, + SP: EventSendProvider, + EV: GenericEvent + Copy, + AUX: Clone, + > EventManager +{ pub fn remove_duplicates(&mut self, key: &ListenerKey) { - self.listener_table.remove_duplicates(key) + self.listener_map.remove_duplicates(key) } /// Subscribe for a unique event. - pub fn subscribe_single(&mut self, event: &Event, sender_id: ChannelId) { + pub fn subscribe_single(&mut self, event: &EV, sender_id: ChannelId) { self.update_listeners(ListenerKey::Single(event.raw_as_largest_type()), sender_id); } @@ -194,49 +194,37 @@ impl EventManager { } } -impl - EventManager +impl< + ERP: EventReceiveProvider, + SMP: SenderMapProvider, + LTR: ListenerMapProvider, + SP: EventSendProvider, + EV: GenericEvent + Copy, + AUX: Clone, + > EventManager { - /// Create an event manager where the sender table will be the [DefaultSenderTableProvider] - /// and the listener table will be the [DefaultListenerTableProvider]. - pub fn new(event_receiver: Box>) -> Self { - let listener_table: Box = Box::default(); - let sender_table: Box> = - Box::default(); - Self::new_custom_tables(listener_table, sender_table, event_receiver) - } -} - -impl - EventManager -{ - pub fn new_custom_tables( - listener_table: Box, - sender_table: Box>, - event_receiver: Box>, - ) -> Self { + pub fn new_with_custom_maps(event_receiver: ERP, sender_map: SMP, listener_map: LTR) -> Self { EventManager { - listener_table, - sender_table, + listener_map, + sender_map, event_receiver, + phantom: PhantomData, } } - pub fn add_sender( - &mut self, - send_provider: impl SendEventProvider + 'static, - ) { + /// Add a new sender component which can be used to send events to subscribers. + pub fn add_sender(&mut self, send_provider: SP) { if !self - .sender_table - .contains_send_event_provider(&send_provider.id()) + .sender_map + .contains_send_event_provider(&send_provider.channel_id()) { - self.sender_table - .add_send_event_provider(Box::new(send_provider)); + self.sender_map.add_send_event_provider(send_provider); } } + /// Generic function to update the event subscribers. fn update_listeners(&mut self, key: ListenerKey, sender_id: ChannelId) { - self.listener_table.add_listener(key, sender_id); + self.listener_map.add_listener(key, sender_id); } /// This function will use the cached event receiver and try to receive one event. @@ -248,40 +236,36 @@ impl /// [EventRoutingErrorsWithResult] error struct. pub fn try_event_handling( &self, - ) -> Result< - EventRoutingResult, - EventRoutingErrorsWithResult, - > { + ) -> Result, EventRoutingErrorsWithResult> { let mut err_idx = 0; let mut err_slice = [None, None, None]; let mut num_recipients = 0; - let mut add_error = |error: EventRoutingError| { + let mut add_error = |error: EventRoutingError| { if err_idx < 3 { err_slice[err_idx] = Some(error); err_idx += 1; } }; - let mut send_handler = - |key: &ListenerKey, event: Event, aux_data: &Option| { - if self.listener_table.contains_listener(key) { - if let Some(ids) = self.listener_table.get_listener_ids(key) { - for id in ids { - if let Some(sender) = self.sender_table.get_send_event_provider(id) { - if let Err(e) = sender.send(event, aux_data.clone()) { - add_error(EventRoutingError::SendError(e)); - } else { - num_recipients += 1; - } + let mut send_handler = |key: &ListenerKey, event: EV, aux_data: &Option| { + if self.listener_map.contains_listener(key) { + if let Some(ids) = self.listener_map.get_listener_ids(key) { + for id in ids { + if let Some(sender) = self.sender_map.get_send_event_provider(id) { + if let Err(e) = sender.send(event, aux_data.clone()) { + add_error(EventRoutingError::Send(e)); } else { - add_error(EventRoutingError::NoSenderForId(*id)); + num_recipients += 1; } + } else { + add_error(EventRoutingError::NoSenderForId(*id)); } - } else { - add_error(EventRoutingError::NoSendersForKey(*key)); } + } else { + add_error(EventRoutingError::NoSendersForKey(*key)); } - }; - if let Some((event, aux_data)) = self.event_receiver.receive() { + } + }; + if let Some((event, aux_data)) = self.event_receiver.try_recv_event() { let single_key = ListenerKey::Single(event.raw_as_largest_type()); send_handler(&single_key, event, &aux_data); let group_key = ListenerKey::Group(event.group_id_as_largest_type()); @@ -289,130 +273,177 @@ impl send_handler(&ListenerKey::All, event, &aux_data); if err_idx > 0 { return Err(EventRoutingErrorsWithResult { - result: EventRoutingResult::Handled(num_recipients, event, aux_data), + result: EventRoutingResult::Handled { + num_recipients, + event, + aux_data, + }, errors: err_slice, }); } - return Ok(EventRoutingResult::Handled(num_recipients, event, aux_data)); + return Ok(EventRoutingResult::Handled { + num_recipients, + event, + aux_data, + }); } Ok(EventRoutingResult::Empty) } } -#[derive(Default)] -pub struct DefaultListenerTableProvider { - listeners: HashMap>, -} +#[cfg(feature = "alloc")] +pub mod alloc_mod { + use alloc::vec::Vec; + use hashbrown::HashMap; -pub struct DefaultSenderTableProvider< - SendProviderError, - Event: GenericEvent = EventU32, - AuxDataProvider = Params, -> { - senders: HashMap< - ChannelId, - Box>, - >, -} + use super::*; -impl Default - for DefaultSenderTableProvider -{ - fn default() -> Self { - Self { - senders: HashMap::new(), + /// Helper type which constrains the sender map and listener map generics to the [DefaultSenderMap] + /// and the [DefaultListenerMap]. It uses regular mpsc channels as the message queue backend. + pub type EventManagerWithMpsc = EventManager< + MpscEventReceiver, + DefaultSenderMap, EV, AUX>, + DefaultListenerMap, + EventSenderMpsc, + >; + + /// Helper type which constrains the sender map and listener map generics to the [DefaultSenderMap] + /// and the [DefaultListenerMap]. It uses + /// [bounded mpsc senders](https://doc.rust-lang.org/std/sync/mpsc/struct.SyncSender.html) as the + /// message queue backend. + pub type EventManagerWithBoundedMpsc = EventManager< + MpscEventReceiver, + DefaultSenderMap, EV, AUX>, + DefaultListenerMap, + EventSenderMpscBounded, + >; + + impl< + ER: EventReceiveProvider, + SP: EventSendProvider, + EV: GenericEvent + Copy, + AUX: 'static, + > EventManager, DefaultListenerMap, SP, EV, AUX> + { + /// Create an event manager where the sender table will be the [DefaultSenderMap] + /// and the listener table will be the [DefaultListenerMap]. + pub fn new(event_receiver: ER) -> Self { + Self { + listener_map: DefaultListenerMap::default(), + sender_map: DefaultSenderMap::default(), + event_receiver, + phantom: PhantomData, + } } } -} -impl ListenerTable for DefaultListenerTableProvider { - fn get_listeners(&self) -> Vec { - let mut key_list = Vec::new(); - for key in self.listeners.keys() { - key_list.push(*key); + /// Default listener map. + /// + /// Simple implementation which uses a [HashMap] and a [Vec] internally. + #[derive(Default)] + pub struct DefaultListenerMap { + listeners: HashMap>, + } + + impl ListenerMapProvider for DefaultListenerMap { + fn get_listeners(&self) -> Vec { + let mut key_list = Vec::new(); + for key in self.listeners.keys() { + key_list.push(*key); + } + key_list } - key_list - } - fn contains_listener(&self, key: &ListenerKey) -> bool { - self.listeners.contains_key(key) - } - - fn get_listener_ids(&self, key: &ListenerKey) -> Option> { - self.listeners.get(key).map(|vec| vec.iter()) - } - - fn add_listener(&mut self, key: ListenerKey, sender_id: ChannelId) -> bool { - if let Some(existing_list) = self.listeners.get_mut(&key) { - existing_list.push(sender_id); - } else { - let new_list = vec![sender_id]; - self.listeners.insert(key, new_list); + fn contains_listener(&self, key: &ListenerKey) -> bool { + self.listeners.contains_key(key) } - true - } - fn remove_duplicates(&mut self, key: &ListenerKey) { - if let Some(list) = self.listeners.get_mut(key) { - list.sort_unstable(); - list.dedup(); + fn get_listener_ids(&self, key: &ListenerKey) -> Option> { + self.listeners.get(key).map(|vec| vec.iter()) + } + + fn add_listener(&mut self, key: ListenerKey, sender_id: ChannelId) -> bool { + if let Some(existing_list) = self.listeners.get_mut(&key) { + existing_list.push(sender_id); + } else { + let new_list = alloc::vec![sender_id]; + self.listeners.insert(key, new_list); + } + true + } + + fn remove_duplicates(&mut self, key: &ListenerKey) { + if let Some(list) = self.listeners.get_mut(key) { + list.sort_unstable(); + list.dedup(); + } } } -} -impl - SenderTable - for DefaultSenderTableProvider -{ - fn contains_send_event_provider(&self, id: &ChannelId) -> bool { - self.senders.contains_key(id) + /// Default sender map. + /// + /// Simple implementation which uses a [HashMap] internally. + pub struct DefaultSenderMap< + SP: EventSendProvider, + EV: GenericEvent = EventU32, + AUX = Params, + > { + senders: HashMap, + phantom: PhantomData<(EV, AUX)>, } - fn get_send_event_provider( - &self, - id: &ChannelId, - ) -> Option<&dyn SendEventProvider> { - self.senders - .get(id) - .filter(|sender| sender.id() == *id) - .map(|v| v.as_ref()) - } - - fn add_send_event_provider( - &mut self, - send_provider: Box< - dyn SendEventProvider, - >, - ) -> bool { - let id = send_provider.id(); - if self.senders.contains_key(&id) { - return false; + impl, EV: GenericEvent, AUX> Default + for DefaultSenderMap + { + fn default() -> Self { + Self { + senders: Default::default(), + phantom: Default::default(), + } + } + } + + impl, EV: GenericEvent, AUX> SenderMapProvider + for DefaultSenderMap + { + fn contains_send_event_provider(&self, id: &ChannelId) -> bool { + self.senders.contains_key(id) + } + + fn get_send_event_provider(&self, id: &ChannelId) -> Option<&SP> { + self.senders + .get(id) + .filter(|sender| sender.channel_id() == *id) + } + + fn add_send_event_provider(&mut self, send_provider: SP) -> bool { + let id = send_provider.channel_id(); + if self.senders.contains_key(&id) { + return false; + } + self.senders.insert(id, send_provider).is_none() } - self.senders.insert(id, send_provider).is_none() } } #[cfg(feature = "std")] -pub mod stdmod { +pub mod std_mod { use super::*; - use crate::event_man::{EventReceiver, EventWithAuxData}; - use crate::events::{EventU16, EventU32, GenericEvent}; - use crate::params::Params; - use std::sync::mpsc::{Receiver, SendError, Sender}; + use std::sync::mpsc; pub struct MpscEventReceiver { - mpsc_receiver: Receiver<(Event, Option)>, + mpsc_receiver: mpsc::Receiver<(Event, Option)>, } impl MpscEventReceiver { - pub fn new(receiver: Receiver<(Event, Option)>) -> Self { + pub fn new(receiver: mpsc::Receiver<(Event, Option)>) -> Self { Self { mpsc_receiver: receiver, } } } - impl EventReceiver for MpscEventReceiver { - fn receive(&self) -> Option> { + impl EventReceiveProvider for MpscEventReceiver { + fn try_recv_event(&self) -> Option> { if let Ok(event_and_data) = self.mpsc_receiver.try_recv() { return Some(event_and_data); } @@ -423,31 +454,75 @@ pub mod stdmod { pub type MpscEventU32Receiver = MpscEventReceiver; pub type MpscEventU16Receiver = MpscEventReceiver; + /// Generic event sender which uses a regular [mpsc::Sender] as the messaging backend to + /// send events. #[derive(Clone)] - pub struct MpscEventSendProvider { + pub struct EventSenderMpsc { id: u32, - sender: Sender<(Event, Option)>, + sender: mpsc::Sender<(Event, Option)>, } - impl MpscEventSendProvider { - pub fn new(id: u32, sender: Sender<(Event, Option)>) -> Self { + impl EventSenderMpsc { + pub fn new(id: u32, sender: mpsc::Sender<(Event, Option)>) -> Self { Self { id, sender } } } - impl SendEventProvider for MpscEventSendProvider { - type Error = SendError<(Event, Option)>; - - fn id(&self) -> u32 { + impl EventSendProvider for EventSenderMpsc { + fn channel_id(&self) -> u32 { self.id } - fn send(&self, event: Event, aux_data: Option) -> Result<(), Self::Error> { - self.sender.send((event, aux_data)) + fn send(&self, event: Event, aux_data: Option) -> Result<(), GenericSendError> { + self.sender + .send((event, aux_data)) + .map_err(|_| GenericSendError::RxDisconnected) } } - pub type MpscEventU32SendProvider = MpscEventSendProvider; - pub type MpscEventU16SendProvider = MpscEventSendProvider; + /// Generic event sender which uses the [mpsc::SyncSender] as the messaging backend to send + /// events. This has the advantage that the channel is bounded and thus more deterministic. + #[derive(Clone)] + pub struct EventSenderMpscBounded { + channel_id: u32, + sender: mpsc::SyncSender<(Event, Option)>, + capacity: usize, + } + + impl EventSenderMpscBounded { + pub fn new( + channel_id: u32, + sender: mpsc::SyncSender<(Event, Option)>, + capacity: usize, + ) -> Self { + Self { + channel_id, + sender, + capacity, + } + } + } + + impl EventSendProvider for EventSenderMpscBounded { + fn channel_id(&self) -> u32 { + self.channel_id + } + fn send(&self, event: Event, aux_data: Option) -> Result<(), GenericSendError> { + if let Err(e) = self.sender.try_send((event, aux_data)) { + return match e { + mpsc::TrySendError::Full(_) => { + Err(GenericSendError::QueueFull(Some(self.capacity as u32))) + } + mpsc::TrySendError::Disconnected(_) => Err(GenericSendError::RxDisconnected), + }; + } + Ok(()) + } + } + + pub type EventU32SenderMpsc = EventSenderMpsc; + pub type EventU16SenderMpsc = EventSenderMpsc; + pub type EventU32SenderMpscBounded = EventSenderMpscBounded; + pub type EventU16SenderMpscBounded = EventSenderMpscBounded; } #[cfg(test)] @@ -456,32 +531,10 @@ mod tests { use crate::event_man::EventManager; use crate::events::{EventU32, GenericEvent, Severity}; use crate::params::ParamsRaw; - use alloc::boxed::Box; use std::format; - use std::sync::mpsc::{channel, Receiver, SendError, Sender}; + use std::sync::mpsc::{self, channel, Receiver, Sender}; - #[derive(Clone)] - struct MpscEventSenderQueue { - id: u32, - mpsc_sender: Sender, - } - - impl MpscEventSenderQueue { - fn new(id: u32, mpsc_sender: Sender) -> Self { - Self { id, mpsc_sender } - } - } - - impl SendEventProvider for MpscEventSenderQueue { - type Error = SendError; - - fn id(&self) -> u32 { - self.id - } - fn send(&self, event: EventU32, aux_data: Option) -> Result<(), Self::Error> { - self.mpsc_sender.send((event, aux_data)) - } - } + const TEST_EVENT: EventU32 = EventU32::const_new(Severity::INFO, 0, 5); fn check_next_event( expected: EventU32, @@ -500,22 +553,21 @@ mod tests { expected_num_sent: u32, ) { assert!(matches!(res, EventRoutingResult::Handled { .. })); - if let EventRoutingResult::Handled(num_recipients, event, _aux_data) = res { + if let EventRoutingResult::Handled { + num_recipients, + event, + .. + } = res + { assert_eq!(event, expected); assert_eq!(num_recipients, expected_num_sent); } } - fn generic_event_man() -> ( - Sender, - EventManager>, - ) { + fn generic_event_man() -> (Sender, EventManagerWithMpsc) { let (event_sender, manager_queue) = channel(); let event_man_receiver = MpscEventReceiver::new(manager_queue); - ( - event_sender, - EventManager::new(Box::new(event_man_receiver)), - ) + (event_sender, EventManager::new(event_man_receiver)) } #[test] @@ -524,15 +576,12 @@ mod tests { let event_grp_0 = EventU32::new(Severity::INFO, 0, 0).unwrap(); let event_grp_1_0 = EventU32::new(Severity::HIGH, 1, 0).unwrap(); let (single_event_sender, single_event_receiver) = channel(); - let single_event_listener = MpscEventSenderQueue::new(0, single_event_sender); - event_man.subscribe_single(&event_grp_0, single_event_listener.id()); + let single_event_listener = EventSenderMpsc::new(0, single_event_sender); + event_man.subscribe_single(&event_grp_0, single_event_listener.channel_id()); event_man.add_sender(single_event_listener); let (group_event_sender_0, group_event_receiver_0) = channel(); - let group_event_listener = MpscEventSenderQueue { - id: 1, - mpsc_sender: group_event_sender_0, - }; - event_man.subscribe_group(event_grp_1_0.group_id(), group_event_listener.id()); + let group_event_listener = EventU32SenderMpsc::new(1, group_event_sender_0); + event_man.subscribe_group(event_grp_1_0.group_id(), group_event_listener.channel_id()); event_man.add_sender(group_event_listener); // Test event with one listener @@ -559,8 +608,8 @@ mod tests { let (event_sender, mut event_man) = generic_event_man(); let event_grp_0 = EventU32::new(Severity::INFO, 0, 0).unwrap(); let (single_event_sender, single_event_receiver) = channel(); - let single_event_listener = MpscEventSenderQueue::new(0, single_event_sender); - event_man.subscribe_single(&event_grp_0, single_event_listener.id()); + let single_event_listener = EventSenderMpsc::new(0, single_event_sender); + event_man.subscribe_single(&event_grp_0, single_event_listener.channel_id()); event_man.add_sender(single_event_listener); event_sender .send((event_grp_0, Some(Params::Heapless((2_u32, 3_u32).into())))) @@ -591,12 +640,15 @@ mod tests { let event_grp_0 = EventU32::new(Severity::INFO, 0, 0).unwrap(); let event_grp_1_0 = EventU32::new(Severity::HIGH, 1, 0).unwrap(); let (event_grp_0_sender, event_grp_0_receiver) = channel(); - let event_grp_0_and_1_listener = MpscEventSenderQueue { - id: 0, - mpsc_sender: event_grp_0_sender, - }; - event_man.subscribe_group(event_grp_0.group_id(), event_grp_0_and_1_listener.id()); - event_man.subscribe_group(event_grp_1_0.group_id(), event_grp_0_and_1_listener.id()); + let event_grp_0_and_1_listener = EventU32SenderMpsc::new(0, event_grp_0_sender); + event_man.subscribe_group( + event_grp_0.group_id(), + event_grp_0_and_1_listener.channel_id(), + ); + event_man.subscribe_group( + event_grp_1_0.group_id(), + event_grp_0_and_1_listener.channel_id(), + ); event_man.add_sender(event_grp_0_and_1_listener); event_sender @@ -625,18 +677,12 @@ mod tests { let event_1 = EventU32::new(Severity::HIGH, 1, 0).unwrap(); let (event_0_tx_0, event_0_rx_0) = channel(); let (event_0_tx_1, event_0_rx_1) = channel(); - let event_listener_0 = MpscEventSenderQueue { - id: 0, - mpsc_sender: event_0_tx_0, - }; - let event_listener_1 = MpscEventSenderQueue { - id: 1, - mpsc_sender: event_0_tx_1, - }; - let event_listener_0_sender_id = event_listener_0.id(); + let event_listener_0 = EventU32SenderMpsc::new(0, event_0_tx_0); + let event_listener_1 = EventU32SenderMpsc::new(1, event_0_tx_1); + let event_listener_0_sender_id = event_listener_0.channel_id(); event_man.subscribe_single(&event_0, event_listener_0_sender_id); event_man.add_sender(event_listener_0); - let event_listener_1_sender_id = event_listener_1.id(); + let event_listener_1_sender_id = event_listener_1.channel_id(); event_man.subscribe_single(&event_0, event_listener_1_sender_id); event_man.add_sender(event_listener_1); event_sender @@ -681,16 +727,12 @@ mod tests { fn test_all_events_listener() { let (event_sender, manager_queue) = channel(); let event_man_receiver = MpscEventReceiver::new(manager_queue); - let mut event_man: EventManager> = - EventManager::new(Box::new(event_man_receiver)); + let mut event_man = EventManagerWithMpsc::new(event_man_receiver); let event_0 = EventU32::new(Severity::INFO, 0, 5).unwrap(); let event_1 = EventU32::new(Severity::HIGH, 1, 0).unwrap(); let (event_0_tx_0, all_events_rx) = channel(); - let all_events_listener = MpscEventSenderQueue { - id: 0, - mpsc_sender: event_0_tx_0, - }; - event_man.subscribe_all(all_events_listener.id()); + let all_events_listener = EventU32SenderMpsc::new(0, event_0_tx_0); + event_man.subscribe_all(all_events_listener.channel_id()); event_man.add_sender(all_events_listener); event_sender .send((event_0, None)) @@ -707,4 +749,36 @@ mod tests { check_next_event(event_0, &all_events_rx); check_next_event(event_1, &all_events_rx); } + + #[test] + fn test_bounded_event_sender_queue_full() { + let (event_sender, _event_receiver) = mpsc::sync_channel(3); + let event_sender = EventU32SenderMpscBounded::new(1, event_sender, 3); + event_sender + .send_no_data(TEST_EVENT) + .expect("sending test event failed"); + event_sender + .send_no_data(TEST_EVENT) + .expect("sending test event failed"); + event_sender + .send_no_data(TEST_EVENT) + .expect("sending test event failed"); + let error = event_sender.send_no_data(TEST_EVENT); + if let Err(e) = error { + assert!(matches!(e, GenericSendError::QueueFull(Some(3)))); + } else { + panic!("unexpected error {error:?}"); + } + } + #[test] + fn test_bounded_event_sender_rx_dropped() { + let (event_sender, event_receiver) = mpsc::sync_channel(3); + let event_sender = EventU32SenderMpscBounded::new(1, event_sender, 3); + drop(event_receiver); + if let Err(e) = event_sender.send_no_data(TEST_EVENT) { + assert!(matches!(e, GenericSendError::RxDisconnected)); + } else { + panic!("Expected error"); + } + } } diff --git a/satrs/src/hal/std/tcp_cobs_server.rs b/satrs/src/hal/std/tcp_cobs_server.rs index 2d14589..7e7036f 100644 --- a/satrs/src/hal/std/tcp_cobs_server.rs +++ b/satrs/src/hal/std/tcp_cobs_server.rs @@ -107,7 +107,7 @@ impl TcpTmSender for CobsTmSender { /// /// ## Example /// -/// The [TCP integration tests](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/satrs-core/tests/tcp_servers.rs) +/// The [TCP integration tests](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/satrs/tests/tcp_servers.rs) /// test also serves as the example application for this module. pub struct TcpTmtcInCobsServer< TmError, diff --git a/satrs/src/hal/std/tcp_spacepackets_server.rs b/satrs/src/hal/std/tcp_spacepackets_server.rs index 6ade0d1..257f0c1 100644 --- a/satrs/src/hal/std/tcp_spacepackets_server.rs +++ b/satrs/src/hal/std/tcp_spacepackets_server.rs @@ -88,7 +88,7 @@ impl TcpTmSender for SpacepacketsTmSender { /// [spacepackets::PacketId]s as part of the server configuration for that purpose. /// /// ## Example -/// The [TCP server integration tests](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/satrs-core/tests/tcp_servers.rs) +/// The [TCP server integration tests](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/satrs/tests/tcp_servers.rs) /// also serves as the example application for this module. pub struct TcpSpacepacketsServer< TmError, diff --git a/satrs/src/lib.rs b/satrs/src/lib.rs index c31df8d..5040d58 100644 --- a/satrs/src/lib.rs +++ b/satrs/src/lib.rs @@ -26,8 +26,6 @@ extern crate std; #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] pub mod cfdp; pub mod encoding; -#[cfg(feature = "alloc")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] pub mod event_man; pub mod events; #[cfg(feature = "std")] diff --git a/satrs/src/params.rs b/satrs/src/params.rs index 5cad28b..1279015 100644 --- a/satrs/src/params.rs +++ b/satrs/src/params.rs @@ -43,22 +43,19 @@ //! This includes the [ParamsHeapless] enumeration for contained values which do not require heap //! allocation, and the [Params] which enumerates [ParamsHeapless] and some additional types which //! require [alloc] support but allow for more flexbility. -#[cfg(feature = "alloc")] use crate::pool::StoreAddr; -#[cfg(feature = "alloc")] -use alloc::string::{String, ToString}; -#[cfg(feature = "alloc")] -use alloc::vec::Vec; use core::fmt::Debug; use core::mem::size_of; use paste::paste; use spacepackets::ecss::{EcssEnumU16, EcssEnumU32, EcssEnumU64, EcssEnumU8}; +pub use spacepackets::util::ToBeBytes; use spacepackets::util::UnsignedEnum; use spacepackets::ByteConversionError; #[cfg(feature = "alloc")] -pub use alloc_mod::*; -pub use spacepackets::util::ToBeBytes; +use alloc::string::{String, ToString}; +#[cfg(feature = "alloc")] +use alloc::vec::Vec; /// Generic trait which is used for objects which can be converted into a raw network (big) endian /// byte format. @@ -560,56 +557,64 @@ from_conversions_for_raw!( (f64, Self::F64), ); -#[cfg(feature = "alloc")] -mod alloc_mod { - use super::*; - /// Generic enumeration for additional parameters, including parameters which rely on heap - /// allocations. +/// Generic enumeration for additional parameters, including parameters which rely on heap +/// allocations. +#[derive(Debug, Clone)] +#[non_exhaustive] +pub enum Params { + Heapless(ParamsHeapless), + Store(StoreAddr), + #[cfg(feature = "alloc")] #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] - #[derive(Debug, Clone)] - pub enum Params { - Heapless(ParamsHeapless), - Store(StoreAddr), - Vec(Vec), - String(String), - } + Vec(Vec), + #[cfg(feature = "alloc")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] + String(String), +} - impl From for Params { - fn from(x: StoreAddr) -> Self { - Self::Store(x) - } +impl From for Params { + fn from(x: StoreAddr) -> Self { + Self::Store(x) } +} - impl From for Params { - fn from(x: ParamsHeapless) -> Self { - Self::Heapless(x) - } +impl From for Params { + fn from(x: ParamsHeapless) -> Self { + Self::Heapless(x) } +} - impl From> for Params { - fn from(val: Vec) -> Self { - Self::Vec(val) - } +#[cfg(feature = "alloc")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] +impl From> for Params { + fn from(val: Vec) -> Self { + Self::Vec(val) } +} - /// Converts a byte slice into the [Params::Vec] variant - impl From<&[u8]> for Params { - fn from(val: &[u8]) -> Self { - Self::Vec(val.to_vec()) - } +/// Converts a byte slice into the [Params::Vec] variant +#[cfg(feature = "alloc")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] +impl From<&[u8]> for Params { + fn from(val: &[u8]) -> Self { + Self::Vec(val.to_vec()) } +} - impl From for Params { - fn from(val: String) -> Self { - Self::String(val) - } +#[cfg(feature = "alloc")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] +impl From for Params { + fn from(val: String) -> Self { + Self::String(val) } +} - /// Converts a string slice into the [Params::String] variant - impl From<&str> for Params { - fn from(val: &str) -> Self { - Self::String(val.to_string()) - } +#[cfg(feature = "alloc")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] +/// Converts a string slice into the [Params::String] variant +impl From<&str> for Params { + fn from(val: &str) -> Self { + Self::String(val.to_string()) } } diff --git a/satrs/src/pus/action.rs b/satrs/src/pus/action.rs index cd6de15..2ee4815 100644 --- a/satrs/src/pus/action.rs +++ b/satrs/src/pus/action.rs @@ -44,7 +44,7 @@ pub mod alloc_mod { /// - Checking the validity of the APID, service ID, subservice ID. /// - Checking the validity of the user data. /// - /// A [VerificationReporterWithSender] instance is passed to the user to also allow handling + /// A [VerificationReportingProvider] instance is passed to the user to also allow handling /// of the verification process as part of the PUS standard requirements. pub trait PusActionToRequestConverter { type Error; @@ -62,9 +62,9 @@ pub mod alloc_mod { #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] pub mod std_mod { use crate::pus::{ - verification::VerificationReportingProvider, EcssTcInMemConverter, GenericRoutingError, - PusPacketHandlerResult, PusPacketHandlingError, PusRoutingErrorHandler, PusServiceBase, - PusServiceHelper, + get_current_cds_short_timestamp, verification::VerificationReportingProvider, + EcssTcInMemConverter, EcssTcReceiverCore, EcssTmSenderCore, GenericRoutingError, + PusPacketHandlerResult, PusPacketHandlingError, PusRoutingErrorHandler, PusServiceHelper, }; use super::*; @@ -81,6 +81,8 @@ pub mod std_mod { /// 3. Route the action request using the provided [PusActionRequestRouter]. /// 4. Handle all routing errors using the provided [PusRoutingErrorHandler]. pub struct PusService8ActionHandler< + TcReceiver: EcssTcReceiverCore, + TmSender: EcssTmSenderCore, TcInMemConverter: EcssTcInMemConverter, VerificationReporter: VerificationReportingProvider, RequestConverter: PusActionToRequestConverter, @@ -88,13 +90,16 @@ pub mod std_mod { RoutingErrorHandler: PusRoutingErrorHandler, RoutingError = GenericRoutingError, > { - service_helper: PusServiceHelper, + service_helper: + PusServiceHelper, pub request_converter: RequestConverter, pub request_router: RequestRouter, pub routing_error_handler: RoutingErrorHandler, } impl< + TcReceiver: EcssTcReceiverCore, + TmSender: EcssTmSenderCore, TcInMemConverter: EcssTcInMemConverter, VerificationReporter: VerificationReportingProvider, RequestConverter: PusActionToRequestConverter, @@ -103,6 +108,8 @@ pub mod std_mod { RoutingError: Clone, > PusService8ActionHandler< + TcReceiver, + TmSender, TcInMemConverter, VerificationReporter, RequestConverter, @@ -114,7 +121,12 @@ pub mod std_mod { PusPacketHandlingError: From, { pub fn new( - service_helper: PusServiceHelper, + service_helper: PusServiceHelper< + TcReceiver, + TmSender, + TcInMemConverter, + VerificationReporter, + >, request_converter: RequestConverter, request_router: RequestRouter, routing_error_handler: RoutingErrorHandler, @@ -139,10 +151,7 @@ pub mod std_mod { .tc_in_mem_converter .convert_ecss_tc_in_memory_to_reader(&ecss_tc_and_token.tc_in_memory)?; let mut partial_error = None; - let time_stamp = - PusServiceBase::::get_current_cds_short_timestamp( - &mut partial_error, - ); + let time_stamp = get_current_cds_short_timestamp(&mut partial_error); let (target_id, action_request) = self.request_converter.convert( ecss_tc_and_token.token, &tc, @@ -189,7 +198,8 @@ mod tests { verification::{ tests::TestVerificationReporter, FailParams, RequestId, VerificationReportingProvider, }, - EcssTcInVecConverter, GenericRoutingError, PusPacketHandlerResult, PusPacketHandlingError, + EcssTcInVecConverter, GenericRoutingError, MpscTcReceiver, PusPacketHandlerResult, + PusPacketHandlingError, TmAsVecSenderWithMpsc, }; use super::*; @@ -259,6 +269,8 @@ mod tests { struct Pus8HandlerWithVecTester { common: PusServiceHandlerWithVecCommon, handler: PusService8ActionHandler< + MpscTcReceiver, + TmAsVecSenderWithMpsc, EcssTcInVecConverter, TestVerificationReporter, TestConverter<8>, diff --git a/satrs/src/pus/event.rs b/satrs/src/pus/event.rs index 9424b24..5cde422 100644 --- a/satrs/src/pus/event.rs +++ b/satrs/src/pus/event.rs @@ -269,7 +269,7 @@ mod tests { } impl EcssChannel for TestSender { - fn id(&self) -> ChannelId { + fn channel_id(&self) -> ChannelId { 0 } } diff --git a/satrs/src/pus/event_man.rs b/satrs/src/pus/event_man.rs index d51135a..e6e18c9 100644 --- a/satrs/src/pus/event_man.rs +++ b/satrs/src/pus/event_man.rs @@ -2,8 +2,6 @@ use crate::events::{EventU32, GenericEvent, Severity}; #[cfg(feature = "alloc")] use crate::events::{EventU32TypedSev, HasSeverity}; #[cfg(feature = "alloc")] -use alloc::boxed::Box; -#[cfg(feature = "alloc")] use core::hash::Hash; #[cfg(feature = "alloc")] use hashbrown::HashSet; @@ -32,19 +30,19 @@ pub use heapless_mod::*; /// structure to track disabled events. A more primitive and embedded friendly /// solution could track this information in a static or pre-allocated list which contains /// the disabled events. -pub trait PusEventMgmtBackendProvider { +pub trait PusEventMgmtBackendProvider { type Error; - fn event_enabled(&self, event: &Provider) -> bool; - fn enable_event_reporting(&mut self, event: &Provider) -> Result; - fn disable_event_reporting(&mut self, event: &Provider) -> Result; + fn event_enabled(&self, event: &Event) -> bool; + fn enable_event_reporting(&mut self, event: &Event) -> Result; + fn disable_event_reporting(&mut self, event: &Event) -> Result; } #[cfg(feature = "heapless")] pub mod heapless_mod { use super::*; - use crate::events::{GenericEvent, LargestEventRaw}; - use std::marker::PhantomData; + use crate::events::LargestEventRaw; + use core::marker::PhantomData; #[cfg_attr(doc_cfg, doc(cfg(feature = "heapless")))] // TODO: After a new version of heapless is released which uses hash32 version 0.3, try using @@ -108,6 +106,10 @@ impl From for EventManError { #[cfg(feature = "alloc")] pub mod alloc_mod { + use core::marker::PhantomData; + + use crate::events::EventU16; + use super::*; /// Default backend provider which uses a hash set as the event reporting status container @@ -115,14 +117,11 @@ pub mod alloc_mod { /// /// This provider is a good option for host systems or larger embedded systems where /// the expected occasional memory allocation performed by the [HashSet] is not an issue. - pub struct DefaultPusMgmtBackendProvider { + pub struct DefaultPusEventMgmtBackend { disabled: HashSet, } - /// Safety: All contained field are [Send] as well - unsafe impl Send for DefaultPusMgmtBackendProvider {} - - impl Default for DefaultPusMgmtBackendProvider { + impl Default for DefaultPusEventMgmtBackend { fn default() -> Self { Self { disabled: HashSet::default(), @@ -130,46 +129,50 @@ pub mod alloc_mod { } } - impl - PusEventMgmtBackendProvider for DefaultPusMgmtBackendProvider + impl PusEventMgmtBackendProvider + for DefaultPusEventMgmtBackend { type Error = (); - fn event_enabled(&self, event: &Provider) -> bool { + + fn event_enabled(&self, event: &EV) -> bool { !self.disabled.contains(event) } - fn enable_event_reporting(&mut self, event: &Provider) -> Result { + fn enable_event_reporting(&mut self, event: &EV) -> Result { Ok(self.disabled.remove(event)) } - fn disable_event_reporting(&mut self, event: &Provider) -> Result { + fn disable_event_reporting(&mut self, event: &EV) -> Result { Ok(self.disabled.insert(*event)) } } - pub struct PusEventDispatcher { + pub struct PusEventDispatcher< + B: PusEventMgmtBackendProvider, + EV: GenericEvent, + E, + > { reporter: EventReporter, - backend: Box>, + backend: B, + phantom: PhantomData<(E, EV)>, } - /// Safety: All contained fields are send as well. - unsafe impl Send for PusEventDispatcher {} - - impl PusEventDispatcher { - pub fn new( - reporter: EventReporter, - backend: Box>, - ) -> Self { - Self { reporter, backend } + impl, EV: GenericEvent, E> + PusEventDispatcher + { + pub fn new(reporter: EventReporter, backend: B) -> Self { + Self { + reporter, + backend, + phantom: PhantomData, + } } - } - impl PusEventDispatcher { - pub fn enable_tm_for_event(&mut self, event: &Event) -> Result { + pub fn enable_tm_for_event(&mut self, event: &EV) -> Result { self.backend.enable_event_reporting(event) } - pub fn disable_tm_for_event(&mut self, event: &Event) -> Result { + pub fn disable_tm_for_event(&mut self, event: &EV) -> Result { self.backend.disable_event_reporting(event) } @@ -177,7 +180,7 @@ pub mod alloc_mod { &mut self, sender: &mut (impl EcssTmSenderCore + ?Sized), time_stamp: &[u8], - event: Event, + event: EV, aux_data: Option<&[u8]>, ) -> Result { if !self.backend.event_enabled(&event) { @@ -208,18 +211,30 @@ pub mod alloc_mod { } } - impl PusEventDispatcher { + impl + PusEventDispatcher, EV, ()> + { + pub fn new_with_default_backend(reporter: EventReporter) -> Self { + Self { + reporter, + backend: DefaultPusEventMgmtBackend::default(), + phantom: PhantomData, + } + } + } + + impl, E> PusEventDispatcher { pub fn enable_tm_for_event_with_sev( &mut self, event: &EventU32TypedSev, - ) -> Result { + ) -> Result { self.backend.enable_event_reporting(event.as_ref()) } pub fn disable_tm_for_event_with_sev( &mut self, event: &EventU32TypedSev, - ) -> Result { + ) -> Result { self.backend.disable_event_reporting(event.as_ref()) } @@ -233,30 +248,38 @@ pub mod alloc_mod { self.generate_pus_event_tm_generic(sender, time_stamp, event.into(), aux_data) } } + + pub type DefaultPusEventU16Dispatcher = + PusEventDispatcher, EventU16, E>; + pub type DefaultPusEventU32Dispatcher = + PusEventDispatcher, EventU32, E>; } #[cfg(test)] mod tests { use super::*; - use crate::events::SeverityInfo; - use crate::pus::MpscTmAsVecSender; - use std::sync::mpsc::{channel, TryRecvError}; + use crate::{events::SeverityInfo, pus::TmAsVecSenderWithMpsc}; + use std::sync::mpsc::{self, TryRecvError}; const INFO_EVENT: EventU32TypedSev = EventU32TypedSev::::const_new(1, 0); const LOW_SEV_EVENT: EventU32 = EventU32::const_new(Severity::LOW, 1, 5); const EMPTY_STAMP: [u8; 7] = [0; 7]; - fn create_basic_man() -> PusEventDispatcher<(), EventU32> { + fn create_basic_man_1() -> DefaultPusEventU32Dispatcher<()> { let reporter = EventReporter::new(0x02, 128).expect("Creating event repoter failed"); - let backend = DefaultPusMgmtBackendProvider::::default(); - PusEventDispatcher::new(reporter, Box::new(backend)) + PusEventDispatcher::new_with_default_backend(reporter) + } + fn create_basic_man_2() -> DefaultPusEventU32Dispatcher<()> { + let reporter = EventReporter::new(0x02, 128).expect("Creating event repoter failed"); + let backend = DefaultPusEventMgmtBackend::default(); + PusEventDispatcher::new(reporter, backend) } #[test] fn test_basic() { - let mut event_man = create_basic_man(); - let (event_tx, event_rx) = channel(); - let mut sender = MpscTmAsVecSender::new(0, "test_sender", event_tx); + let mut event_man = create_basic_man_1(); + let (event_tx, event_rx) = mpsc::channel(); + let mut sender = TmAsVecSenderWithMpsc::new(0, "test_sender", event_tx); let event_sent = event_man .generate_pus_event_tm(&mut sender, &EMPTY_STAMP, INFO_EVENT, None) .expect("Sending info event failed"); @@ -268,9 +291,9 @@ mod tests { #[test] fn test_disable_event() { - let mut event_man = create_basic_man(); - let (event_tx, event_rx) = channel(); - let mut sender = MpscTmAsVecSender::new(0, "test", event_tx); + let mut event_man = create_basic_man_2(); + let (event_tx, event_rx) = mpsc::channel(); + let mut sender = TmAsVecSenderWithMpsc::new(0, "test", event_tx); let res = event_man.disable_tm_for_event(&LOW_SEV_EVENT); assert!(res.is_ok()); assert!(res.unwrap()); @@ -291,9 +314,9 @@ mod tests { #[test] fn test_reenable_event() { - let mut event_man = create_basic_man(); - let (event_tx, event_rx) = channel(); - let mut sender = MpscTmAsVecSender::new(0, "test", event_tx); + let mut event_man = create_basic_man_1(); + let (event_tx, event_rx) = mpsc::channel(); + let mut sender = TmAsVecSenderWithMpsc::new(0, "test", event_tx); let mut res = event_man.disable_tm_for_event_with_sev(&INFO_EVENT); assert!(res.is_ok()); assert!(res.unwrap()); diff --git a/satrs/src/pus/event_srv.rs b/satrs/src/pus/event_srv.rs index b55a5c9..64c1ba0 100644 --- a/satrs/src/pus/event_srv.rs +++ b/satrs/src/pus/event_srv.rs @@ -7,27 +7,40 @@ use spacepackets::ecss::PusPacket; use std::sync::mpsc::Sender; use super::verification::VerificationReportingProvider; -use super::{EcssTcInMemConverter, PusServiceBase, PusServiceHelper}; +use super::{ + get_current_cds_short_timestamp, EcssTcInMemConverter, EcssTcReceiverCore, EcssTmSenderCore, + PusServiceHelper, +}; pub struct PusService5EventHandler< + TcReceiver: EcssTcReceiverCore, + TmSender: EcssTmSenderCore, TcInMemConverter: EcssTcInMemConverter, VerificationReporter: VerificationReportingProvider, > { - pub service_helper: PusServiceHelper, + pub service_helper: + PusServiceHelper, event_request_tx: Sender, } impl< + TcReceiver: EcssTcReceiverCore, + TmSender: EcssTmSenderCore, TcInMemConverter: EcssTcInMemConverter, VerificationReporter: VerificationReportingProvider, - > PusService5EventHandler + > PusService5EventHandler { pub fn new( - service_handler: PusServiceHelper, + service_helper: PusServiceHelper< + TcReceiver, + TmSender, + TcInMemConverter, + VerificationReporter, + >, event_request_tx: Sender, ) -> Self { Self { - service_helper: service_handler, + service_helper, event_request_tx, } } @@ -94,9 +107,7 @@ impl< Ok(PusPacketHandlerResult::RequestHandled) }; let mut partial_error = None; - let time_stamp = PusServiceBase::::get_current_cds_short_timestamp( - &mut partial_error, - ); + let time_stamp = get_current_cds_short_timestamp(&mut partial_error); match srv.unwrap() { Subservice::TmInfoReport | Subservice::TmLowSeverityReport @@ -138,7 +149,10 @@ mod tests { use crate::pus::event_man::EventRequest; use crate::pus::tests::SimplePusPacketHandler; - use crate::pus::verification::{RequestId, VerificationReporterWithSender}; + use crate::pus::verification::{ + RequestId, VerificationReporterWithSharedPoolMpscBoundedSender, + }; + use crate::pus::{MpscTcReceiver, TmInSharedPoolSenderWithBoundedMpsc}; use crate::{ events::EventU32, pus::{ @@ -155,8 +169,12 @@ mod tests { struct Pus5HandlerWithStoreTester { common: PusServiceHandlerWithSharedStoreCommon, - handler: - PusService5EventHandler, + handler: PusService5EventHandler< + MpscTcReceiver, + TmInSharedPoolSenderWithBoundedMpsc, + EcssTcInSharedStoreConverter, + VerificationReporterWithSharedPoolMpscBoundedSender, + >, } impl Pus5HandlerWithStoreTester { diff --git a/satrs/src/pus/hk.rs b/satrs/src/pus/hk.rs index a2a5354..852e8f7 100644 --- a/satrs/src/pus/hk.rs +++ b/satrs/src/pus/hk.rs @@ -46,7 +46,7 @@ pub mod alloc_mod { /// - Checking the validity of the APID, service ID, subservice ID. /// - Checking the validity of the user data. /// - /// A [VerificationReporterWithSender] instance is passed to the user to also allow handling + /// A [VerificationReportingProvider] is passed to the user to also allow handling /// of the verification process as part of the PUS standard requirements. pub trait PusHkToRequestConverter { type Error; @@ -64,9 +64,9 @@ pub mod alloc_mod { #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] pub mod std_mod { use crate::pus::{ - verification::VerificationReportingProvider, EcssTcInMemConverter, GenericRoutingError, - PusPacketHandlerResult, PusPacketHandlingError, PusRoutingErrorHandler, PusServiceBase, - PusServiceHelper, + get_current_cds_short_timestamp, verification::VerificationReportingProvider, + EcssTcInMemConverter, EcssTcReceiverCore, EcssTmSenderCore, GenericRoutingError, + PusPacketHandlerResult, PusPacketHandlingError, PusRoutingErrorHandler, PusServiceHelper, }; use super::*; @@ -78,13 +78,15 @@ pub mod std_mod { /// 1. Retrieve the next TC packet from the [PusServiceHelper]. The [EcssTcInMemConverter] /// allows to configure the used telecommand memory backend. /// 2. Convert the TC to a targeted action request using the provided - /// [PusActionToRequestConverter]. The generic error type is constrained to the + /// [PusHkToRequestConverter]. The generic error type is constrained to the /// [PusPacketHandlerResult] for the concrete implementation which offers a packet handler. - /// 3. Route the action request using the provided [PusActionRequestRouter]. The generic error + /// 3. Route the action request using the provided [PusHkRequestRouter]. The generic error /// type is constrained to the [GenericRoutingError] for the concrete implementation. /// 4. Handle all routing errors using the provided [PusRoutingErrorHandler]. The generic error /// type is constrained to the [GenericRoutingError] for the concrete implementation. pub struct PusService3HkHandler< + TcReceiver: EcssTcReceiverCore, + TmSender: EcssTmSenderCore, TcInMemConverter: EcssTcInMemConverter, VerificationReporter: VerificationReportingProvider, RequestConverter: PusHkToRequestConverter, @@ -92,13 +94,16 @@ pub mod std_mod { RoutingErrorHandler: PusRoutingErrorHandler, RoutingError = GenericRoutingError, > { - service_helper: PusServiceHelper, + service_helper: + PusServiceHelper, pub request_converter: RequestConverter, pub request_router: RequestRouter, pub routing_error_handler: RoutingErrorHandler, } impl< + TcReceiver: EcssTcReceiverCore, + TmSender: EcssTmSenderCore, TcInMemConverter: EcssTcInMemConverter, VerificationReporter: VerificationReportingProvider, RequestConverter: PusHkToRequestConverter, @@ -107,6 +112,8 @@ pub mod std_mod { RoutingError: Clone, > PusService3HkHandler< + TcReceiver, + TmSender, TcInMemConverter, VerificationReporter, RequestConverter, @@ -118,7 +125,12 @@ pub mod std_mod { PusPacketHandlingError: From, { pub fn new( - service_helper: PusServiceHelper, + service_helper: PusServiceHelper< + TcReceiver, + TmSender, + TcInMemConverter, + VerificationReporter, + >, request_converter: RequestConverter, request_router: RequestRouter, routing_error_handler: RoutingErrorHandler, @@ -142,10 +154,7 @@ pub mod std_mod { .tc_in_mem_converter .convert_ecss_tc_in_memory_to_reader(&ecss_tc_and_token.tc_in_memory)?; let mut partial_error = None; - let time_stamp = - PusServiceBase::::get_current_cds_short_timestamp( - &mut partial_error, - ); + let time_stamp = get_current_cds_short_timestamp(&mut partial_error); let (target_id, hk_request) = self.request_converter.convert( ecss_tc_and_token.token, &tc, @@ -185,6 +194,7 @@ mod tests { CcsdsPacket, SequenceFlags, SpHeader, }; + use crate::pus::{MpscTcReceiver, TmAsVecSenderWithMpsc}; use crate::{ hk::HkRequest, pus::{ @@ -268,6 +278,8 @@ mod tests { struct Pus3HandlerWithVecTester { common: PusServiceHandlerWithVecCommon, handler: PusService3HkHandler< + MpscTcReceiver, + TmAsVecSenderWithMpsc, EcssTcInVecConverter, TestVerificationReporter, TestConverter<3>, diff --git a/satrs/src/pus/mod.rs b/satrs/src/pus/mod.rs index 91be068..ba0ff1d 100644 --- a/satrs/src/pus/mod.rs +++ b/satrs/src/pus/mod.rs @@ -2,6 +2,8 @@ //! //! This module contains structures to make working with the PUS C standard easier. //! The satrs-example application contains various usage examples of these components. +use crate::pool::{StoreAddr, StoreError}; +use crate::pus::verification::{TcStateAccepted, TcStateToken, VerificationToken}; use crate::queue::{GenericRecvError, GenericSendError}; use crate::ChannelId; use core::fmt::{Display, Formatter}; @@ -34,8 +36,6 @@ pub mod verification; #[cfg(feature = "alloc")] pub use alloc_mod::*; -use crate::pool::{StoreAddr, StoreError}; -use crate::pus::verification::{TcStateAccepted, TcStateToken, VerificationToken}; #[cfg(feature = "std")] pub use std_mod::*; @@ -63,6 +63,7 @@ pub enum EcssTmtcError { Store(StoreError), Pus(PusError), CantSendAddr(StoreAddr), + CantSendDirectTm, Send(GenericSendError), Recv(GenericRecvError), } @@ -82,6 +83,9 @@ impl Display for EcssTmtcError { EcssTmtcError::CantSendAddr(addr) => { write!(f, "can not send address {addr}") } + EcssTmtcError::CantSendDirectTm => { + write!(f, "can not send TM directly") + } EcssTmtcError::Send(send_e) => { write!(f, "send error {send_e}") } @@ -123,13 +127,14 @@ impl Error for EcssTmtcError { EcssTmtcError::Store(e) => Some(e), EcssTmtcError::Pus(e) => Some(e), EcssTmtcError::Send(e) => Some(e), + EcssTmtcError::Recv(e) => Some(e), _ => None, } } } pub trait EcssChannel: Send { /// Each sender can have an ID associated with it - fn id(&self) -> ChannelId; + fn channel_id(&self) -> ChannelId; fn name(&self) -> &'static str { "unset" } @@ -138,7 +143,7 @@ pub trait EcssChannel: Send { /// Generic trait for a user supplied sender object. /// /// This sender object is responsible for sending PUS telemetry to a TM sink. -pub trait EcssTmSenderCore: EcssChannel { +pub trait EcssTmSenderCore: Send { fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError>; } @@ -146,7 +151,7 @@ pub trait EcssTmSenderCore: EcssChannel { /// /// This sender object is responsible for sending PUS telecommands to a TC recipient. Each /// telecommand can optionally have a token which contains its verification state. -pub trait EcssTcSenderCore: EcssChannel { +pub trait EcssTcSenderCore { fn send_tc(&self, tc: PusTcCreator, token: Option) -> Result<(), EcssTmtcError>; } @@ -221,25 +226,25 @@ impl TryFrom for AcceptedEcssTcAndToken { #[derive(Debug, Clone)] pub enum TryRecvTmtcError { - Error(EcssTmtcError), + Tmtc(EcssTmtcError), Empty, } impl From for TryRecvTmtcError { fn from(value: EcssTmtcError) -> Self { - Self::Error(value) + Self::Tmtc(value) } } impl From for TryRecvTmtcError { fn from(value: PusError) -> Self { - Self::Error(value.into()) + Self::Tmtc(value.into()) } } impl From for TryRecvTmtcError { fn from(value: StoreError) -> Self { - Self::Error(value.into()) + Self::Tmtc(value.into()) } } @@ -366,18 +371,15 @@ pub mod std_mod { use crate::pool::{PoolProvider, PoolProviderWithGuards, SharedStaticMemoryPool, StoreAddr}; use crate::pus::verification::{TcStateAccepted, VerificationToken}; use crate::pus::{ - EcssChannel, EcssTcAndToken, EcssTcReceiver, EcssTcReceiverCore, EcssTmSender, - EcssTmSenderCore, EcssTmtcError, GenericRecvError, GenericSendError, PusTmWrapper, - TryRecvTmtcError, + EcssChannel, EcssTcAndToken, EcssTcReceiverCore, EcssTmSenderCore, EcssTmtcError, + GenericRecvError, GenericSendError, PusTmWrapper, TryRecvTmtcError, }; use crate::tmtc::tm_helper::SharedTmPool; use crate::{ChannelId, TargetId}; - use alloc::boxed::Box; use alloc::vec::Vec; - use crossbeam_channel as cb; use spacepackets::ecss::tc::PusTcReader; use spacepackets::ecss::tm::PusTmCreator; - use spacepackets::ecss::PusError; + use spacepackets::ecss::{PusError, WritablePusPacket}; use spacepackets::time::cds::TimeProvider; use spacepackets::time::StdTimestampError; use spacepackets::time::TimeWriter; @@ -386,6 +388,9 @@ pub mod std_mod { use std::sync::mpsc::TryRecvError; use thiserror::Error; + #[cfg(feature = "crossbeam")] + pub use cb_mod::*; + use super::verification::VerificationReportingProvider; use super::{AcceptedEcssTcAndToken, TcInMemory}; @@ -395,32 +400,65 @@ pub mod std_mod { } } - impl From> for EcssTmtcError { - fn from(_: cb::SendError) -> Self { - Self::Send(GenericSendError::RxDisconnected) + impl EcssTmSenderCore for mpsc::Sender { + fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> { + match tm { + PusTmWrapper::InStore(addr) => self + .send(addr) + .map_err(|_| GenericSendError::RxDisconnected)?, + PusTmWrapper::Direct(_) => return Err(EcssTmtcError::CantSendDirectTm), + }; + Ok(()) } } - impl From> for EcssTmtcError { - fn from(value: cb::TrySendError) -> Self { - match value { - cb::TrySendError::Full(_) => Self::Send(GenericSendError::QueueFull(None)), - cb::TrySendError::Disconnected(_) => Self::Send(GenericSendError::RxDisconnected), - } + impl EcssTmSenderCore for mpsc::SyncSender { + fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> { + match tm { + PusTmWrapper::InStore(addr) => self + .try_send(addr) + .map_err(|e| EcssTmtcError::Send(e.into()))?, + PusTmWrapper::Direct(_) => return Err(EcssTmtcError::CantSendDirectTm), + }; + Ok(()) + } + } + + impl EcssTmSenderCore for mpsc::Sender> { + fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> { + match tm { + PusTmWrapper::InStore(addr) => return Err(EcssTmtcError::CantSendAddr(addr)), + PusTmWrapper::Direct(tm) => self + .send(tm.to_vec()?) + .map_err(|e| EcssTmtcError::Send(e.into()))?, + }; + Ok(()) + } + } + + impl EcssTmSenderCore for mpsc::SyncSender> { + fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> { + match tm { + PusTmWrapper::InStore(addr) => return Err(EcssTmtcError::CantSendAddr(addr)), + PusTmWrapper::Direct(tm) => self + .send(tm.to_vec()?) + .map_err(|e| EcssTmtcError::Send(e.into()))?, + }; + Ok(()) } } #[derive(Clone)] - pub struct MpscTmInSharedPoolSender { - id: ChannelId, + pub struct TmInSharedPoolSenderWithId { + channel_id: ChannelId, name: &'static str, shared_tm_store: SharedTmPool, - sender: mpsc::Sender, + sender: Sender, } - impl EcssChannel for MpscTmInSharedPoolSender { - fn id(&self) -> ChannelId { - self.id + impl EcssChannel for TmInSharedPoolSenderWithId { + fn channel_id(&self) -> ChannelId { + self.channel_id } fn name(&self) -> &'static str { @@ -428,36 +466,31 @@ pub mod std_mod { } } - impl MpscTmInSharedPoolSender { + impl TmInSharedPoolSenderWithId { pub fn send_direct_tm(&self, tm: PusTmCreator) -> Result<(), EcssTmtcError> { let addr = self.shared_tm_store.add_pus_tm(&tm)?; - self.sender - .send(addr) - .map_err(|_| EcssTmtcError::Send(GenericSendError::RxDisconnected)) + self.sender.send_tm(PusTmWrapper::InStore(addr)) } } - impl EcssTmSenderCore for MpscTmInSharedPoolSender { + impl EcssTmSenderCore for TmInSharedPoolSenderWithId { fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> { - match tm { - PusTmWrapper::InStore(addr) => { - self.sender.send(addr)?; - Ok(()) - } - PusTmWrapper::Direct(tm) => self.send_direct_tm(tm), + if let PusTmWrapper::Direct(tm) = tm { + return self.send_direct_tm(tm); } + self.sender.send_tm(tm) } } - impl MpscTmInSharedPoolSender { + impl TmInSharedPoolSenderWithId { pub fn new( id: ChannelId, name: &'static str, shared_tm_store: SharedTmPool, - sender: mpsc::Sender, + sender: Sender, ) -> Self { Self { - id, + channel_id: id, name, shared_tm_store, sender, @@ -465,6 +498,51 @@ pub mod std_mod { } } + pub type TmInSharedPoolSenderWithMpsc = TmInSharedPoolSenderWithId>; + pub type TmInSharedPoolSenderWithBoundedMpsc = + TmInSharedPoolSenderWithId>; + + /// This class can be used if frequent heap allocations during run-time are not an issue. + /// PUS TM packets will be sent around as [Vec]s. Please note that the current implementation + /// of this class can not deal with store addresses, so it is assumed that is is always + /// going to be called with direct packets. + #[derive(Clone)] + pub struct TmAsVecSenderWithId { + id: ChannelId, + name: &'static str, + sender: Sender, + } + + impl From>> for EcssTmtcError { + fn from(_: mpsc::SendError>) -> Self { + Self::Send(GenericSendError::RxDisconnected) + } + } + + impl TmAsVecSenderWithId { + pub fn new(id: u32, name: &'static str, sender: Sender) -> Self { + Self { id, sender, name } + } + } + + impl EcssChannel for TmAsVecSenderWithId { + fn channel_id(&self) -> ChannelId { + self.id + } + fn name(&self) -> &'static str { + self.name + } + } + + impl EcssTmSenderCore for TmAsVecSenderWithId { + fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> { + self.sender.send_tm(tm) + } + } + + pub type TmAsVecSenderWithMpsc = TmAsVecSenderWithId>>; + pub type TmAsVecSenderWithBoundedMpsc = TmAsVecSenderWithId>>; + pub struct MpscTcReceiver { id: ChannelId, name: &'static str, @@ -472,7 +550,7 @@ pub mod std_mod { } impl EcssChannel for MpscTcReceiver { - fn id(&self) -> ChannelId { + fn channel_id(&self) -> ChannelId { self.id } @@ -486,7 +564,7 @@ pub mod std_mod { self.receiver.try_recv().map_err(|e| match e { TryRecvError::Empty => TryRecvTmtcError::Empty, TryRecvError::Disconnected => { - TryRecvTmtcError::Error(EcssTmtcError::from(GenericRecvError::TxDisconnected)) + TryRecvTmtcError::Tmtc(EcssTmtcError::from(GenericRecvError::TxDisconnected)) } }) } @@ -502,133 +580,89 @@ pub mod std_mod { } } - /// This class can be used if frequent heap allocations during run-time are not an issue. - /// PUS TM packets will be sent around as [Vec]s. Please note that the current implementation - /// of this class can not deal with store addresses, so it is assumed that is is always - /// going to be called with direct packets. - #[derive(Clone)] - pub struct MpscTmAsVecSender { - id: ChannelId, - name: &'static str, - sender: mpsc::Sender>, - } + #[cfg(feature = "crossbeam")] + pub mod cb_mod { + use super::*; + use crossbeam_channel as cb; - impl From>> for EcssTmtcError { - fn from(_: mpsc::SendError>) -> Self { - Self::Send(GenericSendError::RxDisconnected) - } - } + pub type TmInSharedPoolSenderWithCrossbeam = + TmInSharedPoolSenderWithId>; - impl MpscTmAsVecSender { - pub fn new(id: u32, name: &'static str, sender: mpsc::Sender>) -> Self { - Self { id, sender, name } + impl From> for EcssTmtcError { + fn from(_: cb::SendError) -> Self { + Self::Send(GenericSendError::RxDisconnected) + } } - } - impl EcssChannel for MpscTmAsVecSender { - fn id(&self) -> ChannelId { - self.id - } - fn name(&self) -> &'static str { - self.name - } - } - - impl EcssTmSenderCore for MpscTmAsVecSender { - fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> { - match tm { - PusTmWrapper::InStore(addr) => Err(EcssTmtcError::CantSendAddr(addr)), - PusTmWrapper::Direct(tm) => { - let mut vec = Vec::new(); - tm.append_to_vec(&mut vec).map_err(EcssTmtcError::Pus)?; - self.sender.send(vec)?; - Ok(()) + impl From> for EcssTmtcError { + fn from(value: cb::TrySendError) -> Self { + match value { + cb::TrySendError::Full(_) => Self::Send(GenericSendError::QueueFull(None)), + cb::TrySendError::Disconnected(_) => { + Self::Send(GenericSendError::RxDisconnected) + } } } } - } - #[derive(Clone)] - pub struct CrossbeamTmInStoreSender { - id: ChannelId, - name: &'static str, - shared_tm_store: SharedTmPool, - sender: crossbeam_channel::Sender, - } - - impl CrossbeamTmInStoreSender { - pub fn new( - id: ChannelId, - name: &'static str, - shared_tm_store: SharedTmPool, - sender: crossbeam_channel::Sender, - ) -> Self { - Self { - id, - name, - shared_tm_store, - sender, + impl EcssTmSenderCore for cb::Sender { + fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> { + match tm { + PusTmWrapper::InStore(addr) => self + .try_send(addr) + .map_err(|e| EcssTmtcError::Send(e.into()))?, + PusTmWrapper::Direct(_) => return Err(EcssTmtcError::CantSendDirectTm), + }; + Ok(()) } } - } - - impl EcssChannel for CrossbeamTmInStoreSender { - fn id(&self) -> ChannelId { - self.id - } - - fn name(&self) -> &'static str { - self.name - } - } - - impl EcssTmSenderCore for CrossbeamTmInStoreSender { - fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> { - match tm { - PusTmWrapper::InStore(addr) => self.sender.try_send(addr)?, - PusTmWrapper::Direct(tm) => { - let addr = self.shared_tm_store.add_pus_tm(&tm)?; - self.sender.try_send(addr)?; - } + impl EcssTmSenderCore for cb::Sender> { + fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> { + match tm { + PusTmWrapper::InStore(addr) => return Err(EcssTmtcError::CantSendAddr(addr)), + PusTmWrapper::Direct(tm) => self + .send(tm.to_vec()?) + .map_err(|e| EcssTmtcError::Send(e.into()))?, + }; + Ok(()) } - Ok(()) } - } - pub struct CrossbeamTcReceiver { - id: ChannelId, - name: &'static str, - receiver: cb::Receiver, - } - - impl CrossbeamTcReceiver { - pub fn new( + pub struct CrossbeamTcReceiver { id: ChannelId, name: &'static str, receiver: cb::Receiver, - ) -> Self { - Self { id, name, receiver } - } - } - - impl EcssChannel for CrossbeamTcReceiver { - fn id(&self) -> ChannelId { - self.id } - fn name(&self) -> &'static str { - self.name + impl CrossbeamTcReceiver { + pub fn new( + id: ChannelId, + name: &'static str, + receiver: cb::Receiver, + ) -> Self { + Self { id, name, receiver } + } } - } - impl EcssTcReceiverCore for CrossbeamTcReceiver { - fn recv_tc(&self) -> Result { - self.receiver.try_recv().map_err(|e| match e { - cb::TryRecvError::Empty => TryRecvTmtcError::Empty, - cb::TryRecvError::Disconnected => { - TryRecvTmtcError::Error(EcssTmtcError::from(GenericRecvError::TxDisconnected)) - } - }) + impl EcssChannel for CrossbeamTcReceiver { + fn channel_id(&self) -> ChannelId { + self.id + } + + fn name(&self) -> &'static str { + self.name + } + } + + impl EcssTcReceiverCore for CrossbeamTcReceiver { + fn recv_tc(&self) -> Result { + self.receiver.try_recv().map_err(|e| match e { + cb::TryRecvError::Empty => TryRecvTmtcError::Empty, + cb::TryRecvError::Disconnected => TryRecvTmtcError::Tmtc(EcssTmtcError::from( + GenericRecvError::TxDisconnected, + )), + }) + } } } @@ -811,36 +845,35 @@ pub mod std_mod { } } - pub struct PusServiceBase { - pub tc_receiver: Box, - pub tm_sender: Box, + pub struct PusServiceBase< + TcReceiver: EcssTcReceiverCore, + TmSender: EcssTmSenderCore, + VerificationReporter: VerificationReportingProvider, + > { + pub tc_receiver: TcReceiver, + pub tm_sender: TmSender, pub tm_apid: u16, - /// 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. pub verification_handler: VerificationReporter, } - - impl PusServiceBase { - #[cfg(feature = "std")] - pub fn get_current_cds_short_timestamp( - partial_error: &mut Option, - ) -> [u8; 7] { - let mut time_stamp: [u8; 7] = [0; 7]; - let time_provider = - TimeProvider::from_now_with_u16_days().map_err(PartialPusHandlingError::Time); - if let Ok(time_provider) = time_provider { - // Can't fail, we have a buffer with the exact required size. - time_provider.write_to_bytes(&mut time_stamp).unwrap(); - } else { - *partial_error = Some(time_provider.unwrap_err()); - } - time_stamp - } - #[cfg(feature = "std")] - pub fn get_current_timestamp_ignore_error() -> [u8; 7] { - let mut dummy = None; - Self::get_current_cds_short_timestamp(&mut dummy) + #[cfg(feature = "std")] + pub fn get_current_cds_short_timestamp( + partial_error: &mut Option, + ) -> [u8; 7] { + let mut time_stamp: [u8; 7] = [0; 7]; + let time_provider = + TimeProvider::from_now_with_u16_days().map_err(PartialPusHandlingError::Time); + if let Ok(time_provider) = time_provider { + // Can't fail, we have a buffer with the exact required size. + time_provider.write_to_bytes(&mut time_stamp).unwrap(); + } else { + *partial_error = Some(time_provider.unwrap_err()); } + time_stamp + } + #[cfg(feature = "std")] + pub fn get_current_timestamp_ignore_error() -> [u8; 7] { + let mut dummy = None; + get_current_cds_short_timestamp(&mut dummy) } /// This is a high-level PUS packet handler helper. @@ -853,21 +886,25 @@ pub mod std_mod { /// by using the [EcssTcInMemConverter] abstraction. This object provides some convenience /// methods to make the generic parts of TC handling easier. pub struct PusServiceHelper< + TcReceiver: EcssTcReceiverCore, + TmSender: EcssTmSenderCore, TcInMemConverter: EcssTcInMemConverter, VerificationReporter: VerificationReportingProvider, > { - pub common: PusServiceBase, + pub common: PusServiceBase, pub tc_in_mem_converter: TcInMemConverter, } impl< + TcReceiver: EcssTcReceiverCore, + TmSender: EcssTmSenderCore, TcInMemConverter: EcssTcInMemConverter, VerificationReporter: VerificationReportingProvider, - > PusServiceHelper + > PusServiceHelper { pub fn new( - tc_receiver: Box, - tm_sender: Box, + tc_receiver: TcReceiver, + tm_sender: TmSender, tm_apid: u16, verification_handler: VerificationReporter, tc_in_mem_converter: TcInMemConverter, @@ -886,7 +923,7 @@ pub mod std_mod { /// This function can be used to poll the internal [EcssTcReceiver] object for the next /// telecommand packet. It will return `Ok(None)` if there are not packets available. /// In any other case, it will perform the acceptance of the ECSS TC packet using the - /// internal [VerificationReporterWithSender] object. It will then return the telecommand + /// internal [VerificationReportingProvider] object. It will then return the telecommand /// and the according accepted token. pub fn retrieve_and_accept_next_packet( &mut self, @@ -908,12 +945,40 @@ pub mod std_mod { })) } Err(e) => match e { - TryRecvTmtcError::Error(e) => Err(PusPacketHandlingError::EcssTmtc(e)), + TryRecvTmtcError::Tmtc(e) => Err(PusPacketHandlingError::EcssTmtc(e)), TryRecvTmtcError::Empty => Ok(None), }, } } } + + pub type PusServiceHelperDynWithMpsc = PusServiceHelper< + MpscTcReceiver, + TmAsVecSenderWithMpsc, + TcInMemConverter, + VerificationReporter, + >; + pub type PusServiceHelperDynWithBoundedMpsc = + PusServiceHelper< + MpscTcReceiver, + TmAsVecSenderWithBoundedMpsc, + TcInMemConverter, + VerificationReporter, + >; + pub type PusServiceHelperStaticWithMpsc = + PusServiceHelper< + MpscTcReceiver, + TmInSharedPoolSenderWithMpsc, + TcInMemConverter, + VerificationReporter, + >; + pub type PusServiceHelperStaticWithBoundedMpsc = + PusServiceHelper< + MpscTcReceiver, + TmInSharedPoolSenderWithBoundedMpsc, + TcInMemConverter, + VerificationReporter, + >; } pub(crate) fn source_buffer_large_enough(cap: usize, len: usize) -> Result<(), EcssTmtcError> { @@ -935,7 +1000,6 @@ pub mod tests { use std::sync::mpsc::TryRecvError; use std::sync::{mpsc, RwLock}; - use alloc::boxed::Box; use alloc::collections::VecDeque; use alloc::vec::Vec; use satrs_shared::res_code::ResultU16; @@ -951,6 +1015,9 @@ pub mod tests { use crate::tmtc::tm_helper::SharedTmPool; use crate::TargetId; + use super::verification::std_mod::{ + VerificationReporterWithSharedPoolMpscBoundedSender, VerificationReporterWithVecMpscSender, + }; use super::verification::tests::{SharedVerificationMap, TestVerificationReporter}; use super::verification::{ TcStateAccepted, VerificationReporterCfg, VerificationReporterWithSender, @@ -958,8 +1025,9 @@ pub mod tests { }; use super::{ EcssTcAndToken, EcssTcInSharedStoreConverter, EcssTcInVecConverter, GenericRoutingError, - MpscTcReceiver, MpscTmAsVecSender, MpscTmInSharedPoolSender, PusPacketHandlerResult, - PusPacketHandlingError, PusRoutingErrorHandler, PusServiceHelper, TcInMemory, + MpscTcReceiver, PusPacketHandlerResult, PusPacketHandlingError, PusRoutingErrorHandler, + PusServiceHelper, TcInMemory, TmAsVecSenderWithId, TmAsVecSenderWithMpsc, + TmInSharedPoolSenderWithBoundedMpsc, TmInSharedPoolSenderWithId, }; pub const TEST_APID: u16 = 0x101; @@ -1004,29 +1072,33 @@ pub mod tests { tm_buf: [u8; 2048], tc_pool: SharedStaticMemoryPool, tm_pool: SharedTmPool, - tc_sender: mpsc::Sender, + tc_sender: mpsc::SyncSender, tm_receiver: mpsc::Receiver, - verification_handler: VerificationReporterWithSender, + verification_handler: VerificationReporterWithSharedPoolMpscBoundedSender, } + pub type PusServiceHelperStatic = PusServiceHelper< + MpscTcReceiver, + TmInSharedPoolSenderWithBoundedMpsc, + EcssTcInSharedStoreConverter, + VerificationReporterWithSharedPoolMpscBoundedSender, + >; + impl PusServiceHandlerWithSharedStoreCommon { /// This function generates the structure in addition to the PUS service handler /// [PusServiceHandler] which might be required for a specific PUS service handler. /// /// The PUS service handler is instantiated with a [EcssTcInStoreConverter]. - pub fn new() -> ( - Self, - PusServiceHelper, - ) { + pub fn new() -> (Self, PusServiceHelperStatic) { let pool_cfg = StaticPoolConfig::new(alloc::vec![(16, 16), (8, 32), (4, 64)], false); let tc_pool = StaticMemoryPool::new(pool_cfg.clone()); let tm_pool = StaticMemoryPool::new(pool_cfg); let shared_tc_pool = SharedStaticMemoryPool::new(RwLock::new(tc_pool)); let shared_tm_pool = SharedTmPool::new(tm_pool); - let (test_srv_tc_tx, test_srv_tc_rx) = mpsc::channel(); - let (tm_tx, tm_rx) = mpsc::channel(); + let (test_srv_tc_tx, test_srv_tc_rx) = mpsc::sync_channel(10); + let (tm_tx, tm_rx) = mpsc::sync_channel(10); - let verif_sender = MpscTmInSharedPoolSender::new( + let verif_sender = TmInSharedPoolSenderWithBoundedMpsc::new( 0, "verif_sender", shared_tm_pool.clone(), @@ -1034,9 +1106,9 @@ pub mod tests { ); let verif_cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8).unwrap(); let verification_handler = - VerificationReporterWithSender::new(&verif_cfg, Box::new(verif_sender)); + VerificationReporterWithSharedPoolMpscBoundedSender::new(&verif_cfg, verif_sender); let test_srv_tm_sender = - MpscTmInSharedPoolSender::new(0, "TEST_SENDER", shared_tm_pool.clone(), tm_tx); + TmInSharedPoolSenderWithId::new(0, "TEST_SENDER", shared_tm_pool.clone(), tm_tx); let test_srv_tc_receiver = MpscTcReceiver::new(0, "TEST_RECEIVER", test_srv_tc_rx); let in_store_converter = EcssTcInSharedStoreConverter::new(shared_tc_pool.clone(), 2048); @@ -1051,8 +1123,8 @@ pub mod tests { verification_handler: verification_handler.clone(), }, PusServiceHelper::new( - Box::new(test_srv_tc_receiver), - Box::new(test_srv_tm_sender), + test_srv_tc_receiver, + test_srv_tm_sender, TEST_APID, verification_handler, in_store_converter, @@ -1116,21 +1188,24 @@ pub mod tests { tm_receiver: mpsc::Receiver>, pub verification_handler: VerificationReporter, } + pub type PusServiceHelperDynamic = PusServiceHelper< + MpscTcReceiver, + TmAsVecSenderWithMpsc, + EcssTcInVecConverter, + VerificationReporterWithVecMpscSender, + >; - impl PusServiceHandlerWithVecCommon { - pub fn new_with_standard_verif_reporter() -> ( - Self, - PusServiceHelper, - ) { + impl PusServiceHandlerWithVecCommon { + pub fn new_with_standard_verif_reporter() -> (Self, PusServiceHelperDynamic) { let (test_srv_tc_tx, test_srv_tc_rx) = mpsc::channel(); let (tm_tx, tm_rx) = mpsc::channel(); - let verif_sender = MpscTmAsVecSender::new(0, "verififcatio-sender", tm_tx.clone()); + let verif_sender = TmAsVecSenderWithId::new(0, "verififcatio-sender", tm_tx.clone()); let verif_cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8).unwrap(); let verification_handler = - VerificationReporterWithSender::new(&verif_cfg, Box::new(verif_sender)); + VerificationReporterWithSender::new(&verif_cfg, verif_sender); - let test_srv_tm_sender = MpscTmAsVecSender::new(0, "test-sender", tm_tx); + let test_srv_tm_sender = TmAsVecSenderWithId::new(0, "test-sender", tm_tx); let test_srv_tc_receiver = MpscTcReceiver::new(0, "test-receiver", test_srv_tc_rx); let in_store_converter = EcssTcInVecConverter::default(); ( @@ -1141,8 +1216,8 @@ pub mod tests { verification_handler: verification_handler.clone(), }, PusServiceHelper::new( - Box::new(test_srv_tc_receiver), - Box::new(test_srv_tm_sender), + test_srv_tc_receiver, + test_srv_tm_sender, TEST_APID, verification_handler, in_store_converter, @@ -1154,12 +1229,17 @@ pub mod tests { impl PusServiceHandlerWithVecCommon { pub fn new_with_test_verif_sender() -> ( Self, - PusServiceHelper, + PusServiceHelper< + MpscTcReceiver, + TmAsVecSenderWithMpsc, + EcssTcInVecConverter, + TestVerificationReporter, + >, ) { let (test_srv_tc_tx, test_srv_tc_rx) = mpsc::channel(); let (tm_tx, tm_rx) = mpsc::channel(); - let test_srv_tm_sender = MpscTmAsVecSender::new(0, "test-sender", tm_tx); + let test_srv_tm_sender = TmAsVecSenderWithId::new(0, "test-sender", tm_tx); let test_srv_tc_receiver = MpscTcReceiver::new(0, "test-receiver", test_srv_tc_rx); let in_store_converter = EcssTcInVecConverter::default(); let shared_verif_map = SharedVerificationMap::default(); @@ -1172,8 +1252,8 @@ pub mod tests { verification_handler: verification_handler.clone(), }, PusServiceHelper::new( - Box::new(test_srv_tc_receiver), - Box::new(test_srv_tm_sender), + test_srv_tc_receiver, + test_srv_tm_sender, TEST_APID, verification_handler, in_store_converter, diff --git a/satrs/src/pus/scheduler.rs b/satrs/src/pus/scheduler.rs index e55028c..cebcf2c 100644 --- a/satrs/src/pus/scheduler.rs +++ b/satrs/src/pus/scheduler.rs @@ -340,18 +340,18 @@ pub fn generate_insert_telecommand_app_data( #[cfg(feature = "alloc")] pub mod alloc_mod { + use alloc::{ + collections::{ + btree_map::{Entry, Range}, + BTreeMap, + }, + vec::Vec, + }; + use spacepackets::time::cds::{self, DaysLen24Bits}; + + use crate::pool::StoreAddr; + use super::*; - use crate::pool::{PoolProvider, StoreAddr, StoreError}; - use alloc::collections::btree_map::{Entry, Range}; - use alloc::collections::BTreeMap; - use alloc::vec; - use alloc::vec::Vec; - use core::time::Duration; - use spacepackets::ecss::scheduling::TimeWindowType; - use spacepackets::ecss::tc::{PusTc, PusTcReader}; - use spacepackets::ecss::PusPacket; - use spacepackets::time::cds::DaysLen24Bits; - use spacepackets::time::{cds, CcsdsTimeProvider, UnixTimestamp}; #[cfg(feature = "std")] use std::time::SystemTimeError; @@ -461,7 +461,7 @@ pub mod alloc_mod { } match self.tc_map.entry(time_stamp) { Entry::Vacant(e) => { - e.insert(vec![info]); + e.insert(alloc::vec![info]); } Entry::Occupied(mut v) => { v.get_mut().push(info); @@ -498,7 +498,7 @@ pub mod alloc_mod { /// short timestamp with 16-bit length of days field. pub fn insert_wrapped_tc_cds_short( &mut self, - pus_tc: &PusTc, + pus_tc: &(impl IsPusTelecommand + PusPacket + GenericPusTcSecondaryHeader), pool: &mut (impl PoolProvider + ?Sized), ) -> Result { self.insert_wrapped_tc::(pus_tc, pool) @@ -508,7 +508,7 @@ pub mod alloc_mod { /// long timestamp with a 24-bit length of days field. pub fn insert_wrapped_tc_cds_long( &mut self, - pus_tc: &PusTc, + pus_tc: &(impl IsPusTelecommand + PusPacket + GenericPusTcSecondaryHeader), pool: &mut (impl PoolProvider + ?Sized), ) -> Result { self.insert_wrapped_tc::>(pus_tc, pool) @@ -530,7 +530,7 @@ pub mod alloc_mod { let range = self.retrieve_by_time_filter(time_window); let mut del_packets = 0; let mut res_if_fails = None; - let mut keys_to_delete = Vec::new(); + let mut keys_to_delete = alloc::vec::Vec::new(); for time_bucket in range { for tc in time_bucket.1 { match pool.delete(tc.addr) { @@ -561,7 +561,10 @@ pub mod alloc_mod { } /// Retrieve a range over all scheduled commands. - pub fn retrieve_all(&mut self) -> Range<'_, UnixTimestamp, Vec> { + pub fn retrieve_all( + &mut self, + ) -> alloc::collections::btree_map::Range<'_, UnixTimestamp, alloc::vec::Vec> + { self.tc_map.range(..) } @@ -572,7 +575,7 @@ pub mod alloc_mod { pub fn retrieve_by_time_filter( &mut self, time_window: TimeWindow, - ) -> Range<'_, UnixTimestamp, Vec> { + ) -> Range<'_, UnixTimestamp, alloc::vec::Vec> { match time_window.time_window_type() { TimeWindowType::SelectAll => self.tc_map.range(..), TimeWindowType::TimeTagToTimeTag => { @@ -761,9 +764,9 @@ pub mod alloc_mod { mut releaser: R, tc_store: &(impl PoolProvider + ?Sized), tc_buf: &mut [u8], - ) -> Result, (Vec, StoreError)> { + ) -> Result, (alloc::vec::Vec, StoreError)> { let tcs_to_release = self.telecommands_to_release(); - let mut released_tcs = Vec::new(); + let mut released_tcs = alloc::vec::Vec::new(); for tc in tcs_to_release { for info in tc.1 { tc_store @@ -835,7 +838,7 @@ pub mod alloc_mod { } match self.tc_map.entry(time_stamp) { Entry::Vacant(e) => { - e.insert(vec![info]); + e.insert(alloc::vec![info]); } Entry::Occupied(mut v) => { v.get_mut().push(info); diff --git a/satrs/src/pus/scheduler_srv.rs b/satrs/src/pus/scheduler_srv.rs index 72e8a7b..9cfb920 100644 --- a/satrs/src/pus/scheduler_srv.rs +++ b/satrs/src/pus/scheduler_srv.rs @@ -1,6 +1,15 @@ use super::scheduler::PusSchedulerProvider; -use super::verification::VerificationReportingProvider; -use super::{EcssTcInMemConverter, PusServiceBase, PusServiceHelper}; +use super::verification::{ + VerificationReporterWithSharedPoolMpscBoundedSender, + VerificationReporterWithSharedPoolMpscSender, VerificationReporterWithVecMpscBoundedSender, + VerificationReporterWithVecMpscSender, VerificationReportingProvider, +}; +use super::{ + get_current_cds_short_timestamp, EcssTcInMemConverter, EcssTcInSharedStoreConverter, + EcssTcInVecConverter, EcssTcReceiverCore, EcssTmSenderCore, MpscTcReceiver, PusServiceHelper, + TmAsVecSenderWithBoundedMpsc, TmAsVecSenderWithMpsc, TmInSharedPoolSenderWithBoundedMpsc, + TmInSharedPoolSenderWithMpsc, +}; use crate::pool::PoolProvider; use crate::pus::{PusPacketHandlerResult, PusPacketHandlingError}; use alloc::string::ToString; @@ -16,22 +25,39 @@ use spacepackets::time::cds::TimeProvider; /// [Self::scheduler] and [Self::scheduler_mut] function and then use the scheduler API to release /// telecommands when applicable. pub struct PusService11SchedHandler< + TcReceiver: EcssTcReceiverCore, + TmSender: EcssTmSenderCore, TcInMemConverter: EcssTcInMemConverter, VerificationReporter: VerificationReportingProvider, PusScheduler: PusSchedulerProvider, > { - pub service_helper: PusServiceHelper, + pub service_helper: + PusServiceHelper, scheduler: PusScheduler, } impl< + TcReceiver: EcssTcReceiverCore, + TmSender: EcssTmSenderCore, TcInMemConverter: EcssTcInMemConverter, VerificationReporter: VerificationReportingProvider, Scheduler: PusSchedulerProvider, - > PusService11SchedHandler + > + PusService11SchedHandler< + TcReceiver, + TmSender, + TcInMemConverter, + VerificationReporter, + Scheduler, + > { pub fn new( - service_helper: PusServiceHelper, + service_helper: PusServiceHelper< + TcReceiver, + TmSender, + TcInMemConverter, + VerificationReporter, + >, scheduler: Scheduler, ) -> Self { Self { @@ -70,9 +96,7 @@ impl< )); } let mut partial_error = None; - let time_stamp = PusServiceBase::::get_current_cds_short_timestamp( - &mut partial_error, - ); + let time_stamp = get_current_cds_short_timestamp(&mut partial_error); match standard_subservice.unwrap() { scheduling::Subservice::TcEnableScheduling => { let start_token = self @@ -169,18 +193,55 @@ impl< Ok(PusPacketHandlerResult::RequestHandled) } } +/// Helper type definition for a PUS 11 handler with a dynamic TMTC memory backend and regular +/// mpsc queues. +pub type PusService11SchedHandlerDynWithMpsc = PusService11SchedHandler< + MpscTcReceiver, + TmAsVecSenderWithMpsc, + EcssTcInVecConverter, + VerificationReporterWithVecMpscSender, + PusScheduler, +>; +/// Helper type definition for a PUS 11 handler with a dynamic TMTC memory backend and bounded MPSC +/// queues. +pub type PusService11SchedHandlerDynWithBoundedMpsc = PusService11SchedHandler< + MpscTcReceiver, + TmAsVecSenderWithBoundedMpsc, + EcssTcInVecConverter, + VerificationReporterWithVecMpscBoundedSender, + PusScheduler, +>; +/// Helper type definition for a PUS 11 handler with a shared store TMTC memory backend and regular +/// mpsc queues. +pub type PusService11SchedHandlerStaticWithMpsc = PusService11SchedHandler< + MpscTcReceiver, + TmInSharedPoolSenderWithMpsc, + EcssTcInSharedStoreConverter, + VerificationReporterWithSharedPoolMpscSender, + PusScheduler, +>; +/// Helper type definition for a PUS 11 handler with a shared store TMTC memory backend and bounded +/// mpsc queues. +pub type PusService11SchedHandlerStaticWithBoundedMpsc = PusService11SchedHandler< + MpscTcReceiver, + TmInSharedPoolSenderWithBoundedMpsc, + EcssTcInSharedStoreConverter, + VerificationReporterWithSharedPoolMpscBoundedSender, + PusScheduler, +>; #[cfg(test)] mod tests { use crate::pool::{StaticMemoryPool, StaticPoolConfig}; use crate::pus::tests::TEST_APID; - use crate::pus::verification::VerificationReporterWithSender; + use crate::pus::verification::VerificationReporterWithSharedPoolMpscBoundedSender; use crate::pus::{ scheduler::{self, PusSchedulerProvider, TcInfo}, tests::{PusServiceHandlerWithSharedStoreCommon, PusTestHarness}, verification::{RequestId, TcStateAccepted, VerificationToken}, EcssTcInSharedStoreConverter, }; + use crate::pus::{MpscTcReceiver, TmInSharedPoolSenderWithBoundedMpsc}; use alloc::collections::VecDeque; use delegate::delegate; use spacepackets::ecss::scheduling::Subservice; @@ -198,8 +259,10 @@ mod tests { struct Pus11HandlerWithStoreTester { common: PusServiceHandlerWithSharedStoreCommon, handler: PusService11SchedHandler< + MpscTcReceiver, + TmInSharedPoolSenderWithBoundedMpsc, EcssTcInSharedStoreConverter, - VerificationReporterWithSender, + VerificationReporterWithSharedPoolMpscBoundedSender, TestScheduler, >, sched_tc_pool: StaticMemoryPool, diff --git a/satrs/src/pus/test.rs b/satrs/src/pus/test.rs index bfea48b..ea5a720 100644 --- a/satrs/src/pus/test.rs +++ b/satrs/src/pus/test.rs @@ -5,24 +5,45 @@ use spacepackets::ecss::tm::{PusTmCreator, PusTmSecondaryHeader}; use spacepackets::ecss::PusPacket; use spacepackets::SpHeader; -use super::verification::VerificationReportingProvider; -use super::{EcssTcInMemConverter, PusServiceBase, PusServiceHelper}; +use super::verification::{ + VerificationReporterWithSharedPoolMpscBoundedSender, + VerificationReporterWithSharedPoolMpscSender, VerificationReporterWithVecMpscBoundedSender, + VerificationReporterWithVecMpscSender, VerificationReportingProvider, +}; +use super::{ + get_current_cds_short_timestamp, EcssTcInMemConverter, EcssTcInSharedStoreConverter, + EcssTcInVecConverter, EcssTcReceiverCore, EcssTmSenderCore, MpscTcReceiver, PusServiceHelper, + TmAsVecSenderWithBoundedMpsc, TmAsVecSenderWithMpsc, TmInSharedPoolSenderWithBoundedMpsc, + TmInSharedPoolSenderWithMpsc, +}; /// 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. pub struct PusService17TestHandler< + TcReceiver: EcssTcReceiverCore, + TmSender: EcssTmSenderCore, TcInMemConverter: EcssTcInMemConverter, VerificationReporter: VerificationReportingProvider, > { - pub service_helper: PusServiceHelper, + pub service_helper: + PusServiceHelper, } impl< + TcReceiver: EcssTcReceiverCore, + TmSender: EcssTmSenderCore, TcInMemConverter: EcssTcInMemConverter, VerificationReporter: VerificationReportingProvider, - > PusService17TestHandler + > PusService17TestHandler { - pub fn new(service_helper: PusServiceHelper) -> Self { + pub fn new( + service_helper: PusServiceHelper< + TcReceiver, + TmSender, + TcInMemConverter, + VerificationReporter, + >, + ) -> Self { Self { service_helper } } @@ -41,10 +62,7 @@ impl< } if tc.subservice() == 1 { let mut partial_error = None; - let time_stamp = - PusServiceBase::::get_current_cds_short_timestamp( - &mut partial_error, - ); + let time_stamp = get_current_cds_short_timestamp(&mut partial_error); let result = self .service_helper .common @@ -98,17 +116,53 @@ impl< } } +/// Helper type definition for a PUS 17 handler with a dynamic TMTC memory backend and regular +/// mpsc queues. +pub type PusService17TestHandlerDynWithMpsc = PusService17TestHandler< + MpscTcReceiver, + TmAsVecSenderWithMpsc, + EcssTcInVecConverter, + VerificationReporterWithVecMpscSender, +>; +/// Helper type definition for a PUS 17 handler with a dynamic TMTC memory backend and bounded MPSC +/// queues. +pub type PusService17TestHandlerDynWithBoundedMpsc = PusService17TestHandler< + MpscTcReceiver, + TmAsVecSenderWithBoundedMpsc, + EcssTcInVecConverter, + VerificationReporterWithVecMpscBoundedSender, +>; +/// Helper type definition for a PUS 17 handler with a shared store TMTC memory backend and regular +/// mpsc queues. +pub type PusService17TestHandlerStaticWithMpsc = PusService17TestHandler< + MpscTcReceiver, + TmInSharedPoolSenderWithMpsc, + EcssTcInSharedStoreConverter, + VerificationReporterWithSharedPoolMpscSender, +>; +/// Helper type definition for a PUS 17 handler with a shared store TMTC memory backend and bounded +/// mpsc queues. +pub type PusService17TestHandlerStaticWithBoundedMpsc = PusService17TestHandler< + MpscTcReceiver, + TmInSharedPoolSenderWithBoundedMpsc, + EcssTcInSharedStoreConverter, + VerificationReporterWithSharedPoolMpscBoundedSender, +>; + #[cfg(test)] mod tests { use crate::pus::tests::{ PusServiceHandlerWithSharedStoreCommon, PusServiceHandlerWithVecCommon, PusTestHarness, SimplePusPacketHandler, TEST_APID, }; - use crate::pus::verification::{RequestId, VerificationReporterWithSender}; + use crate::pus::verification::std_mod::{ + VerificationReporterWithSharedPoolMpscBoundedSender, VerificationReporterWithVecMpscSender, + }; + use crate::pus::verification::RequestId; use crate::pus::verification::{TcStateAccepted, VerificationToken}; use crate::pus::{ - EcssTcInSharedStoreConverter, EcssTcInVecConverter, PusPacketHandlerResult, - PusPacketHandlingError, + EcssTcInSharedStoreConverter, EcssTcInVecConverter, MpscTcReceiver, PusPacketHandlerResult, + PusPacketHandlingError, TmAsVecSenderWithMpsc, TmInSharedPoolSenderWithBoundedMpsc, }; use delegate::delegate; use spacepackets::ecss::tc::{PusTcCreator, PusTcSecondaryHeader}; @@ -120,8 +174,12 @@ mod tests { struct Pus17HandlerWithStoreTester { common: PusServiceHandlerWithSharedStoreCommon, - handler: - PusService17TestHandler, + handler: PusService17TestHandler< + MpscTcReceiver, + TmInSharedPoolSenderWithBoundedMpsc, + EcssTcInSharedStoreConverter, + VerificationReporterWithSharedPoolMpscBoundedSender, + >, } impl Pus17HandlerWithStoreTester { @@ -158,8 +216,13 @@ mod tests { } struct Pus17HandlerWithVecTester { - common: PusServiceHandlerWithVecCommon, - handler: PusService17TestHandler, + common: PusServiceHandlerWithVecCommon, + handler: PusService17TestHandler< + MpscTcReceiver, + TmAsVecSenderWithMpsc, + EcssTcInVecConverter, + VerificationReporterWithVecMpscSender, + >, } impl Pus17HandlerWithVecTester { diff --git a/satrs/src/pus/verification.rs b/satrs/src/pus/verification.rs index 369b46e..89ce9b9 100644 --- a/satrs/src/pus/verification.rs +++ b/satrs/src/pus/verification.rs @@ -20,7 +20,7 @@ //! VerificationReportingProvider, VerificationReporterCfg, VerificationReporterWithSender //! }; //! use satrs::seq_count::SeqCountProviderSimple; -//! use satrs::pus::MpscTmInSharedPoolSender; +//! use satrs::pus::TmInSharedPoolSenderWithMpsc; //! use satrs::tmtc::tm_helper::SharedTmPool; //! use spacepackets::ecss::PusPacket; //! use spacepackets::SpHeader; @@ -35,9 +35,9 @@ //! let shared_tm_store = SharedTmPool::new(tm_pool); //! let tm_store = shared_tm_store.clone_backing_pool(); //! let (verif_tx, verif_rx) = mpsc::channel(); -//! let sender = MpscTmInSharedPoolSender::new(0, "Test Sender", shared_tm_store, verif_tx); +//! let sender = TmInSharedPoolSenderWithMpsc::new(0, "Test Sender", shared_tm_store, verif_tx); //! let cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8).unwrap(); -//! let mut reporter = VerificationReporterWithSender::new(&cfg , Box::new(sender)); +//! let mut reporter = VerificationReporterWithSender::new(&cfg , sender); //! //! let mut sph = SpHeader::tc_unseg(TEST_APID, 0, 0).unwrap(); //! let tc_header = PusTcSecondaryHeader::new_simple(17, 1); @@ -95,10 +95,11 @@ pub use crate::seq_count::SeqCountProviderSimple; pub use spacepackets::ecss::verification::*; #[cfg(feature = "alloc")] -pub use alloc_mod::{ - VerificationReporter, VerificationReporterCfg, VerificationReporterWithSender, -}; +#[cfg_attr(feature = "doc_cfg", doc(cfg(feature = "alloc")))] +pub use alloc_mod::*; + #[cfg(feature = "std")] +#[cfg_attr(feature = "doc_cfg", doc(cfg(feature = "std")))] pub use std_mod::*; /// This is a request identifier as specified in 5.4.11.2 c. of the PUS standard. @@ -949,15 +950,13 @@ impl VerificationReporterCore { } #[cfg(feature = "alloc")] -mod alloc_mod { +pub mod alloc_mod { use super::*; - use crate::pus::alloc_mod::EcssTmSender; - use crate::seq_count::SequenceCountProvider; - use alloc::boxed::Box; - use alloc::vec; - use alloc::vec::Vec; + use crate::{ + pus::{TmAsVecSenderWithId, TmInSharedPoolSenderWithId}, + seq_count::SequenceCountProvider, + }; use core::cell::RefCell; - use spacepackets::ecss::tc::IsPusTelecommand; #[derive(Clone)] pub struct VerificationReporterCfg { @@ -992,9 +991,9 @@ mod alloc_mod { /// TM funnel. This helper will always set those fields to 0. #[derive(Clone)] pub struct VerificationReporter { - source_data_buf: RefCell>, - pub seq_count_provider: Option + Send>>, - pub msg_count_provider: Option + Send>>, + source_data_buf: RefCell>, + pub seq_count_provider: Option + Send>>, + pub msg_count_provider: Option + Send>>, pub reporter: VerificationReporterCore, } @@ -1002,7 +1001,7 @@ mod alloc_mod { pub fn new(cfg: &VerificationReporterCfg) -> Self { let reporter = VerificationReporterCore::new(cfg.apid).unwrap(); Self { - source_data_buf: RefCell::new(vec![ + source_data_buf: RefCell::new(alloc::vec![ 0; RequestId::SIZE_AS_BYTES + cfg.step_field_width @@ -1269,21 +1268,18 @@ mod alloc_mod { /// Helper object which caches the sender passed as a trait object. Provides the same /// API as [VerificationReporter] but without the explicit sender arguments. #[derive(Clone)] - pub struct VerificationReporterWithSender { + pub struct VerificationReporterWithSender { pub reporter: VerificationReporter, - pub sender: Box, + pub sender: Sender, } - impl VerificationReporterWithSender { - pub fn new(cfg: &VerificationReporterCfg, sender: Box) -> Self { + impl VerificationReporterWithSender { + pub fn new(cfg: &VerificationReporterCfg, sender: Sender) -> Self { let reporter = VerificationReporter::new(cfg); Self::new_from_reporter(reporter, sender) } - pub fn new_from_reporter( - reporter: VerificationReporter, - sender: Box, - ) -> Self { + pub fn new_from_reporter(reporter: VerificationReporter, sender: Sender) -> Self { Self { reporter, sender } } @@ -1297,7 +1293,9 @@ mod alloc_mod { } } - impl VerificationReportingProvider for VerificationReporterWithSender { + impl VerificationReportingProvider + for VerificationReporterWithSender + { delegate! { to self.reporter { fn add_tc( @@ -1315,7 +1313,7 @@ mod alloc_mod { ) -> Result, VerificationOrSendErrorWithToken> { self.reporter - .acceptance_success(token, self.sender.as_ref(), time_stamp) + .acceptance_success(token, &self.sender, time_stamp) } fn acceptance_failure( @@ -1324,7 +1322,7 @@ mod alloc_mod { params: FailParams, ) -> Result<(), VerificationOrSendErrorWithToken> { self.reporter - .acceptance_failure(token, self.sender.as_ref(), params) + .acceptance_failure(token, &self.sender, params) } fn start_success( @@ -1335,8 +1333,7 @@ mod alloc_mod { VerificationToken, VerificationOrSendErrorWithToken, > { - self.reporter - .start_success(token, self.sender.as_ref(), time_stamp) + self.reporter.start_success(token, &self.sender, time_stamp) } fn start_failure( @@ -1344,8 +1341,7 @@ mod alloc_mod { token: VerificationToken, params: FailParams, ) -> Result<(), VerificationOrSendErrorWithToken> { - self.reporter - .start_failure(token, self.sender.as_ref(), params) + self.reporter.start_failure(token, &self.sender, params) } fn step_success( @@ -1355,7 +1351,7 @@ mod alloc_mod { step: impl EcssEnumeration, ) -> Result<(), EcssTmtcError> { self.reporter - .step_success(token, self.sender.as_ref(), time_stamp, step) + .step_success(token, &self.sender, time_stamp, step) } fn step_failure( @@ -1363,8 +1359,7 @@ mod alloc_mod { token: VerificationToken, params: FailParamsWithStep, ) -> Result<(), VerificationOrSendErrorWithToken> { - self.reporter - .step_failure(token, self.sender.as_ref(), params) + self.reporter.step_failure(token, &self.sender, params) } fn completion_success( @@ -1373,7 +1368,7 @@ mod alloc_mod { time_stamp: &[u8], ) -> Result<(), VerificationOrSendErrorWithToken> { self.reporter - .completion_success(token, self.sender.as_ref(), time_stamp) + .completion_success(token, &self.sender, time_stamp) } fn completion_failure( @@ -1382,18 +1377,34 @@ mod alloc_mod { params: FailParams, ) -> Result<(), VerificationOrSendErrorWithToken> { self.reporter - .completion_failure(token, self.sender.as_ref(), params) + .completion_failure(token, &self.sender, params) } } + + pub type VerificationReporterWithSharedPoolSender = + VerificationReporterWithSender>; + pub type VerificationReporterWithVecSender = + VerificationReporterWithSender>; } #[cfg(feature = "std")] -mod std_mod { - use crate::pus::verification::VerificationReporterWithSender; - use std::sync::{Arc, Mutex}; +pub mod std_mod { + use std::sync::mpsc; - pub type StdVerifReporterWithSender = VerificationReporterWithSender; - pub type SharedStdVerifReporterWithSender = Arc>; + use crate::pool::StoreAddr; + + use super::alloc_mod::{ + VerificationReporterWithSharedPoolSender, VerificationReporterWithVecSender, + }; + + pub type VerificationReporterWithSharedPoolMpscSender = + VerificationReporterWithSharedPoolSender>; + pub type VerificationReporterWithSharedPoolMpscBoundedSender = + VerificationReporterWithSharedPoolSender>; + pub type VerificationReporterWithVecMpscSender = + VerificationReporterWithVecSender>>; + pub type VerificationReporterWithVecMpscBoundedSender = + VerificationReporterWithVecSender>>; } #[cfg(test)] @@ -1405,10 +1416,11 @@ pub mod tests { VerificationReporter, VerificationReporterCfg, VerificationReporterWithSender, VerificationToken, }; - use crate::pus::{EcssChannel, MpscTmInSharedPoolSender, PusTmWrapper}; + use crate::pus::{ + EcssChannel, PusTmWrapper, TmInSharedPoolSenderWithId, TmInSharedPoolSenderWithMpsc, + }; use crate::tmtc::tm_helper::SharedTmPool; use crate::ChannelId; - use alloc::boxed::Box; use alloc::format; use alloc::sync::Arc; use hashbrown::HashMap; @@ -1637,7 +1649,7 @@ pub mod tests { } impl EcssChannel for TestSender { - fn id(&self) -> ChannelId { + fn channel_id(&self) -> ChannelId { 0 } fn name(&self) -> &'static str { @@ -1688,13 +1700,13 @@ pub mod tests { &mut self.vr } } - struct TestBaseWithHelper<'a> { - helper: VerificationReporterWithSender, + struct TestBaseWithHelper<'a, Sender: EcssTmSenderCore + Clone + 'static> { + helper: VerificationReporterWithSender, #[allow(dead_code)] tc: PusTcCreator<'a>, } - impl<'a> TestBaseWithHelper<'a> { + impl<'a, Sender: EcssTmSenderCore + Clone + 'static> TestBaseWithHelper<'a, Sender> { fn rep(&mut self) -> &mut VerificationReporter { &mut self.helper.reporter } @@ -1725,12 +1737,15 @@ pub mod tests { (TestBase { vr: reporter, tc }, init_tok) } - fn base_with_helper_init() -> (TestBaseWithHelper<'static>, VerificationToken) { + fn base_with_helper_init() -> ( + TestBaseWithHelper<'static, TestSender>, + VerificationToken, + ) { let mut reporter = base_reporter(); let (tc, _) = base_tc_init(None); let init_tok = reporter.add_tc(&tc); let sender = TestSender::default(); - let helper = VerificationReporterWithSender::new_from_reporter(reporter, Box::new(sender)); + let helper = VerificationReporterWithSender::new_from_reporter(reporter, sender); (TestBaseWithHelper { helper, tc }, init_tok) } @@ -1758,7 +1773,7 @@ pub mod tests { let shared_tm_store = SharedTmPool::new(pool); let (tx, _) = mpsc::channel(); let mpsc_verif_sender = - MpscTmInSharedPoolSender::new(0, "verif_sender", shared_tm_store, tx); + TmInSharedPoolSenderWithMpsc::new(0, "verif_sender", shared_tm_store, tx); is_send(&mpsc_verif_sender); } @@ -1785,8 +1800,7 @@ pub mod tests { b.helper .acceptance_success(tok, &EMPTY_STAMP) .expect("Sending acceptance success failed"); - let sender: &mut TestSender = b.helper.sender.downcast_mut().unwrap(); - acceptance_check(sender, &tok.req_id); + acceptance_check(&mut b.helper.sender, &tok.req_id); } fn acceptance_fail_check(sender: &mut TestSender, req_id: RequestId, stamp_buf: [u8; 7]) { @@ -1830,8 +1844,7 @@ pub mod tests { b.helper .acceptance_failure(tok, fail_params) .expect("Sending acceptance success failed"); - let sender: &mut TestSender = b.helper.sender.downcast_mut().unwrap(); - acceptance_fail_check(sender, tok.req_id, stamp_buf); + acceptance_fail_check(&mut b.helper.sender, tok.req_id, stamp_buf); } #[test] @@ -1961,8 +1974,7 @@ pub mod tests { b.helper .start_failure(accepted_token, fail_params) .expect("Start failure failure"); - let sender: &mut TestSender = b.helper.sender.downcast_mut().unwrap(); - start_fail_check(sender, tok.req_id, fail_data_raw); + start_fail_check(&mut b.helper.sender, tok.req_id, fail_data_raw); } fn step_success_check(sender: &mut TestSender, req_id: RequestId) { @@ -2059,9 +2071,8 @@ pub mod tests { b.helper .step_success(&started_token, &EMPTY_STAMP, EcssEnumU8::new(1)) .expect("Sending step 1 success failed"); - let sender: &mut TestSender = b.helper.sender.downcast_mut().unwrap(); - assert_eq!(sender.service_queue.borrow().len(), 4); - step_success_check(sender, tok.req_id); + assert_eq!(b.helper.sender.service_queue.borrow().len(), 4); + step_success_check(&mut b.helper.sender, tok.req_id); } fn check_step_failure(sender: &mut TestSender, req_id: RequestId, fail_data_raw: [u8; 4]) { @@ -2191,8 +2202,7 @@ pub mod tests { b.helper .step_failure(started_token, fail_params) .expect("Step failure failed"); - let sender: &mut TestSender = b.helper.sender.downcast_mut().unwrap(); - check_step_failure(sender, req_id, fail_data_raw); + check_step_failure(&mut b.helper.sender, req_id, fail_data_raw); } fn completion_fail_check(sender: &mut TestSender, req_id: RequestId) { @@ -2278,8 +2288,7 @@ pub mod tests { b.helper .completion_failure(started_token, fail_params) .expect("Completion failure"); - let sender: &mut TestSender = b.helper.sender.downcast_mut().unwrap(); - completion_fail_check(sender, req_id); + completion_fail_check(&mut b.helper.sender, req_id); } fn completion_success_check(sender: &mut TestSender, req_id: RequestId) { @@ -2355,8 +2364,7 @@ pub mod tests { b.helper .completion_success(started_token, &EMPTY_STAMP) .expect("Sending completion success failed"); - let sender: &mut TestSender = b.helper.sender.downcast_mut().unwrap(); - completion_success_check(sender, tok.req_id); + completion_success_check(&mut b.helper.sender, tok.req_id); } #[test] @@ -2368,9 +2376,9 @@ pub mod tests { let shared_tm_pool = shared_tm_store.clone_backing_pool(); let (verif_tx, verif_rx) = mpsc::channel(); let sender = - MpscTmInSharedPoolSender::new(0, "Verification Sender", shared_tm_store, verif_tx); + TmInSharedPoolSenderWithId::new(0, "Verification Sender", shared_tm_store, verif_tx); let cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8).unwrap(); - let mut reporter = VerificationReporterWithSender::new(&cfg, Box::new(sender)); + let mut reporter = VerificationReporterWithSender::new(&cfg, sender); let mut sph = SpHeader::tc_unseg(TEST_APID, 0, 0).unwrap(); let tc_header = PusTcSecondaryHeader::new_simple(17, 1); diff --git a/satrs/src/queue.rs b/satrs/src/queue.rs index 25ff6c6..5ba4bdc 100644 --- a/satrs/src/queue.rs +++ b/satrs/src/queue.rs @@ -1,6 +1,8 @@ use core::fmt::{Display, Formatter}; #[cfg(feature = "std")] use std::error::Error; +#[cfg(feature = "std")] +use std::sync::mpsc; /// Generic error type for sending something via a message queue. #[derive(Debug, Copy, Clone)] @@ -47,3 +49,37 @@ impl Display for GenericRecvError { #[cfg(feature = "std")] impl Error for GenericRecvError {} + +#[cfg(feature = "std")] +impl From> for GenericSendError { + fn from(_: mpsc::SendError) -> Self { + GenericSendError::RxDisconnected + } +} + +#[cfg(feature = "std")] +impl From> for GenericSendError { + fn from(err: mpsc::TrySendError) -> Self { + match err { + mpsc::TrySendError::Full(_) => GenericSendError::QueueFull(None), + mpsc::TrySendError::Disconnected(_) => GenericSendError::RxDisconnected, + } + } +} + +#[cfg(feature = "crossbeam")] +impl From> for GenericSendError { + fn from(_: crossbeam_channel::SendError) -> Self { + GenericSendError::RxDisconnected + } +} + +#[cfg(feature = "crossbeam")] +impl From> for GenericSendError { + fn from(err: crossbeam_channel::TrySendError) -> Self { + match err { + crossbeam_channel::TrySendError::Full(_) => GenericSendError::QueueFull(None), + crossbeam_channel::TrySendError::Disconnected(_) => GenericSendError::RxDisconnected, + } + } +} diff --git a/satrs/tests/pus_events.rs b/satrs/tests/pus_events.rs index dbd778c..ca6d71e 100644 --- a/satrs/tests/pus_events.rs +++ b/satrs/tests/pus_events.rs @@ -1,14 +1,14 @@ use satrs::event_man::{ - EventManagerWithMpscQueue, MpscEventU32Receiver, MpscEventU32SendProvider, SendEventProvider, + EventManagerWithMpsc, EventSendProvider, EventU32SenderMpsc, MpscEventU32Receiver, }; use satrs::events::{EventU32, EventU32TypedSev, Severity, SeverityInfo}; use satrs::params::U32Pair; use satrs::params::{Params, ParamsHeapless, WritableToBeBytes}; -use satrs::pus::event_man::{DefaultPusMgmtBackendProvider, EventReporter, PusEventDispatcher}; -use satrs::pus::MpscTmAsVecSender; +use satrs::pus::event_man::{DefaultPusEventMgmtBackend, EventReporter, PusEventDispatcher}; +use satrs::pus::TmAsVecSenderWithMpsc; use spacepackets::ecss::tm::PusTmReader; use spacepackets::ecss::{PusError, PusPacket}; -use std::sync::mpsc::{channel, SendError, TryRecvError}; +use std::sync::mpsc::{self, SendError, TryRecvError}; use std::thread; const INFO_EVENT: EventU32TypedSev = @@ -24,21 +24,21 @@ pub enum CustomTmSenderError { #[test] fn test_threaded_usage() { - let (event_sender, event_man_receiver) = channel(); + let (event_sender, event_man_receiver) = mpsc::channel(); let event_receiver = MpscEventU32Receiver::new(event_man_receiver); - let mut event_man = EventManagerWithMpscQueue::new(Box::new(event_receiver)); + let mut event_man = EventManagerWithMpsc::new(event_receiver); - let (pus_event_man_tx, pus_event_man_rx) = channel(); - let pus_event_man_send_provider = MpscEventU32SendProvider::new(1, pus_event_man_tx); - event_man.subscribe_all(pus_event_man_send_provider.id()); + let (pus_event_man_tx, pus_event_man_rx) = mpsc::channel(); + let pus_event_man_send_provider = EventU32SenderMpsc::new(1, pus_event_man_tx); + event_man.subscribe_all(pus_event_man_send_provider.channel_id()); event_man.add_sender(pus_event_man_send_provider); - let (event_tx, event_rx) = channel(); + let (event_tx, event_rx) = mpsc::channel(); let reporter = EventReporter::new(0x02, 128).expect("Creating event reporter failed"); - let backend = DefaultPusMgmtBackendProvider::::default(); - let mut pus_event_man = PusEventDispatcher::new(reporter, Box::new(backend)); + let mut pus_event_man = + PusEventDispatcher::new(reporter, DefaultPusEventMgmtBackend::default()); // PUS + Generic event manager thread let jh0 = thread::spawn(move || { - let mut sender = MpscTmAsVecSender::new(0, "event_sender", event_tx); + let mut sender = TmAsVecSenderWithMpsc::new(0, "event_sender", event_tx); let mut event_cnt = 0; let mut params_array: [u8; 128] = [0; 128]; loop { @@ -71,6 +71,7 @@ fn test_threaded_usage() { Params::Vec(vec) => gen_event(Some(vec.as_slice())), Params::String(str) => gen_event(Some(str.as_bytes())), Params::Store(_) => gen_event(None), + _ => panic!("unsupported parameter type"), } } else { gen_event(None) @@ -120,10 +121,7 @@ fn test_threaded_usage() { } } event_sender - .send(( - LOW_SEV_EVENT.into(), - Some(Params::Heapless((2_u32, 3_u32).into())), - )) + .send((LOW_SEV_EVENT, Some(Params::Heapless((2_u32, 3_u32).into())))) .expect("Sending low severity event failed"); loop { match event_rx.try_recv() { diff --git a/satrs/tests/pus_verification.rs b/satrs/tests/pus_verification.rs index dd72394..386fea6 100644 --- a/satrs/tests/pus_verification.rs +++ b/satrs/tests/pus_verification.rs @@ -6,7 +6,7 @@ pub mod crossbeam_test { FailParams, RequestId, VerificationReporterCfg, VerificationReporterWithSender, VerificationReportingProvider, }; - use satrs::pus::CrossbeamTmInStoreSender; + use satrs::pus::TmInSharedPoolSenderWithCrossbeam; use satrs::tmtc::tm_helper::SharedTmPool; use spacepackets::ecss::tc::{PusTcCreator, PusTcReader, PusTcSecondaryHeader}; use spacepackets::ecss::tm::PusTmReader; @@ -40,10 +40,13 @@ pub mod crossbeam_test { let shared_tc_pool_0 = Arc::new(RwLock::new(StaticMemoryPool::new(pool_cfg))); let shared_tc_pool_1 = shared_tc_pool_0.clone(); let (tx, rx) = crossbeam_channel::bounded(10); - let sender = - CrossbeamTmInStoreSender::new(0, "verif_sender", shared_tm_pool.clone(), tx.clone()); - let mut reporter_with_sender_0 = - VerificationReporterWithSender::new(&cfg, Box::new(sender)); + let sender = TmInSharedPoolSenderWithCrossbeam::new( + 0, + "verif_sender", + shared_tm_pool.clone(), + tx.clone(), + ); + let mut reporter_with_sender_0 = VerificationReporterWithSender::new(&cfg, sender); let mut reporter_with_sender_1 = reporter_with_sender_0.clone(); // For test purposes, we retrieve the request ID from the TCs and pass them to the receiver // tread.