diff --git a/satrs-core/src/objects.rs b/satrs-core/src/objects.rs index bc17696..0ff117f 100644 --- a/satrs-core/src/objects.rs +++ b/satrs-core/src/objects.rs @@ -51,6 +51,7 @@ //! assert_eq!(example_obj.id, obj_id); //! assert_eq!(example_obj.dummy, 42); //! ``` +use crate::tmtc::TargetId; #[cfg(feature = "alloc")] use alloc::boxed::Box; #[cfg(feature = "alloc")] @@ -64,7 +65,7 @@ use std::error::Error; #[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)] pub struct ObjectId { - pub id: u32, + pub id: TargetId, pub name: &'static str, } diff --git a/satrs-core/src/pus/event_srv.rs b/satrs-core/src/pus/event_srv.rs index ad098fa..83e1d78 100644 --- a/satrs-core/src/pus/event_srv.rs +++ b/satrs-core/src/pus/event_srv.rs @@ -12,7 +12,6 @@ use crate::tmtc::tm_helper::SharedTmStore; use spacepackets::ecss::event::Subservice; use spacepackets::ecss::PusPacket; use spacepackets::tc::PusTc; -use std::format; use std::sync::mpsc::{Receiver, Sender}; pub struct PusService5EventHandler { @@ -57,26 +56,19 @@ impl PusServiceHandler for PusService5EventHandler { addr: StoreAddr, token: VerificationToken, ) -> Result { - { - // Keep locked section as short as possible. - let mut tc_pool = self - .psb - .tc_store - .write() - .map_err(|e| PusPacketHandlingError::RwGuardError(format!("{e}")))?; - let tc_guard = tc_pool.read_with_guard(addr); - let tc_raw = tc_guard.read().unwrap(); - self.psb.pus_buf[0..tc_raw.len()].copy_from_slice(tc_raw); - } + self.copy_tc_to_buf(addr)?; let (tc, _) = PusTc::from_bytes(&self.psb.pus_buf).unwrap(); - let srv = Subservice::try_from(tc.subservice()); + let subservice = tc.subservice(); + let srv = Subservice::try_from(subservice); if srv.is_err() { return Ok(PusPacketHandlerResult::CustomSubservice( tc.subservice(), token, )); } - let mut handle_enable_disable_request = |enable: bool| { + let mut partial_error = None; + let time_stamp = self.psb().get_current_timestamp(&mut partial_error); + let mut handle_enable_disable_request = |enable: bool, stamp: [u8; 7]| { if tc.user_data().is_none() || tc.user_data().unwrap().len() < 4 { return Err(PusPacketHandlingError::NotEnoughAppData( "At least 4 bytes event ID expected".into(), @@ -84,11 +76,10 @@ impl PusServiceHandler for PusService5EventHandler { } let user_data = tc.user_data().unwrap(); let event_u32 = EventU32::from(u32::from_be_bytes(user_data[0..4].try_into().unwrap())); - let start_token = self .psb .verification_handler - .start_success(token, Some(&self.psb.stamp_buf)) + .start_success(token, Some(&stamp)) .map_err(|_| PartialPusHandlingError::VerificationError); let partial_error = start_token.clone().err(); let mut token: TcStateToken = token.into(); @@ -126,15 +117,14 @@ impl PusServiceHandler for PusService5EventHandler { return Err(PusPacketHandlingError::InvalidSubservice(tc.subservice())) } Subservice::TcEnableEventGeneration => { - handle_enable_disable_request(true)?; + handle_enable_disable_request(true, time_stamp)?; } Subservice::TcDisableEventGeneration => { - handle_enable_disable_request(false)?; + handle_enable_disable_request(false, time_stamp)?; } Subservice::TcReportDisabledList | Subservice::TmDisabledEventsReport => { return Ok(PusPacketHandlerResult::SubserviceNotImplemented( - tc.subservice(), - token, + subservice, token, )); } } diff --git a/satrs-core/src/pus/mod.rs b/satrs-core/src/pus/mod.rs index 4c7cd18..f1dda6e 100644 --- a/satrs-core/src/pus/mod.rs +++ b/satrs-core/src/pus/mod.rs @@ -137,17 +137,18 @@ mod alloc_mod { pub mod std_mod { use crate::pool::{ShareablePoolProvider, SharedPool, StoreAddr, StoreError}; use crate::pus::verification::{ - FailParams, StdVerifReporterWithSender, TcStateAccepted, VerificationToken, + StdVerifReporterWithSender, TcStateAccepted, VerificationToken, }; use crate::pus::{EcssSender, EcssTcSenderCore, EcssTmSenderCore}; use crate::tmtc::tm_helper::SharedTmStore; use crate::SenderId; use alloc::vec::Vec; - use spacepackets::ecss::{EcssEnumeration, PusError, SerializablePusPacket}; + use spacepackets::ecss::{PusError, SerializablePusPacket}; use spacepackets::tc::PusTc; use spacepackets::time::cds::TimeProvider; use spacepackets::time::{StdTimestampError, TimeWriter}; use spacepackets::tm::PusTm; + use std::format; use std::string::String; use std::sync::{mpsc, RwLockWriteGuard}; use thiserror::Error; @@ -334,15 +335,14 @@ pub mod std_mod { pub type AcceptedTc = (StoreAddr, VerificationToken); pub struct PusServiceBase { - pub(crate) tc_rx: mpsc::Receiver, - pub(crate) tc_store: SharedPool, - pub(crate) tm_tx: mpsc::Sender, - pub(crate) tm_store: SharedTmStore, - pub(crate) tm_apid: u16, - pub(crate) verification_handler: StdVerifReporterWithSender, - pub(crate) stamp_buf: [u8; 7], - pub(crate) pus_buf: [u8; 2048], - pus_size: usize, + pub tc_rx: mpsc::Receiver, + pub tc_store: SharedPool, + pub tm_tx: mpsc::Sender, + pub tm_store: SharedTmStore, + pub tm_apid: u16, + pub verification_handler: StdVerifReporterWithSender, + pub pus_buf: [u8; 2048], + pub pus_size: usize, } impl PusServiceBase { @@ -361,56 +361,53 @@ pub mod std_mod { tm_tx, tm_store, verification_handler, - stamp_buf: [0; 7], pus_buf: [0; 2048], pus_size: 0, } } - pub fn update_stamp(&mut self) -> Result<(), PartialPusHandlingError> { + pub fn get_current_timestamp( + &self, + partial_error: &mut Option, + ) -> [u8; 7] { + let mut time_stamp: [u8; 7] = [0; 7]; let time_provider = TimeProvider::from_now_with_u16_days().map_err(PartialPusHandlingError::TimeError); if let Ok(time_provider) = time_provider { - time_provider.write_to_bytes(&mut self.stamp_buf).unwrap(); - Ok(()) + time_provider.write_to_bytes(&mut time_stamp).unwrap(); } else { - self.stamp_buf = [0; 7]; - Err(time_provider.unwrap_err()) + *partial_error = Some(time_provider.unwrap_err()); } + time_stamp } - - pub fn report_start_failure( - &mut self, - token: VerificationToken, - failure_code: &impl EcssEnumeration, - failure_data: Option<&[u8]>, - ) -> Result<(), VerificationToken> { - self.verification_handler - .start_failure( - token, - FailParams::new(Some(&self.stamp_buf), failure_code, failure_data), - ) - .map_err(|e| e.1) + pub fn get_current_timestamp_ignore_error(&self) -> [u8; 7] { + let mut dummy = None; + self.get_current_timestamp(&mut dummy) } } pub trait PusServiceHandler { fn psb_mut(&mut self) -> &mut PusServiceBase; fn psb(&self) -> &PusServiceBase; - fn verification_reporter(&mut self) -> &mut StdVerifReporterWithSender { - &mut self.psb_mut().verification_handler - } - fn tc_store(&mut self) -> &mut SharedPool { - &mut self.psb_mut().tc_store - } - fn pus_tc_buf(&self) -> (&[u8], usize) { - (&self.psb().pus_buf, self.psb().pus_size) - } fn handle_one_tc( &mut self, addr: StoreAddr, token: VerificationToken, ) -> Result; + + fn copy_tc_to_buf(&mut self, addr: StoreAddr) -> Result<(), PusPacketHandlingError> { + // Keep locked section as short as possible. + let psb_mut = self.psb_mut(); + let mut tc_pool = psb_mut + .tc_store + .write() + .map_err(|e| PusPacketHandlingError::RwGuardError(format!("{e}")))?; + let tc_guard = tc_pool.read_with_guard(addr); + let tc_raw = tc_guard.read().unwrap(); + psb_mut.pus_buf[0..tc_raw.len()].copy_from_slice(tc_raw); + Ok(()) + } + fn handle_next_packet(&mut self) -> Result { return match self.psb().tc_rx.try_recv() { Ok((addr, token)) => self.handle_one_tc(addr, token), diff --git a/satrs-core/src/pus/scheduler_srv.rs b/satrs-core/src/pus/scheduler_srv.rs index 9de4981..036c724 100644 --- a/satrs-core/src/pus/scheduler_srv.rs +++ b/satrs-core/src/pus/scheduler_srv.rs @@ -2,15 +2,12 @@ use crate::pool::{SharedPool, StoreAddr}; use crate::pus::scheduler::PusScheduler; use crate::pus::verification::{StdVerifReporterWithSender, TcStateAccepted, VerificationToken}; use crate::pus::{ - AcceptedTc, PartialPusHandlingError, PusPacketHandlerResult, PusPacketHandlingError, - PusServiceBase, PusServiceHandler, + AcceptedTc, PusPacketHandlerResult, PusPacketHandlingError, PusServiceBase, PusServiceHandler, }; use crate::tmtc::tm_helper::SharedTmStore; use spacepackets::ecss::{scheduling, PusPacket}; use spacepackets::tc::PusTc; use spacepackets::time::cds::TimeProvider; -use spacepackets::time::TimeWriter; -use std::format; use std::sync::mpsc::{Receiver, Sender}; pub struct PusService11SchedHandler { @@ -59,17 +56,7 @@ impl PusServiceHandler for PusService11SchedHandler { addr: StoreAddr, token: VerificationToken, ) -> Result { - { - // Keep locked section as short as possible. - let mut tc_pool = self - .psb - .tc_store - .write() - .map_err(|e| PusPacketHandlingError::RwGuardError(format!("{e}")))?; - let tc_guard = tc_pool.read_with_guard(addr); - let tc_raw = tc_guard.read().unwrap(); - self.psb.pus_buf[0..tc_raw.len()].copy_from_slice(tc_raw); - } + self.copy_tc_to_buf(addr)?; let (tc, _) = PusTc::from_bytes(&self.psb.pus_buf).unwrap(); let std_service = scheduling::Subservice::try_from(tc.subservice()); if std_service.is_err() { @@ -78,32 +65,21 @@ impl PusServiceHandler for PusService11SchedHandler { token, )); } - //let partial_error = self.psb.update_stamp().err(); - let time_provider = - TimeProvider::from_now_with_u16_days().map_err(PartialPusHandlingError::TimeError); - let partial_error = if let Ok(time_provider) = time_provider { - time_provider - .write_to_bytes(&mut self.psb.stamp_buf) - .unwrap(); - Ok(()) - } else { - self.psb.stamp_buf = [0; 7]; - Err(time_provider.unwrap_err()) - }; - let partial_error = partial_error.err(); + let mut partial_error = None; + let time_stamp = self.psb().get_current_timestamp(&mut partial_error); match std_service.unwrap() { scheduling::Subservice::TcEnableScheduling => { let start_token = self .psb .verification_handler - .start_success(token, Some(&self.psb.stamp_buf)) + .start_success(token, Some(&time_stamp)) .expect("Error sending start success"); self.scheduler.enable(); if self.scheduler.is_enabled() { self.psb .verification_handler - .completion_success(start_token, Some(&self.psb.stamp_buf)) + .completion_success(start_token, Some(&time_stamp)) .expect("Error sending completion success"); } else { panic!("Failed to enable scheduler"); @@ -113,14 +89,14 @@ impl PusServiceHandler for PusService11SchedHandler { let start_token = self .psb .verification_handler - .start_success(token, Some(&self.psb.stamp_buf)) + .start_success(token, Some(&time_stamp)) .expect("Error sending start success"); self.scheduler.disable(); if !self.scheduler.is_enabled() { self.psb .verification_handler - .completion_success(start_token, Some(&self.psb.stamp_buf)) + .completion_success(start_token, Some(&time_stamp)) .expect("Error sending completion success"); } else { panic!("Failed to disable scheduler"); @@ -130,7 +106,7 @@ impl PusServiceHandler for PusService11SchedHandler { let start_token = self .psb .verification_handler - .start_success(token, Some(&self.psb.stamp_buf)) + .start_success(token, Some(&time_stamp)) .expect("Error sending start success"); let mut pool = self.psb.tc_store.write().expect("Locking pool failed"); @@ -141,14 +117,14 @@ impl PusServiceHandler for PusService11SchedHandler { self.psb .verification_handler - .completion_success(start_token, Some(&self.psb.stamp_buf)) + .completion_success(start_token, Some(&time_stamp)) .expect("Error sending completion success"); } scheduling::Subservice::TcInsertActivity => { let start_token = self .psb .verification_handler - .start_success(token, Some(&self.psb.stamp_buf)) + .start_success(token, Some(&time_stamp)) .expect("error sending start success"); let mut pool = self.psb.tc_store.write().expect("locking pool failed"); @@ -158,7 +134,7 @@ impl PusServiceHandler for PusService11SchedHandler { self.psb .verification_handler - .completion_success(start_token, Some(&self.psb.stamp_buf)) + .completion_success(start_token, Some(&time_stamp)) .expect("sending completion success failed"); } _ => { diff --git a/satrs-core/src/pus/test.rs b/satrs-core/src/pus/test.rs index 09614bc..a74f910 100644 --- a/satrs-core/src/pus/test.rs +++ b/satrs-core/src/pus/test.rs @@ -51,27 +51,18 @@ impl PusServiceHandler for PusService17TestHandler { addr: StoreAddr, token: VerificationToken, ) -> Result { - { - // Keep locked section as short as possible. - let mut tc_pool = self - .psb - .tc_store - .write() - .map_err(|e| PusPacketHandlingError::RwGuardError(format!("{e}")))?; - let tc_guard = tc_pool.read_with_guard(addr); - let tc_raw = tc_guard.read()?; - self.psb.pus_buf[0..tc_raw.len()].copy_from_slice(tc_raw); - } + self.copy_tc_to_buf(addr)?; let (tc, _) = PusTc::from_bytes(&self.psb.pus_buf)?; if tc.service() != 17 { return Err(PusPacketHandlingError::WrongService(tc.service())); } if tc.subservice() == 1 { - let mut partial_error = self.psb.update_stamp().err(); + let mut partial_error = None; + let time_stamp = self.psb().get_current_timestamp(&mut partial_error); let result = self .psb .verification_handler - .start_success(token, Some(&self.psb.stamp_buf)) + .start_success(token, Some(&time_stamp)) .map_err(|_| PartialPusHandlingError::VerificationError); let start_token = if let Ok(result) = result { Some(result) @@ -81,7 +72,7 @@ impl PusServiceHandler for PusService17TestHandler { }; // Sequence count will be handled centrally in TM funnel. let mut reply_header = SpHeader::tm_unseg(self.psb.tm_apid, 0, 0).unwrap(); - let tc_header = PusTmSecondaryHeader::new_simple(17, 2, &self.psb.stamp_buf); + let tc_header = PusTmSecondaryHeader::new_simple(17, 2, &time_stamp); let ping_reply = PusTm::new(&mut reply_header, tc_header, None, true); let addr = self.psb.tm_store.add_pus_tm(&ping_reply); if let Err(e) = self @@ -96,7 +87,7 @@ impl PusServiceHandler for PusService17TestHandler { if self .psb .verification_handler - .completion_success(start_token, Some(&self.psb.stamp_buf)) + .completion_success(start_token, Some(&time_stamp)) .is_err() { partial_error = Some(PartialPusHandlingError::VerificationError) diff --git a/satrs-core/src/pus/verification.rs b/satrs-core/src/pus/verification.rs index 99a1c68..b4db15f 100644 --- a/satrs-core/src/pus/verification.rs +++ b/satrs-core/src/pus/verification.rs @@ -467,7 +467,7 @@ impl VerificationReporterCore { // 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>( - &mut self, + &self, src_data_buf: &'src_data mut [u8], subservice: u8, token: VerificationToken, @@ -621,7 +621,7 @@ impl VerificationReporterCore { /// 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>( - &mut self, + &self, src_data_buf: &'src_data mut [u8], token: VerificationToken, seq_count: u16, @@ -838,7 +838,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>( - &mut self, + &self, src_data_buf: &'src_data mut [u8], subservice: u8, seq_count: u16, @@ -883,7 +883,7 @@ impl VerificationReporterCore { } fn create_pus_verif_tm_base<'src_data>( - &mut self, + &self, src_data_buf: &'src_data mut [u8], subservice: u8, msg_counter: u16, diff --git a/satrs-example/src/lib.rs b/satrs-example/src/lib.rs index 9429755..754be9b 100644 --- a/satrs-example/src/lib.rs +++ b/satrs-example/src/lib.rs @@ -1,5 +1,6 @@ use num_enum::{IntoPrimitive, TryFromPrimitive}; use satrs_core::events::{EventU32TypedSev, SeverityInfo}; +use satrs_core::objects::ObjectId; use std::net::Ipv4Addr; use satrs_mib::res_code::{ResultU16, ResultU16Info}; @@ -17,6 +18,11 @@ pub enum RequestTargetId { AcsSubsystem = 1, } +pub const ACS_OBJECT_ID: ObjectId = ObjectId { + id: RequestTargetId::AcsSubsystem as u32, + name: "ACS_SUBSYSTEM", +}; + #[derive(Debug)] pub enum GroupId { Tmtc = 0, @@ -38,6 +44,8 @@ pub mod tmtc_err { pub const INVALID_PUS_SUBSERVICE: ResultU16 = ResultU16::const_new(GroupId::Tmtc as u8, 1); #[resultcode] pub const PUS_SERVICE_NOT_IMPLEMENTED: ResultU16 = ResultU16::const_new(GroupId::Tmtc as u8, 2); + #[resultcode] + pub const UNKNOWN_TARGET_ID: ResultU16 = ResultU16::const_new(GroupId::Tmtc as u8, 3); #[resultcode( info = "Not enough data inside the TC application data field. Optionally includes: \ diff --git a/satrs-example/src/main.rs b/satrs-example/src/main.rs index 2e830f0..6cfe305 100644 --- a/satrs-example/src/main.rs +++ b/satrs-example/src/main.rs @@ -9,6 +9,7 @@ use log::{info, warn}; use crate::hk::AcsHkIds; use crate::logging::setup_logger; +use crate::pus::action::{Pus8Wrapper, PusService8ActionHandler}; use crate::pus::event::Pus5Wrapper; use crate::pus::scheduler::Pus11Wrapper; use crate::pus::test::Service17CustomWrapper; @@ -45,7 +46,7 @@ use satrs_core::spacepackets::{ SequenceFlags, SpHeader, }; use satrs_core::tmtc::tm_helper::SharedTmStore; -use satrs_core::tmtc::AddressableId; +use satrs_core::tmtc::{AddressableId, TargetId}; use satrs_example::{RequestTargetId, OBSW_SERVER_ADDR, SERVER_PORT}; use std::collections::HashMap; use std::net::{IpAddr, SocketAddr}; @@ -123,7 +124,7 @@ fn main() { // Some request are targetable. This map is used to retrieve sender handles based on a target ID. let mut request_map = HashMap::new(); let (acs_thread_tx, acs_thread_rx) = channel::(); - request_map.insert(RequestTargetId::AcsSubsystem as u32, acs_thread_tx); + request_map.insert(RequestTargetId::AcsSubsystem as TargetId, acs_thread_tx); let tc_source_wrapper = PusTcSource { tc_store: tc_store.clone(), @@ -135,7 +136,6 @@ fn main() { sock_addr, verif_reporter: verif_reporter.clone(), event_sender, - request_map, }; let tc_args = TcArgs { tc_source: tc_source_wrapper.clone(), @@ -153,7 +153,7 @@ fn main() { 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_hk_tx, _pus_hk_rx) = channel(); let (pus_action_tx, pus_action_rx) = channel(); let pus_router = PusTcMpscRouter { test_service_receiver: pus_test_tx, @@ -195,11 +195,22 @@ fn main() { tm_funnel_tx.clone(), tm_store.clone(), PUS_APID, - verif_reporter, + verif_reporter.clone(), event_request_tx, ); let mut pus_5_wrapper = Pus5Wrapper { pus_5_handler }; + let pus_8_handler = PusService8ActionHandler::new( + pus_action_rx, + tc_store.pool.clone(), + tm_funnel_tx.clone(), + tm_store.clone(), + PUS_APID, + verif_reporter, + request_map.clone(), + ); + let mut pus_8_wrapper = Pus8Wrapper { pus_8_handler }; + info!("Starting TMTC task"); let jh0 = thread::Builder::new() .name("TMTC".to_string()) @@ -320,7 +331,7 @@ fn main() { ); update_time(&mut time_provider, &mut timestamp); match request.targeted_request.request { - Request::HkRequest(hk_req) => match hk_req { + Request::Hk(hk_req) => match hk_req { HkRequest::OneShot(unique_id) => { let target = request.targeted_request.target_id; assert_eq!(target, RequestTargetId::AcsSubsystem as u32); @@ -359,9 +370,12 @@ fn main() { HkRequest::Disable(_) => {} HkRequest::ModifyCollectionInterval(_, _) => {} }, - Request::ModeRequest(_mode_req) => { + Request::Mode(_mode_req) => { warn!("mode request handling not implemented yet") } + Request::Action(_action_req) => { + warn!("action request handling not implemented yet") + } } let started_token = reporter_aocs .start_success(request.token, Some(×tamp)) @@ -397,6 +411,7 @@ fn main() { is_srv_finished(pus_17_wrapper.handle_next_packet()); is_srv_finished(pus_11_wrapper.handle_next_packet()); is_srv_finished(pus_5_wrapper.handle_next_packet()); + is_srv_finished(pus_8_wrapper.handle_next_packet()); if all_queues_empty { break; } diff --git a/satrs-example/src/pus/action.rs b/satrs-example/src/pus/action.rs new file mode 100644 index 0000000..f240648 --- /dev/null +++ b/satrs-example/src/pus/action.rs @@ -0,0 +1,165 @@ +use crate::requests::{ActionRequest, Request, RequestWithToken}; +use log::{error, warn}; +use satrs_core::pool::{SharedPool, StoreAddr}; +use satrs_core::pus::verification::{ + FailParams, StdVerifReporterWithSender, TcStateAccepted, VerificationToken, +}; +use satrs_core::pus::{ + AcceptedTc, PusPacketHandlerResult, PusPacketHandlingError, PusServiceBase, PusServiceHandler, +}; +use satrs_core::spacepackets::ecss::PusPacket; +use satrs_core::spacepackets::tc::PusTc; +use satrs_core::tmtc::tm_helper::SharedTmStore; +use satrs_core::tmtc::TargetId; +use satrs_example::tmtc_err; +use std::collections::HashMap; +use std::sync::mpsc::{Receiver, Sender}; + +pub struct PusService8ActionHandler { + psb: PusServiceBase, + request_handlers: HashMap>, +} + +impl PusService8ActionHandler { + pub fn new( + receiver: Receiver, + tc_pool: SharedPool, + tm_tx: Sender, + tm_store: SharedTmStore, + tm_apid: u16, + verification_handler: StdVerifReporterWithSender, + request_handlers: HashMap>, + ) -> Self { + Self { + psb: PusServiceBase::new( + receiver, + tc_pool, + tm_tx, + tm_store, + tm_apid, + verification_handler, + ), + request_handlers, + } + } +} + +impl PusServiceHandler for PusService8ActionHandler { + fn psb_mut(&mut self) -> &mut PusServiceBase { + &mut self.psb + } + fn psb(&self) -> &PusServiceBase { + &self.psb + } + + fn handle_one_tc( + &mut self, + addr: StoreAddr, + token: VerificationToken, + ) -> Result { + self.copy_tc_to_buf(addr)?; + let (tc, _) = PusTc::from_bytes(&self.psb().pus_buf).unwrap(); + let subservice = tc.subservice(); + let mut partial_error = None; + let time_stamp = self.psb().get_current_timestamp(&mut partial_error); + match subservice { + 128 => { + let user_data = tc.user_data(); + if user_data.is_none() || user_data.unwrap().len() < 8 { + self.psb_mut() + .verification_handler + .start_failure( + token, + FailParams::new( + Some(&time_stamp), + &tmtc_err::NOT_ENOUGH_APP_DATA, + None, + ), + ) + .expect("Sending start failure failed"); + return Err(PusPacketHandlingError::NotEnoughAppData( + "Expected at least 4 bytes".into(), + )); + } + let user_data = user_data.unwrap(); + let target_id = u32::from_be_bytes(user_data[0..4].try_into().unwrap()); + let action_id = u32::from_be_bytes(user_data[4..8].try_into().unwrap()); + if let Some(sender) = self.request_handlers.get(&target_id) { + sender + .send(RequestWithToken::new( + target_id, + Request::Action(ActionRequest::CmdWithU32Id(( + action_id, + Vec::from(&user_data[8..]), + ))), + token, + )) + .expect("Forwarding action request failed"); + } else { + let mut fail_data: [u8; 4] = [0; 4]; + fail_data.copy_from_slice(&target_id.to_be_bytes()); + self.psb_mut() + .verification_handler + .start_failure( + token, + FailParams::new( + Some(&time_stamp), + &tmtc_err::UNKNOWN_TARGET_ID, + Some(&fail_data), + ), + ) + .expect("Sending start failure failed"); + return Err(PusPacketHandlingError::OtherError(format!( + "Unknown target ID {target_id}" + ))); + } + } + _ => { + let fail_data = [subservice]; + self.psb_mut() + .verification_handler + .start_failure( + token, + FailParams::new( + Some(&time_stamp), + &tmtc_err::INVALID_PUS_SUBSERVICE, + Some(&fail_data), + ), + ) + .expect("Sending start failure failed"); + return Err(PusPacketHandlingError::InvalidSubservice(subservice)); + } + } + Ok(PusPacketHandlerResult::RequestHandled) + } +} + +pub struct Pus8Wrapper { + pub(crate) pus_8_handler: PusService8ActionHandler, +} + +impl Pus8Wrapper { + pub fn handle_next_packet(&mut self) -> bool { + match self.pus_8_handler.handle_next_packet() { + Ok(result) => match result { + PusPacketHandlerResult::RequestHandled => {} + PusPacketHandlerResult::RequestHandledPartialSuccess(e) => { + warn!("PUS 8 partial packet handling success: {e:?}") + } + PusPacketHandlerResult::CustomSubservice(invalid, _) => { + warn!("PUS 8 invalid subservice {invalid}"); + } + PusPacketHandlerResult::SubserviceNotImplemented(subservice, _) => { + warn!("PUS 8 subservice {subservice} not implemented"); + } + PusPacketHandlerResult::Empty => { + return true; + } + }, + Err(error) => { + error!("PUS packet handling error: {error:?}") + } + } + false + } +} diff --git a/satrs-example/src/pus/mod.rs b/satrs-example/src/pus/mod.rs index 4186359..e17fd78 100644 --- a/satrs-example/src/pus/mod.rs +++ b/satrs-example/src/pus/mod.rs @@ -12,6 +12,7 @@ use satrs_core::tmtc::tm_helper::PusTmWithCdsShortHelper; use satrs_example::{tmtc_err, CustomPusServiceId}; use std::sync::mpsc::Sender; +pub mod action; pub mod event; pub mod scheduler; pub mod test; diff --git a/satrs-example/src/pus/test.rs b/satrs-example/src/pus/test.rs index 5248028..707dae1 100644 --- a/satrs-example/src/pus/test.rs +++ b/satrs-example/src/pus/test.rs @@ -2,6 +2,7 @@ use log::{info, warn}; use satrs_core::events::EventU32; use satrs_core::params::Params; use satrs_core::pus::test::PusService17TestHandler; +use satrs_core::pus::verification::FailParams; use satrs_core::pus::{PusPacketHandlerResult, PusServiceHandler}; use satrs_core::spacepackets::ecss::PusPacket; use satrs_core::spacepackets::tc::PusTc; @@ -37,8 +38,9 @@ impl Service17CustomWrapper { warn!("PUS17: Subservice {subservice} not implemented") } PusPacketHandlerResult::CustomSubservice(subservice, token) => { - let (buf, _) = self.pus17_handler.pus_tc_buf(); - let (tc, _) = PusTc::from_bytes(buf).unwrap(); + let psb_mut = self.pus17_handler.psb_mut(); + let buf = psb_mut.pus_buf; + let (tc, _) = PusTc::from_bytes(&buf).unwrap(); let time_stamper = TimeProvider::from_now_with_u16_days().unwrap(); let mut stamp_buf: [u8; 7] = [0; 7]; time_stamper.write_to_bytes(&mut stamp_buf).unwrap(); @@ -47,23 +49,26 @@ impl Service17CustomWrapper { self.test_srv_event_sender .send((TEST_EVENT.into(), None)) .expect("Sending test event failed"); - let start_token = self - .pus17_handler - .verification_reporter() + let start_token = psb_mut + .verification_handler .start_success(token, Some(&stamp_buf)) .expect("Error sending start success"); - self.pus17_handler - .verification_reporter() + psb_mut + .verification_handler .completion_success(start_token, Some(&stamp_buf)) .expect("Error sending completion success"); } else { let fail_data = [tc.subservice()]; self.pus17_handler .psb_mut() - .report_start_failure( + .verification_handler + .start_failure( token, - &tmtc_err::INVALID_PUS_SUBSERVICE, - Some(&fail_data), + FailParams::new( + Some(&stamp_buf), + &tmtc_err::INVALID_PUS_SUBSERVICE, + Some(&fail_data), + ), ) .expect("Sending start failure verification failed"); } diff --git a/satrs-example/src/requests.rs b/satrs-example/src/requests.rs index 6f11eef..5fa2549 100644 --- a/satrs-example/src/requests.rs +++ b/satrs-example/src/requests.rs @@ -3,14 +3,23 @@ use satrs_core::mode::ModeRequest; use satrs_core::pus::verification::{TcStateAccepted, VerificationToken}; use satrs_core::tmtc::TargetId; -#[derive(Copy, Clone, Eq, PartialEq, Debug)] -#[non_exhaustive] -pub enum Request { - HkRequest(HkRequest), - ModeRequest(ModeRequest), +#[allow(dead_code)] +#[derive(Clone, Eq, PartialEq, Debug)] +pub enum ActionRequest { + CmdWithU32Id((u32, Vec)), + CmdWithStringId((String, Vec)), } -#[derive(Copy, Clone, Eq, PartialEq, Debug)] +#[allow(dead_code)] +#[derive(Clone, Eq, PartialEq, Debug)] +#[non_exhaustive] +pub enum Request { + Hk(HkRequest), + Mode(ModeRequest), + Action(ActionRequest), +} + +#[derive(Clone, Eq, PartialEq, Debug)] pub struct TargetedRequest { pub(crate) target_id: TargetId, pub(crate) request: Request, @@ -22,7 +31,7 @@ impl TargetedRequest { } } -#[derive(Copy, Clone, Eq, PartialEq, Debug)] +#[derive(Clone, Eq, PartialEq, Debug)] pub struct RequestWithToken { pub(crate) targeted_request: TargetedRequest, pub(crate) token: VerificationToken, diff --git a/satrs-example/src/tmtc.rs b/satrs-example/src/tmtc.rs index 5299017..b26eb42 100644 --- a/satrs-example/src/tmtc.rs +++ b/satrs-example/src/tmtc.rs @@ -2,7 +2,6 @@ use log::info; use satrs_core::events::EventU32; use satrs_core::hal::host::udp_server::{ReceiveResult, UdpTcServer}; use satrs_core::params::Params; -use std::collections::HashMap; use std::error::Error; use std::fmt::{Display, Formatter}; use std::net::SocketAddr; @@ -12,7 +11,6 @@ use std::time::Duration; use crate::ccsds::CcsdsReceiver; use crate::pus::{PusReceiver, PusTcArgs, PusTcMpscRouter, PusTmArgs}; -use crate::requests::RequestWithToken; use satrs_core::pool::{SharedPool, StoreAddr, StoreError}; use satrs_core::pus::verification::StdVerifReporterWithSender; use satrs_core::spacepackets::ecss::{PusPacket, SerializablePusPacket}; @@ -27,7 +25,6 @@ pub struct OtherArgs { pub sock_addr: SocketAddr, pub verif_reporter: StdVerifReporterWithSender, pub event_sender: Sender<(EventU32, Option)>, - pub request_map: HashMap>, } pub struct TmArgs {