From bc042757632d00f22c5dec7ddb864600ca820721 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 2 Apr 2024 09:55:30 +0200 Subject: [PATCH] Continue update --- satrs-example/Cargo.toml | 5 +- satrs-example/src/acs/mgm.rs | 131 +- satrs-example/src/acs/mod.rs | 6 +- satrs-example/src/ccsds.rs | 12 +- satrs-example/src/config.rs | 55 +- satrs-example/src/events.rs | 58 +- satrs-example/src/hk.rs | 18 +- satrs-example/src/lib.rs | 38 + satrs-example/src/main.rs | 277 ++-- satrs-example/src/pus/action.rs | 348 ++-- satrs-example/src/pus/event.rs | 102 +- satrs-example/src/pus/hk.rs | 207 ++- satrs-example/src/pus/mod.rs | 396 ++--- satrs-example/src/pus/mode.rs | 244 ++- satrs-example/src/pus/scheduler.rs | 103 +- satrs-example/src/pus/stack.rs | 66 +- satrs-example/src/pus/test.rs | 120 +- satrs-example/src/requests.rs | 68 +- satrs-example/src/tcp.rs | 9 +- satrs-example/src/tm_funnel.rs | 31 +- satrs-example/src/tmtc.rs | 13 +- satrs-example/src/udp.rs | 29 +- satrs-mib/codegen/Cargo.toml | 1 - satrs-shared/Cargo.toml | 2 + satrs/Cargo.toml | 2 + satrs/src/hk.rs | 4 +- satrs/src/mode.rs | 72 +- satrs/src/pus/action.rs | 8 +- satrs/src/pus/event.rs | 228 ++- satrs/src/pus/event_man.rs | 38 +- satrs/src/pus/event_srv.rs | 54 +- satrs/src/pus/mod.rs | 470 +++--- satrs/src/pus/mode.rs | 162 +- satrs/src/pus/scheduler.rs | 379 +++-- satrs/src/pus/scheduler_srv.rs | 156 +- satrs/src/pus/test.rs | 133 +- satrs/src/pus/verification.rs | 2356 +++++++++++++--------------- satrs/src/request.rs | 195 ++- satrs/src/tmtc/ccsds_distrib.rs | 3 +- satrs/src/tmtc/tm_helper.rs | 10 +- satrs/tests/hk_helpers.rs | 6 +- satrs/tests/mode_tree.rs | 133 +- satrs/tests/pus_events.rs | 26 +- satrs/tests/pus_verification.rs | 47 +- 44 files changed, 3384 insertions(+), 3437 deletions(-) diff --git a/satrs-example/Cargo.toml b/satrs-example/Cargo.toml index 2723de7..1893db8 100644 --- a/satrs-example/Cargo.toml +++ b/satrs-example/Cargo.toml @@ -18,14 +18,15 @@ csv = "1" num_enum = "0.7" thiserror = "1" derive-new = "0.5" +serde = { version = "1", features = ["derive"] } +serde_json = "1" [dependencies.satrs] -# version = "0.2.0-rc.0" path = "../satrs" features = ["test_util"] [dependencies.satrs-mib] -# version = "0.1.1" +version = "0.1.1" path = "../satrs-mib" [features] diff --git a/satrs-example/src/acs/mgm.rs b/satrs-example/src/acs/mgm.rs index 9926ba2..12e7129 100644 --- a/satrs-example/src/acs/mgm.rs +++ b/satrs-example/src/acs/mgm.rs @@ -1,44 +1,123 @@ // TODO: Remove this at a later stage. #![allow(dead_code)] +use derive_new::new; +use satrs::hk::HkRequestVariant; +use satrs::spacepackets::ecss::hk; +use satrs::spacepackets::ecss::tm::{PusTmCreator, PusTmSecondaryHeader}; +use satrs::spacepackets::SpHeader; +use satrs_example::TimeStampHelper; use std::sync::mpsc::{self}; use std::sync::{Arc, Mutex}; use satrs::mode::{ModeAndSubmode, ModeProvider, ModeReply, ModeRequest, ModeRequestHandler}; -use satrs::pus::EcssTmSenderCore; -use satrs::request::GenericMessage; +use satrs::pus::{EcssTmSenderCore, PusTmVariant}; +use satrs::request::{GenericMessage, MessageMetadata, UniqueApidTargetId}; use satrs::ComponentId; +use satrs_example::config::components::PUS_MODE_SERVICE; -use crate::pus::hk::HkReply; +use crate::pus::hk::{HkReply, HkReplyVariant}; use crate::requests::CompositeRequest; +use serde::{Deserialize, Serialize}; + pub trait SpiInterface { type Error; fn transfer(&mut self, data: &mut [u8]) -> Result<(), Self::Error>; } -#[derive(Debug, Copy, Clone)] +#[derive(Default)] +pub struct SpiDummyInterface {} + +impl SpiInterface for SpiDummyInterface { + type Error = (); + + fn transfer(&mut self, _data: &mut [u8]) -> Result<(), Self::Error> { + Ok(()) + } +} + +#[derive(Default, Debug, Copy, Clone, Serialize, Deserialize)] pub struct MgmData { pub x: f32, pub y: f32, pub z: f32, } +#[derive(new)] pub struct MgmHandler { - id: ComponentId, + id: UniqueApidTargetId, dev_str: &'static str, mode_request_receiver: mpsc::Receiver>, + composite_request_receiver: mpsc::Receiver>, mode_reply_sender_to_pus: mpsc::Sender>, mode_reply_sender_to_parent: mpsc::Sender>, - composite_request_receiver: mpsc::Receiver>, hk_reply_sender: mpsc::Sender>, hk_tm_sender: TmSender, - mode: ModeAndSubmode, spi_interface: ComInterface, shared_mgm_set: Arc>, + #[new(value = "ModeAndSubmode::new(satrs_example::DeviceMode::Off as u32, 0)")] + mode: ModeAndSubmode, + #[new(default)] + stamp_helper: TimeStampHelper, } impl MgmHandler { - pub fn perform_operation(&mut self) {} + pub fn periodic_operation(&mut self) { + self.stamp_helper.update_from_now(); + // Handle messages. + match self.composite_request_receiver.try_recv() { + Ok(ref msg) => match &msg.message { + CompositeRequest::Hk(hk_req) => match hk_req.variant { + HkRequestVariant::OneShot => { + self.hk_reply_sender + .send(GenericMessage::new( + msg.requestor_info, + HkReply::new(hk_req.unique_id, HkReplyVariant::Ack), + )) + .expect("failed to send HK reply"); + let mut sp_header = SpHeader::tm_unseg(self.id.apid, 0, 0).unwrap(); + let sec_header = PusTmSecondaryHeader::new( + 3, + hk::Subservice::TmHkPacket as u8, + 0, + 0, + Some(self.stamp_helper.stamp()), + ); + // Let's serialize it as JSON for now.. This is a lot simpler than binary + // serialization. + let mgm_data_serialized = + serde_json::to_vec(&*self.shared_mgm_set.lock().unwrap()).unwrap(); + let hk_tm = PusTmCreator::new( + &mut sp_header, + sec_header, + &mgm_data_serialized, + true, + ); + self.hk_tm_sender + .send_tm(self.id.id(), PusTmVariant::Direct(hk_tm)) + .expect("failed to send HK TM"); + } + HkRequestVariant::EnablePeriodic => todo!(), + HkRequestVariant::DisablePeriodic => todo!(), + HkRequestVariant::ModifyCollectionInterval(_) => todo!(), + }, + // This object does not have actions (yet).. Still send back completion failure + // reply. + CompositeRequest::Action(action_req) => {} + }, + Err(_) => todo!(), + } + match self.mode_request_receiver.try_recv() { + Ok(msg) => match msg.message { + ModeRequest::SetMode(_) => todo!(), + ModeRequest::ReadMode => todo!(), + ModeRequest::AnnounceMode => todo!(), + ModeRequest::AnnounceModeRecursive => todo!(), + ModeRequest::ModeInfo(_) => todo!(), + }, + Err(_) => todo!(), + } + } } impl ModeProvider @@ -54,23 +133,37 @@ impl ModeRequestHandler { fn start_transition( &mut self, - request_id: satrs::request::RequestId, - sender_id: ComponentId, + requestor: MessageMetadata, mode_and_submode: ModeAndSubmode, ) -> Result<(), satrs::mode::ModeError> { - todo!() + self.mode = mode_and_submode; + self.handle_mode_reached(Some(requestor))?; + Ok(()) } - fn announce_mode( - &self, - request_id: satrs::request::RequestId, - sender_id: satrs::ComponentId, - recursive: bool, - ) { + fn announce_mode(&self, _requestor_info: MessageMetadata, _recursive: bool) { log::info!("{} announcing mode: {:?}", self.dev_str, self.mode); } - fn handle_mode_reached(&mut self) -> Result<(), satrs::queue::GenericTargetedMessagingError> { - todo!() + fn handle_mode_reached( + &mut self, + requestor: Option, + ) -> Result<(), satrs::queue::GenericTargetedMessagingError> { + if let Some(requestor) = requestor { + if requestor.sender_id() == PUS_MODE_SERVICE.raw() { + // self.mode_reply_sender_to_pus.send( + //GenericMessage::new(requestor.request_id, requestor.sender_id, ModeReply::ModeReply(self.mode)) + // )?; + } + } + Ok(()) + } + + fn send_mode_reply( + &self, + _requestor: MessageMetadata, + _reply: ModeReply, + ) -> Result<(), satrs::queue::GenericTargetedMessagingError> { + Ok(()) } } diff --git a/satrs-example/src/acs/mod.rs b/satrs-example/src/acs/mod.rs index 719fbe7..57f20cc 100644 --- a/satrs-example/src/acs/mod.rs +++ b/satrs-example/src/acs/mod.rs @@ -1,9 +1,9 @@ -mod mgm; +pub mod mgm; /* pub struct AcsTask { timestamp: [u8; 7], - time_provider: TimeProvider, + time_provider: CdsTime, verif_reporter: VerificationReporter, tm_sender: Box, request_rx: mpsc::Receiver, @@ -17,7 +17,7 @@ impl AcsTask Self { Self { timestamp: [0; 7], - time_provider: TimeProvider::new_with_u16_days(0, 0), + time_provider: CdsTime::new_with_u16_days(0, 0), verif_reporter, tm_sender: Box::new(tm_sender), request_rx, diff --git a/satrs-example/src/ccsds.rs b/satrs-example/src/ccsds.rs index e61172e..7f15fb0 100644 --- a/satrs-example/src/ccsds.rs +++ b/satrs-example/src/ccsds.rs @@ -1,7 +1,7 @@ use satrs::pus::ReceivesEcssPusTc; use satrs::spacepackets::{CcsdsPacket, SpHeader}; use satrs::tmtc::{CcsdsPacketHandler, ReceivesCcsdsTc}; -use satrs_example::config::PUS_APID; +use satrs_example::config::components::Apid; #[derive(Clone)] pub struct CcsdsReceiver< @@ -19,7 +19,12 @@ impl< type Error = E; fn valid_apids(&self) -> &'static [u16] { - &[PUS_APID] + &[ + Apid::GenericPus as u16, + Apid::Acs as u16, + Apid::Sched as u16, + Apid::EventTm as u16, + ] } fn handle_known_apid( @@ -27,7 +32,8 @@ impl< sp_header: &SpHeader, tc_raw: &[u8], ) -> Result<(), Self::Error> { - if sp_header.apid() == PUS_APID { + if sp_header.apid() == Apid::Cfdp as u16 { + } else { return self.tc_source.pass_ccsds(sp_header, tc_raw); } Ok(()) diff --git a/satrs-example/src/config.rs b/satrs-example/src/config.rs index f557e08..07d01ed 100644 --- a/satrs-example/src/config.rs +++ b/satrs-example/src/config.rs @@ -9,8 +9,6 @@ use satrs::{ pool::{StaticMemoryPool, StaticPoolConfig}, }; -pub const PUS_APID: u16 = 0x02; - #[derive(Copy, Clone, PartialEq, Eq, Debug, TryFromPrimitive, IntoPrimitive)] #[repr(u8)] pub enum CustomPusServiceId { @@ -102,14 +100,51 @@ pub mod mode_err { pub const WRONG_MODE: ResultU16 = ResultU16::new(GroupId::Mode as u8, 0); } -#[derive(Copy, Clone, PartialEq, Eq)] -pub enum ComponentIdList { - PusVerification = 0, - EventManagement = 1, - PusTest = 2, - PusAction = 3, - PusSched = 4, - PusHk = 5, +pub mod components { + use satrs::request::UniqueApidTargetId; + + #[derive(Copy, Clone, PartialEq, Eq)] + pub enum Apid { + VerificationTm = 1, + Sched = 2, + EventTm = 3, + HkTm = 4, + GenericPus = 5, + Acs = 6, + Cfdp = 7, + } + + // Component IDs for components with the PUS APID. + #[derive(Copy, Clone, PartialEq, Eq)] + pub enum PusId { + PusRouting = 0, + PusTest = 1, + PusAction = 2, + PusMode = 3, + PusHk = 4, + } + + #[derive(Copy, Clone, PartialEq, Eq)] + pub enum AcsId { + Mgm0 = 0, + } + + pub const PUS_ACTION_SERVICE: UniqueApidTargetId = + UniqueApidTargetId::new(Apid::GenericPus as u16, PusId::PusAction as u32); + pub const PUS_EVENT_MANAGEMENT: UniqueApidTargetId = + UniqueApidTargetId::new(Apid::EventTm as u16, 0); + pub const PUS_ROUTING_SERVICE: UniqueApidTargetId = + UniqueApidTargetId::new(Apid::GenericPus as u16, PusId::PusRouting as u32); + pub const PUS_TEST_SERVICE: UniqueApidTargetId = + UniqueApidTargetId::new(Apid::GenericPus as u16, PusId::PusTest as u32); + pub const PUS_MODE_SERVICE: UniqueApidTargetId = + UniqueApidTargetId::new(Apid::GenericPus as u16, PusId::PusMode as u32); + pub const PUS_HK_SERVICE: UniqueApidTargetId = + UniqueApidTargetId::new(Apid::GenericPus as u16, PusId::PusHk as u32); + pub const PUS_SCHED_SERVICE: UniqueApidTargetId = + UniqueApidTargetId::new(Apid::Sched as u16, 0); + pub const MGM_HANDLER_0: UniqueApidTargetId = + UniqueApidTargetId::new(Apid::Acs as u16, AcsId::Mgm0 as u32); } pub mod pool { diff --git a/satrs-example/src/events.rs b/satrs-example/src/events.rs index 7d8b3f4..f45792c 100644 --- a/satrs-example/src/events.rs +++ b/satrs-example/src/events.rs @@ -1,5 +1,8 @@ use std::sync::mpsc::{self}; +use crate::pus::create_verification_reporter; +use satrs::pus::verification::VerificationReporter; +use satrs::pus::EcssTmSenderCore; use satrs::{ event_man::{ EventManagerWithBoundedMpsc, EventSendProvider, EventU32SenderMpscBounded, @@ -12,44 +15,51 @@ use satrs::{ DefaultPusEventU32Dispatcher, EventReporter, EventRequest, EventRequestWithToken, }, verification::{TcStateStarted, VerificationReportingProvider, VerificationToken}, - EcssTmSender, }, - spacepackets::time::cds::{self, TimeProvider}, + spacepackets::time::cds::CdsTime, ComponentId, }; -use satrs_example::config::{ComponentIdList, PUS_APID}; +use satrs_example::config::components; +use satrs_example::config::components::PUS_EVENT_MANAGEMENT; use crate::update_time; /// The PUS event handler subscribes for all events and converts them into ECSS PUS 5 event /// packets. It also handles the verification completion of PUS event service requests. -pub struct PusEventHandler { +pub struct PusEventHandler { + id: ComponentId, event_request_rx: mpsc::Receiver, pus_event_dispatcher: DefaultPusEventU32Dispatcher<()>, pus_event_man_rx: mpsc::Receiver<(EventU32, Option)>, - tm_sender: Box, - time_provider: TimeProvider, + tm_sender: TmSender, + time_provider: CdsTime, timestamp: [u8; 7], verif_handler: VerificationReporter, } -impl PusEventHandler { +impl PusEventHandler { pub fn new( + id: ComponentId, + tm_sender: TmSender, verif_handler: VerificationReporter, event_manager: &mut EventManagerWithBoundedMpsc, event_request_rx: mpsc::Receiver, - tm_sender: impl EcssTmSender, ) -> Self { 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 event_reporter = EventReporter::new( + PUS_EVENT_MANAGEMENT.raw(), + components::Apid::EventTm as u16, + 128, + ) + .unwrap(); let pus_event_dispatcher = DefaultPusEventU32Dispatcher::new_with_default_backend(event_reporter); let pus_event_man_send_provider = EventU32SenderMpscBounded::new( - ComponentIdList::EventManagement as ComponentId, + PUS_EVENT_MANAGEMENT.raw(), pus_event_man_tx, event_queue_cap, ); @@ -58,13 +68,14 @@ impl PusEventHandler PusEventHandler PusEventHandler { +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: VerificationReporter, + tm_sender: TmSender, event_request_rx: mpsc::Receiver, ) -> Self { let mut event_man_wrapper = EventManagerWrapper::new(); let pus_event_handler = PusEventHandler::new( - verif_handler, + PUS_EVENT_MANAGEMENT.raw(), + tm_sender, + create_verification_reporter(PUS_EVENT_MANAGEMENT.apid), event_man_wrapper.event_manager(), event_request_rx, - tm_sender, ); Self { event_man_wrapper, diff --git a/satrs-example/src/hk.rs b/satrs-example/src/hk.rs index 3147cbf..0852d04 100644 --- a/satrs-example/src/hk.rs +++ b/satrs-example/src/hk.rs @@ -1,27 +1,25 @@ use derive_new::new; +use satrs::hk::UniqueId; +use satrs::request::UniqueApidTargetId; use satrs::spacepackets::ByteConversionError; -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum AcsHkIds { - TestMgmSet = 1, -} - #[derive(Debug, new, Copy, Clone)] pub struct HkUniqueId { - target_id: u32, - set_id: u32, + target_id: UniqueApidTargetId, + set_id: UniqueId, } impl HkUniqueId { #[allow(dead_code)] - pub fn target_id(&self) -> u32 { + pub fn target_id(&self) -> UniqueApidTargetId { self.target_id } #[allow(dead_code)] - pub fn set_id(&self) -> u32 { + pub fn set_id(&self) -> UniqueId { self.set_id } + #[allow(dead_code)] pub fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result { if buf.len() < 8 { return Err(ByteConversionError::ToSliceTooSmall { @@ -29,7 +27,7 @@ impl HkUniqueId { expected: 8, }); } - buf[0..4].copy_from_slice(&self.target_id.to_be_bytes()); + buf[0..4].copy_from_slice(&self.target_id.unique_id.to_be_bytes()); buf[4..8].copy_from_slice(&self.set_id.to_be_bytes()); Ok(8) diff --git a/satrs-example/src/lib.rs b/satrs-example/src/lib.rs index ef68c36..a224fe5 100644 --- a/satrs-example/src/lib.rs +++ b/satrs-example/src/lib.rs @@ -1 +1,39 @@ +use satrs::spacepackets::time::{cds::CdsTime, TimeWriter}; + pub mod config; + +#[derive(Debug, PartialEq, Eq, Copy, Clone)] +pub enum DeviceMode { + Off = 0, + On = 1, + Normal = 2, +} + +pub struct TimeStampHelper { + stamper: CdsTime, + time_stamp: [u8; 7], +} + +impl TimeStampHelper { + pub fn stamp(&self) -> &[u8] { + &self.time_stamp + } + + pub fn update_from_now(&mut self) { + self.stamper + .update_from_now() + .expect("Updating timestamp failed"); + self.stamper + .write_to_bytes(&mut self.time_stamp) + .expect("Writing timestamp failed"); + } +} + +impl Default for TimeStampHelper { + fn default() -> Self { + Self { + stamper: CdsTime::now_with_u16_days().expect("creating time stamper failed"), + time_stamp: Default::default(), + } + } +} diff --git a/satrs-example/src/main.rs b/satrs-example/src/main.rs index 07accaa..3b8ce8b 100644 --- a/satrs-example/src/main.rs +++ b/satrs-example/src/main.rs @@ -17,24 +17,23 @@ use log::info; use pus::test::create_test_service_dynamic; use satrs::hal::std::tcp_server::ServerConfig; use satrs::hal::std::udp_server::UdpTcServer; -use satrs::request::{GenericMessage, TargetAndApidId}; +use satrs::request::GenericMessage; use satrs::tmtc::tm_helper::SharedTmPool; use satrs_example::config::pool::{create_sched_tc_pool, create_static_pools}; use satrs_example::config::tasks::{ FREQ_MS_AOCS, FREQ_MS_EVENT_HANDLING, FREQ_MS_PUS_STACK, FREQ_MS_UDP_TMTC, }; -use satrs_example::config::{ - ComponentIdList, RequestTargetId, OBSW_SERVER_ADDR, PUS_APID, SERVER_PORT, -}; +use satrs_example::config::{OBSW_SERVER_ADDR, SERVER_PORT}; use tmtc::PusTcSourceProviderDynamic; use udp::DynamicUdpTmHandler; -// use crate::acs::AcsTask; +use crate::acs::mgm::{MgmHandler, SpiDummyInterface}; use crate::ccsds::CcsdsReceiver; use crate::logger::setup_logger; use crate::pus::action::{create_action_service_dynamic, create_action_service_static}; use crate::pus::event::{create_event_service_dynamic, create_event_service_static}; use crate::pus::hk::{create_hk_service_dynamic, create_hk_service_static}; +use crate::pus::mode::{create_mode_service_dynamic, create_mode_service_static}; use crate::pus::scheduler::{create_scheduler_service_dynamic, create_scheduler_service_static}; use crate::pus::test::create_test_service_static; use crate::pus::{PusReceiver, PusTcMpscRouter}; @@ -44,27 +43,18 @@ use crate::tmtc::{ PusTcSourceProviderSharedPool, SharedTcPool, TcSourceTaskDynamic, TcSourceTaskStatic, }; use crate::udp::{StaticUdpTmHandler, UdpTmtcServer}; +use satrs::mode::ModeRequest; use satrs::pus::event_man::EventRequestWithToken; -use satrs::pus::verification::{VerificationReporterCfg, VerificationReporterWithSender}; -use satrs::pus::{EcssTmSender, TmAsVecSenderWithId, TmInSharedPoolSenderWithId}; -use satrs::spacepackets::{time::cds::TimeProvider, time::TimeWriter}; +use satrs::pus::TmInSharedPoolSender; +use satrs::spacepackets::{time::cds::CdsTime, time::TimeWriter}; use satrs::tmtc::CcsdsDistributor; -use satrs::ComponentId; +use satrs_example::config::components::MGM_HANDLER_0; use std::net::{IpAddr, SocketAddr}; -use std::sync::mpsc::{self, channel}; +use std::sync::mpsc; use std::sync::{Arc, RwLock}; use std::thread; use std::time::Duration; -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, verif_sender) -} - #[allow(dead_code)] fn static_tmtc_pool_main() { let (tm_pool, tc_pool) = create_static_pools(); @@ -76,20 +66,21 @@ fn static_tmtc_pool_main() { 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(TmInSharedPoolSenderWithId::new( - ComponentIdList::PusVerification as ComponentId, - "verif_sender", - shared_tm_pool.clone(), - tm_funnel_tx.clone(), - )); + let tm_funnel_tx_sender = + TmInSharedPoolSender::new(shared_tm_pool.clone(), tm_funnel_tx.clone()); + + let (mgm_handler_composite_tx, mgm_handler_composite_rx) = + mpsc::channel::>(); + let (mgm_handler_mode_tx, mgm_handler_mode_rx) = mpsc::channel::>(); - let acs_target_id = TargetAndApidId::new(PUS_APID, RequestTargetId::AcsSubsystem as u32); - let (acs_thread_tx, acs_thread_rx) = channel::>(); // Some request are targetable. This map is used to retrieve sender handles based on a target ID. let mut request_map = GenericRequestRouter::default(); - request_map.0.insert(acs_target_id.into(), acs_thread_tx); + request_map + .composite_router_map + .insert(MGM_HANDLER_0.id(), mgm_handler_composite_tx); + request_map + .mode_router_map + .insert(MGM_HANDLER_0.id(), mgm_handler_mode_tx); // This helper structure is used by all telecommand providers which need to send telecommands // to the TC source. @@ -105,88 +96,80 @@ 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( - TmInSharedPoolSenderWithId::new( - ComponentIdList::EventManagement as ComponentId, - "ALL_EVENTS_TX", - shared_tm_pool.clone(), - tm_funnel_tx.clone(), - ), - verif_reporter.clone(), - event_request_rx, - ); + let mut event_handler = EventHandler::new(tm_funnel_tx.clone(), event_request_rx); - let (pus_test_tx, pus_test_rx) = channel(); - let (pus_event_tx, pus_event_rx) = channel(); - let (pus_sched_tx, pus_sched_rx) = channel(); - let (pus_hk_tx, pus_hk_rx) = channel(); - let (pus_action_tx, pus_action_rx) = channel(); + let (pus_test_tx, pus_test_rx) = mpsc::channel(); + let (pus_event_tx, pus_event_rx) = mpsc::channel(); + let (pus_sched_tx, pus_sched_rx) = mpsc::channel(); + let (pus_hk_tx, pus_hk_rx) = mpsc::channel(); + let (pus_action_tx, pus_action_rx) = mpsc::channel(); + let (pus_mode_tx, pus_mode_rx) = mpsc::channel(); - let (pus_action_reply_tx, pus_action_reply_rx) = channel(); - let (pus_hk_reply_tx, pus_hk_reply_rx) = channel(); + let (_pus_action_reply_tx, pus_action_reply_rx) = mpsc::channel(); + let (pus_hk_reply_tx, pus_hk_reply_rx) = mpsc::channel(); + let (pus_mode_reply_tx, pus_mode_reply_rx) = mpsc::channel(); let pus_router = PusTcMpscRouter { - test_service_receiver: pus_test_tx, - event_service_receiver: pus_event_tx, - sched_service_receiver: pus_sched_tx, - hk_service_receiver: pus_hk_tx, - action_service_receiver: pus_action_tx, + test_tc_sender: pus_test_tx, + event_tc_sender: pus_event_tx, + sched_tc_sender: pus_sched_tx, + hk_tc_sender: pus_hk_tx, + action_tc_sender: pus_action_tx, + mode_tc_sender: pus_mode_tx, }; let pus_test_service = create_test_service_static( - shared_tm_pool.clone(), - tm_funnel_tx.clone(), - verif_reporter.clone(), + tm_funnel_tx_sender.clone(), shared_tc_pool.pool.clone(), event_handler.clone_event_sender(), pus_test_rx, ); let pus_scheduler_service = create_scheduler_service_static( - shared_tm_pool.clone(), - tm_funnel_tx.clone(), - verif_reporter.clone(), + tm_funnel_tx_sender.clone(), tc_source.clone(), pus_sched_rx, create_sched_tc_pool(), ); let pus_event_service = create_event_service_static( - shared_tm_pool.clone(), - tm_funnel_tx.clone(), - verif_reporter.clone(), + tm_funnel_tx_sender.clone(), shared_tc_pool.pool.clone(), pus_event_rx, event_request_tx, ); let pus_action_service = create_action_service_static( - shared_tm_pool.clone(), - tm_funnel_tx.clone(), - verif_reporter.clone(), + tm_funnel_tx_sender.clone(), shared_tc_pool.pool.clone(), pus_action_rx, request_map.clone(), pus_action_reply_rx, ); let pus_hk_service = create_hk_service_static( - shared_tm_pool.clone(), - tm_funnel_tx.clone(), - verif_reporter.clone(), + tm_funnel_tx_sender.clone(), shared_tc_pool.pool.clone(), pus_hk_rx, - request_map, + request_map.clone(), pus_hk_reply_rx, ); + let pus_mode_service = create_mode_service_static( + tm_funnel_tx_sender.clone(), + shared_tc_pool.pool.clone(), + pus_mode_rx, + request_map, + pus_mode_reply_rx, + ); let mut pus_stack = PusStack::new( + pus_test_service, pus_hk_service, pus_event_service, pus_action_service, pus_scheduler_service, - pus_test_service, + pus_mode_service, ); let ccsds_receiver = CcsdsReceiver { tc_source }; let mut tmtc_task = TcSourceTaskStatic::new( shared_tc_pool.clone(), tc_source_rx, - PusReceiver::new(verif_reporter.clone(), pus_router), + PusReceiver::new(tm_funnel_tx_sender, pus_router), ); let sock_addr = SocketAddr::new(IpAddr::V4(OBSW_SERVER_ADDR), SERVER_PORT); @@ -211,19 +194,6 @@ fn static_tmtc_pool_main() { ) .expect("tcp server creation failed"); - /* - let mut acs_task = AcsTask::new( - TmInSharedPoolSenderWithId::new( - TmSenderId::AcsSubsystem as ChannelId, - "ACS_TASK_SENDER", - shared_tm_pool.clone(), - tm_funnel_tx.clone(), - ), - acs_thread_rx, - verif_reporter, - ); - */ - let mut tm_funnel = TmFunnelStatic::new( shared_tm_pool, sync_tm_tcp_source, @@ -231,6 +201,24 @@ fn static_tmtc_pool_main() { tm_server_tx, ); + let (mgm_handler_mode_reply_to_parent_tx, _mgm_handler_mode_reply_to_parent_rx) = + mpsc::channel(); + + let dummy_spi_interface = SpiDummyInterface::default(); + let shared_mgm_set = Arc::default(); + let mut mgm_handler = MgmHandler::new( + MGM_HANDLER_0, + "MGM_0", + mgm_handler_mode_rx, + mgm_handler_composite_rx, + pus_mode_reply_tx, + mgm_handler_mode_reply_to_parent_tx, + pus_hk_reply_tx, + tm_funnel_tx, + dummy_spi_interface, + shared_mgm_set, + ); + info!("Starting TMTC and UDP task"); let jh_udp_tmtc = thread::Builder::new() .name("TMTC and UDP".to_string()) @@ -276,7 +264,7 @@ fn static_tmtc_pool_main() { let jh_aocs = thread::Builder::new() .name("AOCS".to_string()) .spawn(move || loop { - // acs_task.periodic_operation(); + mgm_handler.periodic_operation(); thread::sleep(Duration::from_millis(FREQ_MS_AOCS)); }) .unwrap(); @@ -310,22 +298,23 @@ fn static_tmtc_pool_main() { #[allow(dead_code)] fn dyn_tmtc_pool_main() { - let (tc_source_tx, tc_source_rx) = channel(); - let (tm_funnel_tx, tm_funnel_rx) = channel(); - 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(TmAsVecSenderWithId::new( - ComponentIdList::PusVerification as ComponentId, - "verif_sender", - tm_funnel_tx.clone(), - )); + let (tc_source_tx, tc_source_rx) = mpsc::channel(); + let (tm_funnel_tx, tm_funnel_rx) = mpsc::channel(); + let (tm_server_tx, tm_server_rx) = mpsc::channel(); + + // Some request are targetable. This map is used to retrieve sender handles based on a target ID. + let (mgm_handler_composite_tx, mgm_handler_composite_rx) = + mpsc::channel::>(); + let (mgm_handler_mode_tx, mgm_handler_mode_rx) = mpsc::channel::>(); - let acs_target_id = TargetAndApidId::new(PUS_APID, RequestTargetId::AcsSubsystem as u32); - let (acs_thread_tx, acs_thread_rx) = channel::>(); // Some request are targetable. This map is used to retrieve sender handles based on a target ID. let mut request_map = GenericRequestRouter::default(); - request_map.0.insert(acs_target_id.into(), acs_thread_tx); + request_map + .composite_router_map + .insert(MGM_HANDLER_0.raw(), mgm_handler_composite_tx); + request_map + .mode_router_map + .insert(MGM_HANDLER_0.raw(), mgm_handler_mode_tx); let tc_source = PusTcSourceProviderDynamic(tc_source_tx); @@ -335,80 +324,74 @@ fn dyn_tmtc_pool_main() { let (event_request_tx, event_request_rx) = mpsc::channel::(); // 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( - TmAsVecSenderWithId::new( - ComponentIdList::EventManagement as ComponentId, - "ALL_EVENTS_TX", - tm_funnel_tx.clone(), - ), - verif_reporter.clone(), - event_request_rx, - ); + let mut event_handler = EventHandler::new(tm_funnel_tx.clone(), event_request_rx); - let (pus_test_tx, pus_test_rx) = channel(); - let (pus_event_tx, pus_event_rx) = channel(); - let (pus_sched_tx, pus_sched_rx) = channel(); - let (pus_hk_tx, pus_hk_rx) = channel(); - let (pus_action_tx, pus_action_rx) = channel(); + let (pus_test_tx, pus_test_rx) = mpsc::channel(); + let (pus_event_tx, pus_event_rx) = mpsc::channel(); + let (pus_sched_tx, pus_sched_rx) = mpsc::channel(); + let (pus_hk_tx, pus_hk_rx) = mpsc::channel(); + let (pus_action_tx, pus_action_rx) = mpsc::channel(); + let (pus_mode_tx, pus_mode_rx) = mpsc::channel(); - let (pus_action_reply_tx, pus_action_reply_rx) = channel(); - let (pus_hk_reply_tx, pus_hk_reply_rx) = channel(); + let (_pus_action_reply_tx, pus_action_reply_rx) = mpsc::channel(); + let (pus_hk_reply_tx, pus_hk_reply_rx) = mpsc::channel(); + let (pus_mode_reply_tx, pus_mode_reply_rx) = mpsc::channel(); let pus_router = PusTcMpscRouter { - test_service_receiver: pus_test_tx, - event_service_receiver: pus_event_tx, - sched_service_receiver: pus_sched_tx, - hk_service_receiver: pus_hk_tx, - action_service_receiver: pus_action_tx, + test_tc_sender: pus_test_tx, + event_tc_sender: pus_event_tx, + sched_tc_sender: pus_sched_tx, + hk_tc_sender: pus_hk_tx, + action_tc_sender: pus_action_tx, + mode_tc_sender: pus_mode_tx, }; let pus_test_service = create_test_service_dynamic( tm_funnel_tx.clone(), - verif_reporter.clone(), event_handler.clone_event_sender(), pus_test_rx, ); let pus_scheduler_service = create_scheduler_service_dynamic( tm_funnel_tx.clone(), - verif_reporter.clone(), tc_source.0.clone(), pus_sched_rx, create_sched_tc_pool(), ); - let pus_event_service = create_event_service_dynamic( - tm_funnel_tx.clone(), - verif_reporter.clone(), - pus_event_rx, - event_request_tx, - ); + let pus_event_service = + create_event_service_dynamic(tm_funnel_tx.clone(), pus_event_rx, event_request_tx); let pus_action_service = create_action_service_dynamic( tm_funnel_tx.clone(), - verif_reporter.clone(), pus_action_rx, request_map.clone(), pus_action_reply_rx, ); let pus_hk_service = create_hk_service_dynamic( tm_funnel_tx.clone(), - verif_reporter.clone(), pus_hk_rx, - request_map, + request_map.clone(), pus_hk_reply_rx, ); + let pus_mode_service = create_mode_service_dynamic( + tm_funnel_tx.clone(), + pus_mode_rx, + request_map, + pus_mode_reply_rx, + ); let mut pus_stack = PusStack::new( + pus_test_service, pus_hk_service, pus_event_service, pus_action_service, pus_scheduler_service, - pus_test_service, + pus_mode_service, ); let ccsds_receiver = CcsdsReceiver { tc_source }; let mut tmtc_task = TcSourceTaskDynamic::new( tc_source_rx, - PusReceiver::new(verif_reporter.clone(), pus_router), + PusReceiver::new(tm_funnel_tx.clone(), pus_router), ); let sock_addr = SocketAddr::new(IpAddr::V4(OBSW_SERVER_ADDR), SERVER_PORT); @@ -432,19 +415,25 @@ fn dyn_tmtc_pool_main() { ) .expect("tcp server creation failed"); - /* - let mut acs_task = AcsTask::new( - TmAsVecSenderWithId::new( - TmSenderId::AcsSubsystem as ComponentId, - "ACS_TASK_SENDER", - tm_funnel_tx.clone(), - ), - acs_thread_rx, - verif_reporter, - ); - */ let mut tm_funnel = TmFunnelDynamic::new(sync_tm_tcp_source, tm_funnel_rx, tm_server_tx); + let (mgm_handler_mode_reply_to_parent_tx, _mgm_handler_mode_reply_to_parent_rx) = + mpsc::channel(); + let dummy_spi_interface = SpiDummyInterface::default(); + let shared_mgm_set = Arc::default(); + let mut mgm_handler = MgmHandler::new( + MGM_HANDLER_0, + "MGM_0", + mgm_handler_mode_rx, + mgm_handler_composite_rx, + pus_mode_reply_tx, + mgm_handler_mode_reply_to_parent_tx, + pus_hk_reply_tx, + tm_funnel_tx, + dummy_spi_interface, + shared_mgm_set, + ); + info!("Starting TMTC and UDP task"); let jh_udp_tmtc = thread::Builder::new() .name("TMTC and UDP".to_string()) @@ -490,7 +479,7 @@ fn dyn_tmtc_pool_main() { let jh_aocs = thread::Builder::new() .name("AOCS".to_string()) .spawn(move || loop { - // acs_task.periodic_operation(); + mgm_handler.periodic_operation(); thread::sleep(Duration::from_millis(FREQ_MS_AOCS)); }) .unwrap(); @@ -531,7 +520,7 @@ fn main() { dyn_tmtc_pool_main(); } -pub fn update_time(time_provider: &mut TimeProvider, timestamp: &mut [u8]) { +pub fn update_time(time_provider: &mut CdsTime, timestamp: &mut [u8]) { time_provider .update_from_now() .expect("Could not get current time"); diff --git a/satrs-example/src/pus/action.rs b/satrs-example/src/pus/action.rs index 8ebac89..1e34df8 100644 --- a/satrs-example/src/pus/action.rs +++ b/satrs-example/src/pus/action.rs @@ -1,34 +1,35 @@ use log::{error, warn}; use satrs::action::{ActionRequest, ActionRequestVariant}; use satrs::params::WritableToBeBytes; -use satrs::pool::{SharedStaticMemoryPool, StoreAddr}; +use satrs::pool::SharedStaticMemoryPool; use satrs::pus::action::{ ActionReplyVariant, ActivePusActionRequestStd, DefaultActiveActionRequestMap, PusActionReply, }; use satrs::pus::verification::{ - FailParams, FailParamsWithStep, TcStateAccepted, TcStateStarted, - VerificationReporterWithSharedPoolMpscBoundedSender, VerificationReporterWithVecMpscSender, + FailParams, FailParamsWithStep, TcStateAccepted, TcStateStarted, VerificationReporter, VerificationReportingProvider, VerificationToken, }; use satrs::pus::{ ActiveRequestProvider, EcssTcAndToken, EcssTcInMemConverter, EcssTcInSharedStoreConverter, - EcssTcInVecConverter, EcssTcReceiverCore, EcssTmSenderCore, EcssTmtcError, - GenericConversionError, MpscTcReceiver, PusPacketHandlerResult, PusReplyHandler, - PusServiceHelper, PusTcToRequestConverter, TmAsVecSenderWithId, TmAsVecSenderWithMpsc, - TmInSharedPoolSenderWithBoundedMpsc, TmInSharedPoolSenderWithId, + EcssTcInVecConverter, EcssTmSenderCore, EcssTmtcError, GenericConversionError, MpscTcReceiver, + MpscTmAsVecSender, MpscTmInSharedPoolSenderBounded, PusPacketHandlerResult, PusReplyHandler, + PusServiceHelper, PusTcToRequestConverter, PusTmAsVec, PusTmInPool, TmInSharedPoolSender, }; -use satrs::request::{GenericMessage, TargetAndApidId}; +use satrs::request::{GenericMessage, UniqueApidTargetId}; use satrs::spacepackets::ecss::tc::PusTcReader; use satrs::spacepackets::ecss::{EcssEnumU16, PusPacket}; -use satrs::tmtc::tm_helper::SharedTmPool; use satrs::ComponentId; -use satrs_example::config::{tmtc_err, ComponentIdList, PUS_APID}; -use std::sync::mpsc::{self}; +use satrs_example::config::components::PUS_ACTION_SERVICE; +use satrs_example::config::tmtc_err; +use std::sync::mpsc; use std::time::Duration; use crate::requests::GenericRequestRouter; -use super::{generic_pus_request_timeout_handler, PusTargetedRequestService, TargetedPusService}; +use super::{ + create_verification_reporter, generic_pus_request_timeout_handler, PusTargetedRequestService, + TargetedPusService, +}; pub struct ActionReplyHandler { fail_data_buf: [u8; 128], @@ -47,20 +48,22 @@ impl PusReplyHandler for ActionReplyH fn handle_unrequested_reply( &mut self, + _caller_id: ComponentId, reply: &GenericMessage, _tm_sender: &impl EcssTmSenderCore, ) -> Result<(), Self::Error> { - log::warn!("received unexpected reply for service 8: {reply:?}"); + warn!("received unexpected reply for service 8: {reply:?}"); Ok(()) } fn handle_reply( &mut self, - reply: &satrs::request::GenericMessage, + caller_id: ComponentId, + reply: &GenericMessage, active_request: &ActivePusActionRequestStd, + tm_sender: &(impl EcssTmSenderCore + ?Sized), verification_handler: &impl VerificationReportingProvider, time_stamp: &[u8], - _tm_sender: &impl EcssTmSenderCore, ) -> Result { let verif_token: VerificationToken = active_request .token() @@ -72,16 +75,12 @@ impl PusReplyHandler for ActionReplyH if let Some(params) = params { fail_data_len = params.write_to_be_bytes(&mut self.fail_data_buf)?; } - verification_handler - .completion_failure( - verif_token, - FailParams::new( - time_stamp, - error_code, - &self.fail_data_buf[..fail_data_len], - ), - ) - .map_err(|e| e.0)?; + verification_handler.completion_failure( + caller_id, + tm_sender, + verif_token, + FailParams::new(time_stamp, error_code, &self.fail_data_buf[..fail_data_len]), + )?; true } ActionReplyVariant::StepFailed { @@ -93,27 +92,32 @@ impl PusReplyHandler for ActionReplyH if let Some(params) = params { fail_data_len = params.write_to_be_bytes(&mut self.fail_data_buf)?; } - verification_handler - .step_failure( - verif_token, - FailParamsWithStep::new( - time_stamp, - &EcssEnumU16::new(*step), - error_code, - &self.fail_data_buf[..fail_data_len], - ), - ) - .map_err(|e| e.0)?; + verification_handler.step_failure( + caller_id, + tm_sender, + verif_token, + FailParamsWithStep::new( + time_stamp, + &EcssEnumU16::new(*step), + error_code, + &self.fail_data_buf[..fail_data_len], + ), + )?; true } ActionReplyVariant::Completed => { - verification_handler - .completion_success(verif_token, time_stamp) - .map_err(|e| e.0)?; + verification_handler.completion_success( + caller_id, + tm_sender, + verif_token, + time_stamp, + )?; true } ActionReplyVariant::StepSuccess { step } => { verification_handler.step_success( + caller_id, + tm_sender, &verif_token, time_stamp, EcssEnumU16::new(*step), @@ -127,12 +131,15 @@ impl PusReplyHandler for ActionReplyH fn handle_request_timeout( &mut self, + caller_id: ComponentId, active_request: &ActivePusActionRequestStd, + tm_sender: &impl EcssTmSenderCore, verification_handler: &impl VerificationReportingProvider, time_stamp: &[u8], - _tm_sender: &impl EcssTmSenderCore, ) -> Result<(), Self::Error> { generic_pus_request_timeout_handler( + caller_id, + tm_sender, active_request, verification_handler, time_stamp, @@ -149,16 +156,20 @@ impl PusTcToRequestConverter for Actio fn convert( &mut self, + caller_id: ComponentId, token: VerificationToken, tc: &PusTcReader, - time_stamp: &[u8], + tm_sender: &(impl EcssTmSenderCore + ?Sized), verif_reporter: &impl VerificationReportingProvider, + time_stamp: &[u8], ) -> Result<(ActivePusActionRequestStd, ActionRequest), Self::Error> { let subservice = tc.subservice(); let user_data = tc.user_data(); if user_data.len() < 8 { verif_reporter .start_failure( + caller_id, + tm_sender, token, FailParams::new_no_fail_data(time_stamp, &tmtc_err::NOT_ENOUGH_APP_DATA), ) @@ -168,7 +179,7 @@ impl PusTcToRequestConverter for Actio found: user_data.len(), }); } - let target_id_and_apid = TargetAndApidId::from_pus_tc(tc).unwrap(); + let target_id_and_apid = UniqueApidTargetId::from_pus_tc(tc).unwrap(); let action_id = u32::from_be_bytes(user_data[4..8].try_into().unwrap()); if subservice == 128 { let req_variant = if user_data.len() == 8 { @@ -188,6 +199,8 @@ impl PusTcToRequestConverter for Actio } else { verif_reporter .start_failure( + caller_id, + tm_sender, token, FailParams::new_no_fail_data(time_stamp, &tmtc_err::INVALID_PUS_SUBSERVICE), ) @@ -198,37 +211,18 @@ impl PusTcToRequestConverter for Actio } pub fn create_action_service_static( - shared_tm_store: SharedTmPool, - tm_funnel_tx: mpsc::SyncSender, - verif_reporter: VerificationReporterWithSharedPoolMpscBoundedSender, + tm_sender: TmInSharedPoolSender>, tc_pool: SharedStaticMemoryPool, pus_action_rx: mpsc::Receiver, action_router: GenericRequestRouter, reply_receiver: mpsc::Receiver>, -) -> Pus8Wrapper< - MpscTcReceiver, - TmInSharedPoolSenderWithBoundedMpsc, - EcssTcInSharedStoreConverter, - VerificationReporterWithSharedPoolMpscBoundedSender, -> { - let action_srv_tm_sender = TmInSharedPoolSenderWithId::new( - ComponentIdList::PusAction as ComponentId, - "PUS_8_TM_SENDER", - shared_tm_store.clone(), - tm_funnel_tx.clone(), - ); - let action_srv_receiver = MpscTcReceiver::new( - ComponentIdList::PusAction as ComponentId, - "PUS_8_TC_RECV", - pus_action_rx, - ); +) -> ActionServiceWrapper { let action_request_handler = PusTargetedRequestService::new( - ComponentIdList::PusAction as ComponentId, PusServiceHelper::new( - action_srv_receiver, - action_srv_tm_sender.clone(), - PUS_APID, - verif_reporter.clone(), + PUS_ACTION_SERVICE.raw(), + pus_action_rx, + tm_sender, + create_verification_reporter(PUS_ACTION_SERVICE.apid), EcssTcInSharedStoreConverter::new(tc_pool.clone(), 2048), ), ActionRequestConverter::default(), @@ -239,40 +233,23 @@ pub fn create_action_service_static( action_router, reply_receiver, ); - Pus8Wrapper { + ActionServiceWrapper { service: action_request_handler, } } pub fn create_action_service_dynamic( - tm_funnel_tx: mpsc::Sender>, - verif_reporter: VerificationReporterWithVecMpscSender, + tm_funnel_tx: mpsc::Sender, pus_action_rx: mpsc::Receiver, action_router: GenericRequestRouter, reply_receiver: mpsc::Receiver>, -) -> Pus8Wrapper< - MpscTcReceiver, - TmAsVecSenderWithMpsc, - EcssTcInVecConverter, - VerificationReporterWithVecMpscSender, -> { - let action_srv_tm_sender = TmAsVecSenderWithId::new( - ComponentIdList::PusAction as ComponentId, - "PUS_8_TM_SENDER", - tm_funnel_tx.clone(), - ); - let action_srv_receiver = MpscTcReceiver::new( - ComponentIdList::PusAction as ComponentId, - "PUS_8_TC_RECV", - pus_action_rx, - ); +) -> ActionServiceWrapper { let action_request_handler = PusTargetedRequestService::new( - ComponentIdList::PusAction as ComponentId, PusServiceHelper::new( - action_srv_receiver, - action_srv_tm_sender.clone(), - PUS_APID, - verif_reporter.clone(), + PUS_ACTION_SERVICE.raw(), + pus_action_rx, + tm_funnel_tx, + create_verification_reporter(PUS_ACTION_SERVICE.apid), EcssTcInVecConverter::default(), ), ActionRequestConverter::default(), @@ -281,19 +258,15 @@ pub fn create_action_service_dynamic( action_router, reply_receiver, ); - Pus8Wrapper { + ActionServiceWrapper { service: action_request_handler, } } -pub struct Pus8Wrapper< - TcReceiver: EcssTcReceiverCore, - TmSender: EcssTmSenderCore, - TcInMemConverter: EcssTcInMemConverter, - VerificationReporter: VerificationReportingProvider, -> { +pub struct ActionServiceWrapper +{ pub(crate) service: PusTargetedRequestService< - TcReceiver, + MpscTcReceiver, TmSender, TcInMemConverter, VerificationReporter, @@ -306,13 +279,8 @@ pub struct Pus8Wrapper< >, } -impl< - TcReceiver: EcssTcReceiverCore, - TmSender: EcssTmSenderCore, - TcInMemConverter: EcssTcInMemConverter, - VerificationReporter: VerificationReportingProvider, - > TargetedPusService - for Pus8Wrapper +impl TargetedPusService + for ActionServiceWrapper { /// Returns [true] if the packet handling is finished. fn poll_and_handle_next_tc(&mut self, time_stamp: &[u8]) -> bool { @@ -340,13 +308,12 @@ impl< } fn poll_and_handle_next_reply(&mut self, time_stamp: &[u8]) -> bool { - match self.service.poll_and_check_next_reply(time_stamp) { - Ok(packet_handled) => packet_handled, - Err(e) => { - log::warn!("PUS 8: Handling reply failed with error {e:?}"); + self.service + .poll_and_check_next_reply(time_stamp) + .unwrap_or_else(|e| { + warn!("PUS 8: Handling reply failed with error {e:?}"); false - } - } + }) } fn check_for_request_timeouts(&mut self) { @@ -356,8 +323,10 @@ impl< #[cfg(test)] mod tests { + use satrs::pus::test_util::{TEST_APID, TEST_COMPONENT_ID, TEST_UNIQUE_ID}; + use satrs::pus::verification::test_util::TestVerificationReporter; + use satrs::request::MessageMetadata; use satrs::{ - pus::verification::VerificationReporterCfg, res_code::ResultU16, spacepackets::{ ecss::{ @@ -370,10 +339,7 @@ mod tests { }; use crate::{ - pus::tests::{ - PusConverterTestbench, ReplyHandlerTestbench, TargetedPusRequestTestbench, TARGET_ID, - TEST_APID, TEST_APID_TARGET_ID, - }, + pus::tests::{PusConverterTestbench, ReplyHandlerTestbench, TargetedPusRequestTestbench}, requests::CompositeRequest, }; @@ -391,31 +357,22 @@ mod tests { { pub fn new_for_action() -> Self { let _ = env_logger::builder().is_test(true).try_init(); - let target_and_apid_id = TargetAndApidId::new(TEST_APID, TEST_APID_TARGET_ID); let (tm_funnel_tx, tm_funnel_rx) = mpsc::channel(); let (pus_action_tx, pus_action_rx) = mpsc::channel(); let (action_reply_tx, action_reply_rx) = mpsc::channel(); let (action_req_tx, action_req_rx) = mpsc::channel(); - let verif_reporter_cfg = VerificationReporterCfg::new(TEST_APID, 2, 2, 64).unwrap(); - let tm_as_vec_sender = - TmAsVecSenderWithMpsc::new(1, "VERIF_SENDER", tm_funnel_tx.clone()); - let verif_reporter = - VerificationReporterWithVecMpscSender::new(&verif_reporter_cfg, tm_as_vec_sender); + let verif_reporter = TestVerificationReporter::default(); let mut generic_req_router = GenericRequestRouter::default(); generic_req_router - .0 - .insert(target_and_apid_id.into(), action_req_tx); - let action_srv_tm_sender = - TmAsVecSenderWithId::new(0, "TESTBENCH", tm_funnel_tx.clone()); - let action_srv_receiver = MpscTcReceiver::new(0, "TESTBENCH", pus_action_rx); + .composite_router_map + .insert(TEST_APID.into(), action_req_tx); Self { service: PusTargetedRequestService::new( - 0, PusServiceHelper::new( - action_srv_receiver, - action_srv_tm_sender.clone(), - PUS_APID, - verif_reporter.clone(), + 0, + pus_action_rx, + tm_funnel_tx.clone(), + verif_reporter, EcssTcInVecConverter::default(), ), ActionRequestConverter::default(), @@ -424,7 +381,6 @@ mod tests { generic_req_router, action_reply_rx, ), - verif_reporter, pus_packet_tx: pus_action_tx, tm_funnel_rx, reply_tx: action_reply_tx, @@ -434,7 +390,7 @@ mod tests { pub fn verify_packet_verification(&self, subservice: u8) { let next_tm = self.tm_funnel_rx.try_recv().unwrap(); - let verif_tm = PusTmReader::new(&next_tm, 7).unwrap().0; + let verif_tm = PusTmReader::new(&next_tm.packet, 7).unwrap().0; assert_eq!(verif_tm.apid(), TEST_APID); assert_eq!(verif_tm.service(), 1); assert_eq!(verif_tm.subservice(), subservice); @@ -445,7 +401,7 @@ mod tests { if let Err(mpsc::TryRecvError::Empty) = packet { } else { let tm = packet.unwrap(); - let unexpected_tm = PusTmReader::new(&tm, 7).unwrap().0; + let unexpected_tm = PusTmReader::new(&tm.packet, 7).unwrap().0; panic!("unexpected TM packet {unexpected_tm:?}"); } } @@ -483,19 +439,26 @@ mod tests { } pub fn add_tc(&mut self, tc: &PusTcCreator) { - let token = self.verif_reporter.add_tc(tc); + let token = self.service.service_helper.verif_reporter_mut().add_tc(tc); let accepted_token = self - .verif_reporter - .acceptance_success(token, &[0; 7]) + .service + .service_helper + .verif_reporter() + .acceptance_success( + self.service.service_helper.id(), + self.service.service_helper.tm_sender(), + token, + &[0; 7], + ) .expect("TC acceptance failed"); let next_tm = self.tm_funnel_rx.try_recv().unwrap(); - let verif_tm = PusTmReader::new(&next_tm, 7).unwrap().0; + let verif_tm = PusTmReader::new(&next_tm.packet, 7).unwrap().0; assert_eq!(verif_tm.apid(), TEST_APID); assert_eq!(verif_tm.service(), 1); assert_eq!(verif_tm.subservice(), 1); if let Err(mpsc::TryRecvError::Empty) = self.tm_funnel_rx.try_recv() { } else { - let unexpected_tm = PusTmReader::new(&next_tm, 7).unwrap().0; + let unexpected_tm = PusTmReader::new(&next_tm.packet, 7).unwrap().0; panic!("unexpected TM packet {unexpected_tm:?}"); } self.pus_packet_tx @@ -512,7 +475,7 @@ mod tests { let sec_header = PusTcSecondaryHeader::new_simple(8, 128); let action_id = 5_u32; let mut app_data: [u8; 8] = [0; 8]; - app_data[0..4].copy_from_slice(&TEST_APID_TARGET_ID.to_be_bytes()); + app_data[0..4].copy_from_slice(&TEST_UNIQUE_ID.to_be_bytes()); app_data[4..8].copy_from_slice(&action_id.to_be_bytes()); let pus8_packet = PusTcCreator::new(&mut sp_header, sec_header, &app_data, true); testbench.add_tc(&pus8_packet); @@ -531,11 +494,7 @@ mod tests { let action_reply = PusActionReply::new(action_id, ActionReplyVariant::Completed); testbench .reply_tx - .send(GenericMessage::new( - req.request_id, - TARGET_ID.into(), - action_reply, - )) + .send(GenericMessage::new(req.requestor_info, action_reply)) .unwrap(); } else { panic!("unexpected request type"); @@ -556,7 +515,7 @@ mod tests { let action_id = 5_u32; let mut app_data: [u8; 8] = [0; 8]; // Invalid ID, routing should fail. - app_data[0..4].copy_from_slice(&(TEST_APID_TARGET_ID + 1).to_be_bytes()); + app_data[0..4].copy_from_slice(&(TEST_UNIQUE_ID + 1).to_be_bytes()); app_data[4..8].copy_from_slice(&action_id.to_be_bytes()); let pus8_packet = PusTcCreator::new(&mut sp_header, sec_header, &app_data, true); testbench.add_tc(&pus8_packet); @@ -575,11 +534,11 @@ mod tests { let action_id = 5_u32; let mut app_data: [u8; 8] = [0; 8]; // Invalid ID, routing should fail. - app_data[0..4].copy_from_slice(&TEST_APID_TARGET_ID.to_be_bytes()); + app_data[0..4].copy_from_slice(&TEST_UNIQUE_ID.to_be_bytes()); app_data[4..8].copy_from_slice(&action_id.to_be_bytes()); let pus8_packet = PusTcCreator::new(&mut sp_header, sec_header, &app_data, true); let token = testbench.add_tc(&pus8_packet); - let result = testbench.convert(token, &[], TEST_APID, TEST_APID_TARGET_ID); + let result = testbench.convert(token, &[], TEST_APID, TEST_UNIQUE_ID); assert!(result.is_ok()); let (active_req, request) = result.unwrap(); if let ActionRequestVariant::NoData = request.variant { @@ -587,7 +546,7 @@ mod tests { assert_eq!(active_req.action_id, action_id); assert_eq!( active_req.target_id(), - TargetAndApidId::new(TEST_APID, TEST_APID_TARGET_ID).raw() + UniqueApidTargetId::new(TEST_APID, TEST_UNIQUE_ID).raw() ); assert_eq!( active_req.token().request_id(), @@ -606,14 +565,14 @@ mod tests { let action_id = 5_u32; let mut app_data: [u8; 16] = [0; 16]; // Invalid ID, routing should fail. - app_data[0..4].copy_from_slice(&TEST_APID_TARGET_ID.to_be_bytes()); + app_data[0..4].copy_from_slice(&TEST_UNIQUE_ID.to_be_bytes()); app_data[4..8].copy_from_slice(&action_id.to_be_bytes()); for i in 0..8 { app_data[i + 8] = i as u8; } let pus8_packet = PusTcCreator::new(&mut sp_header, sec_header, &app_data, true); let token = testbench.add_tc(&pus8_packet); - let result = testbench.convert(token, &[], TEST_APID, TEST_APID_TARGET_ID); + let result = testbench.convert(token, &[], TEST_APID, TEST_UNIQUE_ID); assert!(result.is_ok()); let (active_req, request) = result.unwrap(); if let ActionRequestVariant::VecData(vec) = request.variant { @@ -629,24 +588,26 @@ mod tests { fn reply_handling_completion_success() { let mut testbench = ReplyHandlerTestbench::new(ActionReplyHandler::default()); let action_id = 5_u32; - let (req_id, active_req) = testbench.add_tc(TEST_APID, TEST_APID_TARGET_ID, &[]); + let (req_id, active_req) = testbench.add_tc(TEST_APID, TEST_UNIQUE_ID, &[]); let active_action_req = ActivePusActionRequestStd::new_from_common_req(action_id, active_req); let reply = PusActionReply::new(action_id, ActionReplyVariant::Completed); - let generic_reply = GenericMessage::new(req_id.into(), 0, reply); + let generic_reply = GenericMessage::new(MessageMetadata::new(req_id.into(), 0), reply); let result = testbench.handle_reply(&generic_reply, &active_action_req, &[]); assert!(result.is_ok()); assert!(result.unwrap()); - testbench - .verif_reporter - .assert_full_completion_success(&req_id, None); + testbench.verif_reporter.assert_full_completion_success( + TEST_COMPONENT_ID.raw(), + req_id, + None, + ); } #[test] fn reply_handling_completion_failure() { let mut testbench = ReplyHandlerTestbench::new(ActionReplyHandler::default()); let action_id = 5_u32; - let (req_id, active_req) = testbench.add_tc(TEST_APID, TEST_APID_TARGET_ID, &[]); + let (req_id, active_req) = testbench.add_tc(TEST_APID, TEST_UNIQUE_ID, &[]); let active_action_req = ActivePusActionRequestStd::new_from_common_req(action_id, active_req); let error_code = ResultU16::new(2, 3); @@ -657,40 +618,48 @@ mod tests { params: None, }, ); - let generic_reply = GenericMessage::new(req_id.into(), 0, reply); + let generic_reply = GenericMessage::new(MessageMetadata::new(req_id.into(), 0), reply); let result = testbench.handle_reply(&generic_reply, &active_action_req, &[]); assert!(result.is_ok()); assert!(result.unwrap()); - testbench - .verif_reporter - .assert_completion_failure(&req_id, None, error_code.raw() as u64); + testbench.verif_reporter.assert_completion_failure( + TEST_COMPONENT_ID.into(), + req_id, + None, + error_code.raw() as u64, + ); } #[test] fn reply_handling_step_success() { let mut testbench = ReplyHandlerTestbench::new(ActionReplyHandler::default()); let action_id = 5_u32; - let (req_id, active_req) = testbench.add_tc(TEST_APID, TEST_APID_TARGET_ID, &[]); + let (req_id, active_req) = testbench.add_tc(TEST_APID, TEST_UNIQUE_ID, &[]); let active_action_req = ActivePusActionRequestStd::new_from_common_req(action_id, active_req); let reply = PusActionReply::new(action_id, ActionReplyVariant::StepSuccess { step: 1 }); - let generic_reply = GenericMessage::new(req_id.into(), 0, reply); + let generic_reply = GenericMessage::new(MessageMetadata::new(req_id.into(), 0), reply); let result = testbench.handle_reply(&generic_reply, &active_action_req, &[]); assert!(result.is_ok()); // Entry should not be removed, completion not done yet. assert!(!result.unwrap()); - let verif_info = testbench.verif_reporter.verification_info(&req_id); - assert!(verif_info.is_some()); - let verif_info = verif_info.unwrap(); - assert!(verif_info.step_status.unwrap()); - assert_eq!(verif_info.step, 1); + testbench.verif_reporter.check_next_was_added(req_id); + testbench + .verif_reporter + .check_next_is_acceptance_success(TEST_COMPONENT_ID.raw(), req_id); + testbench + .verif_reporter + .check_next_is_started_success(TEST_COMPONENT_ID.raw(), req_id); + testbench + .verif_reporter + .check_next_is_step_success(TEST_COMPONENT_ID.raw(), req_id, 1); } #[test] fn reply_handling_step_failure() { let mut testbench = ReplyHandlerTestbench::new(ActionReplyHandler::default()); let action_id = 5_u32; - let (req_id, active_req) = testbench.add_tc(TEST_APID, TEST_APID_TARGET_ID, &[]); + let (req_id, active_req) = testbench.add_tc(TEST_APID, TEST_UNIQUE_ID, &[]); let active_action_req = ActivePusActionRequestStd::new_from_common_req(action_id, active_req); let error_code = ResultU16::new(2, 3); @@ -702,22 +671,28 @@ mod tests { params: None, }, ); - let generic_reply = GenericMessage::new(req_id.into(), 0, reply); + let generic_reply = GenericMessage::new(MessageMetadata::new(req_id.into(), 0), reply); let result = testbench.handle_reply(&generic_reply, &active_action_req, &[]); assert!(result.is_ok()); assert!(result.unwrap()); - let verif_info = testbench.verif_reporter.verification_info(&req_id); - assert!(verif_info.is_some()); - let verif_info = verif_info.unwrap(); - assert!(!verif_info.step_status.unwrap()); - assert_eq!(verif_info.step, 1); + testbench.verif_reporter.check_next_was_added(req_id); + testbench + .verif_reporter + .check_next_is_acceptance_success(TEST_COMPONENT_ID.raw(), req_id); + testbench + .verif_reporter + .check_next_is_started_success(TEST_COMPONENT_ID.raw(), req_id); + testbench + .verif_reporter + .check_next_is_step_success(TEST_COMPONENT_ID.raw(), req_id, 1); } #[test] fn reply_handling_unrequested_reply() { let mut testbench = ReplyHandlerTestbench::new(ActionReplyHandler::default()); let action_reply = PusActionReply::new(5_u32, ActionReplyVariant::Completed); - let unrequested_reply = GenericMessage::new(10_u32, 15_u64, action_reply); + let unrequested_reply = + GenericMessage::new(MessageMetadata::new(10_u32, 15_u64), action_reply); // Right now this function does not do a lot. We simply check that it does not panic or do // weird stuff. let result = testbench.handle_unrequested_reply(&unrequested_reply); @@ -727,9 +702,18 @@ mod tests { #[test] fn reply_handling_reply_timeout() { let mut testbench = ReplyHandlerTestbench::new(ActionReplyHandler::default()); - // TODO: Start a request, then time it out with the API and check verification completion - // failure. - // testbench.reply_handler.handle_request_timeout(active_request, verification_handler, time_stamp, tm_sender) - // testbench.default_timeout = Duration::from_millis(50); + let action_id = 5_u32; + let (req_id, active_request) = testbench.add_tc(TEST_APID, TEST_UNIQUE_ID, &[]); + let result = testbench.handle_request_timeout( + &ActivePusActionRequestStd::new_from_common_req(action_id, active_request), + &[], + ); + assert!(result.is_ok()); + testbench.verif_reporter.assert_completion_failure( + TEST_COMPONENT_ID.raw(), + req_id, + None, + tmtc_err::REQUEST_TIMEOUT.raw() as u64, + ); } } diff --git a/satrs-example/src/pus/event.rs b/satrs-example/src/pus/event.rs index 25eb230..53fb65b 100644 --- a/satrs-example/src/pus/event.rs +++ b/satrs-example/src/pus/event.rs @@ -1,114 +1,66 @@ use std::sync::mpsc; +use crate::pus::create_verification_reporter; use log::{error, warn}; -use satrs::pool::{SharedStaticMemoryPool, StoreAddr}; +use satrs::pool::SharedStaticMemoryPool; use satrs::pus::event_man::EventRequestWithToken; -use satrs::pus::event_srv::PusService5EventHandler; -use satrs::pus::verification::std_mod::{ - VerificationReporterWithSharedPoolMpscBoundedSender, VerificationReporterWithVecMpscSender, -}; -use satrs::pus::verification::VerificationReportingProvider; +use satrs::pus::event_srv::PusEventServiceHandler; +use satrs::pus::verification::VerificationReporter; use satrs::pus::{ EcssTcAndToken, EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter, - EcssTcReceiverCore, EcssTmSenderCore, MpscTcReceiver, PusPacketHandlerResult, PusServiceHelper, - TmAsVecSenderWithId, TmAsVecSenderWithMpsc, TmInSharedPoolSenderWithBoundedMpsc, - TmInSharedPoolSenderWithId, + EcssTmSenderCore, MpscTcReceiver, MpscTmAsVecSender, MpscTmInSharedPoolSenderBounded, + PusPacketHandlerResult, PusServiceHelper, PusTmAsVec, PusTmInPool, TmInSharedPoolSender, }; -use satrs::tmtc::tm_helper::SharedTmPool; -use satrs::ComponentId; -use satrs_example::config::{ComponentIdList, PUS_APID}; +use satrs_example::config::components::PUS_EVENT_MANAGEMENT; pub fn create_event_service_static( - shared_tm_store: SharedTmPool, - tm_funnel_tx: mpsc::SyncSender, - verif_reporter: VerificationReporterWithSharedPoolMpscBoundedSender, + tm_sender: TmInSharedPoolSender>, tc_pool: SharedStaticMemoryPool, pus_event_rx: mpsc::Receiver, event_request_tx: mpsc::Sender, -) -> Pus5Wrapper< - MpscTcReceiver, - TmInSharedPoolSenderWithBoundedMpsc, - EcssTcInSharedStoreConverter, - VerificationReporterWithSharedPoolMpscBoundedSender, -> { - let event_srv_tm_sender = TmInSharedPoolSenderWithId::new( - ComponentIdList::EventManagement as ComponentId, - "PUS_5_TM_SENDER", - shared_tm_store.clone(), - tm_funnel_tx.clone(), - ); - let event_srv_receiver = MpscTcReceiver::new( - ComponentIdList::EventManagement as ComponentId, - "PUS_5_TC_RECV", - pus_event_rx, - ); - let pus_5_handler = PusService5EventHandler::new( +) -> EventServiceWrapper { + let pus_5_handler = PusEventServiceHandler::new( PusServiceHelper::new( - event_srv_receiver, - event_srv_tm_sender, - PUS_APID, - verif_reporter.clone(), + PUS_EVENT_MANAGEMENT.raw(), + pus_event_rx, + tm_sender, + create_verification_reporter(PUS_EVENT_MANAGEMENT.apid), EcssTcInSharedStoreConverter::new(tc_pool.clone(), 2048), ), event_request_tx, ); - Pus5Wrapper { + EventServiceWrapper { handler: pus_5_handler, } } pub fn create_event_service_dynamic( - tm_funnel_tx: mpsc::Sender>, - verif_reporter: VerificationReporterWithVecMpscSender, + tm_funnel_tx: mpsc::Sender, pus_event_rx: mpsc::Receiver, event_request_tx: mpsc::Sender, -) -> Pus5Wrapper< - MpscTcReceiver, - TmAsVecSenderWithMpsc, - EcssTcInVecConverter, - VerificationReporterWithVecMpscSender, -> { - let event_srv_tm_sender = TmAsVecSenderWithId::new( - ComponentIdList::EventManagement as ComponentId, - "PUS_5_TM_SENDER", - tm_funnel_tx, - ); - let event_srv_receiver = MpscTcReceiver::new( - ComponentIdList::EventManagement as ComponentId, - "PUS_5_TC_RECV", - pus_event_rx, - ); - let pus_5_handler = PusService5EventHandler::new( +) -> EventServiceWrapper { + let pus_5_handler = PusEventServiceHandler::new( PusServiceHelper::new( - event_srv_receiver, - event_srv_tm_sender, - PUS_APID, - verif_reporter.clone(), + PUS_EVENT_MANAGEMENT.raw(), + pus_event_rx, + tm_funnel_tx, + create_verification_reporter(PUS_EVENT_MANAGEMENT.apid), EcssTcInVecConverter::default(), ), event_request_tx, ); - Pus5Wrapper { + EventServiceWrapper { handler: pus_5_handler, } } -pub struct Pus5Wrapper< - TcReceiver: EcssTcReceiverCore, - TmSender: EcssTmSenderCore, - TcInMemConverter: EcssTcInMemConverter, - VerificationReporter: VerificationReportingProvider, -> { +pub struct EventServiceWrapper { pub handler: - PusService5EventHandler, + PusEventServiceHandler, } -impl< - TcReceiver: EcssTcReceiverCore, - TmSender: EcssTmSenderCore, - TcInMemConverter: EcssTcInMemConverter, - VerificationReporter: VerificationReportingProvider, - > Pus5Wrapper +impl + EventServiceWrapper { pub fn poll_and_handle_next_tc(&mut self, time_stamp: &[u8]) -> bool { match self.handler.poll_and_handle_next_tc(time_stamp) { diff --git a/satrs-example/src/pus/hk.rs b/satrs-example/src/pus/hk.rs index 002dd6d..76dc659 100644 --- a/satrs-example/src/pus/hk.rs +++ b/satrs-example/src/pus/hk.rs @@ -1,30 +1,28 @@ use derive_new::new; use log::{error, warn}; use satrs::hk::{CollectionIntervalFactor, HkRequest, HkRequestVariant, UniqueId}; -use satrs::pool::{SharedStaticMemoryPool, StoreAddr}; +use satrs::pool::SharedStaticMemoryPool; use satrs::pus::verification::{ - FailParams, TcStateAccepted, TcStateStarted, - VerificationReporterWithSharedPoolMpscBoundedSender, VerificationReporterWithVecMpscSender, + FailParams, TcStateAccepted, TcStateStarted, VerificationReporter, VerificationReportingProvider, VerificationToken, }; use satrs::pus::{ ActivePusRequestStd, ActiveRequestProvider, DefaultActiveRequestMap, EcssTcAndToken, - EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter, EcssTcReceiverCore, - EcssTmSenderCore, EcssTmtcError, GenericConversionError, MpscTcReceiver, - PusPacketHandlerResult, PusReplyHandler, PusServiceHelper, PusTcToRequestConverter, - TmAsVecSenderWithId, TmAsVecSenderWithMpsc, TmInSharedPoolSenderWithBoundedMpsc, - TmInSharedPoolSenderWithId, + EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter, EcssTmSenderCore, + EcssTmtcError, GenericConversionError, MpscTcReceiver, MpscTmAsVecSender, + MpscTmInSharedPoolSenderBounded, PusPacketHandlerResult, PusReplyHandler, PusServiceHelper, + PusTcToRequestConverter, PusTmAsVec, PusTmInPool, TmInSharedPoolSender, }; -use satrs::request::{GenericMessage, TargetAndApidId}; +use satrs::request::{GenericMessage, UniqueApidTargetId}; use satrs::spacepackets::ecss::tc::PusTcReader; use satrs::spacepackets::ecss::{hk, PusPacket}; -use satrs::tmtc::tm_helper::SharedTmPool; use satrs::ComponentId; -use satrs_example::config::{hk_err, tmtc_err, ComponentIdList, PUS_APID}; -use std::sync::mpsc::{self}; +use satrs_example::config::components::PUS_HK_SERVICE; +use satrs_example::config::{hk_err, tmtc_err}; +use std::sync::mpsc; use std::time::Duration; -use crate::pus::generic_pus_request_timeout_handler; +use crate::pus::{create_verification_reporter, generic_pus_request_timeout_handler}; use crate::requests::GenericRequestRouter; use super::PusTargetedRequestService; @@ -48,7 +46,8 @@ impl PusReplyHandler for HkReplyHandler { fn handle_unrequested_reply( &mut self, - reply: &satrs::request::GenericMessage, + _caller_id: ComponentId, + reply: &GenericMessage, _tm_sender: &impl EcssTmSenderCore, ) -> Result<(), Self::Error> { log::warn!("received unexpected reply for service 3: {reply:?}"); @@ -57,11 +56,12 @@ impl PusReplyHandler for HkReplyHandler { fn handle_reply( &mut self, - reply: &satrs::request::GenericMessage, + caller_id: ComponentId, + reply: &GenericMessage, active_request: &ActivePusRequestStd, + tm_sender: &impl EcssTmSenderCore, verification_handler: &impl VerificationReportingProvider, time_stamp: &[u8], - _tm_sender: &impl EcssTmSenderCore, ) -> Result { let started_token: VerificationToken = active_request .token() @@ -70,8 +70,8 @@ impl PusReplyHandler for HkReplyHandler { match reply.message.variant { HkReplyVariant::Ack => { verification_handler - .completion_success(started_token, time_stamp) - .expect("sending completio success verification failed"); + .completion_success(caller_id, tm_sender, started_token, time_stamp) + .expect("sending completion success verification failed"); } }; Ok(true) @@ -79,12 +79,15 @@ impl PusReplyHandler for HkReplyHandler { fn handle_request_timeout( &mut self, + caller_id: ComponentId, active_request: &ActivePusRequestStd, + tm_sender: &impl EcssTmSenderCore, verification_handler: &impl VerificationReportingProvider, time_stamp: &[u8], - _tm_sender: &impl EcssTmSenderCore, ) -> Result<(), Self::Error> { generic_pus_request_timeout_handler( + caller_id, + tm_sender, active_request, verification_handler, time_stamp, @@ -111,10 +114,12 @@ impl PusTcToRequestConverter for HkRequestConver fn convert( &mut self, + caller_id: ComponentId, token: VerificationToken, tc: &PusTcReader, - time_stamp: &[u8], + tm_sender: &(impl EcssTmSenderCore + ?Sized), verif_reporter: &impl VerificationReportingProvider, + time_stamp: &[u8], ) -> Result<(ActivePusRequestStd, HkRequest), Self::Error> { let user_data = tc.user_data(); if user_data.is_empty() { @@ -122,6 +127,8 @@ impl PusTcToRequestConverter for HkRequestConver let user_data_len_raw = user_data_len.to_be_bytes(); verif_reporter .start_failure( + caller_id, + tm_sender, token, FailParams::new( time_stamp, @@ -144,7 +151,12 @@ impl PusTcToRequestConverter for HkRequestConver let user_data_len = user_data.len() as u32; let user_data_len_raw = user_data_len.to_be_bytes(); verif_reporter - .start_failure(token, FailParams::new(time_stamp, err, &user_data_len_raw)) + .start_failure( + caller_id, + tm_sender, + token, + FailParams::new(time_stamp, err, &user_data_len_raw), + ) .expect("Sending start failure TM failed"); return Err(GenericConversionError::NotEnoughAppData { expected: 8, @@ -152,13 +164,15 @@ impl PusTcToRequestConverter for HkRequestConver }); } let subservice = tc.subservice(); - let target_id_and_apid = TargetAndApidId::from_pus_tc(tc).expect("invalid tc format"); + let target_id_and_apid = UniqueApidTargetId::from_pus_tc(tc).expect("invalid tc format"); let unique_id = u32::from_be_bytes(tc.user_data()[4..8].try_into().unwrap()); let standard_subservice = hk::Subservice::try_from(subservice); if standard_subservice.is_err() { verif_reporter .start_failure( + caller_id, + tm_sender, token, FailParams::new(time_stamp, &tmtc_err::INVALID_PUS_SUBSERVICE, &[subservice]), ) @@ -167,10 +181,10 @@ impl PusTcToRequestConverter for HkRequestConver } let request = match standard_subservice.unwrap() { hk::Subservice::TcEnableHkGeneration | hk::Subservice::TcEnableDiagGeneration => { - HkRequest::new(unique_id, HkRequestVariant::Enable) + HkRequest::new(unique_id, HkRequestVariant::EnablePeriodic) } hk::Subservice::TcDisableHkGeneration | hk::Subservice::TcDisableDiagGeneration => { - HkRequest::new(unique_id, HkRequestVariant::Disable) + HkRequest::new(unique_id, HkRequestVariant::DisablePeriodic) } hk::Subservice::TcReportHkReportStructures => todo!(), hk::Subservice::TmHkPacket => todo!(), @@ -182,6 +196,8 @@ impl PusTcToRequestConverter for HkRequestConver if user_data.len() < 12 { verif_reporter .start_failure( + caller_id, + tm_sender, token, FailParams::new_no_fail_data( time_stamp, @@ -206,6 +222,8 @@ impl PusTcToRequestConverter for HkRequestConver _ => { verif_reporter .start_failure( + caller_id, + tm_sender, token, FailParams::new( time_stamp, @@ -225,37 +243,18 @@ impl PusTcToRequestConverter for HkRequestConver } pub fn create_hk_service_static( - shared_tm_store: SharedTmPool, - tm_funnel_tx: mpsc::SyncSender, - verif_reporter: VerificationReporterWithSharedPoolMpscBoundedSender, + tm_sender: TmInSharedPoolSender>, tc_pool: SharedStaticMemoryPool, pus_hk_rx: mpsc::Receiver, request_router: GenericRequestRouter, reply_receiver: mpsc::Receiver>, -) -> Pus3Wrapper< - MpscTcReceiver, - TmInSharedPoolSenderWithBoundedMpsc, - EcssTcInSharedStoreConverter, - VerificationReporterWithSharedPoolMpscBoundedSender, -> { - let hk_srv_tm_sender = TmInSharedPoolSenderWithId::new( - ComponentIdList::PusHk as ComponentId, - "PUS_3_TM_SENDER", - shared_tm_store.clone(), - tm_funnel_tx.clone(), - ); - let hk_srv_receiver = MpscTcReceiver::new( - ComponentIdList::PusHk as ComponentId, - "PUS_8_TC_RECV", - pus_hk_rx, - ); +) -> HkServiceWrapper { let pus_3_handler = PusTargetedRequestService::new( - ComponentIdList::PusHk as ComponentId, PusServiceHelper::new( - hk_srv_receiver, - hk_srv_tm_sender, - PUS_APID, - verif_reporter.clone(), + PUS_HK_SERVICE.raw(), + pus_hk_rx, + tm_sender, + create_verification_reporter(PUS_HK_SERVICE.apid), EcssTcInSharedStoreConverter::new(tc_pool, 2048), ), HkRequestConverter::default(), @@ -264,40 +263,23 @@ pub fn create_hk_service_static( request_router, reply_receiver, ); - Pus3Wrapper { + HkServiceWrapper { service: pus_3_handler, } } pub fn create_hk_service_dynamic( - tm_funnel_tx: mpsc::Sender>, - verif_reporter: VerificationReporterWithVecMpscSender, + tm_funnel_tx: mpsc::Sender, pus_hk_rx: mpsc::Receiver, request_router: GenericRequestRouter, reply_receiver: mpsc::Receiver>, -) -> Pus3Wrapper< - MpscTcReceiver, - TmAsVecSenderWithMpsc, - EcssTcInVecConverter, - VerificationReporterWithVecMpscSender, -> { - let hk_srv_tm_sender = TmAsVecSenderWithId::new( - ComponentIdList::PusHk as ComponentId, - "PUS_3_TM_SENDER", - tm_funnel_tx.clone(), - ); - let hk_srv_receiver = MpscTcReceiver::new( - ComponentIdList::PusHk as ComponentId, - "PUS_8_TC_RECV", - pus_hk_rx, - ); +) -> HkServiceWrapper { let pus_3_handler = PusTargetedRequestService::new( - ComponentIdList::PusHk as ComponentId, PusServiceHelper::new( - hk_srv_receiver, - hk_srv_tm_sender, - PUS_APID, - verif_reporter.clone(), + PUS_HK_SERVICE.raw(), + pus_hk_rx, + tm_funnel_tx, + create_verification_reporter(PUS_HK_SERVICE.apid), EcssTcInVecConverter::default(), ), HkRequestConverter::default(), @@ -306,19 +288,14 @@ pub fn create_hk_service_dynamic( request_router, reply_receiver, ); - Pus3Wrapper { + HkServiceWrapper { service: pus_3_handler, } } -pub struct Pus3Wrapper< - TcReceiver: EcssTcReceiverCore, - TmSender: EcssTmSenderCore, - TcInMemConverter: EcssTcInMemConverter, - VerificationReporter: VerificationReportingProvider, -> { +pub struct HkServiceWrapper { pub(crate) service: PusTargetedRequestService< - TcReceiver, + MpscTcReceiver, TmSender, TcInMemConverter, VerificationReporter, @@ -331,12 +308,8 @@ pub struct Pus3Wrapper< >, } -impl< - TcReceiver: EcssTcReceiverCore, - TmSender: EcssTmSenderCore, - TcInMemConverter: EcssTcInMemConverter, - VerificationReporter: VerificationReportingProvider, - > Pus3Wrapper +impl + HkServiceWrapper { pub fn poll_and_handle_next_tc(&mut self, time_stamp: &[u8]) -> bool { match self.service.poll_and_handle_next_tc(time_stamp) { @@ -363,13 +336,12 @@ impl< } pub fn poll_and_handle_next_reply(&mut self, time_stamp: &[u8]) -> bool { - match self.service.poll_and_check_next_reply(time_stamp) { - Ok(packet_handled) => packet_handled, - Err(e) => { - log::warn!("PUS 3: Handling reply failed with error {e:?}"); + self.service + .poll_and_check_next_reply(time_stamp) + .unwrap_or_else(|e| { + warn!("PUS 3: Handling reply failed with error {e:?}"); false - } - } + }) } pub fn check_for_request_timeouts(&mut self) { @@ -379,6 +351,8 @@ impl< #[cfg(test)] mod tests { + use satrs::pus::test_util::{TEST_COMPONENT_ID, TEST_UNIQUE_ID}; + use satrs::request::MessageMetadata; use satrs::{ hk::HkRequestVariant, pus::test_util::TEST_APID, @@ -388,10 +362,11 @@ mod tests { SpHeader, }, }; + use satrs_example::config::tmtc_err; use crate::pus::{ hk::HkReplyVariant, - tests::{PusConverterTestbench, ReplyHandlerTestbench, TEST_APID_TARGET_ID}, + tests::{PusConverterTestbench, ReplyHandlerTestbench}, }; use super::{HkReply, HkReplyHandler, HkRequestConverter}; @@ -400,7 +375,7 @@ mod tests { fn hk_converter_one_shot_req() { let mut hk_bench = PusConverterTestbench::new(HkRequestConverter::default()); let mut sp_header = SpHeader::tc_unseg(TEST_APID, 0, 0).unwrap(); - let target_id = TEST_APID_TARGET_ID; + let target_id = TEST_UNIQUE_ID; let unique_id = 5_u32; let mut app_data: [u8; 8] = [0; 8]; app_data[0..4].copy_from_slice(&target_id.to_be_bytes()); @@ -415,7 +390,7 @@ mod tests { ); let accepted_token = hk_bench.add_tc(&hk_req); let (_active_req, req) = hk_bench - .convert(accepted_token, &[], TEST_APID, TEST_APID_TARGET_ID) + .convert(accepted_token, &[], TEST_APID, TEST_UNIQUE_ID) .expect("conversion failed"); assert_eq!(req.unique_id, unique_id); @@ -429,7 +404,7 @@ mod tests { fn hk_converter_enable_periodic_generation() { let mut hk_bench = PusConverterTestbench::new(HkRequestConverter::default()); let mut sp_header = SpHeader::tc_unseg(TEST_APID, 0, 0).unwrap(); - let target_id = TEST_APID_TARGET_ID; + let target_id = TEST_UNIQUE_ID; let unique_id = 5_u32; let mut app_data: [u8; 8] = [0; 8]; app_data[0..4].copy_from_slice(&target_id.to_be_bytes()); @@ -437,10 +412,10 @@ mod tests { let mut generic_check = |tc: &PusTcCreator| { let accepted_token = hk_bench.add_tc(tc); let (_active_req, req) = hk_bench - .convert(accepted_token, &[], TEST_APID, TEST_APID_TARGET_ID) + .convert(accepted_token, &[], TEST_APID, TEST_UNIQUE_ID) .expect("conversion failed"); assert_eq!(req.unique_id, unique_id); - if let HkRequestVariant::Enable = req.variant { + if let HkRequestVariant::EnablePeriodic = req.variant { } else { panic!("unexpected HK request") } @@ -467,7 +442,7 @@ mod tests { fn hk_conversion_disable_periodic_generation() { let mut hk_bench = PusConverterTestbench::new(HkRequestConverter::default()); let mut sp_header = SpHeader::tc_unseg(TEST_APID, 0, 0).unwrap(); - let target_id = TEST_APID_TARGET_ID; + let target_id = TEST_UNIQUE_ID; let unique_id = 5_u32; let mut app_data: [u8; 8] = [0; 8]; app_data[0..4].copy_from_slice(&target_id.to_be_bytes()); @@ -475,10 +450,10 @@ mod tests { let mut generic_check = |tc: &PusTcCreator| { let accepted_token = hk_bench.add_tc(tc); let (_active_req, req) = hk_bench - .convert(accepted_token, &[], TEST_APID, TEST_APID_TARGET_ID) + .convert(accepted_token, &[], TEST_APID, TEST_UNIQUE_ID) .expect("conversion failed"); assert_eq!(req.unique_id, unique_id); - if let HkRequestVariant::Disable = req.variant { + if let HkRequestVariant::DisablePeriodic = req.variant { } else { panic!("unexpected HK request") } @@ -505,7 +480,7 @@ mod tests { fn hk_conversion_modify_interval() { let mut hk_bench = PusConverterTestbench::new(HkRequestConverter::default()); let mut sp_header = SpHeader::tc_unseg(TEST_APID, 0, 0).unwrap(); - let target_id = TEST_APID_TARGET_ID; + let target_id = TEST_UNIQUE_ID; let unique_id = 5_u32; let mut app_data: [u8; 12] = [0; 12]; let collection_interval_factor = 5_u32; @@ -516,7 +491,7 @@ mod tests { let mut generic_check = |tc: &PusTcCreator| { let accepted_token = hk_bench.add_tc(tc); let (_active_req, req) = hk_bench - .convert(accepted_token, &[], TEST_APID, TEST_APID_TARGET_ID) + .convert(accepted_token, &[], TEST_APID, TEST_UNIQUE_ID) .expect("conversion failed"); assert_eq!(req.unique_id, unique_id); if let HkRequestVariant::ModifyCollectionInterval(interval_factor) = req.variant { @@ -551,24 +526,23 @@ mod tests { let unique_id = 5_u32; let (req_id, active_req) = reply_testbench.add_tc(TEST_APID, apid_target_id, &[]); let reply = GenericMessage::new( - req_id.into(), - sender_id, + MessageMetadata::new(req_id.into(), sender_id), HkReply::new(unique_id, HkReplyVariant::Ack), ); let result = reply_testbench.handle_reply(&reply, &active_req, &[]); assert!(result.is_ok()); assert!(result.unwrap()); - assert!(reply_testbench + reply_testbench .verif_reporter - .completion_status(&req_id) - .unwrap()); + .assert_full_completion_success(TEST_COMPONENT_ID.raw(), req_id, None); } #[test] fn reply_handling_unrequested_reply() { let mut testbench = ReplyHandlerTestbench::new(HkReplyHandler::default()); let action_reply = HkReply::new(5_u32, HkReplyVariant::Ack); - let unrequested_reply = GenericMessage::new(10_u32, 15_u64, action_reply); + let unrequested_reply = + GenericMessage::new(MessageMetadata::new(10_u32, 15_u64), action_reply); // Right now this function does not do a lot. We simply check that it does not panic or do // weird stuff. let result = testbench.handle_unrequested_reply(&unrequested_reply); @@ -578,9 +552,14 @@ mod tests { #[test] fn reply_handling_reply_timeout() { let mut testbench = ReplyHandlerTestbench::new(HkReplyHandler::default()); - // TODO: Start a request, then time it out with the API and check verification completion - // failure. - // testbench.reply_handler.handle_request_timeout(active_request, verification_handler, time_stamp, tm_sender) - // testbench.default_timeout = Duration::from_millis(50); + let (req_id, active_request) = testbench.add_tc(TEST_APID, TEST_UNIQUE_ID, &[]); + let result = testbench.handle_request_timeout(&active_request, &[]); + assert!(result.is_ok()); + testbench.verif_reporter.assert_completion_failure( + TEST_COMPONENT_ID.raw(), + req_id, + None, + tmtc_err::REQUEST_TIMEOUT.raw() as u64, + ); } } diff --git a/satrs-example/src/pus/mod.rs b/satrs-example/src/pus/mod.rs index 5763072..8c26488 100644 --- a/satrs-example/src/pus/mod.rs +++ b/satrs-example/src/pus/mod.rs @@ -2,8 +2,8 @@ use crate::requests::GenericRequestRouter; use crate::tmtc::MpscStoreAndSendError; use log::warn; use satrs::pus::verification::{ - self, FailParams, TcStateAccepted, TcStateStarted, VerificationReportingProvider, - VerificationToken, + self, FailParams, TcStateAccepted, TcStateStarted, VerificationReporter, + VerificationReporterCfg, VerificationReportingProvider, VerificationToken, }; use satrs::pus::{ ActiveRequestMapProvider, ActiveRequestProvider, EcssTcAndToken, EcssTcInMemConverter, @@ -12,13 +12,13 @@ use satrs::pus::{ PusRequestRouter, PusServiceHelper, PusTcToRequestConverter, TcInMemory, }; use satrs::queue::GenericReceiveError; -use satrs::request::GenericMessage; +use satrs::request::{Apid, GenericMessage, MessageMetadata}; use satrs::spacepackets::ecss::tc::PusTcReader; use satrs::spacepackets::ecss::PusServiceId; -use satrs::spacepackets::time::cds::TimeProvider; -use satrs::spacepackets::time::TimeWriter; use satrs::ComponentId; +use satrs_example::config::components::PUS_ROUTING_SERVICE; use satrs_example::config::{tmtc_err, CustomPusServiceId}; +use satrs_example::TimeStampHelper; use std::fmt::Debug; use std::sync::mpsc::{self, Sender}; @@ -30,58 +30,125 @@ pub mod scheduler; pub mod stack; pub mod test; -/// Simple router structure which forwards PUS telecommands to dedicated handlers. -pub struct PusTcMpscRouter { - pub test_service_receiver: Sender, - pub event_service_receiver: Sender, - pub sched_service_receiver: Sender, - pub hk_service_receiver: Sender, - pub action_service_receiver: Sender, +pub fn create_verification_reporter(apid: Apid) -> VerificationReporter { + let verif_cfg = VerificationReporterCfg::new(apid, 1, 2, 8).unwrap(); + // Every software component which needs to generate verification telemetry, gets a cloned + // verification reporter. + VerificationReporter::new(&verif_cfg) } -pub struct PusReceiver { +/// Simple router structure which forwards PUS telecommands to dedicated handlers. +pub struct PusTcMpscRouter { + pub test_tc_sender: Sender, + pub event_tc_sender: Sender, + pub sched_tc_sender: Sender, + pub hk_tc_sender: Sender, + pub action_tc_sender: Sender, + pub mode_tc_sender: Sender, +} + +pub struct PusReceiver { + pub id: ComponentId, + pub tm_sender: TmSender, pub verif_reporter: VerificationReporter, pub pus_router: PusTcMpscRouter, stamp_helper: TimeStampHelper, } -struct TimeStampHelper { - stamper: TimeProvider, - time_stamp: [u8; 7], -} - -impl TimeStampHelper { - pub fn stamp(&self) -> &[u8] { - &self.time_stamp - } - - pub fn update_from_now(&mut self) { - self.stamper - .update_from_now() - .expect("Updating timestamp failed"); - self.stamper - .write_to_bytes(&mut self.time_stamp) - .expect("Writing timestamp failed"); - } -} - -impl Default for TimeStampHelper { - fn default() -> Self { +impl PusReceiver { + pub fn new(tm_sender: TmSender, pus_router: PusTcMpscRouter) -> Self { Self { - stamper: TimeProvider::from_now_with_u16_days().expect("creating time stamper failed"), - time_stamp: Default::default(), - } - } -} - -impl PusReceiver { - pub fn new(verif_reporter: VerificationReporter, pus_router: PusTcMpscRouter) -> Self { - Self { - verif_reporter, + id: PUS_ROUTING_SERVICE.raw(), + tm_sender, + verif_reporter: create_verification_reporter(PUS_ROUTING_SERVICE.apid), pus_router, stamp_helper: TimeStampHelper::default(), } } + + pub fn handle_tc_packet( + &mut self, + tc_in_memory: TcInMemory, + service: u8, + pus_tc: &PusTcReader, + ) -> Result { + let init_token = self.verif_reporter.add_tc(pus_tc); + self.stamp_helper.update_from_now(); + let accepted_token = self + .verif_reporter + .acceptance_success( + self.id, + &self.tm_sender, + init_token, + self.stamp_helper.stamp(), + ) + .expect("Acceptance success failure"); + let service = PusServiceId::try_from(service); + match service { + Ok(standard_service) => match standard_service { + PusServiceId::Test => self.pus_router.test_tc_sender.send(EcssTcAndToken { + tc_in_memory, + token: Some(accepted_token.into()), + })?, + PusServiceId::Housekeeping => { + self.pus_router.hk_tc_sender.send(EcssTcAndToken { + tc_in_memory, + token: Some(accepted_token.into()), + })? + } + PusServiceId::Event => self.pus_router.event_tc_sender.send(EcssTcAndToken { + tc_in_memory, + token: Some(accepted_token.into()), + })?, + PusServiceId::Scheduling => { + self.pus_router.sched_tc_sender.send(EcssTcAndToken { + tc_in_memory, + token: Some(accepted_token.into()), + })? + } + _ => { + let result = self.verif_reporter.start_failure( + self.id, + &self.tm_sender, + accepted_token, + FailParams::new( + self.stamp_helper.stamp(), + &tmtc_err::PUS_SERVICE_NOT_IMPLEMENTED, + &[standard_service as u8], + ), + ); + if result.is_err() { + warn!("Sending verification failure failed"); + } + } + }, + Err(e) => { + if let Ok(custom_service) = CustomPusServiceId::try_from(e.number) { + match custom_service { + CustomPusServiceId::Mode => { + // TODO: Fix mode service. + //self.handle_mode_service(pus_tc, accepted_token) + } + CustomPusServiceId::Health => {} + } + } else { + self.verif_reporter + .start_failure( + self.id, + &self.tm_sender, + accepted_token, + FailParams::new( + self.stamp_helper.stamp(), + &tmtc_err::INVALID_PUS_SUBSERVICE, + &[e.number], + ), + ) + .expect("Start failure verification failed") + } + } + } + Ok(PusPacketHandlerResult::RequestHandled) + } } pub trait TargetedPusService { @@ -123,7 +190,6 @@ pub struct PusTargetedRequestService< RequestType, ReplyType, > { - pub id: ComponentId, pub service_helper: PusServiceHelper, pub request_router: GenericRequestRouter, @@ -162,7 +228,6 @@ where GenericRequestRouter: PusRequestRouter, { pub fn new( - id: ComponentId, service_helper: PusServiceHelper< TcReceiver, TmSender, @@ -176,7 +241,6 @@ where reply_receiver: mpsc::Receiver>, ) -> Self { Self { - id, service_helper, request_converter, active_request_map, @@ -201,10 +265,12 @@ where .cache(&ecss_tc_and_token.tc_in_memory)?; let tc = self.service_helper.tc_in_mem_converter().convert()?; let (mut request_info, request) = match self.request_converter.convert( + self.service_helper.id(), ecss_tc_and_token.token, &tc, - time_stamp, + self.service_helper.tm_sender(), &self.service_helper.common.verif_reporter, + time_stamp, ) { Ok((info, req)) => (info, req), Err(e) => { @@ -218,8 +284,7 @@ where .expect("token not in expected accepted state"); let verif_request_id = verification::RequestId::new(&tc).raw(); match self.request_router.route( - verif_request_id, - self.id, + MessageMetadata::new(verif_request_id, self.service_helper.id()), request_info.target_id(), request, ) { @@ -227,7 +292,12 @@ where let started_token = self .service_helper .verif_reporter() - .start_success(accepted_token, time_stamp) + .start_success( + self.service_helper.id(), + &self.service_helper.common.tm_sender, + accepted_token, + time_stamp, + ) .expect("Start success failure"); request_info.set_token(started_token.into()); self.active_request_map @@ -238,8 +308,9 @@ where &request_info, &tc, e.clone(), - time_stamp, + self.service_helper.tm_sender(), self.service_helper.verif_reporter(), + time_stamp, ); return Err(e.into()); } @@ -259,6 +330,8 @@ where self.service_helper .verif_reporter() .completion_failure( + self.service_helper.id(), + self.service_helper.tm_sender(), token, FailParams::new(time_stamp, &tmtc_err::INVALID_PUS_SERVICE, &service_slice), ) @@ -269,6 +342,8 @@ where self.service_helper .verif_reporter() .completion_failure( + self.service_helper.id(), + self.service_helper.tm_sender(), token, FailParams::new( time_stamp, @@ -284,6 +359,8 @@ where self.service_helper .verif_reporter() .completion_failure( + self.service_helper.id(), + self.service_helper.tm_sender(), token, FailParams::new(time_stamp, &tmtc_err::NOT_ENOUGH_APP_DATA, &context_info), ) @@ -314,25 +391,29 @@ where reply: &GenericMessage, time_stamp: &[u8], ) -> Result<(), EcssTmtcError> { - let active_req_opt = self.active_request_map.get(reply.request_id); + let active_req_opt = self.active_request_map.get(reply.request_id()); if active_req_opt.is_none() { - self.reply_handler - .handle_unrequested_reply(reply, &self.service_helper.common.tm_sender)?; + self.reply_handler.handle_unrequested_reply( + self.service_helper.id(), + reply, + &self.service_helper.common.tm_sender, + )?; return Ok(()); } let active_request = active_req_opt.unwrap(); let request_finished = self .reply_handler .handle_reply( + self.service_helper.id(), reply, active_request, + &self.service_helper.common.tm_sender, &self.service_helper.common.verif_reporter, time_stamp, - &self.service_helper.common.tm_sender, ) .unwrap_or(false); if request_finished { - self.active_request_map.remove(reply.request_id); + self.active_request_map.remove(reply.request_id()); } Ok(()) } @@ -356,6 +437,8 @@ where /// Generic timeout handling: Handle the verification failure with a dedicated return code /// and also log the error. pub fn generic_pus_request_timeout_handler( + sender_id: ComponentId, + sender: &(impl EcssTmSenderCore + ?Sized), active_request: &(impl ActiveRequestProvider + Debug), verification_handler: &impl VerificationReportingProvider, time_stamp: &[u8], @@ -366,118 +449,27 @@ pub fn generic_pus_request_timeout_handler( .token() .try_into() .expect("token not in expected started state"); - verification_handler - .completion_failure( - started_token, - FailParams::new( - time_stamp, - &satrs_example::config::tmtc_err::REQUEST_TIMEOUT, - &[], - ), - ) - .map_err(|e| e.0)?; + verification_handler.completion_failure( + sender_id, + sender, + started_token, + FailParams::new(time_stamp, &tmtc_err::REQUEST_TIMEOUT, &[]), + )?; Ok(()) } -impl PusReceiver { - pub fn handle_tc_packet( - &mut self, - tc_in_memory: TcInMemory, - service: u8, - pus_tc: &PusTcReader, - ) -> Result { - let init_token = self.verif_reporter.add_tc(pus_tc); - self.stamp_helper.update_from_now(); - let accepted_token = self - .verif_reporter - .acceptance_success(init_token, self.stamp_helper.stamp()) - .expect("Acceptance success failure"); - let service = PusServiceId::try_from(service); - match service { - Ok(standard_service) => match standard_service { - PusServiceId::Test => { - self.pus_router.test_service_receiver.send(EcssTcAndToken { - tc_in_memory, - token: Some(accepted_token.into()), - })? - } - PusServiceId::Housekeeping => { - self.pus_router.hk_service_receiver.send(EcssTcAndToken { - tc_in_memory, - token: Some(accepted_token.into()), - })? - } - PusServiceId::Event => { - self.pus_router - .event_service_receiver - .send(EcssTcAndToken { - tc_in_memory, - token: Some(accepted_token.into()), - })? - } - PusServiceId::Scheduling => { - self.pus_router - .sched_service_receiver - .send(EcssTcAndToken { - tc_in_memory, - token: Some(accepted_token.into()), - })? - } - _ => { - let result = self.verif_reporter.start_failure( - accepted_token, - FailParams::new( - self.stamp_helper.stamp(), - &tmtc_err::PUS_SERVICE_NOT_IMPLEMENTED, - &[standard_service as u8], - ), - ); - if result.is_err() { - warn!("Sending verification failure failed"); - } - } - }, - Err(e) => { - if let Ok(custom_service) = CustomPusServiceId::try_from(e.number) { - match custom_service { - CustomPusServiceId::Mode => { - // TODO: Fix mode service. - //self.handle_mode_service(pus_tc, accepted_token) - } - CustomPusServiceId::Health => {} - } - } else { - self.verif_reporter - .start_failure( - accepted_token, - FailParams::new( - self.stamp_helper.stamp(), - &tmtc_err::INVALID_PUS_SUBSERVICE, - &[e.number], - ), - ) - .expect("Start failure verification failed") - } - } - } - Ok(PusPacketHandlerResult::RequestHandled) - } -} - #[cfg(test)] pub(crate) mod tests { use std::time::Duration; + use satrs::pus::test_util::TEST_COMPONENT_ID; + use satrs::pus::{MpscTmAsVecSender, PusTmAsVec, PusTmVariant}; use satrs::{ pus::{ - verification::{ - test_util::{SharedVerificationMap, TestVerificationReporter}, - VerificationReporterWithVecMpscSender, - }, - ActivePusRequestStd, ActiveRequestMapProvider, EcssTcInVecConverter, MpscTcReceiver, - TmAsVecSenderWithMpsc, + verification::test_util::TestVerificationReporter, ActivePusRequestStd, + ActiveRequestMapProvider, EcssTcInVecConverter, MpscTcReceiver, }, - request::TargetAndApidId, + request::UniqueApidTargetId, spacepackets::{ ecss::{ tc::{PusTcCreator, PusTcSecondaryHeader}, @@ -491,22 +483,18 @@ pub(crate) mod tests { use super::*; - pub const TEST_APID: u16 = 0x23; - pub const TEST_APID_TARGET_ID: u32 = 5; - pub const TARGET_ID: TargetAndApidId = TargetAndApidId::new(TEST_APID, TEST_APID_TARGET_ID); - // Testbench dedicated to the testing of [PusReplyHandler]s pub struct ReplyHandlerTestbench< ReplyHandler: PusReplyHandler, ActiveRequestInfo: ActiveRequestProvider, Reply, > { - pub shared_verif_map: SharedVerificationMap, + pub id: ComponentId, pub verif_reporter: TestVerificationReporter, pub reply_handler: ReplyHandler, - pub tm_receiver: mpsc::Receiver>, + pub tm_receiver: mpsc::Receiver, pub default_timeout: Duration, - tm_sender: TmAsVecSenderWithMpsc, + tm_sender: MpscTmAsVecSender, phantom: std::marker::PhantomData<(ActiveRequestInfo, Reply)>, } @@ -517,15 +505,14 @@ pub(crate) mod tests { > ReplyHandlerTestbench { pub fn new(reply_handler: ReplyHandler) -> Self { - let shared_verif_map = SharedVerificationMap::default(); - let test_verif_reporter = TestVerificationReporter::new(shared_verif_map.clone()); + let test_verif_reporter = TestVerificationReporter::default(); let (tm_sender, tm_receiver) = mpsc::channel(); Self { - shared_verif_map, + id: TEST_COMPONENT_ID.raw(), verif_reporter: test_verif_reporter, reply_handler, default_timeout: Duration::from_secs(30), - tm_sender: TmAsVecSenderWithMpsc::new(0, "TEST_SENDER", tm_sender), + tm_sender, tm_receiver, phantom: std::marker::PhantomData, } @@ -547,16 +534,16 @@ pub(crate) mod tests { )); let accepted = self .verif_reporter - .acceptance_success(init, time_stamp) + .acceptance_success(self.id, &self.tm_sender, init, time_stamp) .expect("acceptance failed"); let started = self .verif_reporter - .start_success(accepted, time_stamp) + .start_success(self.id, &self.tm_sender, accepted, time_stamp) .expect("start failed"); ( started.request_id(), ActivePusRequestStd::new( - TargetAndApidId::new(apid, apid_target).raw(), + UniqueApidTargetId::new(apid, apid_target).raw(), started, self.default_timeout, ), @@ -570,11 +557,12 @@ pub(crate) mod tests { time_stamp: &[u8], ) -> Result { self.reply_handler.handle_reply( + self.id, reply, active_request, + &self.tm_sender, &self.verif_reporter, time_stamp, - &self.tm_sender, ) } @@ -583,7 +571,32 @@ pub(crate) mod tests { reply: &GenericMessage, ) -> Result<(), ReplyHandler::Error> { self.reply_handler - .handle_unrequested_reply(reply, &self.tm_sender) + .handle_unrequested_reply(self.id, reply, &self.tm_sender) + } + pub fn handle_request_timeout( + &mut self, + active_request_info: &ActiveRequestInfo, + time_stamp: &[u8], + ) -> Result<(), ReplyHandler::Error> { + self.reply_handler.handle_request_timeout( + self.id, + active_request_info, + &self.tm_sender, + &self.verif_reporter, + time_stamp, + ) + } + } + + #[derive(Default)] + pub struct DummySender {} + + /// Dummy sender component which does nothing on the [Self::send_tm] call. + /// + /// Useful for unit tests. + impl EcssTmSenderCore for DummySender { + fn send_tm(&self, _source_id: ComponentId, _tm: PusTmVariant) -> Result<(), EcssTmtcError> { + Ok(()) } } @@ -593,9 +606,10 @@ pub(crate) mod tests { ActiveRequestInfo: ActiveRequestProvider, Request, > { - pub shared_verif_map: SharedVerificationMap, + pub id: ComponentId, pub verif_reporter: TestVerificationReporter, pub converter: Converter, + dummy_sender: DummySender, current_request_id: Option, current_packet: Option>, phantom: std::marker::PhantomData<(ActiveRequestInfo, Request)>, @@ -608,12 +622,12 @@ pub(crate) mod tests { > PusConverterTestbench { pub fn new(converter: Converter) -> Self { - let shared_verif_map = SharedVerificationMap::default(); - let test_verif_reporter = TestVerificationReporter::new(shared_verif_map.clone()); + let test_verif_reporter = TestVerificationReporter::default(); Self { - shared_verif_map, + id: TEST_COMPONENT_ID.raw(), verif_reporter: test_verif_reporter, converter, + dummy_sender: DummySender::default(), current_request_id: None, current_packet: None, phantom: std::marker::PhantomData, @@ -625,7 +639,7 @@ pub(crate) mod tests { self.current_request_id = Some(verification::RequestId::new(tc)); self.current_packet = Some(tc.to_vec().unwrap()); self.verif_reporter - .acceptance_success(token, &[]) + .acceptance_success(self.id, &self.dummy_sender, token, &[]) .expect("acceptance failed") } @@ -647,16 +661,21 @@ pub(crate) mod tests { } let current_packet = self.current_packet.take().unwrap(); let tc_reader = PusTcReader::new(¤t_packet).unwrap(); - let (active_info, request) = - self.converter - .convert(token, &tc_reader.0, time_stamp, &self.verif_reporter)?; + let (active_info, request) = self.converter.convert( + self.id, + token, + &tc_reader.0, + &self.dummy_sender, + &self.verif_reporter, + time_stamp, + )?; assert_eq!( active_info.token().request_id(), self.request_id().expect("no request id is set") ); assert_eq!( active_info.target_id(), - TargetAndApidId::new(expected_apid, expected_apid_target).raw() + UniqueApidTargetId::new(expected_apid, expected_apid_target).raw() ); Ok((active_info, request)) } @@ -672,9 +691,9 @@ pub(crate) mod tests { > { pub service: PusTargetedRequestService< MpscTcReceiver, - TmAsVecSenderWithMpsc, + MpscTmAsVecSender, EcssTcInVecConverter, - VerificationReporterWithVecMpscSender, + TestVerificationReporter, RequestConverter, ReplyHandler, ActiveRequestMap, @@ -682,8 +701,7 @@ pub(crate) mod tests { RequestType, ReplyType, >, - pub verif_reporter: VerificationReporterWithVecMpscSender, - pub tm_funnel_rx: mpsc::Receiver>, + pub tm_funnel_rx: mpsc::Receiver, pub pus_packet_tx: mpsc::Sender, pub reply_tx: mpsc::Sender>, pub request_rx: mpsc::Receiver>, diff --git a/satrs-example/src/pus/mode.rs b/satrs-example/src/pus/mode.rs index 4adcf68..6d1c1b1 100644 --- a/satrs-example/src/pus/mode.rs +++ b/satrs-example/src/pus/mode.rs @@ -1,5 +1,16 @@ +use log::{error, warn}; +use std::sync::mpsc; use std::time::Duration; +use crate::requests::GenericRequestRouter; +use satrs::pool::SharedStaticMemoryPool; +use satrs::pus::verification::VerificationReporter; +use satrs::pus::{ + DefaultActiveRequestMap, EcssTcAndToken, EcssTcInMemConverter, EcssTcInSharedStoreConverter, + EcssTcInVecConverter, MpscTcReceiver, MpscTmAsVecSender, MpscTmInSharedPoolSenderBounded, + PusPacketHandlerResult, PusServiceHelper, PusTmAsVec, PusTmInPool, TmInSharedPoolSender, +}; +use satrs::request::GenericMessage; use satrs::{ mode::{ModeAndSubmode, ModeReply, ModeRequest}, pus::{ @@ -9,9 +20,9 @@ use satrs::{ VerificationToken, }, ActivePusRequestStd, ActiveRequestProvider, EcssTmSenderCore, EcssTmtcError, - GenericConversionError, PusReplyHandler, PusTcToRequestConverter, PusTmWrapper, + GenericConversionError, PusReplyHandler, PusTcToRequestConverter, PusTmVariant, }, - request::TargetAndApidId, + request::UniqueApidTargetId, spacepackets::{ ecss::{ tc::PusTcReader, @@ -20,10 +31,15 @@ use satrs::{ }, SpHeader, }, + ComponentId, }; +use satrs_example::config::components::PUS_MODE_SERVICE; use satrs_example::config::{mode_err, tmtc_err}; -use super::generic_pus_request_timeout_handler; +use super::{ + create_verification_reporter, generic_pus_request_timeout_handler, PusTargetedRequestService, + TargetedPusService, +}; #[derive(Default)] pub struct ModeReplyHandler {} @@ -33,7 +49,8 @@ impl PusReplyHandler for ModeReplyHandler { fn handle_unrequested_reply( &mut self, - reply: &satrs::request::GenericMessage, + _caller_id: ComponentId, + reply: &GenericMessage, _tm_sender: &impl EcssTmSenderCore, ) -> Result<(), Self::Error> { log::warn!("received unexpected reply for mode service 5: {reply:?}"); @@ -42,30 +59,24 @@ impl PusReplyHandler for ModeReplyHandler { fn handle_reply( &mut self, - reply: &satrs::request::GenericMessage, + caller_id: ComponentId, + reply: &GenericMessage, active_request: &ActivePusRequestStd, + tm_sender: &impl EcssTmSenderCore, verification_handler: &impl VerificationReportingProvider, time_stamp: &[u8], - tm_sender: &impl EcssTmSenderCore, ) -> Result { let started_token: VerificationToken = active_request .token() .try_into() .expect("invalid token state"); match reply.message { - ModeReply::ModeInfo(info) => { - log::warn!( - "received unrequest mode information for active request {:?}: {:?}", - active_request, - info - ); - } ModeReply::ModeReply(mode_reply) => { let mut source_data: [u8; 12] = [0; 12]; mode_reply .write_to_be_bytes(&mut source_data) .expect("writing mode reply failed"); - let req_id = verification::RequestId::from(reply.request_id); + let req_id = verification::RequestId::from(reply.request_id()); let mut sp_header = SpHeader::tm_unseg(req_id.packet_id().apid(), 0, 0) .expect("generating SP header failed"); let sec_header = PusTmSecondaryHeader::new( @@ -76,18 +87,21 @@ impl PusReplyHandler for ModeReplyHandler { Some(time_stamp), ); let pus_tm = PusTmCreator::new(&mut sp_header, sec_header, &source_data, true); - tm_sender.send_tm(PusTmWrapper::Direct(pus_tm))?; - verification_handler - .completion_success(started_token, time_stamp) - .map_err(|e| e.0)?; + tm_sender.send_tm(caller_id, PusTmVariant::Direct(pus_tm))?; + verification_handler.completion_success( + caller_id, + tm_sender, + started_token, + time_stamp, + )?; } ModeReply::CantReachMode(error_code) => { - verification_handler - .completion_failure( - started_token, - FailParams::new(time_stamp, &error_code, &[]), - ) - .map_err(|e| e.0)?; + verification_handler.completion_failure( + caller_id, + tm_sender, + started_token, + FailParams::new(time_stamp, &error_code, &[]), + )?; } ModeReply::WrongMode { expected, reached } => { let mut error_info: [u8; 24] = [0; 24]; @@ -97,16 +111,16 @@ impl PusReplyHandler for ModeReplyHandler { written_len += reached .write_to_be_bytes(&mut error_info[ModeAndSubmode::RAW_LEN..]) .expect("writing reached mode failed"); - verification_handler - .completion_failure( - started_token, - FailParams::new( - time_stamp, - &mode_err::WRONG_MODE, - &error_info[..written_len], - ), - ) - .map_err(|e| e.0)?; + verification_handler.completion_failure( + caller_id, + tm_sender, + started_token, + FailParams::new( + time_stamp, + &mode_err::WRONG_MODE, + &error_info[..written_len], + ), + )?; } }; Ok(true) @@ -114,12 +128,15 @@ impl PusReplyHandler for ModeReplyHandler { fn handle_request_timeout( &mut self, + caller_id: ComponentId, active_request: &ActivePusRequestStd, + tm_sender: &impl EcssTmSenderCore, verification_handler: &impl VerificationReportingProvider, time_stamp: &[u8], - _tm_sender: &impl EcssTmSenderCore, ) -> Result<(), Self::Error> { generic_pus_request_timeout_handler( + caller_id, + tm_sender, active_request, verification_handler, time_stamp, @@ -137,16 +154,21 @@ impl PusTcToRequestConverter for ModeRequestCo fn convert( &mut self, + + caller_id: ComponentId, token: VerificationToken, tc: &PusTcReader, - time_stamp: &[u8], + tm_sender: &(impl EcssTmSenderCore + ?Sized), verif_reporter: &impl VerificationReportingProvider, + time_stamp: &[u8], ) -> Result<(ActivePusRequestStd, ModeRequest), Self::Error> { let subservice = tc.subservice(); let user_data = tc.user_data(); let not_enough_app_data = |expected: usize| { verif_reporter .start_failure( + caller_id, + tm_sender, token, FailParams::new_no_fail_data(time_stamp, &tmtc_err::NOT_ENOUGH_APP_DATA), ) @@ -159,7 +181,7 @@ impl PusTcToRequestConverter for ModeRequestCo if user_data.len() < core::mem::size_of::() { return not_enough_app_data(4); } - let target_id_and_apid = TargetAndApidId::from_pus_tc(tc).unwrap(); + let target_id_and_apid = UniqueApidTargetId::from_pus_tc(tc).unwrap(); let active_request = ActivePusRequestStd::new(target_id_and_apid.into(), token, Duration::from_secs(30)); let subservice_typed = Subservice::try_from(subservice); @@ -167,6 +189,8 @@ impl PusTcToRequestConverter for ModeRequestCo // Invalid subservice verif_reporter .start_failure( + caller_id, + tm_sender, token, FailParams::new_no_fail_data(time_stamp, &tmtc_err::INVALID_PUS_SUBSERVICE), ) @@ -196,8 +220,117 @@ impl PusTcToRequestConverter for ModeRequestCo } } +pub fn create_mode_service_static( + tm_sender: TmInSharedPoolSender>, + tc_pool: SharedStaticMemoryPool, + pus_action_rx: mpsc::Receiver, + mode_router: GenericRequestRouter, + reply_receiver: mpsc::Receiver>, +) -> ModeServiceWrapper { + let mode_request_handler = PusTargetedRequestService::new( + PusServiceHelper::new( + PUS_MODE_SERVICE.raw(), + pus_action_rx, + tm_sender, + create_verification_reporter(PUS_MODE_SERVICE.apid), + EcssTcInSharedStoreConverter::new(tc_pool, 2048), + ), + ModeRequestConverter::default(), + DefaultActiveRequestMap::default(), + ModeReplyHandler::default(), + mode_router, + reply_receiver, + ); + ModeServiceWrapper { + service: mode_request_handler, + } +} + +pub fn create_mode_service_dynamic( + tm_funnel_tx: mpsc::Sender, + pus_action_rx: mpsc::Receiver, + mode_router: GenericRequestRouter, + reply_receiver: mpsc::Receiver>, +) -> ModeServiceWrapper { + let mode_request_handler = PusTargetedRequestService::new( + PusServiceHelper::new( + PUS_MODE_SERVICE.raw(), + pus_action_rx, + tm_funnel_tx, + create_verification_reporter(PUS_MODE_SERVICE.apid), + EcssTcInVecConverter::default(), + ), + ModeRequestConverter::default(), + DefaultActiveRequestMap::default(), + ModeReplyHandler::default(), + mode_router, + reply_receiver, + ); + ModeServiceWrapper { + service: mode_request_handler, + } +} + +pub struct ModeServiceWrapper { + pub(crate) service: PusTargetedRequestService< + MpscTcReceiver, + TmSender, + TcInMemConverter, + VerificationReporter, + ModeRequestConverter, + ModeReplyHandler, + DefaultActiveRequestMap, + ActivePusRequestStd, + ModeRequest, + ModeReply, + >, +} + +impl TargetedPusService + for ModeServiceWrapper +{ + /// Returns [true] if the packet handling is finished. + fn poll_and_handle_next_tc(&mut self, time_stamp: &[u8]) -> bool { + match self.service.poll_and_handle_next_tc(time_stamp) { + Ok(result) => match result { + PusPacketHandlerResult::RequestHandled => {} + PusPacketHandlerResult::RequestHandledPartialSuccess(e) => { + warn!("PUS mode service: partial packet handling success: {e:?}") + } + PusPacketHandlerResult::CustomSubservice(invalid, _) => { + warn!("PUS mode service: invalid subservice {invalid}"); + } + PusPacketHandlerResult::SubserviceNotImplemented(subservice, _) => { + warn!("PUS mode service: {subservice} not implemented"); + } + PusPacketHandlerResult::Empty => { + return true; + } + }, + Err(error) => { + error!("PUS mode service: packet handling error: {error:?}") + } + } + false + } + + fn poll_and_handle_next_reply(&mut self, time_stamp: &[u8]) -> bool { + self.service + .poll_and_check_next_reply(time_stamp) + .unwrap_or_else(|e| { + warn!("PUS action service: Handling reply failed with error {e:?}"); + false + }) + } + + fn check_for_request_timeouts(&mut self) { + self.service.check_for_request_timeouts(); + } +} #[cfg(test)] mod tests { + use satrs::pus::test_util::{TEST_APID, TEST_COMPONENT_ID, TEST_UNIQUE_ID}; + use satrs::request::MessageMetadata; use satrs::{ mode::{ModeAndSubmode, ModeReply, ModeRequest}, pus::mode::Subservice, @@ -207,10 +340,11 @@ mod tests { SpHeader, }, }; + use satrs_example::config::tmtc_err; use crate::pus::{ mode::ModeReplyHandler, - tests::{PusConverterTestbench, ReplyHandlerTestbench, TEST_APID, TEST_APID_TARGET_ID}, + tests::{PusConverterTestbench, ReplyHandlerTestbench}, }; use super::ModeRequestConverter; @@ -221,11 +355,11 @@ mod tests { let mut sp_header = SpHeader::tc_unseg(TEST_APID, 0, 0).unwrap(); let sec_header = PusTcSecondaryHeader::new_simple(200, Subservice::TcReadMode as u8); let mut app_data: [u8; 4] = [0; 4]; - app_data[0..4].copy_from_slice(&TEST_APID_TARGET_ID.to_be_bytes()); + app_data[0..4].copy_from_slice(&TEST_UNIQUE_ID.to_be_bytes()); let tc = PusTcCreator::new(&mut sp_header, sec_header, &app_data, true); let token = testbench.add_tc(&tc); let (_active_req, req) = testbench - .convert(token, &[], TEST_APID, TEST_APID_TARGET_ID) + .convert(token, &[], TEST_APID, TEST_UNIQUE_ID) .expect("conversion has failed"); assert_eq!(req, ModeRequest::ReadMode); } @@ -237,14 +371,14 @@ mod tests { let sec_header = PusTcSecondaryHeader::new_simple(200, Subservice::TcSetMode as u8); let mut app_data: [u8; 4 + ModeAndSubmode::RAW_LEN] = [0; 4 + ModeAndSubmode::RAW_LEN]; let mode_and_submode = ModeAndSubmode::new(2, 1); - app_data[0..4].copy_from_slice(&TEST_APID_TARGET_ID.to_be_bytes()); + app_data[0..4].copy_from_slice(&TEST_UNIQUE_ID.to_be_bytes()); mode_and_submode .write_to_be_bytes(&mut app_data[4..]) .unwrap(); let tc = PusTcCreator::new(&mut sp_header, sec_header, &app_data, true); let token = testbench.add_tc(&tc); let (_active_req, req) = testbench - .convert(token, &[], TEST_APID, TEST_APID_TARGET_ID) + .convert(token, &[], TEST_APID, TEST_UNIQUE_ID) .expect("conversion has failed"); assert_eq!(req, ModeRequest::SetMode(mode_and_submode)); } @@ -255,11 +389,11 @@ mod tests { let mut sp_header = SpHeader::tc_unseg(TEST_APID, 0, 0).unwrap(); let sec_header = PusTcSecondaryHeader::new_simple(200, Subservice::TcAnnounceMode as u8); let mut app_data: [u8; 4] = [0; 4]; - app_data[0..4].copy_from_slice(&TEST_APID_TARGET_ID.to_be_bytes()); + app_data[0..4].copy_from_slice(&TEST_UNIQUE_ID.to_be_bytes()); let tc = PusTcCreator::new(&mut sp_header, sec_header, &app_data, true); let token = testbench.add_tc(&tc); let (_active_req, req) = testbench - .convert(token, &[], TEST_APID, TEST_APID_TARGET_ID) + .convert(token, &[], TEST_APID, TEST_UNIQUE_ID) .expect("conversion has failed"); assert_eq!(req, ModeRequest::AnnounceMode); } @@ -271,11 +405,11 @@ mod tests { let sec_header = PusTcSecondaryHeader::new_simple(200, Subservice::TcAnnounceModeRecursive as u8); let mut app_data: [u8; 4] = [0; 4]; - app_data[0..4].copy_from_slice(&TEST_APID_TARGET_ID.to_be_bytes()); + app_data[0..4].copy_from_slice(&TEST_UNIQUE_ID.to_be_bytes()); let tc = PusTcCreator::new(&mut sp_header, sec_header, &app_data, true); let token = testbench.add_tc(&tc); let (_active_req, req) = testbench - .convert(token, &[], TEST_APID, TEST_APID_TARGET_ID) + .convert(token, &[], TEST_APID, TEST_UNIQUE_ID) .expect("conversion has failed"); assert_eq!(req, ModeRequest::AnnounceModeRecursive); } @@ -283,8 +417,9 @@ mod tests { #[test] fn reply_handling_unrequested_reply() { let mut testbench = ReplyHandlerTestbench::new(ModeReplyHandler::default()); - let mode_reply = ModeReply::ModeInfo(ModeAndSubmode::new(5, 1)); - let unrequested_reply = GenericMessage::new(10_u32, 15_u64, mode_reply); + let mode_reply = ModeReply::ModeReply(ModeAndSubmode::new(5, 1)); + let unrequested_reply = + GenericMessage::new(MessageMetadata::new(10_u32, 15_u64), mode_reply); // Right now this function does not do a lot. We simply check that it does not panic or do // weird stuff. let result = testbench.handle_unrequested_reply(&unrequested_reply); @@ -294,9 +429,14 @@ mod tests { #[test] fn reply_handling_reply_timeout() { let mut testbench = ReplyHandlerTestbench::new(ModeReplyHandler::default()); - // TODO: Start a request, then time it out with the API and check verification completion - // failure. - // testbench.reply_handler.handle_request_timeout(active_request, verification_handler, time_stamp, tm_sender) - // testbench.default_timeout = Duration::from_millis(50); + let (req_id, active_request) = testbench.add_tc(TEST_APID, TEST_UNIQUE_ID, &[]); + let result = testbench.handle_request_timeout(&active_request, &[]); + assert!(result.is_ok()); + testbench.verif_reporter.assert_completion_failure( + TEST_COMPONENT_ID.raw(), + req_id, + None, + tmtc_err::REQUEST_TIMEOUT.raw() as u64, + ); } } diff --git a/satrs-example/src/pus/scheduler.rs b/satrs-example/src/pus/scheduler.rs index c47849a..c80574e 100644 --- a/satrs-example/src/pus/scheduler.rs +++ b/satrs-example/src/pus/scheduler.rs @@ -1,23 +1,18 @@ use std::sync::mpsc; use std::time::Duration; +use crate::pus::create_verification_reporter; use log::{error, info, warn}; -use satrs::pool::{PoolProvider, StaticMemoryPool, StoreAddr}; +use satrs::pool::{PoolProvider, StaticMemoryPool}; use satrs::pus::scheduler::{PusScheduler, TcInfo}; -use satrs::pus::scheduler_srv::PusService11SchedHandler; -use satrs::pus::verification::std_mod::{ - VerificationReporterWithSharedPoolMpscBoundedSender, VerificationReporterWithVecMpscSender, -}; -use satrs::pus::verification::VerificationReportingProvider; +use satrs::pus::scheduler_srv::PusSchedServiceHandler; +use satrs::pus::verification::VerificationReporter; use satrs::pus::{ EcssTcAndToken, EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter, - EcssTcReceiverCore, EcssTmSenderCore, MpscTcReceiver, PusPacketHandlerResult, PusServiceHelper, - TmAsVecSenderWithId, TmAsVecSenderWithMpsc, TmInSharedPoolSenderWithBoundedMpsc, - TmInSharedPoolSenderWithId, + EcssTmSenderCore, MpscTcReceiver, MpscTmAsVecSender, MpscTmInSharedPoolSenderBounded, + PusPacketHandlerResult, PusServiceHelper, PusTmAsVec, PusTmInPool, TmInSharedPoolSender, }; -use satrs::tmtc::tm_helper::SharedTmPool; -use satrs::ComponentId; -use satrs_example::config::{ComponentIdList, PUS_APID}; +use satrs_example::config::components::PUS_SCHED_SERVICE; use crate::tmtc::PusTcSourceProviderSharedPool; @@ -55,14 +50,12 @@ impl TcReleaser for mpsc::Sender> { } } -pub struct Pus11Wrapper< - TcReceiver: EcssTcReceiverCore, +pub struct SchedulingServiceWrapper< TmSender: EcssTmSenderCore, TcInMemConverter: EcssTcInMemConverter, - VerificationReporter: VerificationReportingProvider, > { - pub pus_11_handler: PusService11SchedHandler< - TcReceiver, + pub pus_11_handler: PusSchedServiceHandler< + MpscTcReceiver, TmSender, TcInMemConverter, VerificationReporter, @@ -73,12 +66,8 @@ pub struct Pus11Wrapper< pub tc_releaser: Box, } -impl< - TcReceiver: EcssTcReceiverCore, - TmSender: EcssTmSenderCore, - TcInMemConverter: EcssTcInMemConverter, - VerificationReporter: VerificationReportingProvider, - > Pus11Wrapper +impl + SchedulingServiceWrapper { pub fn release_tcs(&mut self) { let releaser = |enabled: bool, info: &TcInfo, tc: &[u8]| -> bool { @@ -132,42 +121,24 @@ impl< } pub fn create_scheduler_service_static( - shared_tm_store: SharedTmPool, - tm_funnel_tx: mpsc::SyncSender, - verif_reporter: VerificationReporterWithSharedPoolMpscBoundedSender, + tm_sender: TmInSharedPoolSender>, tc_releaser: PusTcSourceProviderSharedPool, pus_sched_rx: mpsc::Receiver, sched_tc_pool: StaticMemoryPool, -) -> Pus11Wrapper< - MpscTcReceiver, - TmInSharedPoolSenderWithBoundedMpsc, - EcssTcInSharedStoreConverter, - VerificationReporterWithSharedPoolMpscBoundedSender, -> { - let sched_srv_tm_sender = TmInSharedPoolSenderWithId::new( - ComponentIdList::PusSched as ComponentId, - "PUS_11_TM_SENDER", - shared_tm_store.clone(), - tm_funnel_tx.clone(), - ); - let sched_srv_receiver = MpscTcReceiver::new( - ComponentIdList::PusSched as ComponentId, - "PUS_11_TC_RECV", - pus_sched_rx, - ); +) -> SchedulingServiceWrapper { let scheduler = PusScheduler::new_with_current_init_time(Duration::from_secs(5)) .expect("Creating PUS Scheduler failed"); - let pus_11_handler = PusService11SchedHandler::new( + let pus_11_handler = PusSchedServiceHandler::new( PusServiceHelper::new( - sched_srv_receiver, - sched_srv_tm_sender, - PUS_APID, - verif_reporter.clone(), + PUS_SCHED_SERVICE.raw(), + pus_sched_rx, + tm_sender, + create_verification_reporter(PUS_SCHED_SERVICE.apid), EcssTcInSharedStoreConverter::new(tc_releaser.clone_backing_pool(), 2048), ), scheduler, ); - Pus11Wrapper { + SchedulingServiceWrapper { pus_11_handler, sched_tc_pool, releaser_buf: [0; 4096], @@ -176,40 +147,26 @@ pub fn create_scheduler_service_static( } pub fn create_scheduler_service_dynamic( - tm_funnel_tx: mpsc::Sender>, - verif_reporter: VerificationReporterWithVecMpscSender, + tm_funnel_tx: mpsc::Sender, tc_source_sender: mpsc::Sender>, pus_sched_rx: mpsc::Receiver, sched_tc_pool: StaticMemoryPool, -) -> Pus11Wrapper< - MpscTcReceiver, - TmAsVecSenderWithMpsc, - EcssTcInVecConverter, - VerificationReporterWithVecMpscSender, -> { - let sched_srv_tm_sender = TmAsVecSenderWithId::new( - ComponentIdList::PusSched as ComponentId, - "PUS_11_TM_SENDER", - tm_funnel_tx, - ); - let sched_srv_receiver = MpscTcReceiver::new( - ComponentIdList::PusSched as ComponentId, - "PUS_11_TC_RECV", - pus_sched_rx, - ); +) -> SchedulingServiceWrapper { + //let sched_srv_receiver = + //MpscTcReceiver::new(PUS_SCHED_SERVICE.raw(), "PUS_11_TC_RECV", pus_sched_rx); let scheduler = PusScheduler::new_with_current_init_time(Duration::from_secs(5)) .expect("Creating PUS Scheduler failed"); - let pus_11_handler = PusService11SchedHandler::new( + let pus_11_handler = PusSchedServiceHandler::new( PusServiceHelper::new( - sched_srv_receiver, - sched_srv_tm_sender, - PUS_APID, - verif_reporter.clone(), + PUS_SCHED_SERVICE.raw(), + pus_sched_rx, + tm_funnel_tx, + create_verification_reporter(PUS_SCHED_SERVICE.apid), EcssTcInVecConverter::default(), ), scheduler, ); - Pus11Wrapper { + SchedulingServiceWrapper { pus_11_handler, sched_tc_pool, releaser_buf: [0; 4096], diff --git a/satrs-example/src/pus/stack.rs b/satrs-example/src/pus/stack.rs index 1d3f667..96ca438 100644 --- a/satrs-example/src/pus/stack.rs +++ b/satrs-example/src/pus/stack.rs @@ -1,62 +1,33 @@ +use crate::pus::mode::ModeServiceWrapper; +use derive_new::new; use satrs::{ - pus::{ - verification::VerificationReportingProvider, EcssTcInMemConverter, EcssTcReceiverCore, - EcssTmSenderCore, - }, + pus::{EcssTcInMemConverter, EcssTmSenderCore}, spacepackets::time::{cds, TimeWriter}, }; use super::{ - action::Pus8Wrapper, event::Pus5Wrapper, hk::Pus3Wrapper, scheduler::Pus11Wrapper, - test::Service17CustomWrapper, TargetedPusService, + action::ActionServiceWrapper, event::EventServiceWrapper, hk::HkServiceWrapper, + scheduler::SchedulingServiceWrapper, test::TestCustomServiceWrapper, TargetedPusService, }; -pub struct PusStack< - TcReceiver: EcssTcReceiverCore, - TmSender: EcssTmSenderCore, - TcInMemConverter: EcssTcInMemConverter, - VerificationReporter: VerificationReportingProvider, -> { - event_srv: Pus5Wrapper, - hk_srv_wrapper: Pus3Wrapper, - action_srv_wrapper: Pus8Wrapper, - schedule_srv: Pus11Wrapper, - test_srv: Service17CustomWrapper, +#[derive(new)] +pub struct PusStack { + test_srv: TestCustomServiceWrapper, + hk_srv_wrapper: HkServiceWrapper, + event_srv: EventServiceWrapper, + action_srv_wrapper: ActionServiceWrapper, + schedule_srv: SchedulingServiceWrapper, + mode_srv: ModeServiceWrapper, } -impl< - TcReceiver: EcssTcReceiverCore, - TmSender: EcssTmSenderCore, - TcInMemConverter: EcssTcInMemConverter, - VerificationReporter: VerificationReportingProvider, - > PusStack +impl + PusStack { - pub fn new( - hk_srv: Pus3Wrapper, - event_srv: Pus5Wrapper, - action_srv: Pus8Wrapper, - schedule_srv: Pus11Wrapper, - test_srv: Service17CustomWrapper< - TcReceiver, - TmSender, - TcInMemConverter, - VerificationReporter, - >, - ) -> Self { - Self { - event_srv, - action_srv_wrapper: action_srv, - schedule_srv, - test_srv, - hk_srv_wrapper: hk_srv, - } - } - pub fn periodic_operation(&mut self) { // Release all telecommands which reached their release time before calling the service // handlers. self.schedule_srv.release_tcs(); - let time_stamp = cds::TimeProvider::from_now_with_u16_days() + let time_stamp = cds::CdsTime::now_with_u16_days() .expect("time stamp generation error") .to_vec() .unwrap(); @@ -84,10 +55,15 @@ impl< self.hk_srv_wrapper.poll_and_handle_next_tc(&time_stamp), Some(self.hk_srv_wrapper.poll_and_handle_next_reply(&time_stamp)), ); + is_srv_finished( + self.mode_srv.poll_and_handle_next_tc(&time_stamp), + Some(self.mode_srv.poll_and_handle_next_reply(&time_stamp)), + ); if nothing_to_do { // Timeout checking is only done once. self.action_srv_wrapper.check_for_request_timeouts(); self.hk_srv_wrapper.check_for_request_timeouts(); + self.mode_srv.check_for_request_timeouts(); break; } } diff --git a/satrs-example/src/pus/test.rs b/satrs-example/src/pus/test.rs index ea2eb89..a42a250 100644 --- a/satrs-example/src/pus/test.rs +++ b/satrs-example/src/pus/test.rs @@ -1,115 +1,71 @@ +use crate::pus::create_verification_reporter; use log::{info, warn}; use satrs::params::Params; -use satrs::pool::{SharedStaticMemoryPool, StoreAddr}; +use satrs::pool::SharedStaticMemoryPool; use satrs::pus::test::PusService17TestHandler; -use satrs::pus::verification::{FailParams, VerificationReportingProvider}; -use satrs::pus::verification::{ - VerificationReporterWithSharedPoolMpscBoundedSender, VerificationReporterWithVecMpscSender, -}; +use satrs::pus::verification::{FailParams, VerificationReporter, VerificationReportingProvider}; use satrs::pus::{ - EcssTcAndToken, EcssTcInMemConverter, EcssTcInVecConverter, EcssTcReceiverCore, - EcssTmSenderCore, MpscTcReceiver, PusPacketHandlerResult, PusServiceHelper, - TmAsVecSenderWithId, TmAsVecSenderWithMpsc, TmInSharedPoolSenderWithBoundedMpsc, - TmInSharedPoolSenderWithId, + EcssTcAndToken, EcssTcInMemConverter, EcssTcInVecConverter, EcssTmSenderCore, MpscTcReceiver, + MpscTmAsVecSender, MpscTmInSharedPoolSenderBounded, PusPacketHandlerResult, PusServiceHelper, + PusTmAsVec, PusTmInPool, TmInSharedPoolSender, }; use satrs::spacepackets::ecss::tc::PusTcReader; use satrs::spacepackets::ecss::PusPacket; -use satrs::spacepackets::time::cds::TimeProvider; +use satrs::spacepackets::time::cds::CdsTime; use satrs::spacepackets::time::TimeWriter; -use satrs::tmtc::tm_helper::SharedTmPool; -use satrs::ComponentId; use satrs::{events::EventU32, pus::EcssTcInSharedStoreConverter}; -use satrs_example::config::{tmtc_err, ComponentIdList, PUS_APID, TEST_EVENT}; -use std::sync::mpsc::{self, Sender}; +use satrs_example::config::components::PUS_TEST_SERVICE; +use satrs_example::config::{tmtc_err, TEST_EVENT}; +use std::sync::mpsc; pub fn create_test_service_static( - shared_tm_store: SharedTmPool, - tm_funnel_tx: mpsc::SyncSender, - verif_reporter: VerificationReporterWithSharedPoolMpscBoundedSender, + tm_sender: TmInSharedPoolSender>, tc_pool: SharedStaticMemoryPool, event_sender: mpsc::Sender<(EventU32, Option)>, pus_test_rx: mpsc::Receiver, -) -> Service17CustomWrapper< - MpscTcReceiver, - TmInSharedPoolSenderWithBoundedMpsc, - EcssTcInSharedStoreConverter, - VerificationReporterWithSharedPoolMpscBoundedSender, -> { - let test_srv_tm_sender = TmInSharedPoolSenderWithId::new( - ComponentIdList::PusTest as ComponentId, - "PUS_17_TM_SENDER", - shared_tm_store.clone(), - tm_funnel_tx.clone(), - ); - let test_srv_receiver = MpscTcReceiver::new( - ComponentIdList::PusTest as ComponentId, - "PUS_17_TC_RECV", - pus_test_rx, - ); +) -> TestCustomServiceWrapper { let pus17_handler = PusService17TestHandler::new(PusServiceHelper::new( - test_srv_receiver, - test_srv_tm_sender, - PUS_APID, - verif_reporter.clone(), + PUS_TEST_SERVICE.raw(), + pus_test_rx, + tm_sender, + create_verification_reporter(PUS_TEST_SERVICE.apid), EcssTcInSharedStoreConverter::new(tc_pool, 2048), )); - Service17CustomWrapper { + TestCustomServiceWrapper { handler: pus17_handler, test_srv_event_sender: event_sender, } } pub fn create_test_service_dynamic( - tm_funnel_tx: mpsc::Sender>, - verif_reporter: VerificationReporterWithVecMpscSender, + tm_funnel_tx: mpsc::Sender, event_sender: mpsc::Sender<(EventU32, Option)>, pus_test_rx: mpsc::Receiver, -) -> Service17CustomWrapper< - MpscTcReceiver, - TmAsVecSenderWithMpsc, - EcssTcInVecConverter, - VerificationReporterWithVecMpscSender, -> { - let test_srv_tm_sender = TmAsVecSenderWithId::new( - ComponentIdList::PusTest as ComponentId, - "PUS_17_TM_SENDER", - tm_funnel_tx.clone(), - ); - let test_srv_receiver = MpscTcReceiver::new( - ComponentIdList::PusTest as ComponentId, - "PUS_17_TC_RECV", - pus_test_rx, - ); +) -> TestCustomServiceWrapper { let pus17_handler = PusService17TestHandler::new(PusServiceHelper::new( - test_srv_receiver, - test_srv_tm_sender, - PUS_APID, - verif_reporter.clone(), + PUS_TEST_SERVICE.raw(), + pus_test_rx, + tm_funnel_tx, + create_verification_reporter(PUS_TEST_SERVICE.apid), EcssTcInVecConverter::default(), )); - Service17CustomWrapper { + TestCustomServiceWrapper { handler: pus17_handler, test_srv_event_sender: event_sender, } } -pub struct Service17CustomWrapper< - TcReceiver: EcssTcReceiverCore, +pub struct TestCustomServiceWrapper< TmSender: EcssTmSenderCore, TcInMemConverter: EcssTcInMemConverter, - VerificationReporter: VerificationReportingProvider, > { pub handler: - PusService17TestHandler, - pub test_srv_event_sender: Sender<(EventU32, Option)>, + PusService17TestHandler, + pub test_srv_event_sender: mpsc::Sender<(EventU32, Option)>, } -impl< - TcReceiver: EcssTcReceiverCore, - TmSender: EcssTmSenderCore, - TcInMemConverter: EcssTcInMemConverter, - VerificationReporter: VerificationReportingProvider, - > Service17CustomWrapper +impl + TestCustomServiceWrapper { pub fn poll_and_handle_next_packet(&mut self, time_stamp: &[u8]) -> bool { let res = self.handler.poll_and_handle_next_tc(time_stamp); @@ -139,7 +95,7 @@ impl< .tc_slice_raw(), ) .unwrap(); - let time_stamper = TimeProvider::from_now_with_u16_days().unwrap(); + let time_stamper = CdsTime::now_with_u16_days().unwrap(); let mut stamp_buf: [u8; 7] = [0; 7]; time_stamper.write_to_bytes(&mut stamp_buf).unwrap(); if subservice == 128 { @@ -151,12 +107,22 @@ impl< .handler .service_helper .verif_reporter() - .start_success(token, &stamp_buf) + .start_success( + self.handler.service_helper.common.id, + self.handler.service_helper.tm_sender(), + token, + &stamp_buf, + ) .expect("Error sending start success"); self.handler .service_helper .verif_reporter() - .completion_success(start_token, &stamp_buf) + .completion_success( + self.handler.service_helper.id(), + self.handler.service_helper.tm_sender(), + start_token, + &stamp_buf, + ) .expect("Error sending completion success"); } else { let fail_data = [tc.subservice()]; @@ -164,6 +130,8 @@ impl< .service_helper .verif_reporter() .start_failure( + self.handler.service_helper.id(), + self.handler.service_helper.tm_sender(), token, FailParams::new( &stamp_buf, diff --git a/satrs-example/src/requests.rs b/satrs-example/src/requests.rs index d4a31bb..1fa6f5d 100644 --- a/satrs-example/src/requests.rs +++ b/satrs-example/src/requests.rs @@ -4,15 +4,17 @@ use std::sync::mpsc; use log::warn; use satrs::action::ActionRequest; use satrs::hk::HkRequest; +use satrs::mode::ModeRequest; use satrs::pus::verification::{ FailParams, TcStateAccepted, VerificationReportingProvider, VerificationToken, }; -use satrs::pus::{ActiveRequestProvider, GenericRoutingError, PusRequestRouter}; +use satrs::pus::{ActiveRequestProvider, EcssTmSenderCore, GenericRoutingError, PusRequestRouter}; use satrs::queue::GenericSendError; -use satrs::request::{GenericMessage, RequestId}; +use satrs::request::{GenericMessage, MessageMetadata}; use satrs::spacepackets::ecss::tc::PusTcReader; use satrs::spacepackets::ecss::PusPacket; use satrs::ComponentId; +use satrs_example::config::components::PUS_ROUTING_SERVICE; use satrs_example::config::tmtc_err; #[derive(Clone, Debug)] @@ -22,19 +24,32 @@ pub enum CompositeRequest { Action(ActionRequest), } -#[derive(Default, Clone)] -pub struct GenericRequestRouter( - pub HashMap>>, -); +#[derive(Clone)] +pub struct GenericRequestRouter { + pub id: ComponentId, + // All messages which do not have a dedicated queue. + pub composite_router_map: HashMap>>, + pub mode_router_map: HashMap>>, +} +impl Default for GenericRequestRouter { + fn default() -> Self { + Self { + id: PUS_ROUTING_SERVICE.raw(), + composite_router_map: Default::default(), + mode_router_map: Default::default(), + } + } +} impl GenericRequestRouter { pub(crate) fn handle_error_generic( &self, active_request: &impl ActiveRequestProvider, tc: &PusTcReader, error: GenericRoutingError, - time_stamp: &[u8], + tm_sender: &(impl EcssTmSenderCore + ?Sized), verif_reporter: &impl VerificationReportingProvider, + time_stamp: &[u8], ) { warn!( "Routing request for service {} failed: {error:?}", @@ -50,6 +65,8 @@ impl GenericRequestRouter { fail_data.copy_from_slice(&id.to_be_bytes()); verif_reporter .completion_failure( + self.id, + tm_sender, accepted_token, FailParams::new(time_stamp, &tmtc_err::UNKNOWN_TARGET_ID, &fail_data), ) @@ -60,6 +77,8 @@ impl GenericRequestRouter { fail_data.copy_from_slice(&active_request.target_id().to_be_bytes()); verif_reporter .completion_failure( + self.id, + tm_sender, accepted_token, FailParams::new(time_stamp, &tmtc_err::ROUTING_ERROR, &fail_data), ) @@ -73,16 +92,14 @@ impl PusRequestRouter for GenericRequestRouter { fn route( &self, - request_id: RequestId, - source_id: ComponentId, + requestor_info: MessageMetadata, target_id: ComponentId, hk_request: HkRequest, ) -> Result<(), Self::Error> { - if let Some(sender) = self.0.get(&target_id) { + if let Some(sender) = self.composite_router_map.get(&target_id) { sender .send(GenericMessage::new( - request_id, - source_id, + requestor_info, CompositeRequest::Hk(hk_request), )) .map_err(|_| GenericRoutingError::Send(GenericSendError::RxDisconnected))?; @@ -97,16 +114,14 @@ impl PusRequestRouter for GenericRequestRouter { fn route( &self, - request_id: RequestId, - source_id: ComponentId, + requestor_info: MessageMetadata, target_id: ComponentId, action_request: ActionRequest, ) -> Result<(), Self::Error> { - if let Some(sender) = self.0.get(&target_id) { + if let Some(sender) = self.composite_router_map.get(&target_id) { sender .send(GenericMessage::new( - request_id, - source_id, + requestor_info, CompositeRequest::Action(action_request), )) .map_err(|_| GenericRoutingError::Send(GenericSendError::RxDisconnected))?; @@ -115,3 +130,22 @@ impl PusRequestRouter for GenericRequestRouter { Err(GenericRoutingError::UnknownTargetId(target_id)) } } + +impl PusRequestRouter for GenericRequestRouter { + type Error = GenericRoutingError; + + fn route( + &self, + requestor_info: MessageMetadata, + target_id: ComponentId, + request: ModeRequest, + ) -> Result<(), Self::Error> { + if let Some(sender) = self.mode_router_map.get(&target_id) { + sender + .send(GenericMessage::new(requestor_info, request)) + .map_err(|_| GenericRoutingError::Send(GenericSendError::RxDisconnected))?; + return Ok(()); + } + Err(GenericRoutingError::UnknownTargetId(target_id)) + } +} diff --git a/satrs-example/src/tcp.rs b/satrs-example/src/tcp.rs index 014f300..561a030 100644 --- a/satrs-example/src/tcp.rs +++ b/satrs-example/src/tcp.rs @@ -10,11 +10,16 @@ use satrs::{ spacepackets::PacketId, tmtc::{CcsdsDistributor, CcsdsError, ReceivesCcsdsTc, TmPacketSourceCore}, }; -use satrs_example::config::PUS_APID; +use satrs_example::config::components; use crate::ccsds::CcsdsReceiver; -pub const PACKET_ID_LOOKUP: &[PacketId] = &[PacketId::const_tc(true, PUS_APID)]; +pub const PACKET_ID_LOOKUP: &[PacketId] = &[ + PacketId::const_tc(true, components::Apid::GenericPus as u16), + PacketId::const_tc(true, components::Apid::EventTm as u16), + PacketId::const_tc(true, components::Apid::Acs as u16), + PacketId::const_tc(true, components::Apid::Sched as u16), +]; #[derive(Default, Clone)] pub struct SyncTcpTmSource { diff --git a/satrs-example/src/tm_funnel.rs b/satrs-example/src/tm_funnel.rs index 8b6285f..61cddd1 100644 --- a/satrs-example/src/tm_funnel.rs +++ b/satrs-example/src/tm_funnel.rs @@ -4,8 +4,9 @@ use std::{ }; use log::info; +use satrs::pus::{PusTmAsVec, PusTmInPool}; use satrs::{ - pool::{PoolProvider, StoreAddr}, + pool::PoolProvider, seq_count::{CcsdsSimpleSeqCountProvider, SequenceCountProviderCore}, spacepackets::{ ecss::{tm::PusTmZeroCopyWriter, PusPacket}, @@ -77,16 +78,16 @@ impl TmFunnelCommon { pub struct TmFunnelStatic { common: TmFunnelCommon, shared_tm_store: SharedTmPool, - tm_funnel_rx: mpsc::Receiver, - tm_server_tx: mpsc::SyncSender, + 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: mpsc::Receiver, - tm_server_tx: mpsc::SyncSender, + tm_funnel_rx: mpsc::Receiver, + tm_server_tx: mpsc::SyncSender, ) -> Self { Self { common: TmFunnelCommon::new(sync_tm_tcp_source), @@ -97,14 +98,14 @@ impl TmFunnelStatic { } pub fn operation(&mut self) { - if let Ok(addr) = self.tm_funnel_rx.recv() { + if let Ok(pus_tm_in_pool) = self.tm_funnel_rx.recv() { // Read the TM, set sequence counter and message counter, and finally update // the CRC. let shared_pool = self.shared_tm_store.clone_backing_pool(); let mut pool_guard = shared_pool.write().expect("Locking TM pool failed"); let mut tm_copy = Vec::new(); pool_guard - .modify(&addr, |buf| { + .modify(&pus_tm_in_pool.store_addr, |buf| { let zero_copy_writer = PusTmZeroCopyWriter::new(buf, MIN_CDS_FIELD_LEN) .expect("Creating TM zero copy writer failed"); self.common.apply_packet_processing(zero_copy_writer); @@ -112,7 +113,7 @@ impl TmFunnelStatic { }) .expect("Reading TM from pool failed"); self.tm_server_tx - .send(addr) + .send(pus_tm_in_pool) .expect("Sending TM to server failed"); // We could also do this step in the update closure, but I'd rather avoid this, could // lead to nested locking. @@ -123,15 +124,15 @@ impl TmFunnelStatic { pub struct TmFunnelDynamic { common: TmFunnelCommon, - tm_funnel_rx: mpsc::Receiver>, - tm_server_tx: mpsc::Sender>, + tm_funnel_rx: mpsc::Receiver, + tm_server_tx: mpsc::Sender, } impl TmFunnelDynamic { pub fn new( sync_tm_tcp_source: SyncTcpTmSource, - tm_funnel_rx: mpsc::Receiver>, - tm_server_tx: mpsc::Sender>, + tm_funnel_rx: mpsc::Receiver, + tm_server_tx: mpsc::Sender, ) -> Self { Self { common: TmFunnelCommon::new(sync_tm_tcp_source), @@ -144,13 +145,13 @@ impl TmFunnelDynamic { if let Ok(mut tm) = self.tm_funnel_rx.recv() { // Read the TM, set sequence counter and message counter, and finally update // the CRC. - let zero_copy_writer = PusTmZeroCopyWriter::new(&mut tm, MIN_CDS_FIELD_LEN) + let zero_copy_writer = PusTmZeroCopyWriter::new(&mut tm.packet, MIN_CDS_FIELD_LEN) .expect("Creating TM zero copy writer failed"); self.common.apply_packet_processing(zero_copy_writer); + self.common.sync_tm_tcp_source.add_tm(&tm.packet); self.tm_server_tx - .send(tm.clone()) + .send(tm) .expect("Sending TM to server failed"); - self.common.sync_tm_tcp_source.add_tm(&tm); } } } diff --git a/satrs-example/src/tmtc.rs b/satrs-example/src/tmtc.rs index 0a43504..43d5889 100644 --- a/satrs-example/src/tmtc.rs +++ b/satrs-example/src/tmtc.rs @@ -1,8 +1,7 @@ use log::warn; -use satrs::pus::verification::std_mod::{ - VerificationReporterWithSharedPoolMpscBoundedSender, VerificationReporterWithVecMpscSender, +use satrs::pus::{ + EcssTcAndToken, MpscTmAsVecSender, MpscTmInSharedPoolSenderBounded, ReceivesEcssPusTc, }; -use satrs::pus::{EcssTcAndToken, ReceivesEcssPusTc}; use satrs::spacepackets::SpHeader; use std::sync::mpsc::{self, Receiver, SendError, Sender, SyncSender, TryRecvError}; use thiserror::Error; @@ -100,14 +99,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, @@ -164,13 +163,13 @@ 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, + pus_receiver: PusReceiver, ) -> Self { Self { tc_receiver, diff --git a/satrs-example/src/udp.rs b/satrs-example/src/udp.rs index b6d1f6b..c2f26fa 100644 --- a/satrs-example/src/udp.rs +++ b/satrs-example/src/udp.rs @@ -1,12 +1,11 @@ -use std::{ - net::{SocketAddr, UdpSocket}, - sync::mpsc::Receiver, -}; +use std::net::{SocketAddr, UdpSocket}; +use std::sync::mpsc; use log::{info, warn}; +use satrs::pus::{PusTmAsVec, PusTmInPool}; use satrs::{ hal::std::udp_server::{ReceiveResult, UdpTcServer}, - pool::{PoolProviderWithGuards, SharedStaticMemoryPool, StoreAddr}, + pool::{PoolProviderWithGuards, SharedStaticMemoryPool}, tmtc::CcsdsError, }; @@ -15,20 +14,20 @@ pub trait UdpTmHandler { } pub struct StaticUdpTmHandler { - pub tm_rx: Receiver, + pub tm_rx: mpsc::Receiver, pub tm_store: SharedStaticMemoryPool, } impl UdpTmHandler for StaticUdpTmHandler { fn send_tm_to_udp_client(&mut self, socket: &UdpSocket, &recv_addr: &SocketAddr) { - while let Ok(addr) = self.tm_rx.try_recv() { + while let Ok(pus_tm_in_pool) = self.tm_rx.try_recv() { let store_lock = self.tm_store.write(); if store_lock.is_err() { warn!("Locking TM store failed"); continue; } let mut store_lock = store_lock.unwrap(); - let pg = store_lock.read_with_guard(addr); + let pg = store_lock.read_with_guard(pus_tm_in_pool.store_addr); let read_res = pg.read_as_vec(); if read_res.is_err() { warn!("Error reading TM pool data"); @@ -44,20 +43,20 @@ impl UdpTmHandler for StaticUdpTmHandler { } pub struct DynamicUdpTmHandler { - pub tm_rx: Receiver>, + pub tm_rx: mpsc::Receiver, } impl UdpTmHandler for DynamicUdpTmHandler { fn send_tm_to_udp_client(&mut self, socket: &UdpSocket, recv_addr: &SocketAddr) { while let Ok(tm) = self.tm_rx.try_recv() { - if tm.len() > 9 { - let service = tm[7]; - let subservice = tm[8]; + if tm.packet.len() > 9 { + let service = tm.packet[7]; + let subservice = tm.packet[8]; info!("Sending PUS TM[{service},{subservice}]") } else { info!("Sending PUS TM"); } - let result = socket.send_to(&tm, recv_addr); + let result = socket.send_to(&tm.packet, recv_addr); if let Err(e) = result { warn!("Sending TM with UDP socket failed: {e}") } @@ -120,7 +119,7 @@ mod tests { }, tmtc::ReceivesTcCore, }; - use satrs_example::config::{OBSW_SERVER_ADDR, PUS_APID}; + use satrs_example::config::{components, OBSW_SERVER_ADDR}; use super::*; @@ -178,7 +177,7 @@ mod tests { udp_tc_server, tm_handler, }; - let mut sph = SpHeader::tc_unseg(PUS_APID, 0, 0).unwrap(); + let mut sph = SpHeader::tc_unseg(components::Apid::GenericPus as u16, 0, 0).unwrap(); let ping_tc = PusTcCreator::new_simple(&mut sph, 17, 1, None, true) .to_vec() .unwrap(); diff --git a/satrs-mib/codegen/Cargo.toml b/satrs-mib/codegen/Cargo.toml index a56d70c..0745435 100644 --- a/satrs-mib/codegen/Cargo.toml +++ b/satrs-mib/codegen/Cargo.toml @@ -28,7 +28,6 @@ features = ["full"] trybuild = { version = "1", features = ["diff"] } [dev-dependencies.satrs-shared] -# satrs-shared = "0.1.2" path = "../../satrs-shared" version = "0.1.3" diff --git a/satrs-shared/Cargo.toml b/satrs-shared/Cargo.toml index 8eadd74..7cb4caf 100644 --- a/satrs-shared/Cargo.toml +++ b/satrs-shared/Cargo.toml @@ -18,7 +18,9 @@ default-features = false optional = true [dependencies.spacepackets] +git = "https://egit.irs.uni-stuttgart.de/rust/spacepackets.git" version = "0.11.0-rc.0" +branch = "main" default-features = false [features] diff --git a/satrs/Cargo.toml b/satrs/Cargo.toml index d233eb5..4237bbb 100644 --- a/satrs/Cargo.toml +++ b/satrs/Cargo.toml @@ -71,7 +71,9 @@ features = ["all"] optional = true [dependencies.spacepackets] +git = "https://egit.irs.uni-stuttgart.de/rust/spacepackets.git" version = "0.11.0-rc.0" +branch = "main" default-features = false [dependencies.cobs] diff --git a/satrs/src/hk.rs b/satrs/src/hk.rs index 5cb3575..50edfda 100644 --- a/satrs/src/hk.rs +++ b/satrs/src/hk.rs @@ -19,8 +19,8 @@ impl HkRequest { #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum HkRequestVariant { OneShot, - Enable, - Disable, + EnablePeriodic, + DisablePeriodic, ModifyCollectionInterval(CollectionIntervalFactor), } diff --git a/satrs/src/mode.rs b/satrs/src/mode.rs index 29335b1..9405d36 100644 --- a/satrs/src/mode.rs +++ b/satrs/src/mode.rs @@ -12,7 +12,7 @@ pub use std_mod::*; use crate::{ queue::GenericTargetedMessagingError, - request::{GenericMessage, MessageReceiver, MessageReceiverWithId, RequestId}, + request::{GenericMessage, MessageMetadata, MessageReceiver, MessageReceiverWithId, RequestId}, ComponentId, }; @@ -109,6 +109,8 @@ impl TargetedModeCommand { #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub enum ModeRequest { + /// Mode information. Can be used to notify other components of changed modes. + ModeInfo(ModeAndSubmode), SetMode(ModeAndSubmode), ReadMode, AnnounceMode, @@ -125,8 +127,6 @@ pub struct TargetedModeRequest { #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub enum ModeReply { - /// Unrequest mode information. Can be used to notify other components of changed modes. - ModeInfo(ModeAndSubmode), /// Reply to a mode request to confirm the commanded mode was reached. ModeReply(ModeAndSubmode), // Can not reach the commanded mode. Contains a reason as a [ResultU16]. @@ -184,13 +184,20 @@ impl From for ModeError { pub trait ModeRequestHandler: ModeProvider { fn start_transition( &mut self, - request_id: RequestId, - sender_id: ComponentId, + requestor: MessageMetadata, mode_and_submode: ModeAndSubmode, ) -> Result<(), ModeError>; - fn announce_mode(&self, request_id: RequestId, sender_id: ComponentId, recursive: bool); - fn handle_mode_reached(&mut self) -> Result<(), GenericTargetedMessagingError>; + fn announce_mode(&self, requestor_info: MessageMetadata, recursive: bool); + fn handle_mode_reached( + &mut self, + requestor_info: Option, + ) -> Result<(), GenericTargetedMessagingError>; + fn send_mode_reply( + &self, + requestor_info: MessageMetadata, + reply: ModeReply, + ) -> Result<(), GenericTargetedMessagingError>; } pub trait ModeReplyReceiver { @@ -210,10 +217,10 @@ impl> ModeReplyReceiver for MessageReceiverWithId< pub trait ModeReplySender { fn local_channel_id(&self) -> ComponentId; + /// The requestor is assumed to be the target of the reply. fn send_mode_reply( &self, - request_id: RequestId, - target_id: ComponentId, + requestor_info: MessageMetadata, reply: ModeReply, ) -> Result<(), GenericTargetedMessagingError>; } @@ -225,7 +232,7 @@ pub mod alloc_mod { mode::ModeRequest, queue::GenericTargetedMessagingError, request::{ - MessageSender, MessageSenderAndReceiver, MessageSenderMap, MessageSenderMapWithId, + MessageMetadata, MessageSender, MessageSenderAndReceiver, MessageSenderMap, RequestAndReplySenderAndReceiver, RequestId, }, ComponentId, @@ -236,12 +243,11 @@ pub mod alloc_mod { impl> MessageSenderMap { pub fn send_mode_reply( &self, - request_id: RequestId, - local_id: ComponentId, + requestor_info: MessageMetadata, target_id: ComponentId, request: ModeReply, ) -> Result<(), GenericTargetedMessagingError> { - self.send_message(request_id, local_id, target_id, request) + self.send_message(requestor_info, target_id, request) } pub fn add_reply_target(&mut self, target_id: ComponentId, request_sender: S) { @@ -249,6 +255,7 @@ pub mod alloc_mod { } } + /* impl> ModeReplySender for MessageSenderMapWithId { fn send_mode_reply( &self, @@ -263,6 +270,7 @@ pub mod alloc_mod { self.local_channel_id } } + */ impl, R: MessageReceiver> ModeReplySender for MessageSenderAndReceiver @@ -273,14 +281,12 @@ pub mod alloc_mod { fn send_mode_reply( &self, - request_id: RequestId, - target_id: ComponentId, + requestor_info: MessageMetadata, request: ModeReply, ) -> Result<(), GenericTargetedMessagingError> { self.message_sender_map.send_mode_reply( - request_id, - self.local_channel_id(), - target_id, + MessageMetadata::new(requestor_info.request_id(), self.local_channel_id()), + requestor_info.sender_id(), request, ) } @@ -324,14 +330,12 @@ pub mod alloc_mod { fn send_mode_reply( &self, - request_id: RequestId, - target_id: ComponentId, + requestor_info: MessageMetadata, request: ModeReply, ) -> Result<(), GenericTargetedMessagingError> { self.reply_sender_map.send_mode_reply( - request_id, - self.local_channel_id(), - target_id, + MessageMetadata::new(requestor_info.request_id(), self.local_channel_id()), + requestor_info.sender_id(), request, ) } @@ -368,11 +372,14 @@ pub mod alloc_mod { pub fn send_mode_reply( &self, - request_id: RequestId, - target_id: ComponentId, + requestor_info: MessageMetadata, reply: ModeReply, ) -> Result<(), GenericTargetedMessagingError> { - self.send_message(request_id, target_id, reply) + self.send_message( + requestor_info.request_id(), + requestor_info.sender_id(), + reply, + ) } } @@ -405,12 +412,11 @@ pub mod alloc_mod { impl> MessageSenderMap { pub fn send_mode_request( &self, - request_id: RequestId, - local_id: ComponentId, + requestor_info: MessageMetadata, target_id: ComponentId, request: ModeRequest, ) -> Result<(), GenericTargetedMessagingError> { - self.send_message(request_id, local_id, target_id, request) + self.send_message(requestor_info, target_id, request) } pub fn add_request_target(&mut self, target_id: ComponentId, request_sender: S) { @@ -418,6 +424,7 @@ pub mod alloc_mod { } } + /* impl> ModeRequestSender for MessageSenderMapWithId { fn local_channel_id(&self) -> ComponentId { self.local_channel_id @@ -432,6 +439,7 @@ pub mod alloc_mod { self.send_message(request_id, target_id, request) } } + */ impl, R: MessageReceiver> ModeRequestReceiver for MessageSenderAndReceiver @@ -457,8 +465,7 @@ pub mod alloc_mod { request: ModeRequest, ) -> Result<(), GenericTargetedMessagingError> { self.message_sender_map.send_mode_request( - request_id, - self.local_channel_id(), + MessageMetadata::new(request_id, self.local_channel_id()), target_id, request, ) @@ -499,8 +506,7 @@ pub mod alloc_mod { request: ModeRequest, ) -> Result<(), GenericTargetedMessagingError> { self.request_sender_map.send_mode_request( - request_id, - self.local_channel_id(), + MessageMetadata::new(request_id, self.local_channel_id()), target_id, request, ) diff --git a/satrs/src/pus/action.rs b/satrs/src/pus/action.rs index 4a93722..875621f 100644 --- a/satrs/src/pus/action.rs +++ b/satrs/src/pus/action.rs @@ -1,8 +1,7 @@ use crate::{ action::{ActionId, ActionRequest}, params::Params, - request::{GenericMessage, RequestId}, - ComponentId, + request::{GenericMessage, MessageMetadata, RequestId}, }; use satrs_shared::res_code::ResultU16; @@ -57,12 +56,11 @@ pub type GenericActionReplyPus = GenericMessage; impl GenericActionReplyPus { pub fn new_action_reply( - request_id: RequestId, - sender_id: ComponentId, + requestor_info: MessageMetadata, action_id: ActionId, reply: ActionReplyVariant, ) -> Self { - Self::new(request_id, sender_id, PusActionReply::new(action_id, reply)) + Self::new(requestor_info, PusActionReply::new(action_id, reply)) } } diff --git a/satrs/src/pus/event.rs b/satrs/src/pus/event.rs index 84cf857..3e160a3 100644 --- a/satrs/src/pus/event.rs +++ b/satrs/src/pus/event.rs @@ -2,6 +2,7 @@ use crate::pus::{source_buffer_large_enough, EcssTmtcError}; use spacepackets::ecss::tm::PusTmCreator; use spacepackets::ecss::tm::PusTmSecondaryHeader; use spacepackets::ecss::{EcssEnumeration, PusError}; +use spacepackets::ByteConversionError; use spacepackets::{SpHeader, MAX_APID}; use crate::pus::EcssTmSenderCore; @@ -9,145 +10,125 @@ use crate::pus::EcssTmSenderCore; pub use alloc_mod::EventReporter; pub use spacepackets::ecss::event::*; -pub struct EventReporterBase { - msg_count: u16, +pub struct EventReportCreator { apid: u16, pub dest_id: u16, } -impl EventReporterBase { +impl EventReportCreator { pub fn new(apid: u16) -> Option { if apid > MAX_APID { return None; } Some(Self { - msg_count: 0, + // msg_count: 0, dest_id: 0, apid, }) } - pub fn event_info( - &mut self, - buf: &mut [u8], - sender: &mut (impl EcssTmSenderCore + ?Sized), - time_stamp: &[u8], + pub fn event_info<'time, 'src_data>( + &self, + src_data_buf: &'src_data mut [u8], + time_stamp: &'time [u8], event_id: impl EcssEnumeration, - aux_data: Option<&[u8]>, - ) -> Result<(), EcssTmtcError> { + aux_data: Option<&'src_data [u8]>, + ) -> Result, ByteConversionError> { self.generate_and_send_generic_tm( - buf, + src_data_buf, Subservice::TmInfoReport, - sender, time_stamp, event_id, aux_data, ) } - pub fn event_low_severity( - &mut self, - buf: &mut [u8], - sender: &mut (impl EcssTmSenderCore + ?Sized), - time_stamp: &[u8], + pub fn event_low_severity<'time, 'src_data>( + &self, + src_data_buf: &'src_data mut [u8], + time_stamp: &'time [u8], event_id: impl EcssEnumeration, - aux_data: Option<&[u8]>, - ) -> Result<(), EcssTmtcError> { + aux_data: Option<&'src_data [u8]>, + ) -> Result, ByteConversionError> { self.generate_and_send_generic_tm( - buf, + src_data_buf, Subservice::TmLowSeverityReport, - sender, time_stamp, event_id, aux_data, ) } - pub fn event_medium_severity( - &mut self, - buf: &mut [u8], - sender: &mut (impl EcssTmSenderCore + ?Sized), - time_stamp: &[u8], + pub fn event_medium_severity<'time, 'src_data>( + &self, + buf: &'src_data mut [u8], + time_stamp: &'time [u8], event_id: impl EcssEnumeration, - aux_data: Option<&[u8]>, - ) -> Result<(), EcssTmtcError> { + aux_data: Option<&'src_data [u8]>, + ) -> Result, ByteConversionError> { self.generate_and_send_generic_tm( buf, Subservice::TmMediumSeverityReport, - sender, time_stamp, event_id, aux_data, ) } - pub fn event_high_severity( - &mut self, - buf: &mut [u8], - sender: &mut (impl EcssTmSenderCore + ?Sized), - time_stamp: &[u8], + pub fn event_high_severity<'time, 'src_data>( + &self, + src_data_buf: &'src_data mut [u8], + time_stamp: &'time [u8], event_id: impl EcssEnumeration, - aux_data: Option<&[u8]>, - ) -> Result<(), EcssTmtcError> { + aux_data: Option<&'src_data [u8]>, + ) -> Result, ByteConversionError> { self.generate_and_send_generic_tm( - buf, + src_data_buf, Subservice::TmHighSeverityReport, - sender, time_stamp, event_id, aux_data, ) } - fn generate_and_send_generic_tm( - &mut self, - buf: &mut [u8], + fn generate_and_send_generic_tm<'time, 'src_data>( + &self, + src_data_buf: &'src_data mut [u8], subservice: Subservice, - sender: &mut (impl EcssTmSenderCore + ?Sized), - time_stamp: &[u8], + time_stamp: &'time [u8], event_id: impl EcssEnumeration, - aux_data: Option<&[u8]>, - ) -> Result<(), EcssTmtcError> { - let tm = self.generate_generic_event_tm(buf, subservice, time_stamp, event_id, aux_data)?; - sender.send_tm(tm.into())?; - self.msg_count += 1; - Ok(()) + aux_data: Option<&'src_data [u8]>, + ) -> Result, ByteConversionError> { + self.generate_generic_event_tm(src_data_buf, subservice, time_stamp, event_id, aux_data) } - fn generate_generic_event_tm<'a>( - &'a self, - buf: &'a mut [u8], + fn generate_generic_event_tm<'time, 'src_data>( + &self, + src_data_buf: &'src_data mut [u8], subservice: Subservice, - time_stamp: &'a [u8], + time_stamp: &'time [u8], event_id: impl EcssEnumeration, - aux_data: Option<&[u8]>, - ) -> Result { + aux_data: Option<&'src_data [u8]>, + ) -> Result, ByteConversionError> { let mut src_data_len = event_id.size(); if let Some(aux_data) = aux_data { src_data_len += aux_data.len(); } - source_buffer_large_enough(buf.len(), src_data_len)?; + source_buffer_large_enough(src_data_buf.len(), src_data_len)?; let mut sp_header = SpHeader::tm_unseg(self.apid, 0, 0).unwrap(); - let sec_header = PusTmSecondaryHeader::new( - 5, - subservice.into(), - self.msg_count, - self.dest_id, - Some(time_stamp), - ); + let sec_header = + PusTmSecondaryHeader::new(5, subservice.into(), 0, self.dest_id, Some(time_stamp)); let mut current_idx = 0; - event_id - .write_to_be_bytes(&mut buf[0..event_id.size()]) - .map_err(PusError::ByteConversion)?; + event_id.write_to_be_bytes(&mut src_data_buf[0..event_id.size()])?; current_idx += event_id.size(); if let Some(aux_data) = aux_data { - buf[current_idx..current_idx + aux_data.len()].copy_from_slice(aux_data); + src_data_buf[current_idx..current_idx + aux_data.len()].copy_from_slice(aux_data); current_idx += aux_data.len(); } Ok(PusTmCreator::new( &mut sp_header, sec_header, - &buf[0..current_idx], + &src_data_buf[0..current_idx], true, )) } @@ -156,84 +137,95 @@ impl EventReporterBase { #[cfg(feature = "alloc")] mod alloc_mod { use super::*; + use crate::ComponentId; use alloc::vec; use alloc::vec::Vec; + use core::cell::RefCell; pub struct EventReporter { - source_data_buf: Vec, - pub reporter: EventReporterBase, + id: ComponentId, + // Use interior mutability pattern here. This is just an intermediate buffer to the PUS event packet + // generation. + source_data_buf: RefCell>, + pub report_creator: EventReportCreator, } impl EventReporter { - pub fn new(apid: u16, max_event_id_and_aux_data_size: usize) -> Option { - let reporter = EventReporterBase::new(apid)?; + pub fn new( + id: ComponentId, + apid: u16, + max_event_id_and_aux_data_size: usize, + ) -> Option { + let reporter = EventReportCreator::new(apid)?; Some(Self { - source_data_buf: vec![0; max_event_id_and_aux_data_size], - reporter, + id, + source_data_buf: RefCell::new(vec![0; max_event_id_and_aux_data_size]), + report_creator: reporter, }) } + pub fn event_info( - &mut self, - sender: &mut (impl EcssTmSenderCore + ?Sized), + &self, + sender: &(impl EcssTmSenderCore + ?Sized), time_stamp: &[u8], event_id: impl EcssEnumeration, aux_data: Option<&[u8]>, ) -> Result<(), EcssTmtcError> { - self.reporter.event_info( - self.source_data_buf.as_mut_slice(), - sender, - time_stamp, - event_id, - aux_data, - ) + let mut mut_buf = self.source_data_buf.borrow_mut(); + let tm_creator = self + .report_creator + .event_info(mut_buf.as_mut_slice(), time_stamp, event_id, aux_data) + .map_err(PusError::ByteConversion)?; + sender.send_tm(self.id, tm_creator.into())?; + Ok(()) } pub fn event_low_severity( - &mut self, - sender: &mut (impl EcssTmSenderCore + ?Sized), + &self, + sender: &(impl EcssTmSenderCore + ?Sized), time_stamp: &[u8], event_id: impl EcssEnumeration, aux_data: Option<&[u8]>, ) -> Result<(), EcssTmtcError> { - self.reporter.event_low_severity( - self.source_data_buf.as_mut_slice(), - sender, - time_stamp, - event_id, - aux_data, - ) + let mut mut_buf = self.source_data_buf.borrow_mut(); + let tm_creator = self + .report_creator + .event_low_severity(mut_buf.as_mut_slice(), time_stamp, event_id, aux_data) + .map_err(PusError::ByteConversion)?; + sender.send_tm(self.id, tm_creator.into())?; + Ok(()) } pub fn event_medium_severity( - &mut self, - sender: &mut (impl EcssTmSenderCore + ?Sized), + &self, + sender: &(impl EcssTmSenderCore + ?Sized), time_stamp: &[u8], event_id: impl EcssEnumeration, aux_data: Option<&[u8]>, ) -> Result<(), EcssTmtcError> { - self.reporter.event_medium_severity( - self.source_data_buf.as_mut_slice(), - sender, - time_stamp, - event_id, - aux_data, - ) + let mut mut_buf = self.source_data_buf.borrow_mut(); + let tm_creator = self + .report_creator + .event_medium_severity(mut_buf.as_mut_slice(), time_stamp, event_id, aux_data) + .map_err(PusError::ByteConversion)?; + sender.send_tm(self.id, tm_creator.into())?; + Ok(()) } pub fn event_high_severity( - &mut self, - sender: &mut (impl EcssTmSenderCore + ?Sized), + &self, + sender: &(impl EcssTmSenderCore + ?Sized), time_stamp: &[u8], event_id: impl EcssEnumeration, aux_data: Option<&[u8]>, ) -> Result<(), EcssTmtcError> { - self.reporter.event_high_severity( - self.source_data_buf.as_mut_slice(), - sender, - time_stamp, - event_id, - aux_data, - ) + let mut mut_buf = self.source_data_buf.borrow_mut(); + let tm_creator = self + .report_creator + .event_high_severity(mut_buf.as_mut_slice(), time_stamp, event_id, aux_data) + .map_err(PusError::ByteConversion)?; + sender.send_tm(self.id, tm_creator.into())?; + Ok(()) } } } @@ -243,7 +235,7 @@ mod tests { use super::*; use crate::events::{EventU32, Severity}; use crate::pus::tests::CommonTmInfo; - use crate::pus::{EcssChannel, PusTmWrapper}; + use crate::pus::{ChannelWithId, PusTmVariant}; use crate::ComponentId; use spacepackets::ByteConversionError; use std::cell::RefCell; @@ -268,19 +260,19 @@ mod tests { pub service_queue: RefCell>, } - impl EcssChannel for TestSender { + impl ChannelWithId for TestSender { fn id(&self) -> ComponentId { 0 } } impl EcssTmSenderCore for TestSender { - fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> { + fn send_tm(&self, sender_id: ComponentId, tm: PusTmVariant) -> Result<(), EcssTmtcError> { match tm { - PusTmWrapper::InStore(_) => { + PusTmVariant::InStore(_) => { panic!("TestSender: unexpected call with address"); } - PusTmWrapper::Direct(tm) => { + PusTmVariant::Direct(tm) => { assert!(!tm.source_data().is_empty()); let src_data = tm.source_data(); assert!(src_data.len() >= 4); @@ -348,7 +340,7 @@ mod tests { error_data: Option<&[u8]>, ) { let mut sender = TestSender::default(); - let reporter = EventReporter::new(EXAMPLE_APID, max_event_aux_data_buf); + let reporter = EventReporter::new(0, EXAMPLE_APID, max_event_aux_data_buf); assert!(reporter.is_some()); let mut reporter = reporter.unwrap(); let time_stamp_empty: [u8; 7] = [0; 7]; @@ -440,7 +432,7 @@ mod tests { fn insufficient_buffer() { let mut sender = TestSender::default(); for i in 0..3 { - let reporter = EventReporter::new(EXAMPLE_APID, i); + let reporter = EventReporter::new(0, EXAMPLE_APID, i); assert!(reporter.is_some()); let mut reporter = reporter.unwrap(); check_buf_too_small(&mut reporter, &mut sender, i); diff --git a/satrs/src/pus/event_man.rs b/satrs/src/pus/event_man.rs index e6e18c9..2235096 100644 --- a/satrs/src/pus/event_man.rs +++ b/satrs/src/pus/event_man.rs @@ -177,8 +177,8 @@ pub mod alloc_mod { } pub fn generate_pus_event_tm_generic( - &mut self, - sender: &mut (impl EcssTmSenderCore + ?Sized), + &self, + sender: &(impl EcssTmSenderCore + ?Sized), time_stamp: &[u8], event: EV, aux_data: Option<&[u8]>, @@ -239,8 +239,8 @@ pub mod alloc_mod { } pub fn generate_pus_event_tm( - &mut self, - sender: &mut (impl EcssTmSenderCore + ?Sized), + &self, + sender: &(impl EcssTmSenderCore + ?Sized), time_stamp: &[u8], event: EventU32TypedSev, aux_data: Option<&[u8]>, @@ -257,20 +257,26 @@ pub mod alloc_mod { #[cfg(test)] mod tests { use super::*; - use crate::{events::SeverityInfo, pus::TmAsVecSenderWithMpsc}; + use crate::events::SeverityInfo; + use crate::pus::PusTmAsVec; + use crate::request::UniqueApidTargetId; 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]; + const TEST_APID: u16 = 0x02; + const TEST_ID: UniqueApidTargetId = UniqueApidTargetId::new(TEST_APID, 0x05); fn create_basic_man_1() -> DefaultPusEventU32Dispatcher<()> { - let reporter = EventReporter::new(0x02, 128).expect("Creating event repoter failed"); + let reporter = EventReporter::new(TEST_ID.raw(), TEST_APID, 128) + .expect("Creating event repoter failed"); PusEventDispatcher::new_with_default_backend(reporter) } fn create_basic_man_2() -> DefaultPusEventU32Dispatcher<()> { - let reporter = EventReporter::new(0x02, 128).expect("Creating event repoter failed"); + let reporter = EventReporter::new(TEST_ID.raw(), TEST_APID, 128) + .expect("Creating event repoter failed"); let backend = DefaultPusEventMgmtBackend::default(); PusEventDispatcher::new(reporter, backend) } @@ -278,10 +284,9 @@ mod tests { #[test] fn test_basic() { 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 (mut event_tx, event_rx) = mpsc::channel::(); let event_sent = event_man - .generate_pus_event_tm(&mut sender, &EMPTY_STAMP, INFO_EVENT, None) + .generate_pus_event_tm(&mut event_tx, &EMPTY_STAMP, INFO_EVENT, None) .expect("Sending info event failed"); assert!(event_sent); @@ -292,13 +297,13 @@ mod tests { #[test] fn test_disable_event() { 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 (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()); let mut event_sent = event_man - .generate_pus_event_tm_generic(&mut sender, &EMPTY_STAMP, LOW_SEV_EVENT, None) + .generate_pus_event_tm_generic(&event_tx, &EMPTY_STAMP, LOW_SEV_EVENT, None) .expect("Sending low severity event failed"); assert!(!event_sent); let res = event_rx.try_recv(); @@ -306,7 +311,7 @@ mod tests { assert!(matches!(res.unwrap_err(), TryRecvError::Empty)); // Check that only the low severity event was disabled event_sent = event_man - .generate_pus_event_tm(&mut sender, &EMPTY_STAMP, INFO_EVENT, None) + .generate_pus_event_tm(&event_tx, &EMPTY_STAMP, INFO_EVENT, None) .expect("Sending info event failed"); assert!(event_sent); event_rx.try_recv().expect("No info event received"); @@ -315,8 +320,7 @@ mod tests { #[test] fn test_reenable_event() { 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 (event_tx, event_rx) = mpsc::channel::(); let mut res = event_man.disable_tm_for_event_with_sev(&INFO_EVENT); assert!(res.is_ok()); assert!(res.unwrap()); @@ -324,7 +328,7 @@ mod tests { assert!(res.is_ok()); assert!(res.unwrap()); let event_sent = event_man - .generate_pus_event_tm(&mut sender, &EMPTY_STAMP, INFO_EVENT, None) + .generate_pus_event_tm(&event_tx, &EMPTY_STAMP, INFO_EVENT, None) .expect("Sending info event failed"); assert!(event_sent); event_rx.try_recv().expect("No info event received"); diff --git a/satrs/src/pus/event_srv.rs b/satrs/src/pus/event_srv.rs index 192f02e..cca55ca 100644 --- a/satrs/src/pus/event_srv.rs +++ b/satrs/src/pus/event_srv.rs @@ -13,7 +13,7 @@ use super::{ GenericRoutingError, PusServiceHelper, }; -pub struct PusService5EventHandler< +pub struct PusEventServiceHandler< TcReceiver: EcssTcReceiverCore, TmSender: EcssTmSenderCore, TcInMemConverter: EcssTcInMemConverter, @@ -29,7 +29,7 @@ impl< TmSender: EcssTmSenderCore, TcInMemConverter: EcssTcInMemConverter, VerificationReporter: VerificationReportingProvider, - > PusService5EventHandler + > PusEventServiceHandler { pub fn new( service_helper: PusServiceHelper< @@ -83,7 +83,12 @@ impl< .service_helper .common .verif_reporter - .start_success(ecss_tc_and_token.token, time_stamp) + .start_success( + self.service_helper.common.id, + &self.service_helper.common.tm_sender, + ecss_tc_and_token.token, + time_stamp, + ) .map_err(|_| PartialPusHandlingError::Verification); let partial_error = start_token.clone().err(); let mut token: TcStateToken = ecss_tc_and_token.token.into(); @@ -161,9 +166,9 @@ mod tests { use crate::pus::event_man::EventRequest; use crate::pus::test_util::{PusTestHarness, SimplePusPacketHandler, TEST_APID}; use crate::pus::verification::{ - RequestId, VerificationReporterWithSharedPoolMpscBoundedSender, + RequestId, VerificationReporter, VerificationReportingProvider, }; - use crate::pus::{GenericConversionError, MpscTcReceiver, TmInSharedPoolSenderWithBoundedMpsc}; + use crate::pus::{GenericConversionError, MpscTcReceiver, MpscTmInSharedPoolSenderBounded}; use crate::{ events::EventU32, pus::{ @@ -174,34 +179,48 @@ mod tests { }, }; - use super::PusService5EventHandler; + use super::PusEventServiceHandler; const TEST_EVENT_0: EventU32 = EventU32::const_new(crate::events::Severity::INFO, 5, 25); struct Pus5HandlerWithStoreTester { common: PusServiceHandlerWithSharedStoreCommon, - handler: PusService5EventHandler< + handler: PusEventServiceHandler< MpscTcReceiver, - TmInSharedPoolSenderWithBoundedMpsc, + MpscTmInSharedPoolSenderBounded, EcssTcInSharedStoreConverter, - VerificationReporterWithSharedPoolMpscBoundedSender, + VerificationReporter, >, } impl Pus5HandlerWithStoreTester { pub fn new(event_request_tx: Sender) -> Self { - let (common, srv_handler) = PusServiceHandlerWithSharedStoreCommon::new(); + let (common, srv_handler) = PusServiceHandlerWithSharedStoreCommon::new(0); Self { common, - handler: PusService5EventHandler::new(srv_handler, event_request_tx), + handler: PusEventServiceHandler::new(srv_handler, event_request_tx), } } } impl PusTestHarness for Pus5HandlerWithStoreTester { + fn init_verification(&mut self, tc: &PusTcCreator) -> VerificationToken { + let init_token = self.handler.service_helper.verif_reporter_mut().add_tc(tc); + self.handler + .service_helper + .verif_reporter() + .acceptance_success( + self.handler.service_helper.id(), + self.handler.service_helper.tm_sender(), + init_token, + &[0; 7], + ) + .expect("acceptance success failure") + } + delegate! { to self.common { - fn send_tc(&mut self, tc: &PusTcCreator) -> VerificationToken; + fn send_tc(&self, token: &VerificationToken, tc: &PusTcCreator); fn read_next_tm(&mut self) -> PusTmReader<'_>; fn check_no_tm_available(&self) -> bool; fn check_next_verification_tm(&self, subservice: u8, expected_request_id: RequestId); @@ -212,7 +231,7 @@ mod tests { impl SimplePusPacketHandler for Pus5HandlerWithStoreTester { fn handle_one_tc(&mut self) -> Result { - let time_stamp = cds::TimeProvider::new_with_u16_days(0, 0).to_vec().unwrap(); + let time_stamp = cds::CdsTime::new_with_u16_days(0, 0).to_vec().unwrap(); self.handler.poll_and_handle_next_tc(&time_stamp) } } @@ -230,7 +249,8 @@ mod tests { .write_to_be_bytes(&mut app_data) .expect("writing test event failed"); let ping_tc = PusTcCreator::new(&mut sp_header, sec_header, &app_data, true); - let token = test_harness.send_tc(&ping_tc); + let token = test_harness.init_verification(&ping_tc); + test_harness.send_tc(&token, &ping_tc); let request_id = token.request_id(); test_harness.handle_one_tc().unwrap(); test_harness.check_next_verification_tm(1, request_id); @@ -287,7 +307,8 @@ mod tests { let mut sp_header = SpHeader::tc(TEST_APID, SequenceFlags::Unsegmented, 0, 0).unwrap(); let sec_header = PusTcSecondaryHeader::new_simple(5, 200); let ping_tc = PusTcCreator::new_no_app_data(&mut sp_header, sec_header, true); - test_harness.send_tc(&ping_tc); + let token = test_harness.init_verification(&ping_tc); + test_harness.send_tc(&token, &ping_tc); let result = test_harness.handle_one_tc(); assert!(result.is_ok()); let result = result.unwrap(); @@ -306,7 +327,8 @@ mod tests { let sec_header = PusTcSecondaryHeader::new_simple(5, Subservice::TcEnableEventGeneration as u8); let ping_tc = PusTcCreator::new(&mut sp_header, sec_header, &[0, 1, 2], true); - test_harness.send_tc(&ping_tc); + let token = test_harness.init_verification(&ping_tc); + test_harness.send_tc(&token, &ping_tc); let result = test_harness.handle_one_tc(); assert!(result.is_err()); let result = result.unwrap_err(); diff --git a/satrs/src/pus/mod.rs b/satrs/src/pus/mod.rs index ca449c3..e2a4980 100644 --- a/satrs/src/pus/mod.rs +++ b/satrs/src/pus/mod.rs @@ -5,7 +5,7 @@ use crate::pool::{StoreAddr, StoreError}; use crate::pus::verification::{TcStateAccepted, TcStateToken, VerificationToken}; use crate::queue::{GenericReceiveError, GenericSendError}; -use crate::request::{GenericMessage, RequestId}; +use crate::request::{GenericMessage, MessageMetadata, RequestId}; use crate::ComponentId; use core::fmt::{Display, Formatter}; use core::time::Duration; @@ -43,19 +43,19 @@ pub use std_mod::*; use self::verification::VerificationReportingProvider; #[derive(Debug, PartialEq, Eq, Clone)] -pub enum PusTmWrapper<'tm> { +pub enum PusTmVariant<'time, 'src_data> { InStore(StoreAddr), - Direct(PusTmCreator<'tm>), + Direct(PusTmCreator<'time, 'src_data>), } -impl From for PusTmWrapper<'_> { +impl From for PusTmVariant<'_, '_> { fn from(value: StoreAddr) -> Self { Self::InStore(value) } } -impl<'tm> From> for PusTmWrapper<'tm> { - fn from(value: PusTmCreator<'tm>) -> Self { +impl<'time, 'src_data> From> for PusTmVariant<'time, 'src_data> { + fn from(value: PusTmCreator<'time, 'src_data>) -> Self { Self::Direct(value) } } @@ -142,7 +142,7 @@ impl Error for EcssTmtcError { } } } -pub trait EcssChannel: Send { +pub trait ChannelWithId: Send { /// Each sender can have an ID associated with it fn id(&self) -> ComponentId; fn name(&self) -> &'static str { @@ -154,7 +154,7 @@ pub trait EcssChannel: Send { /// /// This sender object is responsible for sending PUS telemetry to a TM sink. pub trait EcssTmSenderCore: Send { - fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError>; + fn send_tm(&self, source_id: ComponentId, tm: PusTmVariant) -> Result<(), EcssTmtcError>; } /// Generic trait for a user supplied sender object. @@ -165,6 +165,16 @@ pub trait EcssTcSenderCore { fn send_tc(&self, tc: PusTcCreator, token: Option) -> Result<(), EcssTmtcError>; } +/// Dummy object which can be useful for tests. +#[derive(Default)] +pub struct EcssTmDummySender {} + +impl EcssTmSenderCore for EcssTmDummySender { + fn send_tm(&self, _source_id: ComponentId, _tm: PusTmVariant) -> Result<(), EcssTmtcError> { + Ok(()) + } +} + /// A PUS telecommand packet can be stored in memory using different methods. Right now, /// storage inside a pool structure like [crate::pool::StaticMemoryPool], and storage inside a /// `Vec` are supported. @@ -259,7 +269,7 @@ impl From for TryRecvTmtcError { } /// Generic trait for a user supplied receiver object. -pub trait EcssTcReceiverCore: EcssChannel { +pub trait EcssTcReceiverCore { fn recv_tc(&self) -> Result; } @@ -301,8 +311,7 @@ pub trait PusRequestRouter { fn route( &self, - request_id: RequestId, - source_id: ComponentId, + requestor_info: MessageMetadata, target_id: ComponentId, request: Request, ) -> Result<(), Self::Error>; @@ -315,15 +324,17 @@ pub trait PusReplyHandler { /// is finished. A finished PUS request will be removed from the active request map. fn handle_reply( &mut self, + caller_id: ComponentId, reply: &GenericMessage, active_request: &ActiveRequestInfo, + tm_sender: &impl EcssTmSenderCore, verification_handler: &impl VerificationReportingProvider, time_stamp: &[u8], - tm_sender: &impl EcssTmSenderCore, ) -> Result; fn handle_unrequested_reply( &mut self, + caller_id: ComponentId, reply: &GenericMessage, tm_sender: &impl EcssTmSenderCore, ) -> Result<(), Self::Error>; @@ -331,10 +342,11 @@ pub trait PusReplyHandler { /// Handle the timeout of an active request. fn handle_request_timeout( &mut self, + caller_id: ComponentId, active_request: &ActiveRequestInfo, + tm_sender: &impl EcssTmSenderCore, verification_handler: &impl VerificationReportingProvider, time_stamp: &[u8], - tm_sender: &impl EcssTmSenderCore, ) -> Result<(), Self::Error>; } @@ -445,10 +457,12 @@ pub mod alloc_mod { type Error; fn convert( &mut self, + caller_id: ComponentId, token: VerificationToken, tc: &PusTcReader, - time_stamp: &[u8], + tm_sender: &(impl EcssTmSenderCore + ?Sized), verif_reporter: &impl VerificationReportingProvider, + time_stamp: &[u8], ) -> Result<(ActiveRequestInfo, Request), Self::Error>; } @@ -647,8 +661,8 @@ pub mod std_mod { }; use crate::pus::verification::{TcStateAccepted, VerificationToken}; use crate::pus::{ - EcssChannel, EcssTcAndToken, EcssTcReceiverCore, EcssTmSenderCore, EcssTmtcError, - GenericReceiveError, GenericSendError, PusTmWrapper, TryRecvTmtcError, + EcssTcAndToken, EcssTcReceiverCore, EcssTmSenderCore, EcssTmtcError, GenericReceiveError, + GenericSendError, PusTmVariant, TryRecvTmtcError, }; use crate::tmtc::tm_helper::SharedTmPool; use crate::ComponentId; @@ -670,54 +684,82 @@ pub mod std_mod { use super::verification::{TcStateToken, VerificationReportingProvider}; use super::{AcceptedEcssTcAndToken, ActiveRequestProvider, TcInMemory}; + #[derive(Debug)] + pub struct PusTmInPool { + pub source_id: ComponentId, + pub store_addr: StoreAddr, + } + impl From> for EcssTmtcError { fn from(_: mpsc::SendError) -> Self { Self::Send(GenericSendError::RxDisconnected) } } - impl EcssTmSenderCore for mpsc::Sender { - fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> { + impl EcssTmSenderCore for mpsc::Sender { + fn send_tm(&self, source_id: ComponentId, tm: PusTmVariant) -> Result<(), EcssTmtcError> { match tm { - PusTmWrapper::InStore(addr) => self - .send(addr) + PusTmVariant::InStore(store_addr) => self + .send(PusTmInPool { + source_id, + store_addr, + }) .map_err(|_| GenericSendError::RxDisconnected)?, - PusTmWrapper::Direct(_) => return Err(EcssTmtcError::CantSendDirectTm), + PusTmVariant::Direct(_) => return Err(EcssTmtcError::CantSendDirectTm), }; Ok(()) } } - impl EcssTmSenderCore for mpsc::SyncSender { - fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> { + impl EcssTmSenderCore for mpsc::SyncSender { + fn send_tm(&self, source_id: ComponentId, tm: PusTmVariant) -> Result<(), EcssTmtcError> { match tm { - PusTmWrapper::InStore(addr) => self - .try_send(addr) + PusTmVariant::InStore(store_addr) => self + .try_send(PusTmInPool { + source_id, + store_addr, + }) .map_err(|e| EcssTmtcError::Send(e.into()))?, - PusTmWrapper::Direct(_) => return Err(EcssTmtcError::CantSendDirectTm), + PusTmVariant::Direct(_) => return Err(EcssTmtcError::CantSendDirectTm), }; Ok(()) } } - impl EcssTmSenderCore for mpsc::Sender> { - fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> { + #[derive(Debug)] + pub struct PusTmAsVec { + pub source_id: ComponentId, + pub packet: Vec, + } + + pub type MpscTmAsVecSender = mpsc::Sender; + + impl EcssTmSenderCore for MpscTmAsVecSender { + fn send_tm(&self, source_id: ComponentId, tm: PusTmVariant) -> Result<(), EcssTmtcError> { match tm { - PusTmWrapper::InStore(addr) => return Err(EcssTmtcError::CantSendAddr(addr)), - PusTmWrapper::Direct(tm) => self - .send(tm.to_vec()?) + PusTmVariant::InStore(addr) => return Err(EcssTmtcError::CantSendAddr(addr)), + PusTmVariant::Direct(tm) => self + .send(PusTmAsVec { + source_id, + packet: tm.to_vec()?, + }) .map_err(|e| EcssTmtcError::Send(e.into()))?, }; Ok(()) } } - impl EcssTmSenderCore for mpsc::SyncSender> { - fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> { + pub type MpscTmAsVecSenderBounded = mpsc::SyncSender; + + impl EcssTmSenderCore for MpscTmAsVecSenderBounded { + fn send_tm(&self, source_id: ComponentId, tm: PusTmVariant) -> Result<(), EcssTmtcError> { match tm { - PusTmWrapper::InStore(addr) => return Err(EcssTmtcError::CantSendAddr(addr)), - PusTmWrapper::Direct(tm) => self - .send(tm.to_vec()?) + PusTmVariant::InStore(addr) => return Err(EcssTmtcError::CantSendAddr(addr)), + PusTmVariant::Direct(tm) => self + .send(PusTmAsVec { + source_id, + packet: tm.to_vec()?, + }) .map_err(|e| EcssTmtcError::Send(e.into()))?, }; Ok(()) @@ -725,67 +767,52 @@ pub mod std_mod { } #[derive(Clone)] - pub struct TmInSharedPoolSenderWithId { - channel_id: ComponentId, - name: &'static str, + pub struct TmInSharedPoolSender { shared_tm_store: SharedTmPool, sender: Sender, } - impl EcssChannel for TmInSharedPoolSenderWithId { - fn id(&self) -> ComponentId { - self.channel_id - } - - fn name(&self) -> &'static str { - self.name - } - } - - impl TmInSharedPoolSenderWithId { - pub fn send_direct_tm(&self, tm: PusTmCreator) -> Result<(), EcssTmtcError> { + impl TmInSharedPoolSender { + pub fn send_direct_tm( + &self, + source_id: ComponentId, + tm: PusTmCreator, + ) -> Result<(), EcssTmtcError> { let addr = self.shared_tm_store.add_pus_tm(&tm)?; - self.sender.send_tm(PusTmWrapper::InStore(addr)) + self.sender.send_tm(source_id, PusTmVariant::InStore(addr)) } } - impl EcssTmSenderCore for TmInSharedPoolSenderWithId { - fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> { - if let PusTmWrapper::Direct(tm) = tm { - return self.send_direct_tm(tm); + impl EcssTmSenderCore for TmInSharedPoolSender { + fn send_tm(&self, source_id: ComponentId, tm: PusTmVariant) -> Result<(), EcssTmtcError> { + if let PusTmVariant::Direct(tm) = tm { + return self.send_direct_tm(source_id, tm); } - self.sender.send_tm(tm) + self.sender.send_tm(source_id, tm) } } - impl TmInSharedPoolSenderWithId { - pub fn new( - id: ComponentId, - name: &'static str, - shared_tm_store: SharedTmPool, - sender: Sender, - ) -> Self { + impl TmInSharedPoolSender { + pub fn new(shared_tm_store: SharedTmPool, sender: Sender) -> Self { Self { - channel_id: id, - name, shared_tm_store, sender, } } } - pub type TmInSharedPoolSenderWithMpsc = TmInSharedPoolSenderWithId>; - pub type TmInSharedPoolSenderWithBoundedMpsc = - TmInSharedPoolSenderWithId>; + pub type MpscTmInSharedPoolSender = TmInSharedPoolSender>; + pub type MpscTmInSharedPoolSenderBounded = TmInSharedPoolSender>; + /* /// 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: ComponentId, - name: &'static str, + // id: ComponentId, + //name: &'static str, sender: Sender, } @@ -801,7 +828,7 @@ pub mod std_mod { } } - impl EcssChannel for TmAsVecSenderWithId { + impl ChannelWithId for TmAsVecSenderWithId { fn id(&self) -> ComponentId { self.id } @@ -811,58 +838,34 @@ pub mod std_mod { } impl EcssTmSenderCore for TmAsVecSenderWithId { - fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> { + fn send_tm(&self, tm: PusTmVariant) -> Result<(), EcssTmtcError> { self.sender.send_tm(tm) } } pub type TmAsVecSenderWithMpsc = TmAsVecSenderWithId>>; pub type TmAsVecSenderWithBoundedMpsc = TmAsVecSenderWithId>>; + */ - pub struct MpscTcReceiver { - id: ComponentId, - name: &'static str, - receiver: mpsc::Receiver, - } - - impl EcssChannel for MpscTcReceiver { - fn id(&self) -> ComponentId { - self.id - } - - fn name(&self) -> &'static str { - self.name - } - } + pub type MpscTcReceiver = mpsc::Receiver; impl EcssTcReceiverCore for MpscTcReceiver { fn recv_tc(&self) -> Result { - self.receiver.try_recv().map_err(|e| match e { + self.try_recv().map_err(|e| match e { TryRecvError::Empty => TryRecvTmtcError::Empty, TryRecvError::Disconnected => TryRecvTmtcError::Tmtc(EcssTmtcError::from( - GenericReceiveError::TxDisconnected(Some(self.id())), + GenericReceiveError::TxDisconnected(None), )), }) } } - impl MpscTcReceiver { - pub fn new( - id: ComponentId, - name: &'static str, - receiver: mpsc::Receiver, - ) -> Self { - Self { id, name, receiver } - } - } - #[cfg(feature = "crossbeam")] pub mod cb_mod { use super::*; use crossbeam_channel as cb; - pub type TmInSharedPoolSenderWithCrossbeam = - TmInSharedPoolSenderWithId>; + pub type TmInSharedPoolSenderWithCrossbeam = TmInSharedPoolSender>; impl From> for EcssTmtcError { fn from(_: cb::SendError) -> Self { @@ -881,65 +884,44 @@ pub mod std_mod { } } - impl EcssTmSenderCore for cb::Sender { - fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> { + impl EcssTmSenderCore for cb::Sender { + fn send_tm( + &self, + source_id: ComponentId, + tm: PusTmVariant, + ) -> Result<(), EcssTmtcError> { match tm { - PusTmWrapper::InStore(addr) => self - .try_send(addr) + PusTmVariant::InStore(addr) => self + .try_send(PusTmInPool { + source_id, + store_addr: addr, + }) .map_err(|e| EcssTmtcError::Send(e.into()))?, - PusTmWrapper::Direct(_) => return Err(EcssTmtcError::CantSendDirectTm), + PusTmVariant::Direct(_) => return Err(EcssTmtcError::CantSendDirectTm), }; Ok(()) } } - impl EcssTmSenderCore for cb::Sender> { - fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> { + impl EcssTmSenderCore for cb::Sender { + fn send_tm( + &self, + source_id: ComponentId, + tm: PusTmVariant, + ) -> Result<(), EcssTmtcError> { match tm { - PusTmWrapper::InStore(addr) => return Err(EcssTmtcError::CantSendAddr(addr)), - PusTmWrapper::Direct(tm) => self - .send(tm.to_vec()?) + PusTmVariant::InStore(addr) => return Err(EcssTmtcError::CantSendAddr(addr)), + PusTmVariant::Direct(tm) => self + .send(PusTmAsVec { + source_id, + packet: tm.to_vec()?, + }) .map_err(|e| EcssTmtcError::Send(e.into()))?, }; Ok(()) } } - pub struct CrossbeamTcReceiver { - id: ComponentId, - name: &'static str, - receiver: cb::Receiver, - } - - impl CrossbeamTcReceiver { - pub fn new( - id: ComponentId, - name: &'static str, - receiver: cb::Receiver, - ) -> Self { - Self { id, name, receiver } - } - } - - impl EcssChannel for CrossbeamTcReceiver { - fn id(&self) -> ComponentId { - 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( - GenericReceiveError::TxDisconnected(Some(self.id())), - )), - }) - } - } + pub type CrossbeamTcReceiver = cb::Receiver; } /// This is a high-level handler for the generic PUS services which need to convert PUS @@ -1294,9 +1276,9 @@ pub mod std_mod { TmSender: EcssTmSenderCore, VerificationReporter: VerificationReportingProvider, > { + pub id: ComponentId, pub tc_receiver: TcReceiver, pub tm_sender: TmSender, - pub tm_apid: u16, pub verif_reporter: VerificationReporter, } @@ -1327,23 +1309,31 @@ pub mod std_mod { > PusServiceHelper { pub fn new( + id: ComponentId, tc_receiver: TcReceiver, tm_sender: TmSender, - tm_apid: u16, verification_handler: VerificationReporter, tc_in_mem_converter: TcInMemConverter, ) -> Self { Self { common: PusServiceBase { + id, tc_receiver, tm_sender, - tm_apid, verif_reporter: verification_handler, }, tc_in_mem_converter, } } + pub fn id(&self) -> ComponentId { + self.common.id + } + + pub fn tm_sender(&self) -> &TmSender { + &self.common.tm_sender + } + /// This function can be used to poll the internal [EcssTcReceiverCore] 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 @@ -1378,6 +1368,9 @@ pub mod std_mod { pub fn verif_reporter(&self) -> &VerificationReporter { &self.common.verif_reporter } + pub fn verif_reporter_mut(&mut self) -> &mut VerificationReporter { + &mut self.common.verif_reporter + } pub fn tc_in_mem_converter(&self) -> &TcInMemConverter { &self.tc_in_mem_converter @@ -1388,50 +1381,47 @@ pub mod std_mod { } } - pub type PusServiceHelperDynWithMpsc = PusServiceHelper< - MpscTcReceiver, - TmAsVecSenderWithMpsc, - TcInMemConverter, - VerificationReporter, - >; + pub type PusServiceHelperDynWithMpsc = + PusServiceHelper; pub type PusServiceHelperDynWithBoundedMpsc = PusServiceHelper< MpscTcReceiver, - TmAsVecSenderWithBoundedMpsc, + MpscTmAsVecSenderBounded, TcInMemConverter, VerificationReporter, >; pub type PusServiceHelperStaticWithMpsc = PusServiceHelper< MpscTcReceiver, - TmInSharedPoolSenderWithMpsc, + MpscTmInSharedPoolSender, TcInMemConverter, VerificationReporter, >; pub type PusServiceHelperStaticWithBoundedMpsc = PusServiceHelper< MpscTcReceiver, - TmInSharedPoolSenderWithBoundedMpsc, + MpscTmInSharedPoolSenderBounded, TcInMemConverter, VerificationReporter, >; } -pub(crate) fn source_buffer_large_enough(cap: usize, len: usize) -> Result<(), EcssTmtcError> { +pub(crate) fn source_buffer_large_enough( + cap: usize, + len: usize, +) -> Result<(), ByteConversionError> { if len > cap { - return Err( - PusError::ByteConversion(ByteConversionError::ToSliceTooSmall { - found: cap, - expected: len, - }) - .into(), - ); + return Err(ByteConversionError::ToSliceTooSmall { + found: cap, + expected: len, + }); } Ok(()) } #[cfg(any(feature = "test_util", test))] pub mod test_util { + use crate::request::UniqueApidTargetId; use spacepackets::ecss::{tc::PusTcCreator, tm::PusTmReader}; use super::{ @@ -1440,9 +1430,13 @@ pub mod test_util { }; pub const TEST_APID: u16 = 0x101; + pub const TEST_UNIQUE_ID: u32 = 0x05; + pub const TEST_COMPONENT_ID: UniqueApidTargetId = + UniqueApidTargetId::new(TEST_APID, TEST_UNIQUE_ID); pub trait PusTestHarness { - fn send_tc(&mut self, tc: &PusTcCreator) -> VerificationToken; + fn init_verification(&mut self, tc: &PusTcCreator) -> VerificationToken; + fn send_tc(&self, token: &VerificationToken, tc: &PusTcCreator); fn read_next_tm(&mut self) -> PusTmReader<'_>; fn check_no_tm_available(&self) -> bool; fn check_next_verification_tm( @@ -1471,22 +1465,16 @@ pub mod tests { use spacepackets::ecss::{PusPacket, WritablePusPacket}; use spacepackets::CcsdsPacket; - use crate::pool::{ - PoolProvider, SharedStaticMemoryPool, StaticMemoryPool, StaticPoolConfig, StoreAddr, - }; - use crate::pus::verification::RequestId; + use crate::pool::{PoolProvider, SharedStaticMemoryPool, StaticMemoryPool, StaticPoolConfig}; + use crate::pus::verification::{RequestId, VerificationReporter}; use crate::tmtc::tm_helper::SharedTmPool; use crate::ComponentId; - use super::test_util::TEST_APID; + use super::test_util::{TEST_APID, TEST_COMPONENT_ID}; - use super::verification::std_mod::{ - VerificationReporterWithSharedPoolMpscBoundedSender, VerificationReporterWithVecMpscSender, - }; - use super::verification::test_util::{SharedVerificationMap, TestVerificationReporter}; + use super::verification::test_util::TestVerificationReporter; use super::verification::{ - TcStateAccepted, VerificationReporterCfg, VerificationReporterWithSender, - VerificationReportingProvider, VerificationToken, + TcStateAccepted, VerificationReporterCfg, VerificationReportingProvider, VerificationToken, }; use super::*; @@ -1515,20 +1503,19 @@ pub mod tests { /// Common fields for a PUS service test harness. pub struct PusServiceHandlerWithSharedStoreCommon { - pus_buf: [u8; 2048], + pus_buf: RefCell<[u8; 2048]>, tm_buf: [u8; 2048], tc_pool: SharedStaticMemoryPool, tm_pool: SharedTmPool, tc_sender: mpsc::SyncSender, - tm_receiver: mpsc::Receiver, - verification_handler: VerificationReporterWithSharedPoolMpscBoundedSender, + tm_receiver: mpsc::Receiver, } pub type PusServiceHelperStatic = PusServiceHelper< MpscTcReceiver, - TmInSharedPoolSenderWithBoundedMpsc, + MpscTmInSharedPoolSenderBounded, EcssTcInSharedStoreConverter, - VerificationReporterWithSharedPoolMpscBoundedSender, + VerificationReporter, >; impl PusServiceHandlerWithSharedStoreCommon { @@ -1536,7 +1523,7 @@ pub mod tests { /// [PusServiceHandler] which might be required for a specific PUS service handler. /// /// The PUS service handler is instantiated with a [EcssTcInStoreConverter]. - pub fn new() -> (Self, PusServiceHelperStatic) { + pub fn new(id: ComponentId) -> (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); @@ -1545,62 +1532,47 @@ pub mod tests { 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 = TmInSharedPoolSenderWithBoundedMpsc::new( - 0, - "verif_sender", - shared_tm_pool.clone(), - tm_tx.clone(), - ); let verif_cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8).unwrap(); - let verification_handler = - VerificationReporterWithSharedPoolMpscBoundedSender::new(&verif_cfg, verif_sender); - let test_srv_tm_sender = - 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 verification_handler = VerificationReporter::new(&verif_cfg); + let test_srv_tm_sender = TmInSharedPoolSender::new(shared_tm_pool.clone(), tm_tx); let in_store_converter = EcssTcInSharedStoreConverter::new(shared_tc_pool.clone(), 2048); ( Self { - pus_buf: [0; 2048], + pus_buf: RefCell::new([0; 2048]), tm_buf: [0; 2048], tc_pool: shared_tc_pool, tm_pool: shared_tm_pool, tc_sender: test_srv_tc_tx, tm_receiver: tm_rx, - verification_handler: verification_handler.clone(), }, PusServiceHelper::new( - test_srv_tc_receiver, + id, + test_srv_tc_rx, test_srv_tm_sender, - TEST_APID, verification_handler, in_store_converter, ), ) } - pub fn send_tc(&mut self, tc: &PusTcCreator) -> VerificationToken { - let token = self.verification_handler.add_tc(tc); - let token = self - .verification_handler - .acceptance_success(token, &[0; 7]) - .unwrap(); - let tc_size = tc.write_to_bytes(&mut self.pus_buf).unwrap(); + pub fn send_tc(&self, token: &VerificationToken, tc: &PusTcCreator) { + let mut mut_buf = self.pus_buf.borrow_mut(); + let tc_size = tc.write_to_bytes(mut_buf.as_mut_slice()).unwrap(); let mut tc_pool = self.tc_pool.write().unwrap(); - let addr = tc_pool.add(&self.pus_buf[..tc_size]).unwrap(); + let addr = tc_pool.add(&mut_buf[..tc_size]).unwrap(); drop(tc_pool); // Send accepted TC to test service handler. self.tc_sender - .send(EcssTcAndToken::new(addr, token)) + .send(EcssTcAndToken::new(addr, *token)) .expect("sending tc failed"); - token } pub fn read_next_tm(&mut self) -> PusTmReader<'_> { let next_msg = self.tm_receiver.try_recv(); assert!(next_msg.is_ok()); - let tm_addr = next_msg.unwrap(); + let tm_in_pool = next_msg.unwrap(); let tm_pool = self.tm_pool.0.read().unwrap(); - let tm_raw = tm_pool.read_as_vec(&tm_addr).unwrap(); + let tm_raw = tm_pool.read_as_vec(&tm_in_pool.store_addr).unwrap(); self.tm_buf[0..tm_raw.len()].copy_from_slice(&tm_raw); PusTmReader::new(&self.tm_buf, 7).unwrap().0 } @@ -1616,9 +1588,9 @@ pub mod tests { pub fn check_next_verification_tm(&self, subservice: u8, expected_request_id: RequestId) { let next_msg = self.tm_receiver.try_recv(); assert!(next_msg.is_ok()); - let tm_addr = next_msg.unwrap(); + let tm_in_pool = next_msg.unwrap(); let tm_pool = self.tm_pool.0.read().unwrap(); - let tm_raw = tm_pool.read_as_vec(&tm_addr).unwrap(); + let tm_raw = tm_pool.read_as_vec(&tm_in_pool.store_addr).unwrap(); let tm = PusTmReader::new(&tm_raw, 7).unwrap().0; assert_eq!(PusPacket::service(&tm), 1); assert_eq!(PusPacket::subservice(&tm), subservice); @@ -1629,56 +1601,49 @@ pub mod tests { } } - pub struct PusServiceHandlerWithVecCommon { - current_tm: Option>, + pub struct PusServiceHandlerWithVecCommon { + current_tm: Option>, tc_sender: mpsc::Sender, - tm_receiver: mpsc::Receiver>, - pub verification_handler: VerificationReporter, + tm_receiver: mpsc::Receiver, } pub type PusServiceHelperDynamic = PusServiceHelper< MpscTcReceiver, - TmAsVecSenderWithMpsc, + MpscTmAsVecSender, EcssTcInVecConverter, - VerificationReporterWithVecMpscSender, + TestVerificationReporter, >; - impl PusServiceHandlerWithVecCommon { - pub fn new_with_standard_verif_reporter() -> (Self, PusServiceHelperDynamic) { + impl PusServiceHandlerWithVecCommon { + pub fn new_with_standard_verif_reporter( + id: ComponentId, + ) -> (Self, PusServiceHelperDynamic) { let (test_srv_tc_tx, test_srv_tc_rx) = mpsc::channel(); let (tm_tx, tm_rx) = mpsc::channel(); - 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, verif_sender); - - 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(); ( Self { current_tm: None, tc_sender: test_srv_tc_tx, tm_receiver: tm_rx, - verification_handler: verification_handler.clone(), }, PusServiceHelper::new( - test_srv_tc_receiver, - test_srv_tm_sender, - TEST_APID, - verification_handler, + id, + test_srv_tc_rx, + tm_tx, + TestVerificationReporter::default(), in_store_converter, ), ) } } - impl PusServiceHandlerWithVecCommon { + impl PusServiceHandlerWithVecCommon { pub fn new_with_test_verif_sender() -> ( Self, PusServiceHelper< MpscTcReceiver, - TmAsVecSenderWithMpsc, + MpscTmAsVecSender, EcssTcInVecConverter, TestVerificationReporter, >, @@ -1686,22 +1651,19 @@ pub mod tests { let (test_srv_tc_tx, test_srv_tc_rx) = mpsc::channel(); let (tm_tx, tm_rx) = mpsc::channel(); - 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(); - let verification_handler = TestVerificationReporter::new(shared_verif_map); + let verification_handler = TestVerificationReporter::default(); ( Self { current_tm: None, tc_sender: test_srv_tc_tx, tm_receiver: tm_rx, - verification_handler: verification_handler.clone(), + //verification_handler: verification_handler.clone(), }, PusServiceHelper::new( - test_srv_tc_receiver, - test_srv_tm_sender, - TEST_APID, + TEST_COMPONENT_ID.raw(), + test_srv_tc_rx, + tm_tx, verification_handler, in_store_converter, ), @@ -1709,29 +1671,21 @@ pub mod tests { } } - impl - PusServiceHandlerWithVecCommon - { - pub fn send_tc(&mut self, tc: &PusTcCreator) -> VerificationToken { - let token = self.verification_handler.add_tc(tc); - let token = self - .verification_handler - .acceptance_success(token, &[0; 7]) - .unwrap(); + impl PusServiceHandlerWithVecCommon { + pub fn send_tc(&self, token: &VerificationToken, tc: &PusTcCreator) { // Send accepted TC to test service handler. self.tc_sender .send(EcssTcAndToken::new( TcInMemory::Vec(tc.to_vec().expect("pus tc conversion to vec failed")), - token, + *token, )) .expect("sending tc failed"); - token } pub fn read_next_tm(&mut self) -> PusTmReader<'_> { let next_msg = self.tm_receiver.try_recv(); assert!(next_msg.is_ok()); - self.current_tm = Some(next_msg.unwrap()); + self.current_tm = Some(next_msg.unwrap().packet); PusTmReader::new(self.current_tm.as_ref().unwrap(), 7) .unwrap() .0 @@ -1749,7 +1703,7 @@ pub mod tests { let next_msg = self.tm_receiver.try_recv(); assert!(next_msg.is_ok()); let next_msg = next_msg.unwrap(); - let tm = PusTmReader::new(next_msg.as_slice(), 7).unwrap().0; + let tm = PusTmReader::new(next_msg.packet.as_slice(), 7).unwrap().0; assert_eq!(PusPacket::service(&tm), 1); assert_eq!(PusPacket::subservice(&tm), subservice); assert_eq!(tm.apid(), TEST_APID); diff --git a/satrs/src/pus/mode.rs b/satrs/src/pus/mode.rs index be2df24..88d70d1 100644 --- a/satrs/src/pus/mode.rs +++ b/satrs/src/pus/mode.rs @@ -31,139 +31,7 @@ pub mod alloc_mod {} #[cfg(feature = "alloc")] #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] -pub mod std_mod { - /* - use spacepackets::{ - ecss::tm::{PusTmCreator, PusTmSecondaryHeader}, - util::UnsignedEnum, - SpHeader, - }; - - pub trait ModeReplyHook: ReplyHandlerHook { - fn wrong_mode_result_code(&self) -> ResultU16; - fn can_not_reach_mode_result_code(&self) -> ResultU16; - } - - /// Type definition for a PUS mode servicd reply handler which constrains the - /// [PusServiceReplyHandler] active request and reply generics to the [ActiveActionRequest] and - /// [ActionReplyPusWithIds] type. - pub type PusModeServiceReplyHandler< - VerificationReporter, - ActiveRequestMap, - UserHook, - TmSender, - > = PusServiceReplyHandler< - VerificationReporter, - ActiveRequestMap, - UserHook, - TmSender, - ActivePusRequest, - ModeReply, - >; - - impl< - VerificationReporter: VerificationReportingProvider, - ActiveRequestMap: ActiveRequestMapProvider, - UserHook: ModeReplyHook, - TmSender: EcssTmSenderCore, - > PusModeServiceReplyHandler - { - /// Helper method to register a recently routed action request. - pub fn add_routed_mode_request( - &mut self, - request_id: verification::RequestId, - target_id: TargetId, - token: VerificationToken, - timeout: Duration, - ) { - self.active_request_map.insert( - &request_id.into(), - ActivePusRequest { - target_id, - token, - start_time: self.current_time, - timeout, - }, - ) - } - - /// Main handler function to handle all received action replies. - pub fn handle_mode_reply( - &mut self, - mode_reply_with_id: &GenericModeReply, - time_stamp: &[u8], - ) -> Result<(), EcssTmtcError> { - let active_req = self.active_request_map.get(mode_reply_with_id.request_id); - if active_req.is_none() { - self.user_hook.handle_unexpected_reply(mode_reply_with_id); - return Ok(()); - } - let active_req = active_req.unwrap().clone(); - let remove_entry = match mode_reply_with_id.message { - ModeReply::ModeReply(reply) => { - reply.write_to_be_bytes(&mut self.tm_buf)?; - let req_id = verification::RequestId::from(mode_reply_with_id.request_id); - let mut sp_header = SpHeader::tm_unseg( - req_id.packet_id().apid(), - req_id.packet_seq_ctrl().seq_count(), - 0, - ) - .expect("space packet header creation error"); - let sec_header = PusTmSecondaryHeader::new( - MODE_SERVICE_ID, - Subservice::TmModeReply as u8, - 0, - 0, - Some(time_stamp), - ); - let pus_tm = PusTmCreator::new(&mut sp_header, sec_header, &self.tm_buf, true); - self.tm_sender.send_tm(PusTmWrapper::Direct(pus_tm))?; - self.verification_reporter - .completion_success(active_req.token, time_stamp) - .map_err(|e| e.0)?; - true - } - ModeReply::CantReachMode(reason) => { - let fail_data_len = reason.write_to_be_bytes(&mut self.tm_buf)?; - self.verification_reporter - .completion_failure( - active_req.token, - FailParams::new( - time_stamp, - &self.user_hook.can_not_reach_mode_result_code(), - &self.tm_buf[0..fail_data_len], - ), - ) - .map_err(|e| e.0)?; - true - } - ModeReply::WrongMode { expected, reached } => { - let expected_len = expected.write_to_be_bytes(&mut self.tm_buf)?; - let reached_len = - reached.write_to_be_bytes(&mut self.tm_buf[expected_len..])?; - self.verification_reporter - .completion_failure( - active_req.token, - FailParams::new( - time_stamp, - &self.user_hook.can_not_reach_mode_result_code(), - &self.tm_buf[0..expected_len + reached_len], - ), - ) - .map_err(|e| e.0)?; - true - } - _ => true, - }; - if remove_entry { - self.active_request_map - .remove(mode_reply_with_id.request_id); - } - Ok(()) - } - } - */ -} +pub mod std_mod {} #[cfg(test)] mod tests { @@ -175,7 +43,7 @@ mod tests { ModeAndSubmode, ModeReply, ModeReplySender, ModeRequest, ModeRequestSender, ModeRequestorAndHandlerMpsc, ModeRequestorMpsc, }, - request::GenericMessage, + request::{GenericMessage, MessageMetadata}, }; const TEST_COMPONENT_ID_0: u64 = 5; @@ -196,24 +64,23 @@ mod tests { .send_mode_request(request_id, TEST_COMPONENT_ID_1, sent_request) .expect("send failed"); let request = request_receiver.recv().expect("recv failed"); - assert_eq!(request.request_id, 2); - assert_eq!(request.sender_id, TEST_COMPONENT_ID_0); + assert_eq!(request.request_id(), 2); + assert_eq!(request.sender_id(), TEST_COMPONENT_ID_0); assert_eq!(request.message, sent_request); // Send a reply and verify it arrives at the requestor. let mode_reply = ModeReply::ModeReply(ModeAndSubmode::new(1, 5)); reply_sender .send(GenericMessage::new( - request_id, - TEST_COMPONENT_ID_1, + MessageMetadata::new(request_id, TEST_COMPONENT_ID_1), mode_reply, )) .expect("send failed"); let reply = mode_requestor.try_recv_mode_reply().expect("recv failed"); assert!(reply.is_some()); let reply = reply.unwrap(); - assert_eq!(reply.sender_id, TEST_COMPONENT_ID_1); - assert_eq!(reply.request_id, 2); + assert_eq!(reply.sender_id(), TEST_COMPONENT_ID_1); + assert_eq!(reply.request_id(), 2); assert_eq!(reply.message, mode_reply); } @@ -252,8 +119,8 @@ mod tests { .expect("send failed"); let request = request_receiver_channel_1.recv().expect("recv failed"); - assert_eq!(request.request_id, 2); - assert_eq!(request.sender_id, TEST_COMPONENT_ID_0); + assert_eq!(request.request_id(), 2); + assert_eq!(request.sender_id(), TEST_COMPONENT_ID_0); assert_eq!(request.message, ModeRequest::ReadMode); } @@ -272,13 +139,16 @@ mod tests { // Send a request and verify it arrives at the receiver. let request_id = 2; - let sent_reply = ModeReply::ModeInfo(ModeAndSubmode::new(3, 5)); + let sent_reply = ModeReply::ModeReply(ModeAndSubmode::new(3, 5)); mode_connector - .send_mode_reply(request_id, TEST_COMPONENT_ID_2, sent_reply) + .send_mode_reply( + MessageMetadata::new(request_id, TEST_COMPONENT_ID_0), + sent_reply, + ) .expect("send failed"); let reply = reply_receiver_channel_2.recv().expect("recv failed"); - assert_eq!(reply.request_id, 2); - assert_eq!(reply.sender_id, TEST_COMPONENT_ID_0); + assert_eq!(reply.request_id(), 2); + assert_eq!(reply.sender_id(), TEST_COMPONENT_ID_0); assert_eq!(reply.message, sent_reply); } diff --git a/satrs/src/pus/scheduler.rs b/satrs/src/pus/scheduler.rs index cebcf2c..0c2f4db 100644 --- a/satrs/src/pus/scheduler.rs +++ b/satrs/src/pus/scheduler.rs @@ -9,9 +9,7 @@ use serde::{Deserialize, Serialize}; use spacepackets::ecss::scheduling::TimeWindowType; use spacepackets::ecss::tc::{GenericPusTcSecondaryHeader, IsPusTelecommand, PusTcReader}; use spacepackets::ecss::{PusError, PusPacket, WritablePusPacket}; -use spacepackets::time::{ - CcsdsTimeProvider, TimeReader, TimeWriter, TimestampError, UnixTimestamp, -}; +use spacepackets::time::{CcsdsTimeProvider, TimeReader, TimeWriter, TimestampError, UnixTime}; use spacepackets::{ByteConversionError, CcsdsPacket}; #[cfg(feature = "std")] use std::error::Error; @@ -147,9 +145,9 @@ pub enum ScheduleError { /// The first parameter is the current time, the second one the time margin, and the third one /// the release time. ReleaseTimeInTimeMargin { - current_time: UnixTimestamp, + current_time: UnixTime, time_margin: Duration, - release_time: UnixTimestamp, + release_time: UnixTime, }, /// Nested time-tagged commands are not allowed. NestedScheduledTc, @@ -256,7 +254,7 @@ pub trait PusSchedulerProvider { /// inside the telecommand packet pool. fn insert_unwrapped_and_stored_tc( &mut self, - time_stamp: UnixTimestamp, + time_stamp: UnixTime, info: TcInfo, ) -> Result<(), ScheduleError>; @@ -280,7 +278,7 @@ pub trait PusSchedulerProvider { } let user_data = pus_tc.user_data(); let stamp: Self::TimeProvider = TimeReader::from_bytes(user_data)?; - let unix_stamp = stamp.unix_stamp(); + let unix_stamp = stamp.unix_time(); let stamp_len = stamp.len_as_bytes(); self.insert_unwrapped_tc(unix_stamp, &user_data[stamp_len..], pool) } @@ -289,7 +287,7 @@ pub trait PusSchedulerProvider { /// needs to be stored inside the telecommand pool. fn insert_unwrapped_tc( &mut self, - time_stamp: UnixTimestamp, + time_stamp: UnixTime, tc: &[u8], pool: &mut (impl PoolProvider + ?Sized), ) -> Result { @@ -347,7 +345,10 @@ pub mod alloc_mod { }, vec::Vec, }; - use spacepackets::time::cds::{self, DaysLen24Bits}; + use spacepackets::time::{ + cds::{self, DaysLen24Bits}, + UnixTime, + }; use crate::pool::StoreAddr; @@ -397,8 +398,9 @@ pub mod alloc_mod { /// Currently, sub-schedules and groups are not supported. #[derive(Debug)] pub struct PusScheduler { - tc_map: BTreeMap>, - pub(crate) current_time: UnixTimestamp, + // TODO: Use MonotonicTime from tai-time crate instead of UnixTime and cache leap seconds. + tc_map: BTreeMap>, + pub(crate) current_time: UnixTime, time_margin: Duration, enabled: bool, } @@ -413,7 +415,7 @@ pub mod alloc_mod { /// added to the current time, it will not be inserted into the schedule. /// * `tc_buf_size` - Buffer for temporary storage of telecommand packets. This buffer /// should be large enough to accomodate the largest expected TC packets. - pub fn new(init_current_time: UnixTimestamp, time_margin: Duration) -> Self { + pub fn new(init_current_time: UnixTime, time_margin: Duration) -> Self { PusScheduler { tc_map: Default::default(), current_time: init_current_time, @@ -426,7 +428,7 @@ pub mod alloc_mod { #[cfg(feature = "std")] #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] pub fn new_with_current_init_time(time_margin: Duration) -> Result { - Ok(Self::new(UnixTimestamp::from_now()?, time_margin)) + Ok(Self::new(UnixTime::now()?, time_margin)) } pub fn num_scheduled_telecommands(&self) -> u64 { @@ -437,11 +439,11 @@ pub mod alloc_mod { num_entries } - pub fn update_time(&mut self, current_time: UnixTimestamp) { + pub fn update_time(&mut self, current_time: UnixTime) { self.current_time = current_time; } - pub fn current_time(&self) -> &UnixTimestamp { + pub fn current_time(&self) -> &UnixTime { &self.current_time } @@ -449,7 +451,7 @@ pub mod alloc_mod { /// inside the telecommand packet pool. pub fn insert_unwrapped_and_stored_tc( &mut self, - time_stamp: UnixTimestamp, + time_stamp: UnixTime, info: TcInfo, ) -> Result<(), ScheduleError> { if time_stamp < self.current_time + self.time_margin { @@ -474,7 +476,7 @@ pub mod alloc_mod { /// needs to be stored inside the telecommand pool. pub fn insert_unwrapped_tc( &mut self, - time_stamp: UnixTimestamp, + time_stamp: UnixTime, tc: &[u8], pool: &mut (impl PoolProvider + ?Sized), ) -> Result { @@ -501,7 +503,7 @@ pub mod alloc_mod { pus_tc: &(impl IsPusTelecommand + PusPacket + GenericPusTcSecondaryHeader), pool: &mut (impl PoolProvider + ?Sized), ) -> Result { - self.insert_wrapped_tc::(pus_tc, pool) + self.insert_wrapped_tc::(pus_tc, pool) } /// Insert a telecommand based on the fully wrapped time-tagged telecommand using a CDS @@ -511,7 +513,7 @@ pub mod alloc_mod { pus_tc: &(impl IsPusTelecommand + PusPacket + GenericPusTcSecondaryHeader), pool: &mut (impl PoolProvider + ?Sized), ) -> Result { - self.insert_wrapped_tc::>(pus_tc, pool) + self.insert_wrapped_tc::>(pus_tc, pool) } /// This function uses [Self::retrieve_by_time_filter] to extract all scheduled commands inside @@ -557,14 +559,13 @@ pub mod alloc_mod { &mut self, pool: &mut (impl PoolProvider + ?Sized), ) -> Result { - self.delete_by_time_filter(TimeWindow::::new_select_all(), pool) + self.delete_by_time_filter(TimeWindow::::new_select_all(), pool) } /// Retrieve a range over all scheduled commands. pub fn retrieve_all( &mut self, - ) -> alloc::collections::btree_map::Range<'_, UnixTimestamp, alloc::vec::Vec> - { + ) -> alloc::collections::btree_map::Range<'_, UnixTime, alloc::vec::Vec> { self.tc_map.range(..) } @@ -575,23 +576,23 @@ pub mod alloc_mod { pub fn retrieve_by_time_filter( &mut self, time_window: TimeWindow, - ) -> Range<'_, UnixTimestamp, alloc::vec::Vec> { + ) -> Range<'_, UnixTime, alloc::vec::Vec> { match time_window.time_window_type() { TimeWindowType::SelectAll => self.tc_map.range(..), TimeWindowType::TimeTagToTimeTag => { // This should be guaranteed to be valid by library API, so unwrap is okay - let start_time = time_window.start_time().unwrap().unix_stamp(); - let end_time = time_window.end_time().unwrap().unix_stamp(); + let start_time = time_window.start_time().unwrap().unix_time(); + let end_time = time_window.end_time().unwrap().unix_time(); self.tc_map.range(start_time..=end_time) } TimeWindowType::FromTimeTag => { // This should be guaranteed to be valid by library API, so unwrap is okay - let start_time = time_window.start_time().unwrap().unix_stamp(); + let start_time = time_window.start_time().unwrap().unix_time(); self.tc_map.range(start_time..) } TimeWindowType::ToTimeTag => { // This should be guaranteed to be valid by library API, so unwrap is okay - let end_time = time_window.end_time().unwrap().unix_stamp(); + let end_time = time_window.end_time().unwrap().unix_time(); self.tc_map.range(..=end_time) } } @@ -671,7 +672,7 @@ pub mod alloc_mod { #[cfg(feature = "std")] #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] pub fn update_time_from_now(&mut self) -> Result<(), SystemTimeError> { - self.current_time = UnixTimestamp::from_now()?; + self.current_time = UnixTime::now()?; Ok(()) } @@ -781,13 +782,13 @@ pub mod alloc_mod { } /// Retrieve all telecommands which should be release based on the current time. - pub fn telecommands_to_release(&self) -> Range<'_, UnixTimestamp, Vec> { + pub fn telecommands_to_release(&self) -> Range<'_, UnixTime, Vec> { self.tc_map.range(..=self.current_time) } } impl PusSchedulerProvider for PusScheduler { - type TimeProvider = cds::TimeProvider; + type TimeProvider = cds::CdsTime; /// This will disable the scheduler and clear the schedule as specified in 6.11.4.4. /// Be careful with this command as it will delete all the commands in the schedule. @@ -826,7 +827,7 @@ pub mod alloc_mod { fn insert_unwrapped_and_stored_tc( &mut self, - time_stamp: UnixTimestamp, + time_stamp: UnixTime, info: TcInfo, ) -> Result<(), ScheduleError> { if time_stamp < self.current_time + self.time_margin { @@ -858,15 +859,17 @@ mod tests { use alloc::collections::btree_map::Range; use spacepackets::ecss::tc::{PusTcCreator, PusTcReader, PusTcSecondaryHeader}; use spacepackets::ecss::WritablePusPacket; - use spacepackets::time::{cds, TimeWriter, UnixTimestamp}; + use spacepackets::time::{cds, TimeWriter, UnixTime}; use spacepackets::{PacketId, PacketSequenceCtrl, PacketType, SequenceFlags, SpHeader}; use std::time::Duration; use std::vec::Vec; #[allow(unused_imports)] use std::{println, vec}; - fn pus_tc_base(timestamp: UnixTimestamp, buf: &mut [u8]) -> (SpHeader, usize) { - let cds_time = cds::TimeProvider::from_unix_secs_with_u16_days(×tamp).unwrap(); + fn pus_tc_base(timestamp: UnixTime, buf: &mut [u8]) -> (SpHeader, usize) { + let cds_time = + cds::CdsTime::from_unix_time_with_u16_days(×tamp, cds::SubmillisPrecision::Absent) + .unwrap(); let len_time_stamp = cds_time.write_to_bytes(buf).unwrap(); let len_packet = base_ping_tc_simple_ctor(0, None) .write_to_bytes(&mut buf[len_time_stamp..]) @@ -877,23 +880,25 @@ mod tests { ) } - fn scheduled_tc(timestamp: UnixTimestamp, buf: &mut [u8]) -> PusTcCreator { + fn scheduled_tc(timestamp: UnixTime, buf: &mut [u8]) -> PusTcCreator { let (mut sph, len_app_data) = pus_tc_base(timestamp, buf); PusTcCreator::new_simple(&mut sph, 11, 4, Some(&buf[..len_app_data]), true) } - fn wrong_tc_service(timestamp: UnixTimestamp, buf: &mut [u8]) -> PusTcCreator { + fn wrong_tc_service(timestamp: UnixTime, buf: &mut [u8]) -> PusTcCreator { let (mut sph, len_app_data) = pus_tc_base(timestamp, buf); PusTcCreator::new_simple(&mut sph, 12, 4, Some(&buf[..len_app_data]), true) } - fn wrong_tc_subservice(timestamp: UnixTimestamp, buf: &mut [u8]) -> PusTcCreator { + fn wrong_tc_subservice(timestamp: UnixTime, buf: &mut [u8]) -> PusTcCreator { let (mut sph, len_app_data) = pus_tc_base(timestamp, buf); PusTcCreator::new_simple(&mut sph, 11, 5, Some(&buf[..len_app_data]), true) } - fn double_wrapped_time_tagged_tc(timestamp: UnixTimestamp, buf: &mut [u8]) -> PusTcCreator { - let cds_time = cds::TimeProvider::from_unix_secs_with_u16_days(×tamp).unwrap(); + fn double_wrapped_time_tagged_tc(timestamp: UnixTime, buf: &mut [u8]) -> PusTcCreator { + let cds_time = + cds::CdsTime::from_unix_time_with_u16_days(×tamp, cds::SubmillisPrecision::Absent) + .unwrap(); let len_time_stamp = cds_time.write_to_bytes(buf).unwrap(); let mut sph = SpHeader::tc_unseg(0x02, 0x34, 0).unwrap(); // app data should not matter, double wrapped time-tagged commands should be rejected right @@ -938,8 +943,7 @@ mod tests { #[test] fn test_enable_api() { - let mut scheduler = - PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); + let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); assert!(scheduler.is_enabled()); scheduler.disable(); assert!(!scheduler.is_enabled()); @@ -950,15 +954,14 @@ mod tests { #[test] fn test_reset() { let mut pool = StaticMemoryPool::new(StaticPoolConfig::new(vec![(10, 32), (5, 64)], false)); - let mut scheduler = - PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); + let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut buf: [u8; 32] = [0; 32]; let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, 0, None); scheduler .insert_unwrapped_and_stored_tc( - UnixTimestamp::new_only_seconds(100), + UnixTime::new_only_secs(100), TcInfo::new(tc_info_0.addr, tc_info_0.request_id), ) .unwrap(); @@ -967,7 +970,7 @@ mod tests { let tc_info_1 = ping_tc_to_store(&mut pool, &mut buf, 1, Some(app_data)); scheduler .insert_unwrapped_and_stored_tc( - UnixTimestamp::new_only_seconds(200), + UnixTime::new_only_secs(200), TcInfo::new(tc_info_1.addr, tc_info_1.request_id), ) .unwrap(); @@ -976,7 +979,7 @@ mod tests { let tc_info_2 = ping_tc_to_store(&mut pool, &mut buf, 2, Some(app_data)); scheduler .insert_unwrapped_and_stored_tc( - UnixTimestamp::new_only_seconds(300), + UnixTime::new_only_secs(300), TcInfo::new(tc_info_2.addr(), tc_info_2.request_id()), ) .unwrap(); @@ -993,12 +996,11 @@ mod tests { #[test] fn insert_multi_with_same_time() { - let mut scheduler = - PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); + let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); scheduler .insert_unwrapped_and_stored_tc( - UnixTimestamp::new_only_seconds(100), + UnixTime::new_only_secs(100), TcInfo::new( StoreAddr::from(StaticPoolAddr { pool_idx: 0, @@ -1015,7 +1017,7 @@ mod tests { scheduler .insert_unwrapped_and_stored_tc( - UnixTimestamp::new_only_seconds(100), + UnixTime::new_only_secs(100), TcInfo::new( StoreAddr::from(StaticPoolAddr { pool_idx: 0, @@ -1032,7 +1034,7 @@ mod tests { scheduler .insert_unwrapped_and_stored_tc( - UnixTimestamp::new_only_seconds(300), + UnixTime::new_only_secs(300), TcInfo::new( StaticPoolAddr { pool_idx: 0, @@ -1053,9 +1055,8 @@ mod tests { #[test] fn test_time_update() { - let mut scheduler = - PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); - let time = UnixTimestamp::new(1, 2).unwrap(); + let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); + let time = UnixTime::new(1, 2_000_000); scheduler.update_time(time); assert_eq!(scheduler.current_time(), &time); } @@ -1102,19 +1103,18 @@ mod tests { #[test] fn test_release_telecommands() { let mut pool = StaticMemoryPool::new(StaticPoolConfig::new(vec![(10, 32), (5, 64)], false)); - let mut scheduler = - PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); + let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut buf: [u8; 32] = [0; 32]; let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, 0, None); scheduler - .insert_unwrapped_and_stored_tc(UnixTimestamp::new_only_seconds(100), tc_info_0) + .insert_unwrapped_and_stored_tc(UnixTime::new_only_secs(100), tc_info_0) .expect("insertion failed"); let tc_info_1 = ping_tc_to_store(&mut pool, &mut buf, 1, None); scheduler - .insert_unwrapped_and_stored_tc(UnixTimestamp::new_only_seconds(200), tc_info_1) + .insert_unwrapped_and_stored_tc(UnixTime::new_only_secs(200), tc_info_1) .expect("insertion failed"); let mut i = 0; @@ -1124,7 +1124,7 @@ mod tests { }; // test 1: too early, no tcs - scheduler.update_time(UnixTimestamp::new_only_seconds(99)); + scheduler.update_time(UnixTime::new_only_secs(99)); let mut tc_buf: [u8; 128] = [0; 128]; scheduler @@ -1132,7 +1132,7 @@ mod tests { .expect("deletion failed"); // test 2: exact time stamp of tc, releases 1 tc - scheduler.update_time(UnixTimestamp::new_only_seconds(100)); + scheduler.update_time(UnixTime::new_only_secs(100)); let mut released = scheduler .release_telecommands(&mut test_closure_1, &mut pool) @@ -1147,7 +1147,7 @@ mod tests { true }; - scheduler.update_time(UnixTimestamp::new_only_seconds(206)); + scheduler.update_time(UnixTime::new_only_secs(206)); released = scheduler .release_telecommands_with_buffer(&mut test_closure_2, &mut pool, &mut tc_buf) @@ -1168,19 +1168,18 @@ mod tests { #[test] fn release_multi_with_same_time() { let mut pool = StaticMemoryPool::new(StaticPoolConfig::new(vec![(10, 32), (5, 64)], false)); - let mut scheduler = - PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); + let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut buf: [u8; 32] = [0; 32]; let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, 0, None); scheduler - .insert_unwrapped_and_stored_tc(UnixTimestamp::new_only_seconds(100), tc_info_0) + .insert_unwrapped_and_stored_tc(UnixTime::new_only_secs(100), tc_info_0) .expect("insertion failed"); let tc_info_1 = ping_tc_to_store(&mut pool, &mut buf, 1, None); scheduler - .insert_unwrapped_and_stored_tc(UnixTimestamp::new_only_seconds(100), tc_info_1) + .insert_unwrapped_and_stored_tc(UnixTime::new_only_secs(100), tc_info_1) .expect("insertion failed"); let mut i = 0; @@ -1195,7 +1194,7 @@ mod tests { }; // test 1: too early, no tcs - scheduler.update_time(UnixTimestamp::new_only_seconds(99)); + scheduler.update_time(UnixTime::new_only_secs(99)); let mut tc_buf: [u8; 128] = [0; 128]; let mut released = scheduler @@ -1204,7 +1203,7 @@ mod tests { assert_eq!(released, 0); // test 2: exact time stamp of tc, releases 2 tc - scheduler.update_time(UnixTimestamp::new_only_seconds(100)); + scheduler.update_time(UnixTime::new_only_secs(100)); released = scheduler .release_telecommands(&mut test_closure, &mut pool) @@ -1226,8 +1225,7 @@ mod tests { #[test] fn release_with_scheduler_disabled() { let mut pool = StaticMemoryPool::new(StaticPoolConfig::new(vec![(10, 32), (5, 64)], false)); - let mut scheduler = - PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); + let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); scheduler.disable(); @@ -1235,12 +1233,12 @@ mod tests { let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, 0, None); scheduler - .insert_unwrapped_and_stored_tc(UnixTimestamp::new_only_seconds(100), tc_info_0) + .insert_unwrapped_and_stored_tc(UnixTime::new_only_secs(100), tc_info_0) .expect("insertion failed"); let tc_info_1 = ping_tc_to_store(&mut pool, &mut buf, 1, None); scheduler - .insert_unwrapped_and_stored_tc(UnixTimestamp::new_only_seconds(200), tc_info_1) + .insert_unwrapped_and_stored_tc(UnixTime::new_only_secs(200), tc_info_1) .expect("insertion failed"); let mut i = 0; @@ -1252,14 +1250,14 @@ mod tests { let mut tc_buf: [u8; 128] = [0; 128]; // test 1: too early, no tcs - scheduler.update_time(UnixTimestamp::new_only_seconds(99)); + scheduler.update_time(UnixTime::new_only_secs(99)); scheduler .release_telecommands_with_buffer(&mut test_closure_1, &mut pool, &mut tc_buf) .expect("deletion failed"); // test 2: exact time stamp of tc, releases 1 tc - scheduler.update_time(UnixTimestamp::new_only_seconds(100)); + scheduler.update_time(UnixTime::new_only_secs(100)); let mut released = scheduler .release_telecommands(&mut test_closure_1, &mut pool) @@ -1273,7 +1271,7 @@ mod tests { true }; - scheduler.update_time(UnixTimestamp::new_only_seconds(206)); + scheduler.update_time(UnixTime::new_only_secs(206)); released = scheduler .release_telecommands(&mut test_closure_2, &mut pool) @@ -1292,8 +1290,7 @@ mod tests { #[test] fn insert_unwrapped_tc() { - let mut scheduler = - PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); + let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut pool = StaticMemoryPool::new(StaticPoolConfig::new(vec![(10, 32), (5, 64)], false)); let mut buf: [u8; 32] = [0; 32]; @@ -1301,7 +1298,7 @@ mod tests { let info = scheduler .insert_unwrapped_tc( - UnixTimestamp::new_only_seconds(100), + UnixTime::new_only_secs(100), &buf[..pool.len_of_data(&tc_info_0.addr()).unwrap()], &mut pool, ) @@ -1316,7 +1313,7 @@ mod tests { assert_eq!(scheduler.num_scheduled_telecommands(), 1); - scheduler.update_time(UnixTimestamp::new_only_seconds(101)); + scheduler.update_time(UnixTime::new_only_secs(101)); let mut addr_vec = Vec::new(); @@ -1340,15 +1337,14 @@ mod tests { #[test] fn insert_wrapped_tc() { - let mut scheduler = - PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); + let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut pool = StaticMemoryPool::new(StaticPoolConfig::new(vec![(10, 32), (5, 64)], false)); let mut buf: [u8; 32] = [0; 32]; - let tc = scheduled_tc(UnixTimestamp::new_only_seconds(100), &mut buf); + let tc = scheduled_tc(UnixTime::new_only_secs(100), &mut buf); - let info = match scheduler.insert_wrapped_tc::(&tc, &mut pool) { + let info = match scheduler.insert_wrapped_tc::(&tc, &mut pool) { Ok(addr) => addr, Err(e) => { panic!("unexpected error {e}"); @@ -1364,7 +1360,7 @@ mod tests { assert_eq!(scheduler.num_scheduled_telecommands(), 1); - scheduler.update_time(UnixTimestamp::new_only_seconds(101)); + scheduler.update_time(UnixTime::new_only_secs(101)); let mut addr_vec = Vec::new(); @@ -1390,15 +1386,14 @@ mod tests { #[test] fn insert_wrong_service() { - let mut scheduler = - PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); + let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut pool = StaticMemoryPool::new(StaticPoolConfig::new(vec![(10, 32), (5, 64)], false)); let mut buf: [u8; 32] = [0; 32]; - let tc = wrong_tc_service(UnixTimestamp::new_only_seconds(100), &mut buf); + let tc = wrong_tc_service(UnixTime::new_only_secs(100), &mut buf); - let err = scheduler.insert_wrapped_tc::(&tc, &mut pool); + let err = scheduler.insert_wrapped_tc::(&tc, &mut pool); assert!(err.is_err()); let err = err.unwrap_err(); match err { @@ -1413,15 +1408,14 @@ mod tests { #[test] fn insert_wrong_subservice() { - let mut scheduler = - PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); + let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut pool = StaticMemoryPool::new(StaticPoolConfig::new(vec![(10, 32), (5, 64)], false)); let mut buf: [u8; 32] = [0; 32]; - let tc = wrong_tc_subservice(UnixTimestamp::new_only_seconds(100), &mut buf); + let tc = wrong_tc_subservice(UnixTime::new_only_secs(100), &mut buf); - let err = scheduler.insert_wrapped_tc::(&tc, &mut pool); + let err = scheduler.insert_wrapped_tc::(&tc, &mut pool); assert!(err.is_err()); let err = err.unwrap_err(); match err { @@ -1436,11 +1430,10 @@ mod tests { #[test] fn insert_wrapped_tc_faulty_app_data() { - let mut scheduler = - PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); + let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut pool = StaticMemoryPool::new(StaticPoolConfig::new(vec![(10, 32), (5, 64)], false)); let tc = invalid_time_tagged_cmd(); - let insert_res = scheduler.insert_wrapped_tc::(&tc, &mut pool); + let insert_res = scheduler.insert_wrapped_tc::(&tc, &mut pool); assert!(insert_res.is_err()); let err = insert_res.unwrap_err(); match err { @@ -1451,12 +1444,11 @@ mod tests { #[test] fn insert_doubly_wrapped_time_tagged_cmd() { - let mut scheduler = - PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); + let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut pool = StaticMemoryPool::new(StaticPoolConfig::new(vec![(10, 32), (5, 64)], false)); let mut buf: [u8; 64] = [0; 64]; - let tc = double_wrapped_time_tagged_tc(UnixTimestamp::new_only_seconds(50), &mut buf); - let insert_res = scheduler.insert_wrapped_tc::(&tc, &mut pool); + let tc = double_wrapped_time_tagged_tc(UnixTime::new_only_secs(50), &mut buf); + let insert_res = scheduler.insert_wrapped_tc::(&tc, &mut pool); assert!(insert_res.is_err()); let err = insert_res.unwrap_err(); match err { @@ -1470,31 +1462,29 @@ mod tests { let scheduler = PusScheduler::new_with_current_init_time(Duration::from_secs(5)) .expect("creation from current time failed"); let current_time = scheduler.current_time; - assert!(current_time.unix_seconds > 0); + assert!(current_time.as_secs() > 0); } #[test] fn test_update_from_current() { - let mut scheduler = - PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); - assert_eq!(scheduler.current_time.unix_seconds, 0); + let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); + assert_eq!(scheduler.current_time.as_secs(), 0); scheduler .update_time_from_now() .expect("updating scheduler time from now failed"); - assert!(scheduler.current_time.unix_seconds > 0); + assert!(scheduler.current_time.as_secs() > 0); } #[test] fn release_time_within_time_margin() { - let mut scheduler = - PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); + let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut pool = StaticMemoryPool::new(StaticPoolConfig::new(vec![(10, 32), (5, 64)], false)); let mut buf: [u8; 32] = [0; 32]; - let tc = scheduled_tc(UnixTimestamp::new_only_seconds(4), &mut buf); - let insert_res = scheduler.insert_wrapped_tc::(&tc, &mut pool); + let tc = scheduled_tc(UnixTime::new_only_secs(4), &mut buf); + let insert_res = scheduler.insert_wrapped_tc::(&tc, &mut pool); assert!(insert_res.is_err()); let err = insert_res.unwrap_err(); match err { @@ -1503,9 +1493,9 @@ mod tests { time_margin, release_time, } => { - assert_eq!(current_time, UnixTimestamp::new_only_seconds(0)); + assert_eq!(current_time, UnixTime::new_only_secs(0)); assert_eq!(time_margin, Duration::from_secs(5)); - assert_eq!(release_time, UnixTimestamp::new_only_seconds(4)); + assert_eq!(release_time, UnixTime::new_only_secs(4)); } _ => panic!("unexepcted error {err}"), } @@ -1514,12 +1504,11 @@ mod tests { #[test] fn test_store_error_propagation_release() { let mut pool = StaticMemoryPool::new(StaticPoolConfig::new(vec![(10, 32), (5, 64)], false)); - let mut scheduler = - PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); + let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut buf: [u8; 32] = [0; 32]; let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, 0, None); scheduler - .insert_unwrapped_and_stored_tc(UnixTimestamp::new_only_seconds(100), tc_info_0) + .insert_unwrapped_and_stored_tc(UnixTime::new_only_secs(100), tc_info_0) .expect("insertion failed"); let mut i = 0; @@ -1532,7 +1521,7 @@ mod tests { pool.delete(tc_info_0.addr()).expect("deletion failed"); // scheduler will only auto-delete if it is disabled. scheduler.disable(); - scheduler.update_time(UnixTimestamp::new_only_seconds(100)); + scheduler.update_time(UnixTime::new_only_secs(100)); let release_res = scheduler.release_telecommands(test_closure_1, &mut pool); assert!(release_res.is_err()); let err = release_res.unwrap_err(); @@ -1549,12 +1538,11 @@ mod tests { #[test] fn test_store_error_propagation_reset() { let mut pool = StaticMemoryPool::new(StaticPoolConfig::new(vec![(10, 32), (5, 64)], false)); - let mut scheduler = - PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); + let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut buf: [u8; 32] = [0; 32]; let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, 0, None); scheduler - .insert_unwrapped_and_stored_tc(UnixTimestamp::new_only_seconds(100), tc_info_0) + .insert_unwrapped_and_stored_tc(UnixTime::new_only_secs(100), tc_info_0) .expect("insertion failed"); // premature deletion @@ -1573,12 +1561,11 @@ mod tests { #[test] fn test_delete_by_req_id_simple_retrieve_addr() { let mut pool = StaticMemoryPool::new(StaticPoolConfig::new(vec![(10, 32), (5, 64)], false)); - let mut scheduler = - PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); + let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut buf: [u8; 32] = [0; 32]; let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, 0, None); scheduler - .insert_unwrapped_and_stored_tc(UnixTimestamp::new_only_seconds(100), tc_info_0) + .insert_unwrapped_and_stored_tc(UnixTime::new_only_secs(100), tc_info_0) .expect("inserting tc failed"); assert_eq!(scheduler.num_scheduled_telecommands(), 1); let addr = scheduler @@ -1592,12 +1579,11 @@ mod tests { #[test] fn test_delete_by_req_id_simple_delete_all() { let mut pool = StaticMemoryPool::new(StaticPoolConfig::new(vec![(10, 32), (5, 64)], false)); - let mut scheduler = - PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); + let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut buf: [u8; 32] = [0; 32]; let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, 0, None); scheduler - .insert_unwrapped_and_stored_tc(UnixTimestamp::new_only_seconds(100), tc_info_0) + .insert_unwrapped_and_stored_tc(UnixTime::new_only_secs(100), tc_info_0) .expect("inserting tc failed"); assert_eq!(scheduler.num_scheduled_telecommands(), 1); let del_res = @@ -1611,20 +1597,19 @@ mod tests { #[test] fn test_delete_by_req_id_complex() { let mut pool = StaticMemoryPool::new(StaticPoolConfig::new(vec![(10, 32), (5, 64)], false)); - let mut scheduler = - PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); + let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut buf: [u8; 32] = [0; 32]; let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, 0, None); scheduler - .insert_unwrapped_and_stored_tc(UnixTimestamp::new_only_seconds(100), tc_info_0) + .insert_unwrapped_and_stored_tc(UnixTime::new_only_secs(100), tc_info_0) .expect("inserting tc failed"); let tc_info_1 = ping_tc_to_store(&mut pool, &mut buf, 1, None); scheduler - .insert_unwrapped_and_stored_tc(UnixTimestamp::new_only_seconds(100), tc_info_1) + .insert_unwrapped_and_stored_tc(UnixTime::new_only_secs(100), tc_info_1) .expect("inserting tc failed"); let tc_info_2 = ping_tc_to_store(&mut pool, &mut buf, 2, None); scheduler - .insert_unwrapped_and_stored_tc(UnixTimestamp::new_only_seconds(100), tc_info_2) + .insert_unwrapped_and_stored_tc(UnixTime::new_only_secs(100), tc_info_2) .expect("inserting tc failed"); assert_eq!(scheduler.num_scheduled_telecommands(), 3); @@ -1654,17 +1639,16 @@ mod tests { #[test] fn insert_full_store_test() { - let mut scheduler = - PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); + let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut pool = StaticMemoryPool::new(StaticPoolConfig::new(vec![(1, 64)], false)); let mut buf: [u8; 32] = [0; 32]; // Store is full after this. pool.add(&[0, 1, 2]).unwrap(); - let tc = scheduled_tc(UnixTimestamp::new_only_seconds(100), &mut buf); + let tc = scheduled_tc(UnixTime::new_only_secs(100), &mut buf); - let insert_res = scheduler.insert_wrapped_tc::(&tc, &mut pool); + let insert_res = scheduler.insert_wrapped_tc::(&tc, &mut pool); assert!(insert_res.is_err()); let err = insert_res.unwrap_err(); match err { @@ -1686,10 +1670,7 @@ mod tests { let tc_info = ping_tc_to_store(pool, &mut buf, seq_count, None); scheduler - .insert_unwrapped_and_stored_tc( - UnixTimestamp::new_only_seconds(release_secs as i64), - tc_info, - ) + .insert_unwrapped_and_stored_tc(UnixTime::new_only_secs(release_secs as i64), tc_info) .expect("inserting tc failed"); tc_info } @@ -1697,21 +1678,20 @@ mod tests { #[test] fn test_time_window_retrieval_select_all() { let mut pool = StaticMemoryPool::new(StaticPoolConfig::new(vec![(10, 32), (5, 64)], false)); - let mut scheduler = - PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); + let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let tc_info_0 = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 50); let tc_info_1 = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 100); assert_eq!(scheduler.num_scheduled_telecommands(), 2); - let check_range = |range: Range>| { + let check_range = |range: Range>| { let mut tcs_in_range = 0; for (idx, time_bucket) in range.enumerate() { tcs_in_range += 1; if idx == 0 { - assert_eq!(*time_bucket.0, UnixTimestamp::new_only_seconds(50)); + assert_eq!(*time_bucket.0, UnixTime::new_only_secs(50)); assert_eq!(time_bucket.1.len(), 1); assert_eq!(time_bucket.1[0].request_id, tc_info_0.request_id); } else if idx == 1 { - assert_eq!(*time_bucket.0, UnixTimestamp::new_only_seconds(100)); + assert_eq!(*time_bucket.0, UnixTime::new_only_secs(100)); assert_eq!(time_bucket.1.len(), 1); assert_eq!(time_bucket.1[0].request_id, tc_info_1.request_id); } @@ -1720,22 +1700,22 @@ mod tests { }; let range = scheduler.retrieve_all(); check_range(range); - let range = - scheduler.retrieve_by_time_filter(TimeWindow::::new_select_all()); + let range = scheduler.retrieve_by_time_filter(TimeWindow::::new_select_all()); check_range(range); } #[test] fn test_time_window_retrieval_select_from_stamp() { let mut pool = StaticMemoryPool::new(StaticPoolConfig::new(vec![(10, 32), (5, 64)], false)); - let mut scheduler = - PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); + let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let _ = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 50); let tc_info_1 = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 100); let tc_info_2 = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 150); - let start_stamp = - cds::TimeProvider::from_unix_secs_with_u16_days(&UnixTimestamp::new_only_seconds(100)) - .expect("creating start stamp failed"); + let start_stamp = cds::CdsTime::from_unix_time_with_u16_days( + &UnixTime::new_only_secs(100), + cds::SubmillisPrecision::Absent, + ) + .expect("creating start stamp failed"); let time_window = TimeWindow::new_from_time(&start_stamp); assert_eq!(scheduler.num_scheduled_telecommands(), 3); @@ -1744,11 +1724,11 @@ mod tests { for (idx, time_bucket) in range.enumerate() { tcs_in_range += 1; if idx == 0 { - assert_eq!(*time_bucket.0, UnixTimestamp::new_only_seconds(100)); + assert_eq!(*time_bucket.0, UnixTime::new_only_secs(100)); assert_eq!(time_bucket.1.len(), 1); assert_eq!(time_bucket.1[0].request_id, tc_info_1.request_id()); } else if idx == 1 { - assert_eq!(*time_bucket.0, UnixTimestamp::new_only_seconds(150)); + assert_eq!(*time_bucket.0, UnixTime::new_only_secs(150)); assert_eq!(time_bucket.1.len(), 1); assert_eq!(time_bucket.1[0].request_id, tc_info_2.request_id()); } @@ -1759,27 +1739,28 @@ mod tests { #[test] fn test_time_window_retrieval_select_to_time() { let mut pool = StaticMemoryPool::new(StaticPoolConfig::new(vec![(10, 32), (5, 64)], false)); - let mut scheduler = - PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); + let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let tc_info_0 = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 50); let tc_info_1 = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 100); let _ = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 150); assert_eq!(scheduler.num_scheduled_telecommands(), 3); - let end_stamp = - cds::TimeProvider::from_unix_secs_with_u16_days(&UnixTimestamp::new_only_seconds(100)) - .expect("creating start stamp failed"); + let end_stamp = cds::CdsTime::from_unix_time_with_u16_days( + &UnixTime::new_only_secs(100), + cds::SubmillisPrecision::Absent, + ) + .expect("creating start stamp failed"); let time_window = TimeWindow::new_to_time(&end_stamp); let range = scheduler.retrieve_by_time_filter(time_window); let mut tcs_in_range = 0; for (idx, time_bucket) in range.enumerate() { tcs_in_range += 1; if idx == 0 { - assert_eq!(*time_bucket.0, UnixTimestamp::new_only_seconds(50)); + assert_eq!(*time_bucket.0, UnixTime::new_only_secs(50)); assert_eq!(time_bucket.1.len(), 1); assert_eq!(time_bucket.1[0].request_id, tc_info_0.request_id()); } else if idx == 1 { - assert_eq!(*time_bucket.0, UnixTimestamp::new_only_seconds(100)); + assert_eq!(*time_bucket.0, UnixTime::new_only_secs(100)); assert_eq!(time_bucket.1.len(), 1); assert_eq!(time_bucket.1[0].request_id, tc_info_1.request_id()); } @@ -1790,31 +1771,34 @@ mod tests { #[test] fn test_time_window_retrieval_select_from_time_to_time() { let mut pool = StaticMemoryPool::new(StaticPoolConfig::new(vec![(10, 32), (5, 64)], false)); - let mut scheduler = - PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); + let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let _ = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 50); let tc_info_1 = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 100); let tc_info_2 = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 150); let _ = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 200); assert_eq!(scheduler.num_scheduled_telecommands(), 4); - let start_stamp = - cds::TimeProvider::from_unix_secs_with_u16_days(&UnixTimestamp::new_only_seconds(100)) - .expect("creating start stamp failed"); - let end_stamp = - cds::TimeProvider::from_unix_secs_with_u16_days(&UnixTimestamp::new_only_seconds(150)) - .expect("creating end stamp failed"); + let start_stamp = cds::CdsTime::from_unix_time_with_u16_days( + &UnixTime::new_only_secs(100), + cds::SubmillisPrecision::Absent, + ) + .expect("creating start stamp failed"); + let end_stamp = cds::CdsTime::from_unix_time_with_u16_days( + &UnixTime::new_only_secs(150), + cds::SubmillisPrecision::Absent, + ) + .expect("creating end stamp failed"); let time_window = TimeWindow::new_from_time_to_time(&start_stamp, &end_stamp); let range = scheduler.retrieve_by_time_filter(time_window); let mut tcs_in_range = 0; for (idx, time_bucket) in range.enumerate() { tcs_in_range += 1; if idx == 0 { - assert_eq!(*time_bucket.0, UnixTimestamp::new_only_seconds(100)); + assert_eq!(*time_bucket.0, UnixTime::new_only_secs(100)); assert_eq!(time_bucket.1.len(), 1); assert_eq!(time_bucket.1[0].request_id, tc_info_1.request_id()); } else if idx == 1 { - assert_eq!(*time_bucket.0, UnixTimestamp::new_only_seconds(150)); + assert_eq!(*time_bucket.0, UnixTime::new_only_secs(150)); assert_eq!(time_bucket.1.len(), 1); assert_eq!(time_bucket.1[0].request_id, tc_info_2.request_id()); } @@ -1825,8 +1809,7 @@ mod tests { #[test] fn test_deletion_all() { let mut pool = StaticMemoryPool::new(StaticPoolConfig::new(vec![(10, 32), (5, 64)], false)); - let mut scheduler = - PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); + let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); insert_command_with_release_time(&mut pool, &mut scheduler, 0, 50); insert_command_with_release_time(&mut pool, &mut scheduler, 0, 100); assert_eq!(scheduler.num_scheduled_telecommands(), 2); @@ -1841,7 +1824,7 @@ mod tests { insert_command_with_release_time(&mut pool, &mut scheduler, 0, 100); assert_eq!(scheduler.num_scheduled_telecommands(), 2); let del_res = scheduler - .delete_by_time_filter(TimeWindow::::new_select_all(), &mut pool); + .delete_by_time_filter(TimeWindow::::new_select_all(), &mut pool); assert!(del_res.is_ok()); assert_eq!(del_res.unwrap(), 2); assert_eq!(scheduler.num_scheduled_telecommands(), 0); @@ -1852,15 +1835,16 @@ mod tests { #[test] fn test_deletion_from_start_time() { let mut pool = StaticMemoryPool::new(StaticPoolConfig::new(vec![(10, 32), (5, 64)], false)); - let mut scheduler = - PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); + let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); insert_command_with_release_time(&mut pool, &mut scheduler, 0, 50); let cmd_0_to_delete = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 100); let cmd_1_to_delete = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 150); assert_eq!(scheduler.num_scheduled_telecommands(), 3); - let start_stamp = - cds::TimeProvider::from_unix_secs_with_u16_days(&UnixTimestamp::new_only_seconds(100)) - .expect("creating start stamp failed"); + let start_stamp = cds::CdsTime::from_unix_time_with_u16_days( + &UnixTime::new_only_secs(100), + cds::SubmillisPrecision::Absent, + ) + .expect("creating start stamp failed"); let time_window = TimeWindow::new_from_time(&start_stamp); let del_res = scheduler.delete_by_time_filter(time_window, &mut pool); assert!(del_res.is_ok()); @@ -1873,16 +1857,17 @@ mod tests { #[test] fn test_deletion_to_end_time() { let mut pool = StaticMemoryPool::new(StaticPoolConfig::new(vec![(10, 32), (5, 64)], false)); - let mut scheduler = - PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); + let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let cmd_0_to_delete = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 50); let cmd_1_to_delete = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 100); insert_command_with_release_time(&mut pool, &mut scheduler, 0, 150); assert_eq!(scheduler.num_scheduled_telecommands(), 3); - let end_stamp = - cds::TimeProvider::from_unix_secs_with_u16_days(&UnixTimestamp::new_only_seconds(100)) - .expect("creating start stamp failed"); + let end_stamp = cds::CdsTime::from_unix_time_with_u16_days( + &UnixTime::new_only_secs(100), + cds::SubmillisPrecision::Absent, + ) + .expect("creating start stamp failed"); let time_window = TimeWindow::new_to_time(&end_stamp); let del_res = scheduler.delete_by_time_filter(time_window, &mut pool); assert!(del_res.is_ok()); @@ -1895,8 +1880,7 @@ mod tests { #[test] fn test_deletion_from_start_time_to_end_time() { let mut pool = StaticMemoryPool::new(StaticPoolConfig::new(vec![(10, 32), (5, 64)], false)); - let mut scheduler = - PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); + let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let cmd_out_of_range_0 = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 50); let cmd_0_to_delete = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 100); let cmd_1_to_delete = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 150); @@ -1904,12 +1888,16 @@ mod tests { insert_command_with_release_time(&mut pool, &mut scheduler, 0, 200); assert_eq!(scheduler.num_scheduled_telecommands(), 4); - let start_stamp = - cds::TimeProvider::from_unix_secs_with_u16_days(&UnixTimestamp::new_only_seconds(100)) - .expect("creating start stamp failed"); - let end_stamp = - cds::TimeProvider::from_unix_secs_with_u16_days(&UnixTimestamp::new_only_seconds(150)) - .expect("creating end stamp failed"); + let start_stamp = cds::CdsTime::from_unix_time_with_u16_days( + &UnixTime::new_only_secs(100), + cds::SubmillisPrecision::Absent, + ) + .expect("creating start stamp failed"); + let end_stamp = cds::CdsTime::from_unix_time_with_u16_days( + &UnixTime::new_only_secs(150), + cds::SubmillisPrecision::Absent, + ) + .expect("creating end stamp failed"); let time_window = TimeWindow::new_from_time_to_time(&start_stamp, &end_stamp); let del_res = scheduler.delete_by_time_filter(time_window, &mut pool); assert!(del_res.is_ok()); @@ -1924,19 +1912,18 @@ mod tests { #[test] fn test_release_without_deletion() { let mut pool = StaticMemoryPool::new(StaticPoolConfig::new(vec![(10, 32), (5, 64)], false)); - let mut scheduler = - PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); + let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut buf: [u8; 32] = [0; 32]; let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, 0, None); scheduler - .insert_unwrapped_and_stored_tc(UnixTimestamp::new_only_seconds(100), tc_info_0) + .insert_unwrapped_and_stored_tc(UnixTime::new_only_secs(100), tc_info_0) .expect("insertion failed"); let tc_info_1 = ping_tc_to_store(&mut pool, &mut buf, 1, None); scheduler - .insert_unwrapped_and_stored_tc(UnixTimestamp::new_only_seconds(200), tc_info_1) + .insert_unwrapped_and_stored_tc(UnixTime::new_only_secs(200), tc_info_1) .expect("insertion failed"); let mut i = 0; @@ -1949,7 +1936,7 @@ mod tests { ); }; - scheduler.update_time(UnixTimestamp::new_only_seconds(205)); + scheduler.update_time(UnixTime::new_only_secs(205)); let mut tc_buf: [u8; 64] = [0; 64]; let tc_info_vec = scheduler @@ -1961,7 +1948,7 @@ mod tests { #[test] fn test_generic_insert_app_data_test() { - let time_writer = cds::TimeProvider::new_with_u16_days(1, 1); + let time_writer = cds::CdsTime::new_with_u16_days(1, 1); let mut sph = SpHeader::new( PacketId::const_new(PacketType::Tc, true, 0x002), PacketSequenceCtrl::const_new(SequenceFlags::Unsegmented, 5), @@ -1975,7 +1962,7 @@ mod tests { assert_eq!(result.unwrap(), 2 + 7 + ping_tc.len_written()); let n = u16::from_be_bytes(buf[0..2].try_into().unwrap()); assert_eq!(n, 1); - let time_reader = cds::TimeProvider::from_bytes_with_u16_days(&buf[2..2 + 7]).unwrap(); + let time_reader = cds::CdsTime::from_bytes_with_u16_days(&buf[2..2 + 7]).unwrap(); assert_eq!(time_reader, time_writer); let pus_tc_reader = PusTcReader::new(&buf[9..]).unwrap().0; assert_eq!(pus_tc_reader, ping_tc); @@ -1983,7 +1970,7 @@ mod tests { #[test] fn test_generic_insert_app_data_test_byte_conv_error() { - let time_writer = cds::TimeProvider::new_with_u16_days(1, 1); + let time_writer = cds::CdsTime::new_with_u16_days(1, 1); let mut sph = SpHeader::new( PacketId::const_new(PacketType::Tc, true, 0x002), PacketSequenceCtrl::const_new(SequenceFlags::Unsegmented, 5), @@ -2012,7 +1999,7 @@ mod tests { #[test] fn test_generic_insert_app_data_test_as_vec() { - let time_writer = cds::TimeProvider::new_with_u16_days(1, 1); + let time_writer = cds::CdsTime::new_with_u16_days(1, 1); let mut sph = SpHeader::new( PacketId::const_new(PacketType::Tc, true, 0x002), PacketSequenceCtrl::const_new(SequenceFlags::Unsegmented, 5), diff --git a/satrs/src/pus/scheduler_srv.rs b/satrs/src/pus/scheduler_srv.rs index ef42932..6296798 100644 --- a/satrs/src/pus/scheduler_srv.rs +++ b/satrs/src/pus/scheduler_srv.rs @@ -1,19 +1,16 @@ use super::scheduler::PusSchedulerProvider; -use super::verification::{ - VerificationReporterWithSharedPoolMpscBoundedSender, - VerificationReporterWithSharedPoolMpscSender, VerificationReporterWithVecMpscBoundedSender, - VerificationReporterWithVecMpscSender, VerificationReportingProvider, -}; +use super::verification::{VerificationReporter, VerificationReportingProvider}; use super::{ EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter, EcssTcReceiverCore, - EcssTmSenderCore, MpscTcReceiver, PusServiceHelper, TmAsVecSenderWithBoundedMpsc, - TmAsVecSenderWithMpsc, TmInSharedPoolSenderWithBoundedMpsc, TmInSharedPoolSenderWithMpsc, + EcssTmSenderCore, MpscTcReceiver, MpscTmInSharedPoolSender, MpscTmInSharedPoolSenderBounded, + PusServiceHelper, PusTmAsVec, }; use crate::pool::PoolProvider; use crate::pus::{PusPacketHandlerResult, PusPacketHandlingError}; use alloc::string::ToString; use spacepackets::ecss::{scheduling, PusPacket}; -use spacepackets::time::cds::TimeProvider; +use spacepackets::time::cds::CdsTime; +use std::sync::mpsc; /// This is a helper class for [std] environments to handle generic PUS 11 (scheduling service) /// packets. This handler is able to handle the most important PUS requests for a scheduling @@ -23,7 +20,7 @@ use spacepackets::time::cds::TimeProvider; /// telecommands inside the scheduler. The user can retrieve the wrapped scheduler via the /// [Self::scheduler] and [Self::scheduler_mut] function and then use the scheduler API to release /// telecommands when applicable. -pub struct PusService11SchedHandler< +pub struct PusSchedServiceHandler< TcReceiver: EcssTcReceiverCore, TmSender: EcssTmSenderCore, TcInMemConverter: EcssTcInMemConverter, @@ -42,13 +39,7 @@ impl< VerificationReporter: VerificationReportingProvider, Scheduler: PusSchedulerProvider, > - PusService11SchedHandler< - TcReceiver, - TmSender, - TcInMemConverter, - VerificationReporter, - Scheduler, - > + PusSchedServiceHandler { pub fn new( service_helper: PusServiceHelper< @@ -101,14 +92,24 @@ impl< let start_token = self .service_helper .verif_reporter() - .start_success(ecss_tc_and_token.token, time_stamp) + .start_success( + self.service_helper.common.id, + &self.service_helper.common.tm_sender, + ecss_tc_and_token.token, + time_stamp, + ) .expect("Error sending start success"); self.scheduler.enable(); if self.scheduler.is_enabled() { self.service_helper .verif_reporter() - .completion_success(start_token, time_stamp) + .completion_success( + self.service_helper.common.id, + &self.service_helper.common.tm_sender, + start_token, + time_stamp, + ) .expect("Error sending completion success"); } else { return Err(PusPacketHandlingError::Other( @@ -120,14 +121,24 @@ impl< let start_token = self .service_helper .verif_reporter() - .start_success(ecss_tc_and_token.token, time_stamp) + .start_success( + self.service_helper.common.id, + &self.service_helper.common.tm_sender, + ecss_tc_and_token.token, + time_stamp, + ) .expect("Error sending start success"); self.scheduler.disable(); if !self.scheduler.is_enabled() { self.service_helper .verif_reporter() - .completion_success(start_token, time_stamp) + .completion_success( + self.service_helper.common.id, + &self.service_helper.common.tm_sender, + start_token, + time_stamp, + ) .expect("Error sending completion success"); } else { return Err(PusPacketHandlingError::Other( @@ -139,7 +150,12 @@ impl< let start_token = self .service_helper .verif_reporter() - .start_success(ecss_tc_and_token.token, time_stamp) + .start_success( + self.service_helper.common.id, + &self.service_helper.common.tm_sender, + ecss_tc_and_token.token, + time_stamp, + ) .expect("Error sending start success"); self.scheduler @@ -148,7 +164,12 @@ impl< self.service_helper .verif_reporter() - .completion_success(start_token, time_stamp) + .completion_success( + self.service_helper.common.id, + &self.service_helper.common.tm_sender, + start_token, + time_stamp, + ) .expect("Error sending completion success"); } scheduling::Subservice::TcInsertActivity => { @@ -156,17 +177,27 @@ impl< .service_helper .common .verif_reporter - .start_success(ecss_tc_and_token.token, time_stamp) + .start_success( + self.service_helper.common.id, + &self.service_helper.common.tm_sender, + ecss_tc_and_token.token, + time_stamp, + ) .expect("error sending start success"); // let mut pool = self.sched_tc_pool.write().expect("locking pool failed"); self.scheduler - .insert_wrapped_tc::(&tc, sched_tc_pool) + .insert_wrapped_tc::(&tc, sched_tc_pool) .expect("insertion of activity into pool failed"); self.service_helper .verif_reporter() - .completion_success(start_token, time_stamp) + .completion_success( + self.service_helper.common.id, + &self.service_helper.common.tm_sender, + start_token, + time_stamp, + ) .expect("sending completion success failed"); } _ => { @@ -187,38 +218,38 @@ impl< } /// Helper type definition for a PUS 11 handler with a dynamic TMTC memory backend and regular /// mpsc queues. -pub type PusService11SchedHandlerDynWithMpsc = PusService11SchedHandler< +pub type PusService11SchedHandlerDynWithMpsc = PusSchedServiceHandler< MpscTcReceiver, - TmAsVecSenderWithMpsc, + mpsc::Sender, EcssTcInVecConverter, - VerificationReporterWithVecMpscSender, + VerificationReporter, PusScheduler, >; /// Helper type definition for a PUS 11 handler with a dynamic TMTC memory backend and bounded MPSC /// queues. -pub type PusService11SchedHandlerDynWithBoundedMpsc = PusService11SchedHandler< +pub type PusService11SchedHandlerDynWithBoundedMpsc = PusSchedServiceHandler< MpscTcReceiver, - TmAsVecSenderWithBoundedMpsc, + mpsc::SyncSender, EcssTcInVecConverter, - VerificationReporterWithVecMpscBoundedSender, + VerificationReporter, PusScheduler, >; /// Helper type definition for a PUS 11 handler with a shared store TMTC memory backend and regular /// mpsc queues. -pub type PusService11SchedHandlerStaticWithMpsc = PusService11SchedHandler< +pub type PusService11SchedHandlerStaticWithMpsc = PusSchedServiceHandler< MpscTcReceiver, - TmInSharedPoolSenderWithMpsc, + MpscTmInSharedPoolSender, EcssTcInSharedStoreConverter, - VerificationReporterWithSharedPoolMpscSender, + VerificationReporter, PusScheduler, >; /// Helper type definition for a PUS 11 handler with a shared store TMTC memory backend and bounded /// mpsc queues. -pub type PusService11SchedHandlerStaticWithBoundedMpsc = PusService11SchedHandler< +pub type PusService11SchedHandlerStaticWithBoundedMpsc = PusSchedServiceHandler< MpscTcReceiver, - TmInSharedPoolSenderWithBoundedMpsc, + MpscTmInSharedPoolSenderBounded, EcssTcInSharedStoreConverter, - VerificationReporterWithSharedPoolMpscBoundedSender, + VerificationReporter, PusScheduler, >; @@ -226,7 +257,8 @@ pub type PusService11SchedHandlerStaticWithBoundedMpsc = PusServic mod tests { use crate::pool::{StaticMemoryPool, StaticPoolConfig}; use crate::pus::test_util::{PusTestHarness, TEST_APID}; - use crate::pus::verification::VerificationReporterWithSharedPoolMpscBoundedSender; + use crate::pus::verification::{VerificationReporter, VerificationReportingProvider}; + use crate::pus::{ scheduler::{self, PusSchedulerProvider, TcInfo}, tests::PusServiceHandlerWithSharedStoreCommon, @@ -234,8 +266,8 @@ mod tests { EcssTcInSharedStoreConverter, }; use crate::pus::{ - MpscTcReceiver, PusPacketHandlerResult, PusPacketHandlingError, - TmInSharedPoolSenderWithBoundedMpsc, + MpscTcReceiver, MpscTmInSharedPoolSenderBounded, PusPacketHandlerResult, + PusPacketHandlingError, }; use alloc::collections::VecDeque; use delegate::delegate; @@ -249,15 +281,15 @@ mod tests { time::cds, }; - use super::PusService11SchedHandler; + use super::PusSchedServiceHandler; struct Pus11HandlerWithStoreTester { common: PusServiceHandlerWithSharedStoreCommon, - handler: PusService11SchedHandler< + handler: PusSchedServiceHandler< MpscTcReceiver, - TmInSharedPoolSenderWithBoundedMpsc, + MpscTmInSharedPoolSenderBounded, EcssTcInSharedStoreConverter, - VerificationReporterWithSharedPoolMpscBoundedSender, + VerificationReporter, TestScheduler, >, sched_tc_pool: StaticMemoryPool, @@ -268,25 +300,39 @@ mod tests { let test_scheduler = TestScheduler::default(); let pool_cfg = StaticPoolConfig::new(alloc::vec![(16, 16), (8, 32), (4, 64)], false); let sched_tc_pool = StaticMemoryPool::new(pool_cfg.clone()); - let (common, srv_handler) = PusServiceHandlerWithSharedStoreCommon::new(); + let (common, srv_handler) = PusServiceHandlerWithSharedStoreCommon::new(0); Self { common, - handler: PusService11SchedHandler::new(srv_handler, test_scheduler), + handler: PusSchedServiceHandler::new(srv_handler, test_scheduler), sched_tc_pool, } } pub fn handle_one_tc(&mut self) -> Result { - let time_stamp = cds::TimeProvider::new_with_u16_days(0, 0).to_vec().unwrap(); + let time_stamp = cds::CdsTime::new_with_u16_days(0, 0).to_vec().unwrap(); self.handler .poll_and_handle_next_tc(&time_stamp, &mut self.sched_tc_pool) } } impl PusTestHarness for Pus11HandlerWithStoreTester { + fn init_verification(&mut self, tc: &PusTcCreator) -> VerificationToken { + let init_token = self.handler.service_helper.verif_reporter_mut().add_tc(tc); + self.handler + .service_helper + .verif_reporter() + .acceptance_success( + self.handler.service_helper.id(), + self.handler.service_helper.tm_sender(), + init_token, + &[0; 7], + ) + .expect("acceptance success failure") + } + delegate! { to self.common { - fn send_tc(&mut self, tc: &PusTcCreator) -> VerificationToken; + fn send_tc(&self, token: &VerificationToken, tc: &PusTcCreator); fn read_next_tm(&mut self) -> PusTmReader<'_>; fn check_no_tm_available(&self) -> bool; fn check_next_verification_tm(&self, subservice: u8, expected_request_id: RequestId); @@ -304,7 +350,7 @@ mod tests { } impl PusSchedulerProvider for TestScheduler { - type TimeProvider = cds::TimeProvider; + type TimeProvider = cds::CdsTime; fn reset( &mut self, @@ -330,7 +376,7 @@ mod tests { fn insert_unwrapped_and_stored_tc( &mut self, - _time_stamp: spacepackets::time::UnixTimestamp, + _time_stamp: spacepackets::time::UnixTime, info: crate::pus::scheduler::TcInfo, ) -> Result<(), crate::pus::scheduler::ScheduleError> { self.inserted_tcs.push_back(info); @@ -345,10 +391,11 @@ mod tests { let mut reply_header = SpHeader::tm_unseg(TEST_APID, 0, 0).unwrap(); let tc_header = PusTcSecondaryHeader::new_simple(11, subservice as u8); let enable_scheduling = PusTcCreator::new(&mut reply_header, tc_header, &[0; 7], true); - let token = test_harness.send_tc(&enable_scheduling); + let token = test_harness.init_verification(&enable_scheduling); + test_harness.send_tc(&token, &enable_scheduling); let request_id = token.request_id(); - let time_stamp = cds::TimeProvider::new_with_u16_days(0, 0).to_vec().unwrap(); + let time_stamp = cds::CdsTime::new_with_u16_days(0, 0).to_vec().unwrap(); test_harness .handler .poll_and_handle_next_tc(&time_stamp, &mut test_harness.sched_tc_pool) @@ -392,7 +439,7 @@ mod tests { let mut sec_header = PusTcSecondaryHeader::new_simple(17, 1); let ping_tc = PusTcCreator::new(&mut reply_header, sec_header, &[], true); let req_id_ping_tc = scheduler::RequestId::from_tc(&ping_tc); - let stamper = cds::TimeProvider::from_now_with_u16_days().expect("time provider failed"); + let stamper = cds::CdsTime::now_with_u16_days().expect("time provider failed"); let mut sched_app_data: [u8; 64] = [0; 64]; let mut written_len = stamper.write_to_bytes(&mut sched_app_data).unwrap(); let ping_raw = ping_tc.to_vec().expect("generating raw tc failed"); @@ -406,7 +453,8 @@ mod tests { &sched_app_data[..written_len], true, ); - let token = test_harness.send_tc(&enable_scheduling); + let token = test_harness.init_verification(&enable_scheduling); + test_harness.send_tc(&token, &enable_scheduling); let request_id = token.request_id(); test_harness.handle_one_tc().unwrap(); diff --git a/satrs/src/pus/test.rs b/satrs/src/pus/test.rs index abde360..390c433 100644 --- a/satrs/src/pus/test.rs +++ b/satrs/src/pus/test.rs @@ -1,20 +1,17 @@ use crate::pus::{ - PartialPusHandlingError, PusPacketHandlerResult, PusPacketHandlingError, PusTmWrapper, + PartialPusHandlingError, PusPacketHandlerResult, PusPacketHandlingError, PusTmAsVec, + PusTmInPool, PusTmVariant, }; use spacepackets::ecss::tm::{PusTmCreator, PusTmSecondaryHeader}; use spacepackets::ecss::PusPacket; use spacepackets::SpHeader; +use std::sync::mpsc; -use super::verification::{ - VerificationReporterWithSharedPoolMpscBoundedSender, - VerificationReporterWithSharedPoolMpscSender, VerificationReporterWithVecMpscBoundedSender, - VerificationReporterWithVecMpscSender, VerificationReportingProvider, -}; +use super::verification::{VerificationReporter, VerificationReportingProvider}; use super::{ EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter, EcssTcReceiverCore, - EcssTmSenderCore, GenericConversionError, MpscTcReceiver, PusServiceHelper, - TmAsVecSenderWithBoundedMpsc, TmAsVecSenderWithMpsc, TmInSharedPoolSenderWithBoundedMpsc, - TmInSharedPoolSenderWithMpsc, + EcssTmSenderCore, GenericConversionError, MpscTcReceiver, MpscTmInSharedPoolSender, + MpscTmInSharedPoolSenderBounded, PusServiceHelper, }; /// This is a helper class for [std] environments to handle generic PUS 17 (test service) packets. @@ -68,7 +65,12 @@ impl< let result = self .service_helper .verif_reporter() - .start_success(ecss_tc_and_token.token, time_stamp) + .start_success( + self.service_helper.common.id, + &self.service_helper.common.tm_sender, + ecss_tc_and_token.token, + time_stamp, + ) .map_err(|_| PartialPusHandlingError::Verification); let start_token = if let Ok(result) = result { Some(result) @@ -78,14 +80,14 @@ impl< }; // Sequence count will be handled centrally in TM funnel. let mut reply_header = - SpHeader::tm_unseg(self.service_helper.common.tm_apid, 0, 0).unwrap(); + SpHeader::tm_unseg(self.service_helper.verif_reporter().apid(), 0, 0).unwrap(); let tc_header = PusTmSecondaryHeader::new_simple(17, 2, time_stamp); let ping_reply = PusTmCreator::new(&mut reply_header, tc_header, &[], true); let result = self .service_helper .common .tm_sender - .send_tm(PusTmWrapper::Direct(ping_reply)) + .send_tm(self.service_helper.id(), PusTmVariant::Direct(ping_reply)) .map_err(PartialPusHandlingError::TmSend); if let Err(err) = result { partial_error = Some(err); @@ -95,7 +97,12 @@ impl< if self .service_helper .verif_reporter() - .completion_success(start_token, time_stamp) + .completion_success( + self.service_helper.common.id, + &self.service_helper.common.tm_sender, + start_token, + time_stamp, + ) .is_err() { partial_error = Some(PartialPusHandlingError::Verification) @@ -120,33 +127,33 @@ impl< /// mpsc queues. pub type PusService17TestHandlerDynWithMpsc = PusService17TestHandler< MpscTcReceiver, - TmAsVecSenderWithMpsc, + mpsc::Sender, EcssTcInVecConverter, - VerificationReporterWithVecMpscSender, + VerificationReporter, >; /// Helper type definition for a PUS 17 handler with a dynamic TMTC memory backend and bounded MPSC /// queues. pub type PusService17TestHandlerDynWithBoundedMpsc = PusService17TestHandler< MpscTcReceiver, - TmAsVecSenderWithBoundedMpsc, + mpsc::SyncSender, EcssTcInVecConverter, - VerificationReporterWithVecMpscBoundedSender, + VerificationReporter, >; /// 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, + MpscTmInSharedPoolSender, EcssTcInSharedStoreConverter, - VerificationReporterWithSharedPoolMpscSender, + VerificationReporter, >; /// 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, + MpscTmInSharedPoolSenderBounded, EcssTcInSharedStoreConverter, - VerificationReporterWithSharedPoolMpscBoundedSender, + VerificationReporter, >; #[cfg(test)] @@ -155,16 +162,17 @@ mod tests { use crate::pus::tests::{ PusServiceHandlerWithSharedStoreCommon, PusServiceHandlerWithVecCommon, }; - use crate::pus::verification::std_mod::{ - VerificationReporterWithSharedPoolMpscBoundedSender, VerificationReporterWithVecMpscSender, + use crate::pus::verification::test_util::TestVerificationReporter; + use crate::pus::verification::{ + RequestId, VerificationReporter, VerificationReportingProvider, }; - use crate::pus::verification::RequestId; use crate::pus::verification::{TcStateAccepted, VerificationToken}; use crate::pus::{ EcssTcInSharedStoreConverter, EcssTcInVecConverter, GenericConversionError, MpscTcReceiver, - PusPacketHandlerResult, PusPacketHandlingError, TmAsVecSenderWithMpsc, - TmInSharedPoolSenderWithBoundedMpsc, + MpscTmAsVecSender, MpscTmInSharedPoolSenderBounded, PusPacketHandlerResult, + PusPacketHandlingError, }; + use crate::ComponentId; use delegate::delegate; use spacepackets::ecss::tc::{PusTcCreator, PusTcSecondaryHeader}; use spacepackets::ecss::tm::PusTmReader; @@ -178,15 +186,15 @@ mod tests { common: PusServiceHandlerWithSharedStoreCommon, handler: PusService17TestHandler< MpscTcReceiver, - TmInSharedPoolSenderWithBoundedMpsc, + MpscTmInSharedPoolSenderBounded, EcssTcInSharedStoreConverter, - VerificationReporterWithSharedPoolMpscBoundedSender, + VerificationReporter, >, } impl Pus17HandlerWithStoreTester { - pub fn new() -> Self { - let (common, srv_handler) = PusServiceHandlerWithSharedStoreCommon::new(); + pub fn new(id: ComponentId) -> Self { + let (common, srv_handler) = PusServiceHandlerWithSharedStoreCommon::new(id); let pus_17_handler = PusService17TestHandler::new(srv_handler); Self { common, @@ -196,10 +204,24 @@ mod tests { } impl PusTestHarness for Pus17HandlerWithStoreTester { + fn init_verification(&mut self, tc: &PusTcCreator) -> VerificationToken { + let init_token = self.handler.service_helper.verif_reporter_mut().add_tc(tc); + self.handler + .service_helper + .verif_reporter() + .acceptance_success( + self.handler.service_helper.id(), + self.handler.service_helper.tm_sender(), + init_token, + &[0; 7], + ) + .expect("acceptance success failure") + } + delegate! { to self.common { - fn send_tc(&mut self, tc: &PusTcCreator) -> VerificationToken; fn read_next_tm(&mut self) -> PusTmReader<'_>; + fn send_tc(&self, token: &VerificationToken, tc: &PusTcCreator); fn check_no_tm_available(&self) -> bool; fn check_next_verification_tm( &self, @@ -211,25 +233,25 @@ mod tests { } impl SimplePusPacketHandler for Pus17HandlerWithStoreTester { fn handle_one_tc(&mut self) -> Result { - let time_stamp = cds::TimeProvider::new_with_u16_days(0, 0).to_vec().unwrap(); + let time_stamp = cds::CdsTime::new_with_u16_days(0, 0).to_vec().unwrap(); self.handler.poll_and_handle_next_tc(&time_stamp) } } struct Pus17HandlerWithVecTester { - common: PusServiceHandlerWithVecCommon, + common: PusServiceHandlerWithVecCommon, handler: PusService17TestHandler< MpscTcReceiver, - TmAsVecSenderWithMpsc, + MpscTmAsVecSender, EcssTcInVecConverter, - VerificationReporterWithVecMpscSender, + TestVerificationReporter, >, } impl Pus17HandlerWithVecTester { - pub fn new() -> Self { + pub fn new(id: ComponentId) -> Self { let (common, srv_handler) = - PusServiceHandlerWithVecCommon::new_with_standard_verif_reporter(); + PusServiceHandlerWithVecCommon::new_with_standard_verif_reporter(id); Self { common, handler: PusService17TestHandler::new(srv_handler), @@ -238,9 +260,23 @@ mod tests { } impl PusTestHarness for Pus17HandlerWithVecTester { + fn init_verification(&mut self, tc: &PusTcCreator) -> VerificationToken { + let init_token = self.handler.service_helper.verif_reporter_mut().add_tc(tc); + self.handler + .service_helper + .verif_reporter() + .acceptance_success( + self.handler.service_helper.id(), + self.handler.service_helper.tm_sender(), + init_token, + &[0; 7], + ) + .expect("acceptance success failure") + } + delegate! { to self.common { - fn send_tc(&mut self, tc: &PusTcCreator) -> VerificationToken; + fn send_tc(&self, token: &VerificationToken, tc: &PusTcCreator); fn read_next_tm(&mut self) -> PusTmReader<'_>; fn check_no_tm_available(&self) -> bool; fn check_next_verification_tm( @@ -253,7 +289,7 @@ mod tests { } impl SimplePusPacketHandler for Pus17HandlerWithVecTester { fn handle_one_tc(&mut self) -> Result { - let time_stamp = cds::TimeProvider::new_with_u16_days(0, 0).to_vec().unwrap(); + let time_stamp = cds::CdsTime::new_with_u16_days(0, 0).to_vec().unwrap(); self.handler.poll_and_handle_next_tc(&time_stamp) } } @@ -263,7 +299,8 @@ mod tests { let mut sp_header = SpHeader::tc(TEST_APID, SequenceFlags::Unsegmented, 0, 0).unwrap(); let sec_header = PusTcSecondaryHeader::new_simple(17, 1); let ping_tc = PusTcCreator::new_no_app_data(&mut sp_header, sec_header, true); - let token = test_harness.send_tc(&ping_tc); + let token = test_harness.init_verification(&ping_tc); + test_harness.send_tc(&token, &ping_tc); let request_id = token.request_id(); let result = test_harness.handle_one_tc(); assert!(result.is_ok()); @@ -288,19 +325,19 @@ mod tests { #[test] fn test_basic_ping_processing_using_store() { - let mut test_harness = Pus17HandlerWithStoreTester::new(); + let mut test_harness = Pus17HandlerWithStoreTester::new(0); ping_test(&mut test_harness); } #[test] fn test_basic_ping_processing_using_vec() { - let mut test_harness = Pus17HandlerWithVecTester::new(); + let mut test_harness = Pus17HandlerWithVecTester::new(0); ping_test(&mut test_harness); } #[test] fn test_empty_tc_queue() { - let mut test_harness = Pus17HandlerWithStoreTester::new(); + let mut test_harness = Pus17HandlerWithStoreTester::new(0); let result = test_harness.handle_one_tc(); assert!(result.is_ok()); let result = result.unwrap(); @@ -312,11 +349,12 @@ mod tests { #[test] fn test_sending_unsupported_service() { - let mut test_harness = Pus17HandlerWithStoreTester::new(); + let mut test_harness = Pus17HandlerWithStoreTester::new(0); let mut sp_header = SpHeader::tc(TEST_APID, SequenceFlags::Unsegmented, 0, 0).unwrap(); let sec_header = PusTcSecondaryHeader::new_simple(3, 1); let ping_tc = PusTcCreator::new_no_app_data(&mut sp_header, sec_header, true); - test_harness.send_tc(&ping_tc); + let token = test_harness.init_verification(&ping_tc); + test_harness.send_tc(&token, &ping_tc); let result = test_harness.handle_one_tc(); assert!(result.is_err()); let error = result.unwrap_err(); @@ -332,11 +370,12 @@ mod tests { #[test] fn test_sending_custom_subservice() { - let mut test_harness = Pus17HandlerWithStoreTester::new(); + let mut test_harness = Pus17HandlerWithStoreTester::new(0); let mut sp_header = SpHeader::tc(TEST_APID, SequenceFlags::Unsegmented, 0, 0).unwrap(); let sec_header = PusTcSecondaryHeader::new_simple(17, 200); let ping_tc = PusTcCreator::new_no_app_data(&mut sp_header, sec_header, true); - test_harness.send_tc(&ping_tc); + let token = test_harness.init_verification(&ping_tc); + test_harness.send_tc(&token, &ping_tc); let result = test_harness.handle_one_tc(); assert!(result.is_ok()); let result = result.unwrap(); diff --git a/satrs/src/pus/verification.rs b/satrs/src/pus/verification.rs index a498bd5..bc6a0d7 100644 --- a/satrs/src/pus/verification.rs +++ b/satrs/src/pus/verification.rs @@ -17,10 +17,10 @@ //! use std::time::Duration; //! use satrs::pool::{PoolProviderWithGuards, StaticMemoryPool, StaticPoolConfig}; //! use satrs::pus::verification::{ -//! VerificationReportingProvider, VerificationReporterCfg, VerificationReporterWithSender +//! VerificationReportingProvider, VerificationReporterCfg //! }; //! use satrs::seq_count::SeqCountProviderSimple; -//! use satrs::pus::TmInSharedPoolSenderWithMpsc; +//! use satrs::pus::MpscTmInSharedPoolSender; //! use satrs::tmtc::tm_helper::SharedTmPool; //! use spacepackets::ecss::PusPacket; //! use spacepackets::SpHeader; @@ -35,7 +35,7 @@ //! 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 = TmInSharedPoolSenderWithMpsc::new(0, "Test Sender", shared_tm_store, verif_tx); +//! let sender = MpscTmInSharedPoolSender::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 , sender); //! @@ -87,8 +87,8 @@ use delegate::delegate; use serde::{Deserialize, Serialize}; use spacepackets::ecss::tc::IsPusTelecommand; use spacepackets::ecss::tm::{PusTmCreator, PusTmSecondaryHeader}; -use spacepackets::ecss::{EcssEnumeration, PusError, WritablePusPacket}; -use spacepackets::{CcsdsPacket, PacketId, PacketSequenceCtrl}; +use spacepackets::ecss::{EcssEnumeration, PusError}; +use spacepackets::{ByteConversionError, CcsdsPacket, PacketId, PacketSequenceCtrl}; use spacepackets::{SpHeader, MAX_APID}; pub use crate::seq_count::SeqCountProviderSimple; @@ -98,9 +98,14 @@ pub use spacepackets::ecss::verification::*; #[cfg_attr(feature = "doc_cfg", doc(cfg(feature = "alloc")))] pub use alloc_mod::*; +use crate::request::Apid; +use crate::ComponentId; + +/* #[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. /// @@ -372,7 +377,7 @@ impl<'stamp, 'fargs> FailParams<'stamp, 'fargs> { /// Composite helper struct to pass step failure parameters to the [VerificationReporter] pub struct FailParamsWithStep<'stamp, 'fargs> { - pub params: FailParams<'stamp, 'fargs>, + pub common: FailParams<'stamp, 'fargs>, pub step: &'fargs dyn EcssEnumeration, } @@ -384,94 +389,16 @@ impl<'stamp, 'fargs> FailParamsWithStep<'stamp, 'fargs> { failure_data: &'fargs [u8], ) -> Self { Self { - params: FailParams::new(time_stamp, failure_code, failure_data), + common: FailParams::new(time_stamp, failure_code, failure_data), step, } } } -#[derive(Clone)] -pub struct VerificationReporterCore { - pub dest_id: u16, - apid: u16, -} - -pub enum VerifSuccess {} -pub enum VerifFailure {} - -/// Abstraction for a sendable PUS TM. The user is expected to send the TM packet to a TM sink. -/// -/// This struct generally mutably borrows the source data buffer. -pub struct VerificationSendable<'src_data, State, SuccessOrFailure> { - token: Option>, - pus_tm: Option>, - phantom: PhantomData, -} - -impl<'src_data, State, SuccessOrFailure> VerificationSendable<'src_data, State, SuccessOrFailure> { - pub(crate) fn new(pus_tm: PusTmCreator<'src_data>, token: VerificationToken) -> Self { - Self { - token: Some(token), - pus_tm: Some(pus_tm), - phantom: PhantomData, - } - } - pub(crate) fn new_no_token(pus_tm: PusTmCreator<'src_data>) -> Self { - Self { - token: None, - pus_tm: Some(pus_tm), - phantom: PhantomData, - } - } - - pub fn len_packed(&self) -> usize { - self.pus_tm.as_ref().unwrap().len_written() - } - - pub fn pus_tm(&self) -> &PusTmCreator<'src_data> { - self.pus_tm.as_ref().unwrap() - } - - pub fn pus_tm_mut(&mut self) -> &mut PusTmCreator<'src_data> { - self.pus_tm.as_mut().unwrap() - } -} - -impl<'src_data, State> VerificationSendable<'src_data, State, VerifFailure> { - pub fn send_success_verif_failure(self) {} -} - -impl<'src_data, State> VerificationSendable<'src_data, State, VerifFailure> { - pub fn send_failure(self) -> (PusTmCreator<'src_data>, VerificationToken) { - (self.pus_tm.unwrap(), self.token.unwrap()) - } -} - -impl<'src_data> VerificationSendable<'src_data, TcStateNone, VerifSuccess> { - pub fn send_success_acceptance_success(self) -> VerificationToken { - VerificationToken { - state: PhantomData, - request_id: self.token.unwrap().request_id(), - } - } -} - -impl<'src_data> VerificationSendable<'src_data, TcStateAccepted, VerifSuccess> { - pub fn send_success_start_success(self) -> VerificationToken { - VerificationToken { - state: PhantomData, - request_id: self.token.unwrap().request_id(), - } - } -} - -impl<'src_data, TcState: WasAtLeastAccepted + Copy> - VerificationSendable<'src_data, TcState, VerifSuccess> -{ - pub fn send_success_step_or_completion_success(self) {} -} - pub trait VerificationReportingProvider { + fn set_apid(&mut self, apid: Apid); + fn apid(&self) -> Apid; + fn add_tc( &mut self, pus_tc: &(impl CcsdsPacket + IsPusTelecommand), @@ -483,30 +410,40 @@ pub trait VerificationReportingProvider { fn acceptance_success( &self, + sender_id: ComponentId, + sender: &(impl EcssTmSenderCore + ?Sized), token: VerificationToken, time_stamp: &[u8], - ) -> Result, VerificationOrSendErrorWithToken>; + ) -> Result, EcssTmtcError>; fn acceptance_failure( &self, + sender_id: ComponentId, + sender: &(impl EcssTmSenderCore + ?Sized), token: VerificationToken, params: FailParams, - ) -> Result<(), VerificationOrSendErrorWithToken>; + ) -> Result<(), EcssTmtcError>; fn start_success( &self, + sender_id: ComponentId, + sender: &(impl EcssTmSenderCore + ?Sized), token: VerificationToken, time_stamp: &[u8], - ) -> Result, VerificationOrSendErrorWithToken>; + ) -> Result, EcssTmtcError>; fn start_failure( &self, + sender_id: ComponentId, + sender: &(impl EcssTmSenderCore + ?Sized), token: VerificationToken, params: FailParams, - ) -> Result<(), VerificationOrSendErrorWithToken>; + ) -> Result<(), EcssTmtcError>; fn step_success( &self, + sender_id: ComponentId, + sender: &(impl EcssTmSenderCore + ?Sized), token: &VerificationToken, time_stamp: &[u8], step: impl EcssEnumeration, @@ -514,31 +451,43 @@ pub trait VerificationReportingProvider { fn step_failure( &self, + sender_id: ComponentId, + sender: &(impl EcssTmSenderCore + ?Sized), token: VerificationToken, params: FailParamsWithStep, - ) -> Result<(), VerificationOrSendErrorWithToken>; + ) -> Result<(), EcssTmtcError>; fn completion_success( &self, + sender_id: ComponentId, + sender: &(impl EcssTmSenderCore + ?Sized), token: VerificationToken, time_stamp: &[u8], - ) -> Result<(), VerificationOrSendErrorWithToken>; + ) -> Result<(), EcssTmtcError>; fn completion_failure( &self, + sender_id: ComponentId, + sender: &(impl EcssTmSenderCore + ?Sized), token: VerificationToken, params: FailParams, - ) -> Result<(), VerificationOrSendErrorWithToken>; + ) -> Result<(), EcssTmtcError>; } -/// Primary verification handler. It provides an API to send PUS 1 verification telemetry packets -/// and verify the various steps of telecommand handling as specified in the PUS standard. +/// Primary verification handler. It provides an API to generate PUS 1 verification telemetry +/// packets and verify the various steps of telecommand handling as specified in the PUS standard. /// /// This is the core component which can be used without [`alloc`] support. Please note that /// the buffer passed to the API exposes by this struct will be used to serialize the source data. /// This buffer may not be re-used to serialize the whole telemetry because that would overwrite /// the source data itself. -impl VerificationReporterCore { +#[derive(Clone)] +pub struct VerificationReportCreator { + pub dest_id: u16, + apid: u16, +} + +impl VerificationReportCreator { pub fn new(apid: u16) -> Option { if apid > MAX_APID { return None; @@ -581,36 +530,30 @@ impl VerificationReporterCore { VerificationToken::::new(req_id) } - fn sendable_success_no_step<'src_data, State: Copy>( + fn success_verification_no_step<'time, 'src_data, State: Copy>( &self, src_data_buf: &'src_data mut [u8], subservice: u8, token: VerificationToken, seq_count: u16, msg_count: u16, - time_stamp: &'src_data [u8], - ) -> Result< - VerificationSendable<'src_data, State, VerifSuccess>, - VerificationErrorWithToken, - > { - Ok(VerificationSendable::new( - self.create_pus_verif_success_tm( - src_data_buf, - subservice, - seq_count, - msg_count, - &token.request_id, - time_stamp, - None::<&dyn EcssEnumeration>, - ) - .map_err(|e| VerificationErrorWithToken(e, token))?, - token, - )) + time_stamp: &'time [u8], + ) -> Result, ByteConversionError> { + let tm_creator = self.create_pus_verif_success_tm( + src_data_buf, + subservice, + seq_count, + msg_count, + &token.request_id(), + time_stamp, + None::<&dyn EcssEnumeration>, + )?; + Ok(tm_creator) } // Internal helper function, too many arguments is acceptable for this case. #[allow(clippy::too_many_arguments)] - fn sendable_failure_no_step<'src_data, State: Copy>( + fn failure_verification_no_step<'time, 'src_data, State: Copy>( &self, src_data_buf: &'src_data mut [u8], subservice: u8, @@ -618,85 +561,62 @@ impl VerificationReporterCore { seq_count: u16, msg_count: u16, step: Option<&(impl EcssEnumeration + ?Sized)>, - params: &FailParams<'src_data, '_>, - ) -> Result< - VerificationSendable<'src_data, State, VerifFailure>, - VerificationErrorWithToken, - > { - Ok(VerificationSendable::new( - self.create_pus_verif_fail_tm( - src_data_buf, - subservice, - seq_count, - msg_count, - &token.request_id, - step, - params, - ) - .map_err(|e| VerificationErrorWithToken(e, token))?, - token, - )) + params: &FailParams<'time, '_>, + ) -> Result, ByteConversionError> { + let tm_creator = self.create_pus_verif_fail_tm( + src_data_buf, + subservice, + seq_count, + msg_count, + &token.request_id(), + step, + params, + )?; + Ok(tm_creator) } /// Package a PUS TM\[1, 1\] packet, see 8.1.2.1 of the PUS standard. - pub fn acceptance_success<'src_data>( + pub fn acceptance_success<'time, 'src_data>( &self, src_data_buf: &'src_data mut [u8], token: VerificationToken, seq_count: u16, msg_count: u16, - time_stamp: &'src_data [u8], + time_stamp: &'time [u8], ) -> Result< - VerificationSendable<'src_data, TcStateNone, VerifSuccess>, - VerificationErrorWithToken, + ( + PusTmCreator<'time, 'src_data>, + VerificationToken, + ), + ByteConversionError, > { - self.sendable_success_no_step( + let tm_creator = self.success_verification_no_step( src_data_buf, Subservice::TmAcceptanceSuccess.into(), token, seq_count, msg_count, time_stamp, - ) - } - - pub fn send_acceptance_success( - &self, - mut sendable: VerificationSendable<'_, TcStateNone, VerifSuccess>, - sender: &(impl EcssTmSenderCore + ?Sized), - ) -> Result, VerificationOrSendErrorWithToken> - { - sender - .send_tm(sendable.pus_tm.take().unwrap().into()) - .map_err(|e| VerificationOrSendErrorWithToken(e, sendable.token.unwrap()))?; - Ok(sendable.send_success_acceptance_success()) - } - - pub fn send_acceptance_failure( - &self, - mut sendable: VerificationSendable<'_, TcStateNone, VerifFailure>, - sender: &(impl EcssTmSenderCore + ?Sized), - ) -> Result<(), VerificationOrSendErrorWithToken> { - sender - .send_tm(sendable.pus_tm.take().unwrap().into()) - .map_err(|e| VerificationOrSendErrorWithToken(e, sendable.token.unwrap()))?; - sendable.send_success_verif_failure(); - Ok(()) + )?; + Ok(( + tm_creator, + VerificationToken { + state: PhantomData, + request_id: token.request_id(), + }, + )) } /// Package a PUS TM\[1, 2\] packet, see 8.1.2.2 of the PUS standard. - pub fn acceptance_failure<'src_data>( + pub fn acceptance_failure<'time, 'src_data>( &self, src_data_buf: &'src_data mut [u8], token: VerificationToken, seq_count: u16, msg_count: u16, - params: FailParams<'src_data, '_>, - ) -> Result< - VerificationSendable<'src_data, TcStateNone, VerifFailure>, - VerificationErrorWithToken, - > { - self.sendable_failure_no_step( + params: FailParams<'time, '_>, + ) -> Result, ByteConversionError> { + self.failure_verification_no_step( src_data_buf, Subservice::TmAcceptanceFailure.into(), token, @@ -710,55 +630,50 @@ impl VerificationReporterCore { /// Package and send a PUS TM\[1, 3\] packet, see 8.1.2.3 of the PUS standard. /// /// Requires a token previously acquired by calling [Self::acceptance_success]. - pub fn start_success<'src_data>( + pub fn start_success<'time, 'src_data>( &self, src_data_buf: &'src_data mut [u8], token: VerificationToken, seq_count: u16, msg_count: u16, - time_stamp: &'src_data [u8], + time_stamp: &'time [u8], ) -> Result< - VerificationSendable<'src_data, TcStateAccepted, VerifSuccess>, - VerificationErrorWithToken, + ( + PusTmCreator<'time, 'src_data>, + VerificationToken, + ), + ByteConversionError, > { - self.sendable_success_no_step( + let tm_creator = self.success_verification_no_step( src_data_buf, Subservice::TmStartSuccess.into(), token, seq_count, msg_count, time_stamp, - ) - } - - pub fn send_start_success( - &self, - mut sendable: VerificationSendable<'_, TcStateAccepted, VerifSuccess>, - sender: &(impl EcssTmSenderCore + ?Sized), - ) -> Result, VerificationOrSendErrorWithToken> - { - sender - .send_tm(sendable.pus_tm.take().unwrap().into()) - .map_err(|e| VerificationOrSendErrorWithToken(e, sendable.token.unwrap()))?; - Ok(sendable.send_success_start_success()) + )?; + Ok(( + tm_creator, + VerificationToken { + state: PhantomData, + request_id: token.request_id(), + }, + )) } /// Package and send a PUS TM\[1, 4\] packet, see 8.1.2.4 of the PUS standard. /// /// Requires a token previously acquired by calling [Self::acceptance_success]. It consumes /// the token because verification handling is done. - pub fn start_failure<'src_data>( + pub fn start_failure<'time, 'src_data>( &self, src_data_buf: &'src_data mut [u8], token: VerificationToken, seq_count: u16, msg_count: u16, - params: FailParams<'src_data, '_>, - ) -> Result< - VerificationSendable<'src_data, TcStateAccepted, VerifFailure>, - VerificationErrorWithToken, - > { - self.sendable_failure_no_step( + params: FailParams<'time, '_>, + ) -> Result, ByteConversionError> { + self.failure_verification_no_step( src_data_buf, Subservice::TmStartFailure.into(), token, @@ -769,89 +684,65 @@ impl VerificationReporterCore { ) } - pub fn send_start_failure( - &self, - mut sendable: VerificationSendable<'_, TcStateAccepted, VerifFailure>, - sender: &(impl EcssTmSenderCore + ?Sized), - ) -> Result<(), VerificationOrSendErrorWithToken> { - sender - .send_tm(sendable.pus_tm.take().unwrap().into()) - .map_err(|e| VerificationOrSendErrorWithToken(e, sendable.token.unwrap()))?; - sendable.send_success_verif_failure(); - Ok(()) - } - /// Package and send a PUS TM\[1, 5\] packet, see 8.1.2.5 of the PUS standard. /// /// Requires a token previously acquired by calling [Self::start_success]. - pub fn step_success<'src_data>( + pub fn step_success<'time, 'src_data>( &self, src_data_buf: &'src_data mut [u8], token: &VerificationToken, seq_count: u16, msg_count: u16, - time_stamp: &'src_data [u8], + time_stamp: &'time [u8], step: impl EcssEnumeration, - ) -> Result, EcssTmtcError> { - Ok(VerificationSendable::new_no_token( - self.create_pus_verif_success_tm( - src_data_buf, - Subservice::TmStepSuccess.into(), - seq_count, - msg_count, - &token.request_id, - time_stamp, - Some(&step), - )?, - )) + ) -> Result, ByteConversionError> { + self.create_pus_verif_success_tm( + src_data_buf, + Subservice::TmStepSuccess.into(), + seq_count, + msg_count, + &token.request_id(), + time_stamp, + Some(&step), + ) } /// Package and send a PUS TM\[1, 6\] packet, see 8.1.2.6 of the PUS standard. /// /// Requires a token previously acquired by calling [Self::start_success]. It consumes the /// token because verification handling is done. - pub fn step_failure<'src_data>( + pub fn step_failure<'time, 'src_data>( &self, src_data_buf: &'src_data mut [u8], token: VerificationToken, seq_count: u16, msg_count: u16, - params: FailParamsWithStep<'src_data, '_>, - ) -> Result< - VerificationSendable<'src_data, TcStateStarted, VerifFailure>, - VerificationErrorWithToken, - > { - Ok(VerificationSendable::new( - self.create_pus_verif_fail_tm( - src_data_buf, - Subservice::TmStepFailure.into(), - seq_count, - msg_count, - &token.request_id, - Some(params.step), - ¶ms.params, - ) - .map_err(|e| VerificationErrorWithToken(e, token))?, - token, - )) + params: FailParamsWithStep<'time, '_>, + ) -> Result, ByteConversionError> { + self.create_pus_verif_fail_tm( + src_data_buf, + Subservice::TmStepFailure.into(), + seq_count, + msg_count, + &token.request_id(), + Some(params.step), + ¶ms.common, + ) } /// Package and send a PUS TM\[1, 7\] packet, see 8.1.2.7 of the PUS standard. /// /// Requires a token previously acquired by calling [Self::start_success]. It consumes the /// token because verification handling is done. - pub fn completion_success<'src_data, TcState: WasAtLeastAccepted + Copy>( + pub fn completion_success<'time, 'src_data, TcState: WasAtLeastAccepted + Copy>( &self, src_data_buf: &'src_data mut [u8], token: VerificationToken, seq_counter: u16, msg_counter: u16, - time_stamp: &'src_data [u8], - ) -> Result< - VerificationSendable<'src_data, TcState, VerifSuccess>, - VerificationErrorWithToken, - > { - self.sendable_success_no_step( + time_stamp: &'time [u8], + ) -> Result, ByteConversionError> { + self.success_verification_no_step( src_data_buf, Subservice::TmCompletionSuccess.into(), token, @@ -865,18 +756,15 @@ impl VerificationReporterCore { /// /// Requires a token previously acquired by calling [Self::start_success]. It consumes the /// token because verification handling is done. - pub fn completion_failure<'src_data, TcState: WasAtLeastAccepted + Copy>( + pub fn completion_failure<'time, 'src_data, TcState: WasAtLeastAccepted + Copy>( &self, src_data_buf: &'src_data mut [u8], token: VerificationToken, seq_count: u16, msg_count: u16, - params: FailParams<'src_data, '_>, - ) -> Result< - VerificationSendable<'src_data, TcState, VerifFailure>, - VerificationErrorWithToken, - > { - self.sendable_failure_no_step( + params: FailParams<'time, '_>, + ) -> Result, ByteConversionError> { + self.failure_verification_no_step( src_data_buf, Subservice::TmCompletionFailure.into(), token, @@ -887,42 +775,18 @@ impl VerificationReporterCore { ) } - pub fn send_step_or_completion_success( - &self, - mut sendable: VerificationSendable<'_, TcState, VerifSuccess>, - sender: &(impl EcssTmSenderCore + ?Sized), - ) -> Result<(), VerificationOrSendErrorWithToken> { - sender - .send_tm(sendable.pus_tm.take().unwrap().into()) - .map_err(|e| VerificationOrSendErrorWithToken(e, sendable.token.unwrap()))?; - sendable.send_success_step_or_completion_success(); - Ok(()) - } - - pub fn send_step_or_completion_failure( - &self, - mut sendable: VerificationSendable<'_, TcState, VerifFailure>, - sender: &(impl EcssTmSenderCore + ?Sized), - ) -> Result<(), VerificationOrSendErrorWithToken> { - sender - .send_tm(sendable.pus_tm.take().unwrap().into()) - .map_err(|e| VerificationOrSendErrorWithToken(e, sendable.token.unwrap()))?; - sendable.send_success_verif_failure(); - Ok(()) - } - // Internal helper function, too many arguments is acceptable for this case. #[allow(clippy::too_many_arguments)] - fn create_pus_verif_success_tm<'src_data>( + fn create_pus_verif_success_tm<'time, 'src_data>( &self, src_data_buf: &'src_data mut [u8], subservice: u8, seq_count: u16, msg_counter: u16, req_id: &RequestId, - time_stamp: &'src_data [u8], + time_stamp: &'time [u8], step: Option<&(impl EcssEnumeration + ?Sized)>, - ) -> Result, EcssTmtcError> { + ) -> Result, ByteConversionError> { let mut source_data_len = size_of::(); if let Some(step) = step { source_data_len += step.size(); @@ -949,7 +813,7 @@ impl VerificationReporterCore { // Internal helper function, too many arguments is acceptable for this case. #[allow(clippy::too_many_arguments)] - fn create_pus_verif_fail_tm<'src_data>( + fn create_pus_verif_fail_tm<'time, 'src_data>( &self, src_data_buf: &'src_data mut [u8], subservice: u8, @@ -957,8 +821,8 @@ impl VerificationReporterCore { msg_counter: u16, req_id: &RequestId, step: Option<&(impl EcssEnumeration + ?Sized)>, - params: &FailParams<'src_data, '_>, - ) -> Result, EcssTmtcError> { + params: &FailParams<'time, '_>, + ) -> Result, ByteConversionError> { let mut idx = 0; let mut source_data_len = RequestId::SIZE_AS_BYTES + params.failure_code.size(); if let Some(step) = step { @@ -976,8 +840,7 @@ impl VerificationReporterCore { } params .failure_code - .write_to_be_bytes(&mut src_data_buf[idx..idx + params.failure_code.size()]) - .map_err(PusError::ByteConversion)?; + .write_to_be_bytes(&mut src_data_buf[idx..idx + params.failure_code.size()])?; idx += params.failure_code.size(); src_data_buf[idx..idx + params.failure_data.len()].copy_from_slice(params.failure_data); let mut sp_header = SpHeader::tm_unseg(self.apid(), seq_count, 0).unwrap(); @@ -991,15 +854,15 @@ impl VerificationReporterCore { )) } - fn create_pus_verif_tm_base<'src_data>( + fn create_pus_verif_tm_base<'time, 'src_data>( &self, src_data_buf: &'src_data mut [u8], subservice: u8, msg_counter: u16, sp_header: &mut SpHeader, - time_stamp: &'src_data [u8], + time_stamp: &'time [u8], source_data_len: usize, - ) -> PusTmCreator<'src_data> { + ) -> PusTmCreator<'time, 'src_data> { let tm_sec_header = PusTmSecondaryHeader::new(1, subservice, msg_counter, self.dest_id, Some(time_stamp)); PusTmCreator::new( @@ -1014,10 +877,7 @@ impl VerificationReporterCore { #[cfg(feature = "alloc")] pub mod alloc_mod { use super::*; - use crate::{ - pus::{TmAsVecSenderWithId, TmInSharedPoolSenderWithId}, - seq_count::SequenceCountProvider, - }; + use crate::{pus::PusTmVariant, ComponentId}; use core::cell::RefCell; #[derive(Clone)] @@ -1053,15 +913,15 @@ pub mod alloc_mod { /// TM funnel. This helper will always set those fields to 0. #[derive(Clone)] pub struct VerificationReporter { + // TODO: We could add a hook object which allows users to manipulate the verification + // report TM before it is sent.. source_data_buf: RefCell>, - pub seq_count_provider: Option + Send>>, - pub msg_count_provider: Option + Send>>, - pub reporter: VerificationReporterCore, + pub reporter_creator: VerificationReportCreator, } impl VerificationReporter { pub fn new(cfg: &VerificationReporterCfg) -> Self { - let reporter = VerificationReporterCore::new(cfg.apid).unwrap(); + let reporter = VerificationReportCreator::new(cfg.apid).unwrap(); Self { source_data_buf: RefCell::new(alloc::vec![ 0; @@ -1070,14 +930,14 @@ pub mod alloc_mod { + cfg.fail_code_field_width + cfg.max_fail_data_len ]), - seq_count_provider: None, - msg_count_provider: None, - reporter, + // seq_count_provider: None, + // msg_count_provider: None, + reporter_creator: reporter, } } delegate!( - to self.reporter { + to self.reporter_creator { pub fn set_apid(&mut self, apid: u16) -> bool; pub fn apid(&self) -> u16; pub fn add_tc(&mut self, pus_tc: &(impl CcsdsPacket + IsPusTelecommand)) -> VerificationToken; @@ -1090,72 +950,63 @@ pub mod alloc_mod { pub fn allowed_source_data_len(&self) -> usize { self.source_data_buf.borrow().capacity() } + } + + impl VerificationReportingProvider for VerificationReporter { + delegate!( + to self.reporter_creator { + fn set_apid(&mut self, apid: Apid); + fn apid(&self) -> Apid; + fn add_tc(&mut self, pus_tc: &(impl CcsdsPacket + IsPusTelecommand)) -> VerificationToken; + fn add_tc_with_req_id(&mut self, req_id: RequestId) -> VerificationToken; + } + ); /// Package and send a PUS TM\[1, 1\] packet, see 8.1.2.1 of the PUS standard - pub fn acceptance_success( + fn acceptance_success( &self, - token: VerificationToken, + sender_id: ComponentId, sender: &(impl EcssTmSenderCore + ?Sized), + token: VerificationToken, time_stamp: &[u8], - ) -> Result, VerificationOrSendErrorWithToken> - { - let seq_count = self - .seq_count_provider - .as_ref() - .map_or(0, |v| v.get_and_increment()); - let msg_count = self - .seq_count_provider - .as_ref() - .map_or(0, |v| v.get_and_increment()); + ) -> Result, EcssTmtcError> { let mut source_data_buf = self.source_data_buf.borrow_mut(); - let sendable = self.reporter.acceptance_success( - source_data_buf.as_mut_slice(), - token, - seq_count, - msg_count, - time_stamp, - )?; - self.reporter.send_acceptance_success(sendable, sender) + let (tm_creator, token) = self + .reporter_creator + .acceptance_success(source_data_buf.as_mut_slice(), token, 0, 0, time_stamp) + .map_err(PusError::ByteConversion)?; + sender.send_tm(sender_id, PusTmVariant::Direct(tm_creator))?; + Ok(token) } /// Package and send a PUS TM\[1, 2\] packet, see 8.1.2.2 of the PUS standard - pub fn acceptance_failure( + fn acceptance_failure( &self, - token: VerificationToken, + sender_id: ComponentId, sender: &(impl EcssTmSenderCore + ?Sized), + token: VerificationToken, params: FailParams, - ) -> Result<(), VerificationOrSendErrorWithToken> { - let seq_count = self - .seq_count_provider - .as_ref() - .map_or(0, |v| v.get_and_increment()); - let msg_count = self - .seq_count_provider - .as_ref() - .map_or(0, |v| v.get_and_increment()); + ) -> Result<(), EcssTmtcError> { let mut buf = self.source_data_buf.borrow_mut(); - let sendable = self.reporter.acceptance_failure( - buf.as_mut_slice(), - token, - seq_count, - msg_count, - params, - )?; - self.reporter.send_acceptance_failure(sendable, sender) + let sendable = self + .reporter_creator + .acceptance_failure(buf.as_mut_slice(), token, 0, 0, params) + .map_err(PusError::ByteConversion)?; + sender.send_tm(sender_id, PusTmVariant::Direct(sendable))?; + Ok(()) } /// Package and send a PUS TM\[1, 3\] packet, see 8.1.2.3 of the PUS standard. /// /// Requires a token previously acquired by calling [Self::acceptance_success]. - pub fn start_success( + fn start_success( &self, - token: VerificationToken, + sender_id: ComponentId, sender: &(impl EcssTmSenderCore + ?Sized), + token: VerificationToken, time_stamp: &[u8], - ) -> Result< - VerificationToken, - VerificationOrSendErrorWithToken, - > { + ) -> Result, EcssTmtcError> { + /* let seq_count = self .seq_count_provider .as_ref() @@ -1164,27 +1015,29 @@ pub mod alloc_mod { .seq_count_provider .as_ref() .map_or(0, |v| v.get_and_increment()); + */ let mut buf = self.source_data_buf.borrow_mut(); - let sendable = self.reporter.start_success( - buf.as_mut_slice(), - token, - seq_count, - msg_count, - time_stamp, - )?; - self.reporter.send_start_success(sendable, sender) + let (tm_creator, started_token) = self + .reporter_creator + .start_success(buf.as_mut_slice(), token, 0, 0, time_stamp) + .map_err(PusError::ByteConversion)?; + sender.send_tm(sender_id, PusTmVariant::Direct(tm_creator))?; + Ok(started_token) + //self.reporter.send_start_success(sendable, sender) } /// Package and send a PUS TM\[1, 4\] packet, see 8.1.2.4 of the PUS standard. /// /// Requires a token previously acquired by calling [Self::acceptance_success]. It consumes /// the token because verification handling is done. - pub fn start_failure( + fn start_failure( &self, - token: VerificationToken, + sender_id: ComponentId, sender: &(impl EcssTmSenderCore + ?Sized), + token: VerificationToken, params: FailParams, - ) -> Result<(), VerificationOrSendErrorWithToken> { + ) -> Result<(), EcssTmtcError> { + /* let seq_count = self .seq_count_provider .as_ref() @@ -1193,27 +1046,28 @@ pub mod alloc_mod { .seq_count_provider .as_ref() .map_or(0, |v| v.get_and_increment()); + */ let mut buf = self.source_data_buf.borrow_mut(); - let sendable = self.reporter.start_failure( - buf.as_mut_slice(), - token, - seq_count, - msg_count, - params, - )?; - self.reporter.send_start_failure(sendable, sender) + let sendable = self + .reporter_creator + .start_failure(buf.as_mut_slice(), token, 0, 0, params) + .map_err(PusError::ByteConversion)?; + sender.send_tm(sender_id, PusTmVariant::Direct(sendable))?; + Ok(()) } /// Package and send a PUS TM\[1, 5\] packet, see 8.1.2.5 of the PUS standard. /// /// Requires a token previously acquired by calling [Self::start_success]. - pub fn step_success( + fn step_success( &self, - token: &VerificationToken, + sender_id: ComponentId, sender: &(impl EcssTmSenderCore + ?Sized), + token: &VerificationToken, time_stamp: &[u8], step: impl EcssEnumeration, ) -> Result<(), EcssTmtcError> { + /* let seq_count = self .seq_count_provider .as_ref() @@ -1222,30 +1076,29 @@ pub mod alloc_mod { .seq_count_provider .as_ref() .map_or(0, |v| v.get_and_increment()); + + */ let mut buf = self.source_data_buf.borrow_mut(); - let sendable = self.reporter.step_success( - buf.as_mut_slice(), - token, - seq_count, - msg_count, - time_stamp, - step, - )?; - self.reporter - .send_step_or_completion_success(sendable, sender) - .map_err(|e| e.0) + let sendable = self + .reporter_creator + .step_success(buf.as_mut_slice(), token, 0, 0, time_stamp, step) + .map_err(PusError::ByteConversion)?; + sender.send_tm(sender_id, PusTmVariant::Direct(sendable))?; + Ok(()) } /// Package and send a PUS TM\[1, 6\] packet, see 8.1.2.6 of the PUS standard. /// /// Requires a token previously acquired by calling [Self::start_success]. It consumes the /// token because verification handling is done. - pub fn step_failure( + fn step_failure( &self, - token: VerificationToken, + sender_id: ComponentId, sender: &(impl EcssTmSenderCore + ?Sized), + token: VerificationToken, params: FailParamsWithStep, - ) -> Result<(), VerificationOrSendErrorWithToken> { + ) -> Result<(), EcssTmtcError> { + /* let seq_count = self .seq_count_provider .as_ref() @@ -1254,28 +1107,29 @@ pub mod alloc_mod { .seq_count_provider .as_ref() .map_or(0, |v| v.get_and_increment()); + + */ let mut buf = self.source_data_buf.borrow_mut(); - let sendable = self.reporter.step_failure( - buf.as_mut_slice(), - token, - seq_count, - msg_count, - params, - )?; - self.reporter - .send_step_or_completion_failure(sendable, sender) + let sendable = self + .reporter_creator + .step_failure(buf.as_mut_slice(), token, 0, 0, params) + .map_err(PusError::ByteConversion)?; + sender.send_tm(sender_id, PusTmVariant::Direct(sendable))?; + Ok(()) } /// Package and send a PUS TM\[1, 7\] packet, see 8.1.2.7 of the PUS standard. /// /// Requires a token previously acquired by calling [Self::start_success]. It consumes the /// token because verification handling is done. - pub fn completion_success( + fn completion_success( &self, - token: VerificationToken, + sender_id: ComponentId, sender: &(impl EcssTmSenderCore + ?Sized), + token: VerificationToken, time_stamp: &[u8], - ) -> Result<(), VerificationOrSendErrorWithToken> { + ) -> Result<(), EcssTmtcError> { + /* let seq_count = self .seq_count_provider .as_ref() @@ -1284,201 +1138,69 @@ pub mod alloc_mod { .seq_count_provider .as_ref() .map_or(0, |v| v.get_and_increment()); + + */ let mut buf = self.source_data_buf.borrow_mut(); - let sendable = self.reporter.completion_success( - buf.as_mut_slice(), - token, - seq_count, - msg_count, - time_stamp, - )?; - self.reporter - .send_step_or_completion_success(sendable, sender) + let sendable = self + .reporter_creator + .completion_success(buf.as_mut_slice(), token, 0, 0, time_stamp) + .map_err(PusError::ByteConversion)?; + sender.send_tm(sender_id, PusTmVariant::Direct(sendable))?; + Ok(()) } /// Package and send a PUS TM\[1, 8\] packet, see 8.1.2.8 of the PUS standard. /// /// Requires a token previously acquired by calling [Self::start_success]. It consumes the /// token because verification handling is done. - pub fn completion_failure( - &self, - token: VerificationToken, - sender: &(impl EcssTmSenderCore + ?Sized), - params: FailParams, - ) -> Result<(), VerificationOrSendErrorWithToken> { - let seq_count = self - .seq_count_provider - .as_ref() - .map_or(0, |v| v.get_and_increment()); - let msg_count = self - .seq_count_provider - .as_ref() - .map_or(0, |v| v.get_and_increment()); - let mut buf = self.source_data_buf.borrow_mut(); - let sendable = self.reporter.completion_failure( - buf.as_mut_slice(), - token, - seq_count, - msg_count, - params, - )?; - self.reporter - .send_step_or_completion_failure(sendable, sender) - } - } - - /// 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 reporter: VerificationReporter, - pub sender: Sender, - } - - 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: Sender) -> Self { - Self { reporter, sender } - } - - delegate! { - to self.reporter { - pub fn set_apid(&mut self, apid: u16) -> bool; - pub fn apid(&self) -> u16; - pub fn dest_id(&self) -> u16; - pub fn set_dest_id(&mut self, dest_id: u16); - } - } - } - - impl VerificationReportingProvider - for VerificationReporterWithSender - { - delegate! { - to self.reporter { - fn add_tc( - &mut self, - pus_tc: &(impl CcsdsPacket + IsPusTelecommand), - ) -> VerificationToken; - fn add_tc_with_req_id(&mut self, req_id: RequestId) -> VerificationToken; - } - } - - fn acceptance_success( - &self, - token: VerificationToken, - time_stamp: &[u8], - ) -> Result, VerificationOrSendErrorWithToken> - { - self.reporter - .acceptance_success(token, &self.sender, time_stamp) - } - - fn acceptance_failure( - &self, - token: VerificationToken, - params: FailParams, - ) -> Result<(), VerificationOrSendErrorWithToken> { - self.reporter - .acceptance_failure(token, &self.sender, params) - } - - fn start_success( - &self, - token: VerificationToken, - time_stamp: &[u8], - ) -> Result< - VerificationToken, - VerificationOrSendErrorWithToken, - > { - self.reporter.start_success(token, &self.sender, time_stamp) - } - - fn start_failure( - &self, - token: VerificationToken, - params: FailParams, - ) -> Result<(), VerificationOrSendErrorWithToken> { - self.reporter.start_failure(token, &self.sender, params) - } - - fn step_success( - &self, - token: &VerificationToken, - time_stamp: &[u8], - step: impl EcssEnumeration, - ) -> Result<(), EcssTmtcError> { - self.reporter - .step_success(token, &self.sender, time_stamp, step) - } - - fn step_failure( - &self, - token: VerificationToken, - params: FailParamsWithStep, - ) -> Result<(), VerificationOrSendErrorWithToken> { - self.reporter.step_failure(token, &self.sender, params) - } - - fn completion_success( - &self, - token: VerificationToken, - time_stamp: &[u8], - ) -> Result<(), VerificationOrSendErrorWithToken> { - self.reporter - .completion_success(token, &self.sender, time_stamp) - } - fn completion_failure( &self, + sender_id: ComponentId, + sender: &(impl EcssTmSenderCore + ?Sized), token: VerificationToken, params: FailParams, - ) -> Result<(), VerificationOrSendErrorWithToken> { - self.reporter - .completion_failure(token, &self.sender, params) + ) -> Result<(), EcssTmtcError> { + let mut buf = self.source_data_buf.borrow_mut(); + let sendable = self + .reporter_creator + .completion_failure(buf.as_mut_slice(), token, 0, 00, params) + .map_err(PusError::ByteConversion)?; + sender.send_tm(sender_id, PusTmVariant::Direct(sendable))?; + Ok(()) } } - - pub type VerificationReporterWithSharedPoolSender = - VerificationReporterWithSender>; - pub type VerificationReporterWithVecSender = - VerificationReporterWithSender>; } +/* #[cfg(feature = "std")] pub mod std_mod { use std::sync::mpsc; use crate::pool::StoreAddr; + use crate::pus::verification::VerificationReporterWithSender; - use super::alloc_mod::{ - VerificationReporterWithSharedPoolSender, VerificationReporterWithVecSender, - }; + use super::alloc_mod::VerificationReporterWithSharedPoolSender; pub type VerificationReporterWithSharedPoolMpscSender = VerificationReporterWithSharedPoolSender>; pub type VerificationReporterWithSharedPoolMpscBoundedSender = VerificationReporterWithSharedPoolSender>; pub type VerificationReporterWithVecMpscSender = - VerificationReporterWithVecSender>>; + VerificationReporterWithSender>>; pub type VerificationReporterWithVecMpscBoundedSender = - VerificationReporterWithVecSender>>; + VerificationReporterWithSender>>; } + */ #[cfg(any(feature = "test_util", test))] pub mod test_util { + use alloc::vec::Vec; use core::cell::RefCell; - use std::sync::Mutex; - - use alloc::{sync::Arc, vec::Vec}; - use hashbrown::HashMap; + use std::collections::VecDeque; use super::*; + /* #[derive(Clone)] pub struct VerificationStatus { pub accepted: Option, @@ -1489,217 +1211,374 @@ pub mod test_util { pub failure_data: Option>, pub fail_enum: Option, } + */ - pub type SharedVerificationMap = Arc>>>; + //pub type SharedVerificationMap = Arc>>>; - #[derive(Clone)] + #[derive(Default)] pub struct TestVerificationReporter { - pub verification_map: SharedVerificationMap, + pub report_queue: RefCell>, } - impl TestVerificationReporter { - pub fn new(verification_map: SharedVerificationMap) -> Self { - Self { verification_map } - } + #[derive(Debug, PartialEq)] + pub struct SuccessData { + pub sender: ComponentId, + pub time_stamp: Vec, + } + + #[derive(Debug, PartialEq)] + pub struct FailureData { + pub sender: ComponentId, + pub error_enum: u64, + pub fail_data: Vec, + pub time_stamp: Vec, + } + + #[derive(Debug, PartialEq)] + pub enum VerificationReportInfo { + Added, + AcceptanceSuccess(SuccessData), + AcceptanceFailure(FailureData), + StartedSuccess(SuccessData), + StartedFailure(FailureData), + StepSuccess { data: SuccessData, step: u16 }, + StepFailure(FailureData), + CompletionSuccess(SuccessData), + CompletionFailure(FailureData), } impl VerificationReportingProvider for TestVerificationReporter { + fn set_apid(&mut self, _apid: Apid) {} + + fn apid(&self) -> Apid { + 0 + } + fn add_tc_with_req_id(&mut self, req_id: RequestId) -> VerificationToken { - let verif_map = self.verification_map.lock().unwrap(); - verif_map.borrow_mut().insert( - req_id, - VerificationStatus { - accepted: None, - started: None, - step: 0, - step_status: None, - completed: None, - failure_data: None, - fail_enum: None, - }, - ); + self.report_queue + .borrow_mut() + .push_back((req_id, VerificationReportInfo::Added)); VerificationToken { - state: core::marker::PhantomData, + state: PhantomData, request_id: req_id, } } fn acceptance_success( &self, + sender_id: ComponentId, + _sender: &(impl EcssTmSenderCore + ?Sized), token: VerificationToken, - _time_stamp: &[u8], - ) -> Result< - VerificationToken, - super::VerificationOrSendErrorWithToken, - > { - let verif_map = self.verification_map.lock().unwrap(); - match verif_map.borrow_mut().get_mut(&token.request_id) { - Some(entry) => entry.accepted = Some(true), - None => panic!( - "unexpected acceptance success for request ID {}", - token.request_id() - ), - }; + time_stamp: &[u8], + ) -> Result, EcssTmtcError> { + self.report_queue.borrow_mut().push_back(( + token.request_id(), + VerificationReportInfo::AcceptanceSuccess(SuccessData { + sender: sender_id, + time_stamp: time_stamp.to_vec(), + }), + )); Ok(VerificationToken { - state: core::marker::PhantomData, + state: PhantomData, request_id: token.request_id, }) } fn acceptance_failure( &self, + sender_id: ComponentId, + _sender: &(impl EcssTmSenderCore + ?Sized), token: VerificationToken, params: FailParams, - ) -> Result<(), super::VerificationOrSendErrorWithToken> { - let verif_map = self.verification_map.lock().unwrap(); - match verif_map.borrow_mut().get_mut(&token.request_id) { - Some(entry) => { - entry.accepted = Some(false); - entry.failure_data = Some(params.failure_data.to_vec()); - entry.fail_enum = Some(params.failure_code.value()); - } - None => panic!( - "unexpected acceptance failure for request ID {}", - token.request_id() - ), - }; + ) -> Result<(), EcssTmtcError> { + self.report_queue.borrow_mut().push_back(( + token.request_id(), + VerificationReportInfo::AcceptanceFailure(FailureData { + sender: sender_id, + error_enum: params.failure_code.value(), + fail_data: params.failure_data.to_vec(), + time_stamp: params.time_stamp.to_vec(), + }), + )); Ok(()) } fn start_success( &self, - token: VerificationToken, - _time_stamp: &[u8], - ) -> Result< - VerificationToken, - super::VerificationOrSendErrorWithToken, - > { - let verif_map = self.verification_map.lock().unwrap(); - match verif_map.borrow_mut().get_mut(&token.request_id) { - Some(entry) => entry.started = Some(true), - None => panic!( - "unexpected start success for request ID {}", - token.request_id() - ), - }; + sender_id: ComponentId, + _sender: &(impl EcssTmSenderCore + ?Sized), + token: VerificationToken, + time_stamp: &[u8], + ) -> Result, EcssTmtcError> { + self.report_queue.borrow_mut().push_back(( + token.request_id(), + VerificationReportInfo::StartedSuccess(SuccessData { + sender: sender_id, + time_stamp: time_stamp.to_vec(), + }), + )); Ok(VerificationToken { - state: core::marker::PhantomData, + state: PhantomData, request_id: token.request_id, }) } fn start_failure( &self, + sender_id: ComponentId, + _sender: &(impl EcssTmSenderCore + ?Sized), token: VerificationToken, params: FailParams, - ) -> Result<(), super::VerificationOrSendErrorWithToken> { - let verif_map = self.verification_map.lock().unwrap(); - match verif_map.borrow_mut().get_mut(&token.request_id) { - Some(entry) => { - entry.started = Some(false); - entry.failure_data = Some(params.failure_data.to_vec()); - entry.fail_enum = Some(params.failure_code.value()); - } - None => panic!( - "unexpected start failure for request ID {}", - token.request_id() - ), - }; + ) -> Result<(), EcssTmtcError> { + self.report_queue.borrow_mut().push_back(( + token.request_id(), + VerificationReportInfo::StartedFailure(FailureData { + sender: sender_id, + error_enum: params.failure_code.value(), + fail_data: params.failure_data.to_vec(), + time_stamp: params.time_stamp.to_vec(), + }), + )); Ok(()) } fn step_success( &self, - token: &VerificationToken, - _time_stamp: &[u8], - step: impl spacepackets::ecss::EcssEnumeration, + sender_id: ComponentId, + _sender: &(impl EcssTmSenderCore + ?Sized), + token: &VerificationToken, + time_stamp: &[u8], + step: impl EcssEnumeration, ) -> Result<(), EcssTmtcError> { - let verif_map = self.verification_map.lock().unwrap(); - match verif_map.borrow_mut().get_mut(&token.request_id) { - Some(entry) => { - entry.step = step.value().try_into().unwrap(); - entry.step_status = Some(true); - } - None => panic!( - "unexpected start success for request ID {}", - token.request_id() - ), - }; + self.report_queue.borrow_mut().push_back(( + token.request_id(), + VerificationReportInfo::StepSuccess { + data: SuccessData { + sender: sender_id, + time_stamp: time_stamp.to_vec(), + }, + step: step.value() as u16, + }, + )); Ok(()) } fn step_failure( &self, - token: VerificationToken, + sender_id: ComponentId, + _sender: &(impl EcssTmSenderCore + ?Sized), + token: VerificationToken, params: FailParamsWithStep, - ) -> Result<(), super::VerificationOrSendErrorWithToken> { - let verif_map = self.verification_map.lock().unwrap(); - match verif_map.borrow_mut().get_mut(&token.request_id) { - Some(entry) => { - entry.step_status = Some(false); - entry.step = params.step.value().try_into().unwrap(); - entry.failure_data = Some(params.params.failure_data.to_vec()); - entry.fail_enum = Some(params.params.failure_code.value()); - } - None => panic!( - "unexpected start success for request ID {}", - token.request_id() - ), - }; + ) -> Result<(), EcssTmtcError> { + self.report_queue.borrow_mut().push_back(( + token.request_id(), + VerificationReportInfo::StepFailure(FailureData { + sender: sender_id, + error_enum: params.common.failure_code.value(), + fail_data: params.common.failure_data.to_vec(), + time_stamp: params.common.time_stamp.to_vec(), + }), + )); Ok(()) } fn completion_success( &self, + sender_id: ComponentId, + _sender: &(impl EcssTmSenderCore + ?Sized), token: VerificationToken, - _time_stamp: &[u8], - ) -> Result<(), super::VerificationOrSendErrorWithToken> { - let verif_map = self.verification_map.lock().unwrap(); - match verif_map.borrow_mut().get_mut(&token.request_id) { - Some(entry) => entry.completed = Some(true), - None => panic!( - "unexpected acceptance success for request ID {}", - token.request_id() - ), - }; + time_stamp: &[u8], + ) -> Result<(), EcssTmtcError> { + self.report_queue.borrow_mut().push_back(( + token.request_id(), + VerificationReportInfo::CompletionSuccess(SuccessData { + sender: sender_id, + time_stamp: time_stamp.to_vec(), + }), + )); Ok(()) } - fn completion_failure( + fn completion_failure( &self, + sender_id: ComponentId, + _sender: &(impl EcssTmSenderCore + ?Sized), token: VerificationToken, params: FailParams, - ) -> Result<(), super::VerificationOrSendErrorWithToken> { - let verif_map = self.verification_map.lock().unwrap(); - match verif_map.borrow_mut().get_mut(&token.request_id) { - Some(entry) => { - entry.completed = Some(false); - entry.failure_data = Some(params.failure_data.to_vec()); - entry.fail_enum = Some(params.failure_code.value()); - } - None => panic!( - "unexpected acceptance success for request ID {}", - token.request_id() - ), - }; + ) -> Result<(), EcssTmtcError> { + self.report_queue.borrow_mut().push_back(( + token.request_id(), + VerificationReportInfo::CompletionFailure(FailureData { + sender: sender_id, + error_enum: params.failure_code.value(), + fail_data: params.failure_data.to_vec(), + time_stamp: params.time_stamp.to_vec(), + }), + )); Ok(()) } } impl TestVerificationReporter { + pub fn check_next_was_added(&mut self, request_id: RequestId) { + let (last_report_req_id, info) = self + .report_queue + .get_mut() + .pop_front() + .expect("report queue is empty"); + assert_eq!(request_id, last_report_req_id); + assert_eq!(info, VerificationReportInfo::Added); + } + pub fn check_next_is_acceptance_success( + &mut self, + sender_id: ComponentId, + req_id: RequestId, + ) { + let (last_report_req_id, info) = self + .report_queue + .get_mut() + .pop_front() + .expect("report queue is empty"); + assert_eq!(req_id, last_report_req_id); + if let VerificationReportInfo::AcceptanceSuccess(data) = info { + assert_eq!(data.sender, sender_id); + } + panic!("next message is not acceptance success message") + } + + pub fn check_next_is_started_success(&mut self, sender_id: ComponentId, req_id: RequestId) { + let (last_report_req_id, info) = self + .report_queue + .get_mut() + .pop_front() + .expect("report queue is empty"); + assert_eq!(req_id, last_report_req_id); + if let VerificationReportInfo::StartedSuccess(data) = info { + assert_eq!(data.sender, sender_id); + } + panic!("next message is not start success message") + } + + pub fn check_next_is_step_success( + &mut self, + sender_id: ComponentId, + request_id: RequestId, + expected_step: u16, + ) { + let (last_report_req_id, info) = self + .report_queue + .get_mut() + .pop_front() + .expect("report queue is empty"); + assert_eq!(request_id, last_report_req_id); + if let VerificationReportInfo::StepSuccess { data, step } = info { + assert_eq!(data.sender, sender_id); + assert_eq!(expected_step, step); + } + panic!("next message is not step success message") + } + + pub fn check_next_is_step_failure( + &mut self, + sender_id: ComponentId, + request_id: RequestId, + error_code: u64, + ) { + let (last_report_req_id, info) = self + .report_queue + .get_mut() + .pop_front() + .expect("report queue is empty"); + assert_eq!(request_id, last_report_req_id); + if let VerificationReportInfo::StepFailure(data) = info { + assert_eq!(data.sender, sender_id); + assert_eq!(data.error_enum, error_code); + } + panic!("next message is not step success message") + } + + pub fn check_next_is_completion_success( + &mut self, + sender_id: ComponentId, + request_id: RequestId, + ) { + let (last_report_req_id, info) = self + .report_queue + .get_mut() + .pop_front() + .expect("report queue is empty"); + assert_eq!(request_id, last_report_req_id); + if let VerificationReportInfo::CompletionSuccess(data) = info { + assert_eq!(data.sender, sender_id); + } + panic!("next message is not completion success message") + } + + pub fn check_next_is_completion_failure( + &mut self, + sender_id: ComponentId, + request_id: RequestId, + error_code: u64, + ) { + let (last_report_req_id, info) = self + .report_queue + .get_mut() + .pop_front() + .expect("report queue is empty"); + assert_eq!(request_id, last_report_req_id); + if let VerificationReportInfo::CompletionFailure(data) = info { + assert_eq!(data.sender, sender_id); + assert_eq!(data.error_enum, error_code); + } + panic!("next message is not completion success message") + } + + pub fn assert_full_completion_success( + &mut self, + sender_id: ComponentId, + request_id: RequestId, + expected_steps: Option, + ) { + self.check_next_was_added(request_id); + self.check_next_is_acceptance_success(sender_id, request_id); + if let Some(highest_num) = expected_steps { + for i in 0..highest_num { + self.check_next_is_step_success(sender_id, request_id, i); + } + } + self.check_next_is_completion_success(sender_id, request_id); + } + + pub fn assert_completion_failure( + &mut self, + sender_id: ComponentId, + request_id: RequestId, + expected_steps: Option, + error_code: u64, + ) { + self.check_next_was_added(request_id); + self.check_next_is_acceptance_success(sender_id, request_id); + if let Some(highest_num) = expected_steps { + for i in 0..highest_num { + self.check_next_is_step_success(sender_id, request_id, i); + } + } + self.check_next_is_completion_failure(sender_id, request_id, error_code); + } + + pub fn get_next_verification_message(&mut self) -> (RequestId, VerificationReportInfo) { + self.report_queue + .get_mut() + .pop_front() + .expect("report queue is empty") + } + /* pub fn verification_info(&self, req_id: &RequestId) -> Option { let verif_map = self.verification_map.lock().unwrap(); let value = verif_map.borrow().get(req_id).cloned(); value } - pub fn check_accepted(&self, req_id: &RequestId) -> bool { - let verif_map = self.verification_map.lock().unwrap(); - if let Some(entry) = verif_map.borrow().get(req_id) { - return entry.accepted.unwrap_or(false); - } - false - } pub fn check_started(&self, req_id: &RequestId) -> bool { let verif_map = self.verification_map.lock().unwrap(); @@ -1725,14 +1604,6 @@ pub mod test_util { assert_eq!(entry.completed.unwrap(), completion_success); } - pub fn assert_full_completion_success(&self, req_id: &RequestId, step: Option) { - let verif_map = self.verification_map.lock().unwrap(); - if let Some(entry) = verif_map.borrow().get(req_id) { - Self::generic_completion_checks(entry, step, true); - return; - } - panic!("request not in verification map"); - } pub fn assert_completion_failure( &self, @@ -1756,38 +1627,39 @@ pub mod test_util { } panic!("request not in verification map"); } + */ } } #[cfg(test)] pub mod tests { - use crate::pool::{PoolProviderWithGuards, StaticMemoryPool, StaticPoolConfig}; + use crate::pool::{StaticMemoryPool, StaticPoolConfig}; use crate::pus::test_util::TEST_APID; use crate::pus::tests::CommonTmInfo; use crate::pus::verification::{ EcssTmSenderCore, EcssTmtcError, FailParams, FailParamsWithStep, RequestId, TcStateNone, - VerificationReporter, VerificationReporterCfg, VerificationReporterWithSender, - VerificationToken, - }; - use crate::pus::{ - EcssChannel, PusTmWrapper, TmInSharedPoolSenderWithId, TmInSharedPoolSenderWithMpsc, + VerificationReporter, VerificationReporterCfg, VerificationToken, }; + use crate::pus::{ChannelWithId, MpscTmInSharedPoolSender, PusTmVariant}; use crate::tmtc::tm_helper::SharedTmPool; use crate::ComponentId; use alloc::format; - use spacepackets::ecss::tc::{PusTcCreator, PusTcSecondaryHeader}; - use spacepackets::ecss::tm::PusTmReader; - use spacepackets::ecss::{EcssEnumU16, EcssEnumU32, EcssEnumU8, PusError, PusPacket}; + use spacepackets::ecss::tc::{PusTcCreator, PusTcReader, PusTcSecondaryHeader}; + use spacepackets::ecss::{ + EcssEnumU16, EcssEnumU32, EcssEnumU8, EcssEnumeration, PusError, PusPacket, + WritablePusPacket, + }; use spacepackets::util::UnsignedEnum; - use spacepackets::{ByteConversionError, CcsdsPacket, SpHeader}; + use spacepackets::{ByteConversionError, SpHeader}; use std::cell::RefCell; use std::collections::VecDeque; use std::sync::mpsc; - use std::time::Duration; use std::vec; use std::vec::Vec; - use super::VerificationReportingProvider; + use super::{ + TcStateAccepted, TcStateStarted, VerificationReportingProvider, WasAtLeastAccepted, + }; fn is_send(_: &T) {} #[allow(dead_code)] @@ -1807,7 +1679,7 @@ pub mod tests { pub service_queue: RefCell>, } - impl EcssChannel for TestSender { + impl ChannelWithId for TestSender { fn id(&self) -> ComponentId { 0 } @@ -1817,12 +1689,12 @@ pub mod tests { } impl EcssTmSenderCore for TestSender { - fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> { + fn send_tm(&self, sender_id: ComponentId, tm: PusTmVariant) -> Result<(), EcssTmtcError> { match tm { - PusTmWrapper::InStore(_) => { + PusTmVariant::InStore(_) => { panic!("TestSender: Can not deal with addresses"); } - PusTmWrapper::Direct(tm) => { + PusTmVariant::Direct(tm) => { assert_eq!(PusPacket::service(&tm), 1); assert!(!tm.source_data().is_empty()); let mut time_stamp = [0; 7]; @@ -1848,27 +1720,12 @@ pub mod tests { } } - struct TestBase<'a> { - vr: VerificationReporter, - #[allow(dead_code)] - tc: PusTcCreator<'a>, - } - - impl<'a> TestBase<'a> { - fn rep(&mut self) -> &mut VerificationReporter { - &mut self.vr - } - } - struct TestBaseWithHelper<'a, Sender: EcssTmSenderCore + Clone + 'static> { - helper: VerificationReporterWithSender, - #[allow(dead_code)] - tc: PusTcCreator<'a>, - } - - impl<'a, Sender: EcssTmSenderCore + Clone + 'static> TestBaseWithHelper<'a, Sender> { - fn rep(&mut self) -> &mut VerificationReporter { - &mut self.helper.reporter - } + struct VerificationReporterTestbench { + id: ComponentId, + sender: TestSender, + reporter: VerificationReporter, + request_id: RequestId, + tc: Vec, } fn base_reporter() -> VerificationReporter { @@ -1876,180 +1733,484 @@ pub mod tests { VerificationReporter::new(&cfg) } - fn base_tc_init(app_data: Option<&[u8]>) -> (PusTcCreator, RequestId) { + impl VerificationReporterTestbench { + fn new(id: ComponentId, tc: PusTcCreator) -> Self { + let mut reporter = base_reporter(); + Self { + id, + sender: TestSender::default(), + reporter, + request_id: RequestId::new(&tc), + tc: tc.to_vec().unwrap(), + } + } + + fn set_dest_id(&mut self, dest_id: u16) { + self.reporter.set_dest_id(dest_id); + } + + fn init(&mut self) -> VerificationToken { + self.reporter.add_tc(&PusTcReader::new(&self.tc).unwrap().0) + } + + fn acceptance_success( + &self, + token: VerificationToken, + time_stamp: &[u8], + ) -> Result, EcssTmtcError> { + self.reporter + .acceptance_success(self.id, &self.sender, token, time_stamp) + } + + fn acceptance_failure( + &self, + token: VerificationToken, + params: FailParams, + ) -> Result<(), EcssTmtcError> { + self.reporter + .acceptance_failure(self.id, &self.sender, token, params) + } + + fn start_success( + &self, + token: VerificationToken, + time_stamp: &[u8], + ) -> Result, EcssTmtcError> { + self.reporter + .start_success(self.id, &self.sender, token, time_stamp) + } + + fn start_failure( + &self, + token: VerificationToken, + params: FailParams, + ) -> Result<(), EcssTmtcError> { + self.reporter + .start_failure(self.id, &self.sender, token, params) + } + + fn step_success( + &self, + token: &VerificationToken, + time_stamp: &[u8], + step: impl EcssEnumeration, + ) -> Result<(), EcssTmtcError> { + self.reporter + .step_success(self.id, &self.sender, token, time_stamp, step) + } + + fn step_failure( + &self, + token: VerificationToken, + params: FailParamsWithStep, + ) -> Result<(), EcssTmtcError> { + self.reporter + .step_failure(self.id, &self.sender, token, params) + } + + fn completion_success( + &self, + token: VerificationToken, + time_stamp: &[u8], + ) -> Result<(), EcssTmtcError> { + self.reporter + .completion_success(self.id, &self.sender, token, time_stamp) + } + + fn completion_failure( + &self, + token: VerificationToken, + params: FailParams, + ) -> Result<(), EcssTmtcError> { + self.reporter + .completion_failure(self.id, &self.sender, token, params) + } + + fn acceptance_check(&self, time_stamp: &[u8; 7]) { + let cmp_info = TmInfo { + common: CommonTmInfo { + subservice: 1, + apid: TEST_APID, + msg_counter: 0, + dest_id: self.reporter.dest_id(), + time_stamp: *time_stamp, + }, + additional_data: None, + req_id: self.request_id, + }; + let mut service_queue = self.sender.service_queue.borrow_mut(); + assert_eq!(service_queue.len(), 1); + let info = service_queue.pop_front().unwrap(); + assert_eq!(info, cmp_info); + } + + fn acceptance_fail_check(&mut self, stamp_buf: [u8; 7]) { + let cmp_info = TmInfo { + common: CommonTmInfo { + subservice: 2, + apid: TEST_APID, + msg_counter: 0, + dest_id: self.reporter.dest_id(), + time_stamp: stamp_buf, + }, + additional_data: Some([0, 2].to_vec()), + req_id: self.request_id, + }; + let service_queue = self.sender.service_queue.get_mut(); + assert_eq!(service_queue.len(), 1); + let info = service_queue.pop_front().unwrap(); + assert_eq!(info, cmp_info); + } + + fn start_fail_check(&mut self, fail_data_raw: [u8; 4]) { + let mut srv_queue = self.sender.service_queue.borrow_mut(); + assert_eq!(srv_queue.len(), 2); + let mut cmp_info = TmInfo { + common: CommonTmInfo { + subservice: 1, + apid: TEST_APID, + msg_counter: 0, + dest_id: 0, + time_stamp: EMPTY_STAMP, + }, + additional_data: None, + req_id: self.request_id, + }; + let mut info = srv_queue.pop_front().unwrap(); + assert_eq!(info, cmp_info); + + cmp_info = TmInfo { + common: CommonTmInfo { + subservice: 4, + apid: TEST_APID, + msg_counter: 0, + dest_id: 0, + time_stamp: EMPTY_STAMP, + }, + additional_data: Some([&[22], fail_data_raw.as_slice()].concat().to_vec()), + req_id: self.request_id, + }; + info = srv_queue.pop_front().unwrap(); + assert_eq!(info, cmp_info); + } + + fn step_success_check(&mut self, time_stamp: &[u8; 7]) { + let mut cmp_info = TmInfo { + common: CommonTmInfo { + subservice: 1, + apid: TEST_APID, + msg_counter: 0, + dest_id: self.reporter.dest_id(), + time_stamp: *time_stamp, + }, + additional_data: None, + req_id: self.request_id, + }; + let mut srv_queue = self.sender.service_queue.borrow_mut(); + let mut info = srv_queue.pop_front().unwrap(); + assert_eq!(info, cmp_info); + cmp_info = TmInfo { + common: CommonTmInfo { + subservice: 3, + apid: TEST_APID, + msg_counter: 0, + dest_id: self.reporter.dest_id(), + time_stamp: *time_stamp, + }, + additional_data: None, + req_id: self.request_id, + }; + info = srv_queue.pop_front().unwrap(); + assert_eq!(info, cmp_info); + cmp_info = TmInfo { + common: CommonTmInfo { + subservice: 5, + apid: TEST_APID, + msg_counter: 0, + dest_id: self.reporter.dest_id(), + time_stamp: *time_stamp, + }, + additional_data: Some([0].to_vec()), + req_id: self.request_id, + }; + info = srv_queue.pop_front().unwrap(); + assert_eq!(info, cmp_info); + cmp_info = TmInfo { + common: CommonTmInfo { + subservice: 5, + apid: TEST_APID, + msg_counter: 0, + dest_id: 0, + time_stamp: *time_stamp, + }, + additional_data: Some([1].to_vec()), + req_id: self.request_id, + }; + info = srv_queue.pop_front().unwrap(); + assert_eq!(info, cmp_info); + } + + fn check_step_failure(&mut self, fail_data_raw: [u8; 4]) { + assert_eq!(self.sender.service_queue.borrow().len(), 4); + let mut cmp_info = TmInfo { + common: CommonTmInfo { + subservice: 1, + apid: TEST_APID, + msg_counter: 0, + dest_id: self.reporter.dest_id(), + time_stamp: EMPTY_STAMP, + }, + additional_data: None, + req_id: self.request_id, + }; + let mut info = self.sender.service_queue.borrow_mut().pop_front().unwrap(); + assert_eq!(info, cmp_info); + + cmp_info = TmInfo { + common: CommonTmInfo { + subservice: 3, + apid: TEST_APID, + msg_counter: 0, + dest_id: self.reporter.dest_id(), + time_stamp: [0, 1, 0, 1, 0, 1, 0], + }, + additional_data: None, + req_id: self.request_id, + }; + info = self.sender.service_queue.borrow_mut().pop_front().unwrap(); + assert_eq!(info, cmp_info); + + cmp_info = TmInfo { + common: CommonTmInfo { + subservice: 5, + apid: TEST_APID, + msg_counter: 0, + dest_id: self.reporter.dest_id(), + time_stamp: EMPTY_STAMP, + }, + additional_data: Some([0].to_vec()), + req_id: self.request_id, + }; + info = self.sender.service_queue.get_mut().pop_front().unwrap(); + assert_eq!(info, cmp_info); + + cmp_info = TmInfo { + common: CommonTmInfo { + subservice: 6, + apid: TEST_APID, + msg_counter: 0, + dest_id: self.reporter.dest_id(), + time_stamp: EMPTY_STAMP, + }, + additional_data: Some( + [ + [1].as_slice(), + &[0, 0, 0x10, 0x20], + fail_data_raw.as_slice(), + ] + .concat() + .to_vec(), + ), + req_id: self.request_id, + }; + info = self.sender.service_queue.get_mut().pop_front().unwrap(); + assert_eq!(info, cmp_info); + } + + fn completion_fail_check(&mut self) { + assert_eq!(self.sender.service_queue.borrow().len(), 3); + + let mut cmp_info = TmInfo { + common: CommonTmInfo { + subservice: 1, + apid: TEST_APID, + msg_counter: 0, + dest_id: self.reporter.dest_id(), + time_stamp: EMPTY_STAMP, + }, + additional_data: None, + req_id: self.request_id, + }; + let mut info = self.sender.service_queue.get_mut().pop_front().unwrap(); + assert_eq!(info, cmp_info); + + cmp_info = TmInfo { + common: CommonTmInfo { + subservice: 3, + apid: TEST_APID, + msg_counter: 0, + dest_id: 0, + time_stamp: [0, 1, 0, 1, 0, 1, 0], + }, + additional_data: None, + req_id: self.request_id, + }; + info = self.sender.service_queue.get_mut().pop_front().unwrap(); + assert_eq!(info, cmp_info); + + cmp_info = TmInfo { + common: CommonTmInfo { + subservice: 8, + apid: TEST_APID, + msg_counter: 0, + dest_id: self.reporter.dest_id(), + time_stamp: EMPTY_STAMP, + }, + additional_data: Some([0, 0, 0x10, 0x20].to_vec()), + req_id: self.request_id, + }; + info = self.sender.service_queue.get_mut().pop_front().unwrap(); + assert_eq!(info, cmp_info); + } + + fn completion_success_check(&mut self) { + assert_eq!(self.sender.service_queue.borrow().len(), 3); + let cmp_info = TmInfo { + common: CommonTmInfo { + subservice: 1, + apid: TEST_APID, + msg_counter: 0, + dest_id: self.reporter.dest_id(), + time_stamp: EMPTY_STAMP, + }, + additional_data: None, + req_id: self.request_id, + }; + let mut info = self.sender.service_queue.borrow_mut().pop_front().unwrap(); + assert_eq!(info, cmp_info); + + let cmp_info = TmInfo { + common: CommonTmInfo { + subservice: 3, + apid: TEST_APID, + msg_counter: 0, + dest_id: self.reporter.dest_id(), + time_stamp: [0, 1, 0, 1, 0, 1, 0], + }, + additional_data: None, + req_id: self.request_id, + }; + info = self.sender.service_queue.borrow_mut().pop_front().unwrap(); + assert_eq!(info, cmp_info); + let cmp_info = TmInfo { + common: CommonTmInfo { + subservice: 7, + apid: TEST_APID, + msg_counter: 0, + dest_id: self.reporter.dest_id(), + time_stamp: EMPTY_STAMP, + }, + additional_data: None, + req_id: self.request_id, + }; + info = self.sender.service_queue.borrow_mut().pop_front().unwrap(); + assert_eq!(info, cmp_info); + } + } + + fn create_generic_ping() -> PusTcCreator<'static> { let mut sph = SpHeader::tc_unseg(TEST_APID, 0x34, 0).unwrap(); let tc_header = PusTcSecondaryHeader::new_simple(17, 1); - let app_data = app_data.unwrap_or(&[]); - let pus_tc = PusTcCreator::new(&mut sph, tc_header, app_data, true); - let req_id = RequestId::new(&pus_tc); - (pus_tc, req_id) - } - - fn base_init(api_sel: bool) -> (TestBase<'static>, VerificationToken) { - let mut reporter = base_reporter(); - let (tc, req_id) = base_tc_init(None); - let init_tok = if api_sel { - reporter.add_tc_with_req_id(req_id) - } else { - reporter.add_tc(&tc) - }; - (TestBase { vr: reporter, tc }, init_tok) - } - - 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, sender); - (TestBaseWithHelper { helper, tc }, init_tok) - } - - fn acceptance_check(sender: &mut TestSender, req_id: &RequestId) { - let cmp_info = TmInfo { - common: CommonTmInfo { - subservice: 1, - apid: TEST_APID, - msg_counter: 0, - dest_id: 0, - time_stamp: EMPTY_STAMP, - }, - additional_data: None, - req_id: *req_id, - }; - let mut service_queue = sender.service_queue.borrow_mut(); - assert_eq!(service_queue.len(), 1); - let info = service_queue.pop_front().unwrap(); - assert_eq!(info, cmp_info); + PusTcCreator::new(&mut sph, tc_header, &[], true) } #[test] - fn test_mpsc_verif_send_sync() { + fn test_mpsc_verif_send() { let pool = StaticMemoryPool::new(StaticPoolConfig::new(vec![(8, 8)], false)); let shared_tm_store = SharedTmPool::new(pool); let (tx, _) = mpsc::channel(); - let mpsc_verif_sender = - TmInSharedPoolSenderWithMpsc::new(0, "verif_sender", shared_tm_store, tx); + let mpsc_verif_sender = MpscTmInSharedPoolSender::new(shared_tm_store, tx); is_send(&mpsc_verif_sender); } #[test] fn test_state() { - let (mut b, _) = base_init(false); - assert_eq!(b.vr.apid(), TEST_APID); - b.vr.set_apid(TEST_APID + 1); - assert_eq!(b.vr.apid(), TEST_APID + 1); + let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping()); + assert_eq!(testbench.reporter.apid(), TEST_APID); + testbench.reporter.set_apid(TEST_APID + 1); + assert_eq!(testbench.reporter.apid(), TEST_APID + 1); } #[test] fn test_basic_acceptance_success() { - let (b, tok) = base_init(false); - let mut sender = TestSender::default(); - b.vr.acceptance_success(tok, &sender, &EMPTY_STAMP) - .expect("Sending acceptance success failed"); - acceptance_check(&mut sender, &tok.request_id); - } - - #[test] - fn test_basic_acceptance_success_with_helper() { - let (mut b, tok) = base_with_helper_init(); - b.helper - .acceptance_success(tok, &EMPTY_STAMP) - .expect("Sending acceptance success failed"); - acceptance_check(&mut b.helper.sender, &tok.request_id); - } - - fn acceptance_fail_check(sender: &mut TestSender, req_id: RequestId, stamp_buf: [u8; 7]) { - let cmp_info = TmInfo { - common: CommonTmInfo { - subservice: 2, - apid: TEST_APID, - msg_counter: 0, - dest_id: 5, - time_stamp: stamp_buf, - }, - additional_data: Some([0, 2].to_vec()), - req_id, - }; - let mut service_queue = sender.service_queue.borrow_mut(); - assert_eq!(service_queue.len(), 1); - let info = service_queue.pop_front().unwrap(); - assert_eq!(info, cmp_info); + let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping()); + let token = testbench.init(); + testbench + .acceptance_success(token, &EMPTY_STAMP) + .expect("sending acceptance success failed"); + testbench.acceptance_check(&EMPTY_STAMP); } #[test] fn test_basic_acceptance_failure() { - let (mut b, tok) = base_init(true); - b.rep().reporter.dest_id = 5; + let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping()); + let init_token = testbench.init(); let stamp_buf = [1, 2, 3, 4, 5, 6, 7]; - let mut sender = TestSender::default(); let fail_code = EcssEnumU16::new(2); let fail_params = FailParams::new_no_fail_data(stamp_buf.as_slice(), &fail_code); - b.vr.acceptance_failure(tok, &sender, fail_params) - .expect("Sending acceptance success failed"); - acceptance_fail_check(&mut sender, tok.request_id, stamp_buf); + testbench + .acceptance_failure(init_token, fail_params) + .expect("sending acceptance failure failed"); + testbench.acceptance_fail_check(stamp_buf); } #[test] fn test_basic_acceptance_failure_with_helper() { - let (mut b, tok) = base_with_helper_init(); - b.rep().reporter.dest_id = 5; + let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping()); + let init_token = testbench.init(); let stamp_buf = [1, 2, 3, 4, 5, 6, 7]; let fail_code = EcssEnumU16::new(2); let fail_params = FailParams::new_no_fail_data(stamp_buf.as_slice(), &fail_code); - b.helper - .acceptance_failure(tok, fail_params) - .expect("Sending acceptance success failed"); - acceptance_fail_check(&mut b.helper.sender, tok.request_id, stamp_buf); + testbench + .acceptance_failure(init_token, fail_params) + .expect("sending acceptance failure failed"); + testbench.acceptance_fail_check(stamp_buf); } #[test] fn test_acceptance_fail_data_too_large() { - let (mut b, tok) = base_with_helper_init(); - b.rep().reporter.dest_id = 5; + let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping()); + let init_token = testbench.init(); let stamp_buf = [1, 2, 3, 4, 5, 6, 7]; let fail_code = EcssEnumU16::new(2); let fail_data: [u8; 16] = [0; 16]; // 4 req ID + 1 byte step + 2 byte error code + 8 byte fail data - assert_eq!(b.rep().allowed_source_data_len(), 15); + assert_eq!(testbench.reporter.allowed_source_data_len(), 15); let fail_params = FailParams::new(stamp_buf.as_slice(), &fail_code, fail_data.as_slice()); - let res = b.helper.acceptance_failure(tok, fail_params); - assert!(res.is_err()); - let err_with_token = res.unwrap_err(); - assert_eq!(err_with_token.1, tok); - match err_with_token.0 { + let result = testbench.acceptance_failure(init_token, fail_params); + assert!(result.is_err()); + let error = result.unwrap_err(); + match error { EcssTmtcError::Pus(PusError::ByteConversion(e)) => match e { ByteConversionError::ToSliceTooSmall { found, expected } => { assert_eq!( expected, fail_data.len() + RequestId::SIZE_AS_BYTES + fail_code.size() ); - assert_eq!(found, b.rep().allowed_source_data_len()); + assert_eq!(found, testbench.reporter.allowed_source_data_len()); } _ => { panic!("{}", format!("Unexpected error {:?}", e)) } }, _ => { - panic!("{}", format!("Unexpected error {:?}", err_with_token.0)) + panic!("{}", format!("Unexpected error {:?}", error)) } } } #[test] fn test_basic_acceptance_failure_with_fail_data() { - let (b, tok) = base_init(false); - let sender = TestSender::default(); + let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping()); let fail_code = EcssEnumU8::new(10); let fail_data = EcssEnumU32::new(12); let mut fail_data_raw = [0; 4]; fail_data.write_to_be_bytes(&mut fail_data_raw).unwrap(); let fail_params = FailParams::new(&EMPTY_STAMP, &fail_code, fail_data_raw.as_slice()); - b.vr.acceptance_failure(tok, &sender, fail_params) - .expect("Sending acceptance success failed"); + let init_token = testbench.init(); + testbench + .acceptance_failure(init_token, fail_params) + .expect("sending acceptance failure failed"); let cmp_info = TmInfo { common: CommonTmInfo { subservice: 2, @@ -2059,253 +2220,75 @@ pub mod tests { time_stamp: EMPTY_STAMP, }, additional_data: Some([10, 0, 0, 0, 12].to_vec()), - req_id: tok.request_id, + req_id: testbench.request_id, }; - let mut service_queue = sender.service_queue.borrow_mut(); + let mut service_queue = testbench.sender.service_queue.borrow_mut(); assert_eq!(service_queue.len(), 1); let info = service_queue.pop_front().unwrap(); assert_eq!(info, cmp_info); } - fn start_fail_check(sender: &mut TestSender, req_id: RequestId, fail_data_raw: [u8; 4]) { - let mut srv_queue = sender.service_queue.borrow_mut(); - assert_eq!(srv_queue.len(), 2); - let mut cmp_info = TmInfo { - common: CommonTmInfo { - subservice: 1, - apid: TEST_APID, - msg_counter: 0, - dest_id: 0, - time_stamp: EMPTY_STAMP, - }, - additional_data: None, - req_id, - }; - let mut info = srv_queue.pop_front().unwrap(); - assert_eq!(info, cmp_info); - - cmp_info = TmInfo { - common: CommonTmInfo { - subservice: 4, - apid: TEST_APID, - msg_counter: 0, - dest_id: 0, - time_stamp: EMPTY_STAMP, - }, - additional_data: Some([&[22], fail_data_raw.as_slice()].concat().to_vec()), - req_id, - }; - info = srv_queue.pop_front().unwrap(); - assert_eq!(info, cmp_info); - } - - #[test] fn test_start_failure() { - let (b, tok) = base_init(false); - let mut sender = TestSender::default(); + let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping()); + let init_token = testbench.init(); let fail_code = EcssEnumU8::new(22); let fail_data: i32 = -12; let mut fail_data_raw = [0; 4]; fail_data_raw.copy_from_slice(fail_data.to_be_bytes().as_slice()); let fail_params = FailParams::new(&EMPTY_STAMP, &fail_code, fail_data_raw.as_slice()); - let accepted_token = - b.vr.acceptance_success(tok, &sender, &EMPTY_STAMP) - .expect("Sending acceptance success failed"); - b.vr.start_failure(accepted_token, &sender, fail_params) + let accepted_token = testbench + .acceptance_success(init_token, &EMPTY_STAMP) + .expect("Sending acceptance success failed"); + testbench + .start_failure(accepted_token, fail_params) .expect("Start failure failure"); - start_fail_check(&mut sender, tok.request_id, fail_data_raw); + testbench.start_fail_check(fail_data_raw); } #[test] fn test_start_failure_with_helper() { - let (mut b, tok) = base_with_helper_init(); + let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping()); + let token = testbench.init(); let fail_code = EcssEnumU8::new(22); let fail_data: i32 = -12; let mut fail_data_raw = [0; 4]; fail_data_raw.copy_from_slice(fail_data.to_be_bytes().as_slice()); let fail_params = FailParams::new(&EMPTY_STAMP, &fail_code, fail_data_raw.as_slice()); - let accepted_token = b - .helper - .acceptance_success(tok, &EMPTY_STAMP) - .expect("Sending acceptance success failed"); - b.helper + let accepted_token = testbench + .acceptance_success(token, &EMPTY_STAMP) + .expect("acceptance failed"); + testbench .start_failure(accepted_token, fail_params) - .expect("Start failure failure"); - start_fail_check(&mut b.helper.sender, tok.request_id, fail_data_raw); - } - - fn step_success_check(sender: &mut TestSender, req_id: RequestId) { - let mut cmp_info = TmInfo { - common: CommonTmInfo { - subservice: 1, - apid: TEST_APID, - msg_counter: 0, - dest_id: 0, - time_stamp: EMPTY_STAMP, - }, - additional_data: None, - req_id, - }; - let mut srv_queue = sender.service_queue.borrow_mut(); - let mut info = srv_queue.pop_front().unwrap(); - assert_eq!(info, cmp_info); - cmp_info = TmInfo { - common: CommonTmInfo { - subservice: 3, - apid: TEST_APID, - msg_counter: 0, - dest_id: 0, - time_stamp: [0, 1, 0, 1, 0, 1, 0], - }, - additional_data: None, - req_id, - }; - info = srv_queue.pop_front().unwrap(); - assert_eq!(info, cmp_info); - cmp_info = TmInfo { - common: CommonTmInfo { - subservice: 5, - apid: TEST_APID, - msg_counter: 0, - dest_id: 0, - time_stamp: EMPTY_STAMP, - }, - additional_data: Some([0].to_vec()), - req_id, - }; - info = srv_queue.pop_front().unwrap(); - assert_eq!(info, cmp_info); - cmp_info = TmInfo { - common: CommonTmInfo { - subservice: 5, - apid: TEST_APID, - msg_counter: 0, - dest_id: 0, - time_stamp: EMPTY_STAMP, - }, - additional_data: Some([1].to_vec()), - req_id, - }; - info = srv_queue.pop_front().unwrap(); - assert_eq!(info, cmp_info); + .expect("start failure failed"); + testbench.start_fail_check(fail_data_raw); } #[test] fn test_steps_success() { - let (mut b, tok) = base_init(false); - let mut sender = TestSender::default(); - let accepted_token = b - .rep() - .acceptance_success(tok, &sender, &EMPTY_STAMP) - .expect("Sending acceptance success failed"); - let started_token = b - .rep() - .start_success(accepted_token, &sender, &[0, 1, 0, 1, 0, 1, 0]) - .expect("Sending start success failed"); - b.rep() - .step_success(&started_token, &sender, &EMPTY_STAMP, EcssEnumU8::new(0)) - .expect("Sending step 0 success failed"); - b.vr.step_success(&started_token, &sender, &EMPTY_STAMP, EcssEnumU8::new(1)) - .expect("Sending step 1 success failed"); - assert_eq!(sender.service_queue.borrow().len(), 4); - step_success_check(&mut sender, tok.request_id); - } - - #[test] - fn test_steps_success_with_helper() { - let (mut b, tok) = base_with_helper_init(); - let accepted_token = b - .helper - .acceptance_success(tok, &EMPTY_STAMP) - .expect("Sending acceptance success failed"); - let started_token = b - .helper - .start_success(accepted_token, &[0, 1, 0, 1, 0, 1, 0]) - .expect("Sending start success failed"); - b.helper + let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping()); + let token = testbench.init(); + let accepted_token = testbench + .acceptance_success(token, &EMPTY_STAMP) + .expect("acceptance failed"); + let started_token = testbench + .start_success(accepted_token, &EMPTY_STAMP) + .expect("acceptance failed"); + testbench .step_success(&started_token, &EMPTY_STAMP, EcssEnumU8::new(0)) - .expect("Sending step 0 success failed"); - b.helper + .expect("step 0 failed"); + testbench .step_success(&started_token, &EMPTY_STAMP, EcssEnumU8::new(1)) - .expect("Sending step 1 success failed"); - assert_eq!(b.helper.sender.service_queue.borrow().len(), 4); - step_success_check(&mut b.helper.sender, tok.request_id); - } - - fn check_step_failure(sender: &mut TestSender, req_id: RequestId, fail_data_raw: [u8; 4]) { - assert_eq!(sender.service_queue.borrow().len(), 4); - let mut cmp_info = TmInfo { - common: CommonTmInfo { - subservice: 1, - apid: TEST_APID, - msg_counter: 0, - dest_id: 0, - time_stamp: EMPTY_STAMP, - }, - additional_data: None, - req_id, - }; - let mut info = sender.service_queue.borrow_mut().pop_front().unwrap(); - assert_eq!(info, cmp_info); - - cmp_info = TmInfo { - common: CommonTmInfo { - subservice: 3, - apid: TEST_APID, - msg_counter: 0, - dest_id: 0, - time_stamp: [0, 1, 0, 1, 0, 1, 0], - }, - additional_data: None, - req_id, - }; - info = sender.service_queue.borrow_mut().pop_front().unwrap(); - assert_eq!(info, cmp_info); - - cmp_info = TmInfo { - common: CommonTmInfo { - subservice: 5, - apid: TEST_APID, - msg_counter: 0, - dest_id: 0, - time_stamp: EMPTY_STAMP, - }, - additional_data: Some([0].to_vec()), - req_id, - }; - info = sender.service_queue.get_mut().pop_front().unwrap(); - assert_eq!(info, cmp_info); - - cmp_info = TmInfo { - common: CommonTmInfo { - subservice: 6, - apid: TEST_APID, - msg_counter: 0, - dest_id: 0, - time_stamp: EMPTY_STAMP, - }, - additional_data: Some( - [ - [1].as_slice(), - &[0, 0, 0x10, 0x20], - fail_data_raw.as_slice(), - ] - .concat() - .to_vec(), - ), - req_id, - }; - info = sender.service_queue.get_mut().pop_front().unwrap(); - assert_eq!(info, cmp_info); + .expect("step 1 failed"); + assert_eq!(testbench.sender.service_queue.borrow().len(), 4); + testbench.step_success_check(&EMPTY_STAMP); } #[test] fn test_step_failure() { - let (b, tok) = base_init(false); - let mut sender = TestSender::default(); - let req_id = tok.request_id; + let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping()); + let token = testbench.init(); let fail_code = EcssEnumU32::new(0x1020); let fail_data: f32 = -22.3232; let mut fail_data_raw = [0; 4]; @@ -2318,269 +2301,54 @@ pub mod tests { fail_data_raw.as_slice(), ); - let accepted_token = - b.vr.acceptance_success(tok, &sender, &EMPTY_STAMP) - .expect("Sending acceptance success failed"); - let started_token = - b.vr.start_success(accepted_token, &sender, &[0, 1, 0, 1, 0, 1, 0]) - .expect("Sending start success failed"); - b.vr.step_success(&started_token, &sender, &EMPTY_STAMP, EcssEnumU8::new(0)) - .expect("Sending completion success failed"); - b.vr.step_failure(started_token, &sender, fail_params) - .expect("Step failure failed"); - check_step_failure(&mut sender, req_id, fail_data_raw); - } - - #[test] - fn test_steps_failure_with_helper() { - let (mut b, tok) = base_with_helper_init(); - let req_id = tok.request_id; - let fail_code = EcssEnumU32::new(0x1020); - let fail_data: f32 = -22.3232; - let mut fail_data_raw = [0; 4]; - fail_data_raw.copy_from_slice(fail_data.to_be_bytes().as_slice()); - let fail_step = EcssEnumU8::new(1); - let fail_params = FailParamsWithStep::new( - &EMPTY_STAMP, - &fail_step, - &fail_code, - fail_data_raw.as_slice(), - ); - - let accepted_token = b - .helper - .acceptance_success(tok, &EMPTY_STAMP) + let accepted_token = testbench + .acceptance_success(token, &EMPTY_STAMP) .expect("Sending acceptance success failed"); - let started_token = b - .helper + let started_token = testbench .start_success(accepted_token, &[0, 1, 0, 1, 0, 1, 0]) .expect("Sending start success failed"); - b.helper + testbench .step_success(&started_token, &EMPTY_STAMP, EcssEnumU8::new(0)) .expect("Sending completion success failed"); - b.helper + testbench .step_failure(started_token, fail_params) .expect("Step failure failed"); - check_step_failure(&mut b.helper.sender, req_id, fail_data_raw); - } - - fn completion_fail_check(sender: &mut TestSender, req_id: RequestId) { - assert_eq!(sender.service_queue.borrow().len(), 3); - - let mut cmp_info = TmInfo { - common: CommonTmInfo { - subservice: 1, - apid: TEST_APID, - msg_counter: 0, - dest_id: 0, - time_stamp: EMPTY_STAMP, - }, - additional_data: None, - req_id, - }; - let mut info = sender.service_queue.get_mut().pop_front().unwrap(); - assert_eq!(info, cmp_info); - - cmp_info = TmInfo { - common: CommonTmInfo { - subservice: 3, - apid: TEST_APID, - msg_counter: 0, - dest_id: 0, - time_stamp: [0, 1, 0, 1, 0, 1, 0], - }, - additional_data: None, - req_id, - }; - info = sender.service_queue.get_mut().pop_front().unwrap(); - assert_eq!(info, cmp_info); - - cmp_info = TmInfo { - common: CommonTmInfo { - subservice: 8, - apid: TEST_APID, - msg_counter: 0, - dest_id: 0, - time_stamp: EMPTY_STAMP, - }, - additional_data: Some([0, 0, 0x10, 0x20].to_vec()), - req_id, - }; - info = sender.service_queue.get_mut().pop_front().unwrap(); - assert_eq!(info, cmp_info); + testbench.check_step_failure(fail_data_raw); } #[test] fn test_completion_failure() { - let (b, tok) = base_init(false); - let mut sender = TestSender::default(); - let req_id = tok.request_id; + let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping()); + let token = testbench.init(); let fail_code = EcssEnumU32::new(0x1020); let fail_params = FailParams::new_no_fail_data(&EMPTY_STAMP, &fail_code); - let accepted_token = - b.vr.acceptance_success(tok, &sender, &EMPTY_STAMP) - .expect("Sending acceptance success failed"); - let started_token = - b.vr.start_success(accepted_token, &sender, &[0, 1, 0, 1, 0, 1, 0]) - .expect("Sending start success failed"); - b.vr.completion_failure(started_token, &sender, fail_params) - .expect("Completion failure"); - completion_fail_check(&mut sender, req_id); - } - - #[test] - fn test_completion_failure_with_helper() { - let (mut b, tok) = base_with_helper_init(); - let req_id = tok.request_id; - let fail_code = EcssEnumU32::new(0x1020); - let fail_params = FailParams::new_no_fail_data(&EMPTY_STAMP, &fail_code); - - let accepted_token = b - .helper - .acceptance_success(tok, &EMPTY_STAMP) + let accepted_token = testbench + .acceptance_success(token, &EMPTY_STAMP) .expect("Sending acceptance success failed"); - let started_token = b - .helper + let started_token = testbench .start_success(accepted_token, &[0, 1, 0, 1, 0, 1, 0]) .expect("Sending start success failed"); - b.helper + testbench .completion_failure(started_token, fail_params) .expect("Completion failure"); - completion_fail_check(&mut b.helper.sender, req_id); - } - - fn completion_success_check(sender: &mut TestSender, req_id: RequestId) { - assert_eq!(sender.service_queue.borrow().len(), 3); - let cmp_info = TmInfo { - common: CommonTmInfo { - subservice: 1, - apid: TEST_APID, - msg_counter: 0, - dest_id: 0, - time_stamp: EMPTY_STAMP, - }, - additional_data: None, - req_id, - }; - let mut info = sender.service_queue.borrow_mut().pop_front().unwrap(); - assert_eq!(info, cmp_info); - - let cmp_info = TmInfo { - common: CommonTmInfo { - subservice: 3, - apid: TEST_APID, - msg_counter: 0, - dest_id: 0, - time_stamp: [0, 1, 0, 1, 0, 1, 0], - }, - additional_data: None, - req_id, - }; - info = sender.service_queue.borrow_mut().pop_front().unwrap(); - assert_eq!(info, cmp_info); - let cmp_info = TmInfo { - common: CommonTmInfo { - subservice: 7, - apid: TEST_APID, - msg_counter: 0, - dest_id: 0, - time_stamp: EMPTY_STAMP, - }, - additional_data: None, - req_id, - }; - info = sender.service_queue.borrow_mut().pop_front().unwrap(); - assert_eq!(info, cmp_info); + testbench.completion_fail_check(); } #[test] fn test_complete_success_sequence() { - let (b, tok) = base_init(false); + let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping()); + let token = testbench.init(); let mut sender = TestSender::default(); - let accepted_token = - b.vr.acceptance_success(tok, &sender, &EMPTY_STAMP) - .expect("Sending acceptance success failed"); - let started_token = - b.vr.start_success(accepted_token, &sender, &[0, 1, 0, 1, 0, 1, 0]) - .expect("Sending start success failed"); - b.vr.completion_success(started_token, &sender, &EMPTY_STAMP) - .expect("Sending completion success failed"); - completion_success_check(&mut sender, tok.request_id); - } - - #[test] - fn test_complete_success_sequence_with_helper() { - let (mut b, tok) = base_with_helper_init(); - let accepted_token = b - .helper - .acceptance_success(tok, &EMPTY_STAMP) + let accepted_token = testbench + .acceptance_success(token, &EMPTY_STAMP) .expect("Sending acceptance success failed"); - let started_token = b - .helper + let started_token = testbench .start_success(accepted_token, &[0, 1, 0, 1, 0, 1, 0]) .expect("Sending start success failed"); - b.helper + testbench .completion_success(started_token, &EMPTY_STAMP) .expect("Sending completion success failed"); - completion_success_check(&mut b.helper.sender, tok.request_id); - } - - #[test] - fn test_seq_count_increment() { - let pool_cfg = - StaticPoolConfig::new(vec![(10, 32), (10, 64), (10, 128), (10, 1024)], false); - let tm_pool = StaticMemoryPool::new(pool_cfg.clone()); - let shared_tm_store = SharedTmPool::new(tm_pool); - let shared_tm_pool = shared_tm_store.clone_backing_pool(); - let (verif_tx, verif_rx) = mpsc::channel(); - let sender = - 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, sender); - - let mut sph = SpHeader::tc_unseg(TEST_APID, 0, 0).unwrap(); - let tc_header = PusTcSecondaryHeader::new_simple(17, 1); - let pus_tc_0 = PusTcCreator::new_no_app_data(&mut sph, tc_header, true); - let init_token = reporter.add_tc(&pus_tc_0); - - // Complete success sequence for a telecommand - let accepted_token = reporter - .acceptance_success(init_token, &EMPTY_STAMP) - .unwrap(); - let started_token = reporter - .start_success(accepted_token, &EMPTY_STAMP) - .unwrap(); - reporter - .completion_success(started_token, &EMPTY_STAMP) - .unwrap(); - - // Verify it arrives correctly on receiver end - let mut tm_buf: [u8; 1024] = [0; 1024]; - let mut packet_idx = 0; - while packet_idx < 3 { - let addr = verif_rx.recv_timeout(Duration::from_millis(10)).unwrap(); - let tm_len; - { - let mut rg = shared_tm_pool.write().expect("Error locking shared pool"); - let store_guard = rg.read_with_guard(addr); - tm_len = store_guard - .read(&mut tm_buf) - .expect("Error reading TM slice"); - } - let (pus_tm, _) = - PusTmReader::new(&tm_buf[0..tm_len], 7).expect("Error reading verification TM"); - if packet_idx == 0 { - assert_eq!(pus_tm.subservice(), 1); - assert_eq!(pus_tm.sp_header.seq_count(), 0); - } else if packet_idx == 1 { - assert_eq!(pus_tm.subservice(), 3); - assert_eq!(pus_tm.sp_header.seq_count(), 0); - } else if packet_idx == 2 { - assert_eq!(pus_tm.subservice(), 7); - assert_eq!(pus_tm.sp_header.seq_count(), 0); - } - packet_idx += 1; - } + testbench.completion_success_check(); } } diff --git a/satrs/src/request.rs b/satrs/src/request.rs index 65fd8e4..3e744fd 100644 --- a/satrs/src/request.rs +++ b/satrs/src/request.rs @@ -25,21 +25,24 @@ pub type RequestId = u32; pub type Apid = u16; #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] -pub struct TargetAndApidId { +pub struct UniqueApidTargetId { pub apid: Apid, - pub target: u32, + pub unique_id: u32, } -impl TargetAndApidId { +impl UniqueApidTargetId { pub const fn new(apid: Apid, target: u32) -> Self { - Self { apid, target } + Self { + apid, + unique_id: target, + } } pub fn raw(&self) -> ComponentId { - ((self.apid as u64) << 32) | (self.target as u64) + ((self.apid as u64) << 32) | (self.unique_id as u64) } - pub fn full_target_id(&self) -> ComponentId { + pub fn id(&self) -> ComponentId { self.raw() } @@ -61,49 +64,78 @@ impl TargetAndApidId { } } -impl From for TargetAndApidId { +impl From for UniqueApidTargetId { fn from(raw: u64) -> Self { Self { apid: (raw >> 32) as u16, - target: raw as u32, + unique_id: raw as u32, } } } -impl From for u64 { - fn from(target_and_apid_id: TargetAndApidId) -> Self { +impl From for u64 { + fn from(target_and_apid_id: UniqueApidTargetId) -> Self { target_and_apid_id.raw() } } -impl fmt::Display for TargetAndApidId { +impl fmt::Display for UniqueApidTargetId { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "Target and APID ID with APID {:#03x} and target {}", - self.apid, self.target + self.apid, self.unique_id ) } } +#[derive(Debug, Copy, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct MessageMetadata { + request_id: RequestId, + sender_id: ComponentId, +} + +impl MessageMetadata { + pub const fn new(request_id: RequestId, sender_id: ComponentId) -> Self { + Self { + request_id, + sender_id, + } + } + + pub fn request_id(&self) -> RequestId { + self.request_id + } + + pub fn sender_id(&self) -> ComponentId { + self.sender_id + } +} + /// Generic message type which is associated with a sender using a [ChannelId] and associated /// with a request using a [RequestId]. #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct GenericMessage { - pub request_id: RequestId, - pub sender_id: ComponentId, + pub requestor_info: MessageMetadata, pub message: MSG, } impl GenericMessage { - pub fn new(request_id: RequestId, sender_id: ComponentId, message: MSG) -> Self { + pub fn new(requestor_info: MessageMetadata, message: MSG) -> Self { Self { - request_id, - sender_id, + requestor_info, message, } } + + delegate::delegate! { + to self.requestor_info { + pub fn request_id(&self) -> RequestId; + pub fn sender_id(&self) -> ComponentId; + } + } } /// Generic trait for objects which can send targeted messages. @@ -186,8 +218,7 @@ pub mod alloc_mod { pub fn send_message( &self, - request_id: RequestId, - local_channel_id: ComponentId, + requestor_info: MessageMetadata, target_channel_id: ComponentId, message: MSG, ) -> Result<(), GenericTargetedMessagingError> { @@ -196,45 +227,12 @@ pub mod alloc_mod { .0 .get(&target_channel_id) .unwrap() - .send(GenericMessage::new(request_id, local_channel_id, message)); + .send(GenericMessage::new(requestor_info, message)); } Err(GenericSendError::TargetDoesNotExist(target_channel_id).into()) } } - pub struct MessageSenderMapWithId> { - pub local_channel_id: ComponentId, - pub message_sender_map: MessageSenderMap, - } - - impl> MessageSenderMapWithId { - pub fn new(local_channel_id: ComponentId) -> Self { - Self { - local_channel_id, - message_sender_map: Default::default(), - } - } - - pub fn send_message( - &self, - request_id: RequestId, - target_channel_id: ComponentId, - message: MSG, - ) -> Result<(), GenericTargetedMessagingError> { - self.message_sender_map.send_message( - request_id, - self.local_channel_id, - target_channel_id, - message, - ) - } - - pub fn add_message_target(&mut self, target_id: ComponentId, message_sender: S) { - self.message_sender_map - .add_message_target(target_id, message_sender) - } - } - pub struct MessageSenderAndReceiver, R: MessageReceiver> { pub local_channel_id: ComponentId, pub message_sender_map: MessageSenderMap, @@ -265,13 +263,12 @@ pub mod alloc_mod { pub fn send_message( &self, request_id: RequestId, - target_channel_id: ComponentId, + target_id: ComponentId, message: TO, ) -> Result<(), GenericTargetedMessagingError> { self.message_sender_map.send_message( - request_id, - self.local_channel_id_generic(), - target_channel_id, + MessageMetadata::new(request_id, self.local_channel_id_generic()), + target_id, message, ) } @@ -390,9 +387,12 @@ mod tests { ByteConversionError, SpHeader, }; - use crate::queue::{GenericReceiveError, GenericSendError, GenericTargetedMessagingError}; + use crate::{ + queue::{GenericReceiveError, GenericSendError, GenericTargetedMessagingError}, + request::{MessageMetadata, MessageSenderMap}, + }; - use super::{GenericMessage, MessageReceiverWithId, MessageSenderMapWithId, TargetAndApidId}; + use super::{GenericMessage, MessageReceiverWithId, UniqueApidTargetId}; const TEST_CHANNEL_ID_0: u64 = 1; const TEST_CHANNEL_ID_1: u64 = 2; @@ -400,15 +400,15 @@ mod tests { #[test] fn test_basic_target_id_with_apid() { - let id = TargetAndApidId::new(0x111, 0x01); + let id = UniqueApidTargetId::new(0x111, 0x01); assert_eq!(id.apid, 0x111); - assert_eq!(id.target, 0x01); - assert_eq!(id.full_target_id(), id.raw()); + assert_eq!(id.unique_id, 0x01); + assert_eq!(id.id(), id.raw()); assert_eq!(u64::from(id), id.raw()); let id_raw = id.raw(); - let id_from_raw = TargetAndApidId::from(id_raw); + let id_from_raw = UniqueApidTargetId::from(id_raw); assert_eq!(id_from_raw, id); - assert_eq!(id.full_target_id(), (0x111 << 32) | 0x01); + assert_eq!(id.id(), (0x111 << 32) | 0x01); let string = id.to_string(); assert_eq!( string, @@ -421,9 +421,9 @@ mod tests { let mut sp_header = SpHeader::tc_unseg(0x111, 5, 0).unwrap(); let app_data = 1_u32.to_be_bytes(); let pus_tc = PusTcCreator::new_simple(&mut sp_header, 17, 1, Some(&app_data), true); - let id = TargetAndApidId::from_pus_tc(&pus_tc).unwrap(); + let id = UniqueApidTargetId::from_pus_tc(&pus_tc).unwrap(); assert_eq!(id.apid, 0x111); - assert_eq!(id.target, 1); + assert_eq!(id.unique_id, 1); } #[test] @@ -431,7 +431,7 @@ mod tests { let mut sp_header = SpHeader::tc_unseg(0x111, 5, 0).unwrap(); let sec_header = PusTcSecondaryHeader::new_simple(17, 1); let pus_tc = PusTcCreator::new_no_app_data(&mut sp_header, sec_header, true); - let error = TargetAndApidId::from_pus_tc(&pus_tc); + let error = UniqueApidTargetId::from_pus_tc(&pus_tc); assert!(error.is_err()); let error = error.unwrap_err(); if let ByteConversionError::FromSliceTooSmall { found, expected } = error { @@ -449,14 +449,17 @@ mod tests { let receiver = MessageReceiverWithId::new(TEST_CHANNEL_ID_0, receiver); let request_id = 5; sender - .send(GenericMessage::new(request_id, TEST_CHANNEL_ID_1, 5)) + .send(GenericMessage::new( + MessageMetadata::new(request_id, TEST_CHANNEL_ID_1), + 5, + )) .unwrap(); let reply = receiver.try_recv_message().unwrap(); assert!(reply.is_some()); assert_eq!(receiver.local_channel_id(), TEST_CHANNEL_ID_0); let reply = reply.unwrap(); - assert_eq!(reply.request_id, request_id); - assert_eq!(reply.sender_id, TEST_CHANNEL_ID_1); + assert_eq!(reply.requestor_info.request_id, request_id); + assert_eq!(reply.requestor_info.sender_id, TEST_CHANNEL_ID_1); assert_eq!(reply.message, 5); } @@ -490,31 +493,43 @@ mod tests { fn test_sender_map() { let (sender0, receiver0) = mpsc::channel(); let (sender1, receiver1) = mpsc::channel(); - let mut sender_map_with_id = MessageSenderMapWithId::new(TEST_CHANNEL_ID_0); + let mut sender_map_with_id = MessageSenderMap::default(); sender_map_with_id.add_message_target(TEST_CHANNEL_ID_1, sender0); sender_map_with_id.add_message_target(TEST_CHANNEL_ID_2, sender1); sender_map_with_id - .send_message(1, TEST_CHANNEL_ID_1, 5) + .send_message( + MessageMetadata::new(1, TEST_CHANNEL_ID_0), + TEST_CHANNEL_ID_1, + 5, + ) .expect("sending message failed"); let mut reply = receiver0.recv().expect("receiving message failed"); - assert_eq!(reply.request_id, 1); - assert_eq!(reply.sender_id, TEST_CHANNEL_ID_0); + assert_eq!(reply.request_id(), 1); + assert_eq!(reply.sender_id(), TEST_CHANNEL_ID_0); assert_eq!(reply.message, 5); sender_map_with_id - .send_message(2, TEST_CHANNEL_ID_2, 10) + .send_message( + MessageMetadata::new(2, TEST_CHANNEL_ID_1), + TEST_CHANNEL_ID_2, + 10, + ) .expect("sending message failed"); reply = receiver1.recv().expect("receiving message failed"); - assert_eq!(reply.request_id, 2); - assert_eq!(reply.sender_id, TEST_CHANNEL_ID_0); + assert_eq!(reply.request_id(), 2); + assert_eq!(reply.sender_id(), TEST_CHANNEL_ID_0); assert_eq!(reply.message, 10); } #[test] fn test_sender_map_target_does_not_exist() { let (sender0, _) = mpsc::channel(); - let mut sender_map_with_id = MessageSenderMapWithId::new(TEST_CHANNEL_ID_0); + let mut sender_map_with_id = MessageSenderMap::default(); sender_map_with_id.add_message_target(TEST_CHANNEL_ID_1, sender0); - let result = sender_map_with_id.send_message(1, TEST_CHANNEL_ID_2, 5); + let result = sender_map_with_id.send_message( + MessageMetadata::new(1, TEST_CHANNEL_ID_0), + TEST_CHANNEL_ID_2, + 5, + ); assert!(result.is_err()); let error = result.unwrap_err(); if let GenericTargetedMessagingError::Send(GenericSendError::TargetDoesNotExist(target)) = @@ -528,12 +543,20 @@ mod tests { #[test] fn test_sender_map_queue_full() { let (sender0, _receiver0) = mpsc::sync_channel(1); - let mut sender_map_with_id = MessageSenderMapWithId::new(TEST_CHANNEL_ID_0); + let mut sender_map_with_id = MessageSenderMap::default(); sender_map_with_id.add_message_target(TEST_CHANNEL_ID_1, sender0); sender_map_with_id - .send_message(1, TEST_CHANNEL_ID_1, 5) + .send_message( + MessageMetadata::new(1, TEST_CHANNEL_ID_0), + TEST_CHANNEL_ID_1, + 5, + ) .expect("sending message failed"); - let result = sender_map_with_id.send_message(1, TEST_CHANNEL_ID_1, 5); + let result = sender_map_with_id.send_message( + MessageMetadata::new(1, TEST_CHANNEL_ID_0), + TEST_CHANNEL_ID_1, + 5, + ); assert!(result.is_err()); let error = result.unwrap_err(); if let GenericTargetedMessagingError::Send(GenericSendError::QueueFull(capacity)) = error { @@ -546,10 +569,14 @@ mod tests { #[test] fn test_sender_map_queue_receiver_disconnected() { let (sender0, receiver0) = mpsc::sync_channel(1); - let mut sender_map_with_id = MessageSenderMapWithId::new(TEST_CHANNEL_ID_0); + let mut sender_map_with_id = MessageSenderMap::default(); sender_map_with_id.add_message_target(TEST_CHANNEL_ID_1, sender0); drop(receiver0); - let result = sender_map_with_id.send_message(1, TEST_CHANNEL_ID_1, 5); + let result = sender_map_with_id.send_message( + MessageMetadata::new(1, TEST_CHANNEL_ID_0), + TEST_CHANNEL_ID_1, + 5, + ); assert!(result.is_err()); let error = result.unwrap_err(); if let GenericTargetedMessagingError::Send(GenericSendError::RxDisconnected) = error { diff --git a/satrs/src/tmtc/ccsds_distrib.rs b/satrs/src/tmtc/ccsds_distrib.rs index a0d01b0..7b1ac34 100644 --- a/satrs/src/tmtc/ccsds_distrib.rs +++ b/satrs/src/tmtc/ccsds_distrib.rs @@ -22,7 +22,7 @@ //! use satrs::tmtc::{ReceivesTc, ReceivesTcCore}; //! use spacepackets::{CcsdsPacket, SpHeader}; //! use spacepackets::ecss::WritablePusPacket; -//! use spacepackets::ecss::tc::{PusTc, PusTcCreator}; +//! use spacepackets::ecss::tc::PusTcCreator; //! //! #[derive (Default)] //! struct ConcreteApidHandler { @@ -96,6 +96,7 @@ use std::error::Error; pub trait CcsdsPacketHandler { type Error; + // TODO: Rework this to return a boolean based on u16 input.. fn valid_apids(&self) -> &'static [u16]; fn handle_known_apid(&mut self, sp_header: &SpHeader, tc_raw: &[u8]) -> Result<(), Self::Error>; diff --git a/satrs/src/tmtc/tm_helper.rs b/satrs/src/tmtc/tm_helper.rs index 9de359b..630a338 100644 --- a/satrs/src/tmtc/tm_helper.rs +++ b/satrs/src/tmtc/tm_helper.rs @@ -1,5 +1,5 @@ use spacepackets::ecss::tm::{PusTmCreator, PusTmSecondaryHeader}; -use spacepackets::time::cds::TimeProvider; +use spacepackets::time::cds::CdsTime; use spacepackets::time::TimeWriter; use spacepackets::SpHeader; @@ -68,7 +68,7 @@ impl PusTmWithCdsShortHelper { source_data: &'a [u8], seq_count: u16, ) -> PusTmCreator { - let time_stamp = TimeProvider::from_now_with_u16_days().unwrap(); + let time_stamp = CdsTime::now_with_u16_days().unwrap(); time_stamp.write_to_bytes(&mut self.cds_short_buf).unwrap(); self.create_pus_tm_common(service, subservice, source_data, seq_count) } @@ -78,7 +78,7 @@ impl PusTmWithCdsShortHelper { service: u8, subservice: u8, source_data: &'a [u8], - stamper: &TimeProvider, + stamper: &CdsTime, seq_count: u16, ) -> PusTmCreator { stamper.write_to_bytes(&mut self.cds_short_buf).unwrap(); @@ -100,14 +100,14 @@ impl PusTmWithCdsShortHelper { #[cfg(test)] mod tests { - use spacepackets::{ecss::PusPacket, time::cds::TimeProvider, CcsdsPacket}; + use spacepackets::{ecss::PusPacket, time::cds::CdsTime, CcsdsPacket}; use super::PusTmWithCdsShortHelper; #[test] fn test_helper_with_stamper() { let mut pus_tm_helper = PusTmWithCdsShortHelper::new(0x123); - let stamper = TimeProvider::new_with_u16_days(0, 0); + let stamper = CdsTime::new_with_u16_days(0, 0); let tm = pus_tm_helper.create_pus_tm_with_stamper(17, 1, &[1, 2, 3, 4], &stamper, 25); assert_eq!(tm.service(), 17); assert_eq!(tm.subservice(), 1); diff --git a/satrs/tests/hk_helpers.rs b/satrs/tests/hk_helpers.rs index 8791b1e..d1b545e 100644 --- a/satrs/tests/hk_helpers.rs +++ b/satrs/tests/hk_helpers.rs @@ -2,7 +2,7 @@ use core::mem::size_of; use serde::{Deserialize, Serialize}; use spacepackets::ecss::{PfcReal, PfcUnsigned, Ptc}; -use spacepackets::time::cds::TimeProvider; +use spacepackets::time::cds::CdsTime; use spacepackets::time::{CcsdsTimeProvider, TimeWriter}; enum NumOfParamsInfo { @@ -36,7 +36,7 @@ struct TestMgmHkWithIndividualValidity { #[derive(Serialize, Deserialize)] struct TestMgmHkWithGroupValidity { - last_valid_stamp: TimeProvider, + last_valid_stamp: CdsTime, valid: bool, temp: f32, mgm_vals: [u16; 3], @@ -150,7 +150,7 @@ pub fn main() { // The easiest and probably best approach, trading off big advantages for TM downlink capacity: // Use a JSON format let mgm_hk_group_validity = TestMgmHkWithGroupValidity { - last_valid_stamp: TimeProvider::from_now_with_u16_days().unwrap(), + last_valid_stamp: CdsTime::now_with_u16_days().unwrap(), valid: false, temp: 20.0, mgm_vals: [0x1f1f, 0x2f2f, 0x3f3f], diff --git a/satrs/tests/mode_tree.rs b/satrs/tests/mode_tree.rs index 75df867..e70451f 100644 --- a/satrs/tests/mode_tree.rs +++ b/satrs/tests/mode_tree.rs @@ -1,13 +1,12 @@ use core::cell::Cell; use std::{println, sync::mpsc}; -use satrs::action::ActionRequest; use satrs::mode::{ ModeError, ModeProvider, ModeReplyReceiver, ModeReplySender, ModeRequestHandler, ModeRequestHandlerMpscBounded, ModeRequestReceiver, ModeRequestorAndHandlerMpscBounded, ModeRequestorBoundedMpsc, }; -use satrs::request::RequestId; +use satrs::request::{MessageMetadata, RequestId}; use satrs::{ mode::{ModeAndSubmode, ModeReply, ModeRequest}, queue::GenericTargetedMessagingError, @@ -46,11 +45,30 @@ struct TestDevice { pub name: String, pub mode_node: ModeRequestHandlerMpscBounded, pub mode_and_submode: ModeAndSubmode, - pub mode_requestor_info: Option<(RequestId, ComponentId)>, - // pub action_queue: mpsc::Receiver>, + pub mode_requestor_info: Option, } -pub struct ModeLeafDeviceHelper {} +fn mode_leaf_node_req_handler( + handler: &mut impl ModeRequestHandler, + request: GenericMessage, +) { + match request.message { + ModeRequest::SetMode(mode_and_submode) => { + handler + .start_transition(request.requestor_info, mode_and_submode) + .unwrap(); + } + ModeRequest::ReadMode => handler + .send_mode_reply( + request.requestor_info, + ModeReply::ModeReply(handler.mode_and_submode()), + ) + .unwrap(), + ModeRequest::AnnounceMode => handler.announce_mode(request.requestor_info, false), + ModeRequest::AnnounceModeRecursive => handler.announce_mode(request.requestor_info, true), + ModeRequest::ModeInfo(_) => todo!(), + } +} impl TestDevice { pub fn run(&mut self) { @@ -61,24 +79,22 @@ impl TestDevice { if let Some(request) = self.mode_node.try_recv_mode_request()? { match request.message { ModeRequest::SetMode(mode_and_submode) => { - self.start_transition(request.request_id, request.sender_id, mode_and_submode) + self.start_transition(request.requestor_info, mode_and_submode) .unwrap(); - self.mode_requestor_info = Some((request.request_id, request.sender_id)); + self.mode_requestor_info = Some(request.requestor_info); } ModeRequest::ReadMode => self .mode_node .send_mode_reply( - request.request_id, - request.sender_id, + request.requestor_info, ModeReply::ModeReply(self.mode_and_submode), ) .unwrap(), - ModeRequest::AnnounceMode => { - self.announce_mode(request.request_id, request.sender_id, false) - } + ModeRequest::AnnounceMode => self.announce_mode(request.requestor_info, false), ModeRequest::AnnounceModeRecursive => { - self.announce_mode(request.request_id, request.sender_id, true) + self.announce_mode(request.requestor_info, true) } + ModeRequest::ModeInfo(_) => todo!(), } } Ok(()) @@ -90,39 +106,49 @@ impl ModeProvider for TestDevice { self.mode_and_submode } } + impl ModeRequestHandler for TestDevice { fn start_transition( &mut self, - _request_id: RequestId, - _sender_id: ComponentId, + requestor: MessageMetadata, mode_and_submode: ModeAndSubmode, ) -> Result<(), ModeError> { self.mode_and_submode = mode_and_submode; - self.handle_mode_reached()?; + self.handle_mode_reached(Some(requestor))?; Ok(()) } - fn announce_mode(&self, _request_id: RequestId, _sender_id: ComponentId, _recursive: bool) { + fn announce_mode(&self, requestor_info: MessageMetadata, _recursive: bool) { println!( "{}: announcing mode: {:?}", self.name, self.mode_and_submode ); } - fn handle_mode_reached(&mut self) -> Result<(), GenericTargetedMessagingError> { - let (req_id, sender_id) = self.mode_requestor_info.unwrap(); - self.mode_node.send_mode_reply( - req_id, - sender_id, - ModeReply::ModeReply(self.mode_and_submode), - )?; + fn handle_mode_reached( + &mut self, + + requestor: Option, + ) -> Result<(), GenericTargetedMessagingError> { + if let Some(requestor) = requestor { + self.send_mode_reply(requestor, ModeReply::ModeReply(self.mode_and_submode))?; + } + Ok(()) + } + fn send_mode_reply( + &self, + requestor_info: MessageMetadata, + reply: ModeReply, + ) -> Result<(), GenericTargetedMessagingError> { + self.mode_node + .send_mode_reply(requestor_info, ModeReply::ModeReply(self.mode_and_submode))?; Ok(()) } } struct TestAssembly { pub mode_node: ModeRequestorAndHandlerMpscBounded, - pub mode_requestor_info: Option<(RequestId, ComponentId)>, + pub mode_requestor_info: Option, pub mode_and_submode: ModeAndSubmode, pub target_mode_and_submode: Option, } @@ -143,23 +169,21 @@ impl TestAssembly { if let Some(request) = self.mode_node.try_recv_mode_request()? { match request.message { ModeRequest::SetMode(mode_and_submode) => { - self.start_transition(request.request_id, request.sender_id, mode_and_submode) + self.start_transition(request.requestor_info, mode_and_submode) .unwrap(); } ModeRequest::ReadMode => self .mode_node .send_mode_reply( - request.request_id, - request.sender_id, + request.requestor_info, ModeReply::ModeReply(self.mode_and_submode), ) .unwrap(), - ModeRequest::AnnounceMode => { - self.announce_mode(request.request_id, request.sender_id, false) - } + ModeRequest::AnnounceMode => self.announce_mode(request.requestor_info, false), ModeRequest::AnnounceModeRecursive => { - self.announce_mode(request.request_id, request.sender_id, true) + self.announce_mode(request.requestor_info, true) } + ModeRequest::ModeInfo(_) => todo!(), } } Ok(()) @@ -168,18 +192,20 @@ impl TestAssembly { pub fn check_mode_replies(&mut self) -> Result<(), GenericTargetedMessagingError> { if let Some(reply_and_id) = self.mode_node.try_recv_mode_reply()? { match reply_and_id.message { - ModeReply::ModeInfo(_) => todo!(), ModeReply::ModeReply(reply) => { println!( "TestAssembly: Received mode reply from {:?}, reached: {:?}", - reply_and_id.sender_id, reply + reply_and_id.sender_id(), + reply ); } ModeReply::CantReachMode(_) => todo!(), ModeReply::WrongMode { expected, reached } => { println!( "TestAssembly: Wrong mode reply from {:?}, reached {:?}, expected {:?}", - reply_and_id.sender_id, reached, expected + reply_and_id.sender_id(), + reached, + expected ); } } @@ -191,16 +217,15 @@ impl TestAssembly { impl ModeRequestHandler for TestAssembly { fn start_transition( &mut self, - request_id: RequestId, - sender_id: ComponentId, + requestor: MessageMetadata, mode_and_submode: ModeAndSubmode, ) -> Result<(), ModeError> { - self.mode_requestor_info = Some((request_id, sender_id)); + self.mode_requestor_info = Some(requestor); self.target_mode_and_submode = Some(mode_and_submode); Ok(()) } - fn announce_mode(&self, request_id: RequestId, _sender_id: ComponentId, recursive: bool) { + fn announce_mode(&self, requestor_info: MessageMetadata, recursive: bool) { println!( "TestAssembly: Announcing mode (recursively: {}): {:?}", recursive, self.mode_and_submode @@ -217,21 +242,33 @@ impl ModeRequestHandler for TestAssembly { .for_each(|(_, sender)| { sender .send(GenericMessage::new( - request_id, - self.mode_node.local_channel_id_generic(), + MessageMetadata::new( + requestor_info.request_id(), + self.mode_node.local_channel_id_generic(), + ), mode_request, )) .expect("sending mode request failed"); }); } - fn handle_mode_reached(&mut self) -> Result<(), GenericTargetedMessagingError> { - let (req_id, sender_id) = self.mode_requestor_info.unwrap(); - self.mode_node.send_mode_reply( - req_id, - sender_id, - ModeReply::ModeReply(self.mode_and_submode), - )?; + fn handle_mode_reached( + &mut self, + mode_requestor: Option, + ) -> Result<(), GenericTargetedMessagingError> { + if let Some(requestor) = mode_requestor { + self.send_mode_reply(requestor, ModeReply::ModeReply(self.mode_and_submode))?; + } + Ok(()) + } + + fn send_mode_reply( + &self, + requestor: MessageMetadata, + reply: ModeReply, + ) -> Result<(), GenericTargetedMessagingError> { + self.mode_node + .send_mode_reply(requestor, ModeReply::ModeReply(self.mode_and_submode))?; Ok(()) } } diff --git a/satrs/tests/pus_events.rs b/satrs/tests/pus_events.rs index a21b9e7..d9c87fe 100644 --- a/satrs/tests/pus_events.rs +++ b/satrs/tests/pus_events.rs @@ -5,7 +5,8 @@ use satrs::events::{EventU32, EventU32TypedSev, Severity, SeverityInfo}; use satrs::params::U32Pair; use satrs::params::{Params, ParamsHeapless, WritableToBeBytes}; use satrs::pus::event_man::{DefaultPusEventMgmtBackend, EventReporter, PusEventDispatcher}; -use satrs::pus::TmAsVecSenderWithMpsc; +use satrs::pus::PusTmAsVec; +use satrs::request::UniqueApidTargetId; use spacepackets::ecss::tm::PusTmReader; use spacepackets::ecss::{PusError, PusPacket}; use std::sync::mpsc::{self, SendError, TryRecvError}; @@ -15,6 +16,8 @@ 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]; +const TEST_APID: u16 = 0x02; +const TEST_ID: UniqueApidTargetId = UniqueApidTargetId::new(TEST_APID, 0x05); #[derive(Debug, Clone)] pub enum CustomTmSenderError { @@ -32,13 +35,12 @@ fn test_threaded_usage() { let pus_event_man_send_provider = EventU32SenderMpsc::new(1, pus_event_man_tx); event_man.subscribe_all(pus_event_man_send_provider.target_id()); event_man.add_sender(pus_event_man_send_provider); - let (event_tx, event_rx) = mpsc::channel(); - let reporter = EventReporter::new(0x02, 128).expect("Creating event reporter failed"); - let mut pus_event_man = - PusEventDispatcher::new(reporter, DefaultPusEventMgmtBackend::default()); + let (event_tx, event_rx) = mpsc::channel::(); + let reporter = + EventReporter::new(TEST_ID.raw(), 0x02, 128).expect("Creating event reporter failed"); + let pus_event_man = PusEventDispatcher::new(reporter, DefaultPusEventMgmtBackend::default()); // PUS + Generic event manager thread let jh0 = thread::spawn(move || { - let mut sender = TmAsVecSenderWithMpsc::new(0, "event_sender", event_tx); let mut event_cnt = 0; let mut params_array: [u8; 128] = [0; 128]; loop { @@ -46,9 +48,9 @@ fn test_threaded_usage() { assert!(res.is_ok()); match pus_event_man_rx.try_recv() { Ok((event, aux_data)) => { - let mut gen_event = |aux_data| { + let gen_event = |aux_data| { pus_event_man.generate_pus_event_tm_generic( - &mut sender, + &event_tx, &EMPTY_STAMP, event, aux_data, @@ -101,8 +103,8 @@ fn test_threaded_usage() { match event_rx.try_recv() { // Event TM received successfully Ok(event_tm) => { - let tm = - PusTmReader::new(event_tm.as_slice(), 7).expect("Deserializing TM failed"); + let tm = PusTmReader::new(event_tm.packet.as_slice(), 7) + .expect("Deserializing TM failed"); assert_eq!(tm.0.service(), 5); assert_eq!(tm.0.subservice(), 1); let src_data = tm.0.source_data(); @@ -127,8 +129,8 @@ fn test_threaded_usage() { match event_rx.try_recv() { // Event TM received successfully Ok(event_tm) => { - let tm = - PusTmReader::new(event_tm.as_slice(), 7).expect("Deserializing TM failed"); + let tm = PusTmReader::new(event_tm.packet.as_slice(), 7) + .expect("Deserializing TM failed"); assert_eq!(tm.0.service(), 5); assert_eq!(tm.0.subservice(), 2); let src_data = tm.0.source_data(); diff --git a/satrs/tests/pus_verification.rs b/satrs/tests/pus_verification.rs index 386fea6..46dda69 100644 --- a/satrs/tests/pus_verification.rs +++ b/satrs/tests/pus_verification.rs @@ -3,10 +3,11 @@ pub mod crossbeam_test { use hashbrown::HashMap; use satrs::pool::{PoolProvider, PoolProviderWithGuards, StaticMemoryPool, StaticPoolConfig}; use satrs::pus::verification::{ - FailParams, RequestId, VerificationReporterCfg, VerificationReporterWithSender, + FailParams, RequestId, VerificationReporter, VerificationReporterCfg, VerificationReportingProvider, }; use satrs::pus::TmInSharedPoolSenderWithCrossbeam; + use satrs::request::UniqueApidTargetId; use satrs::tmtc::tm_helper::SharedTmPool; use spacepackets::ecss::tc::{PusTcCreator, PusTcReader, PusTcSecondaryHeader}; use spacepackets::ecss::tm::PusTmReader; @@ -17,6 +18,8 @@ pub mod crossbeam_test { use std::time::Duration; const TEST_APID: u16 = 0x03; + const TEST_ID: TargetAndApidId = TargetAndApidId::new(TEST_APID, 0x05); + const FIXED_STAMP: [u8; 7] = [0; 7]; const PACKETS_SENT: u8 = 8; @@ -40,13 +43,9 @@ 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 = TmInSharedPoolSenderWithCrossbeam::new( - 0, - "verif_sender", - shared_tm_pool.clone(), - tx.clone(), - ); - let mut reporter_with_sender_0 = VerificationReporterWithSender::new(&cfg, sender); + let sender_0 = TmInSharedPoolSenderWithCrossbeam::new(shared_tm_pool.clone(), tx.clone()); + let sender_1 = sender_0.clone(); + let mut reporter_with_sender_0 = VerificationReporter::new(&cfg); 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. @@ -93,24 +92,36 @@ pub mod crossbeam_test { let token = reporter_with_sender_0.add_tc_with_req_id(req_id_0); let accepted_token = reporter_with_sender_0 - .acceptance_success(token, &FIXED_STAMP) + .acceptance_success(TEST_ID.raw(), &sender_0, token, &FIXED_STAMP) .expect("Acceptance success failed"); // Do some start handling here let started_token = reporter_with_sender_0 - .start_success(accepted_token, &FIXED_STAMP) + .start_success(TEST_ID.raw(), &sender_0, accepted_token, &FIXED_STAMP) .expect("Start success failed"); // Do some step handling here reporter_with_sender_0 - .step_success(&started_token, &FIXED_STAMP, EcssEnumU8::new(0)) + .step_success( + TEST_ID.raw(), + &sender_0, + &started_token, + &FIXED_STAMP, + EcssEnumU8::new(0), + ) .expect("Start success failed"); // Finish up reporter_with_sender_0 - .step_success(&started_token, &FIXED_STAMP, EcssEnumU8::new(1)) + .step_success( + TEST_ID.raw(), + &sender_0, + &started_token, + &FIXED_STAMP, + EcssEnumU8::new(1), + ) .expect("Start success failed"); reporter_with_sender_0 - .completion_success(started_token, &FIXED_STAMP) + .completion_success(TEST_ID.raw(), &sender_0, started_token, &FIXED_STAMP) .expect("Completion success failed"); }); @@ -128,15 +139,15 @@ pub mod crossbeam_test { let (tc, _) = PusTcReader::new(&tc_buf[0..tc_len]).unwrap(); let token = reporter_with_sender_1.add_tc(&tc); let accepted_token = reporter_with_sender_1 - .acceptance_success(token, &FIXED_STAMP) + .acceptance_success(TEST_ID.raw(), &sender_1, token, &FIXED_STAMP) .expect("Acceptance success failed"); let started_token = reporter_with_sender_1 - .start_success(accepted_token, &FIXED_STAMP) + .start_success(TEST_ID.raw(), &sender_1, accepted_token, &FIXED_STAMP) .expect("Start success failed"); let fail_code = EcssEnumU16::new(2); let params = FailParams::new_no_fail_data(&FIXED_STAMP, &fail_code); reporter_with_sender_1 - .completion_failure(started_token, params) + .completion_failure(TEST_ID.raw(), &sender_1, started_token, params) .expect("Completion success failed"); }); @@ -145,14 +156,14 @@ pub mod crossbeam_test { let mut tm_buf: [u8; 1024] = [0; 1024]; let mut verif_map = HashMap::new(); while packet_counter < PACKETS_SENT { - let verif_addr = rx + let tm_in_pool = rx .recv_timeout(Duration::from_millis(50)) .expect("Packet reception timeout"); let tm_len; let shared_tm_store = shared_tm_pool.clone_backing_pool(); { let mut rg = shared_tm_store.write().expect("Error locking shared pool"); - let store_guard = rg.read_with_guard(verif_addr); + let store_guard = rg.read_with_guard(tm_in_pool.store_addr); tm_len = store_guard .read(&mut tm_buf) .expect("Error reading TM slice");