From 29783b2b0783daa81205bee1763ed44fda339f97 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sat, 25 May 2024 12:29:44 +0200 Subject: [PATCH] introduce new HK helper --- satrs-example/src/acs/mgm.rs | 64 ++++++++++----------- satrs-example/src/eps/pcdu.rs | 101 +++++++++++++++++++--------------- satrs-example/src/hk.rs | 36 +++++++++++- satrs-example/src/pus/hk.rs | 11 ++++ 4 files changed, 131 insertions(+), 81 deletions(-) diff --git a/satrs-example/src/acs/mgm.rs b/satrs-example/src/acs/mgm.rs index 51b4fca..1b0f3b5 100644 --- a/satrs-example/src/acs/mgm.rs +++ b/satrs-example/src/acs/mgm.rs @@ -2,9 +2,6 @@ use derive_new::new; use satrs::hk::{HkRequest, HkRequestVariant}; use satrs::power::{PowerSwitchInfo, PowerSwitcherCommandSender}; use satrs::queue::{GenericSendError, GenericTargetedMessagingError}; -use satrs::spacepackets::ecss::hk; -use satrs::spacepackets::ecss::tm::{PusTmCreator, PusTmSecondaryHeader}; -use satrs::spacepackets::SpHeader; use satrs_example::{DeviceMode, TimestampHelper}; use satrs_minisim::acs::lis3mdl::{ MgmLis3MdlReply, MgmLis3RawValues, FIELD_LSB_PER_GAUSS_4_SENS, GAUSS_TO_MICROTESLA_FACTOR, @@ -24,6 +21,7 @@ use satrs::pus::{EcssTmSender, PusTmVariant}; use satrs::request::{GenericMessage, MessageMetadata, UniqueApidTargetId}; use satrs_example::config::components::PUS_MODE_SERVICE; +use crate::hk::PusHkHelper; use crate::pus::hk::{HkReply, HkReplyVariant}; use crate::requests::CompositeRequest; @@ -179,6 +177,8 @@ pub struct MgmHandlerLis3Mdl< tm_sender: TmSender, pub com_interface: ComInterface, shared_mgm_set: Arc>, + #[new(value = "PusHkHelper::new(id)")] + hk_helper: PusHkHelper, #[new(default)] mode_helpers: ModeHelpers, #[new(default)] @@ -237,39 +237,33 @@ impl< pub fn handle_hk_request(&mut self, requestor_info: &MessageMetadata, hk_request: &HkRequest) { match hk_request.variant { HkRequestVariant::OneShot => { - // TODO: We should provide a helper class for generating some of the boilerplate. - // This includes the APID, subservice, unique ID and set ID handling. The user - // should be able to simply specify the HK data as a slice. - self.hk_reply_tx - .send(GenericMessage::new( - *requestor_info, - HkReply::new(hk_request.unique_id, HkReplyVariant::Ack), - )) - .expect("failed to send HK reply"); - let sec_header = PusTmSecondaryHeader::new( - 3, - hk::Subservice::TmHkPacket as u8, - 0, - 0, - self.stamp_helper.stamp(), - ); let mgm_snapshot = *self.shared_mgm_set.lock().unwrap(); - self.bufs.tm_buf[0..4].copy_from_slice(&self.id.unique_id.to_be_bytes()); - self.bufs.tm_buf[4..8].copy_from_slice(&(SetId::SensorData as u32).to_be_bytes()); - // Use binary serialization here. We want the data to be tightly packed. - self.bufs.tm_buf[8] = mgm_snapshot.valid as u8; - self.bufs.tm_buf[9..13].copy_from_slice(&mgm_snapshot.x.to_be_bytes()); - self.bufs.tm_buf[13..17].copy_from_slice(&mgm_snapshot.y.to_be_bytes()); - self.bufs.tm_buf[17..21].copy_from_slice(&mgm_snapshot.z.to_be_bytes()); - let hk_tm = PusTmCreator::new( - SpHeader::new_from_apid(self.id.apid), - sec_header, - &self.bufs.tm_buf[0..21], - true, - ); - self.tm_sender - .send_tm(self.id.id(), PusTmVariant::Direct(hk_tm)) - .expect("failed to send HK TM"); + if let Ok(hk_tm) = self.hk_helper.generate_hk_report_packet( + self.stamp_helper.stamp(), + SetId::SensorData as u32, + &mut |hk_buf| { + hk_buf[0] = mgm_snapshot.valid as u8; + hk_buf[1..5].copy_from_slice(&mgm_snapshot.x.to_be_bytes()); + hk_buf[5..9].copy_from_slice(&mgm_snapshot.y.to_be_bytes()); + hk_buf[9..13].copy_from_slice(&mgm_snapshot.z.to_be_bytes()); + Ok(13) + }, + &mut self.bufs.tm_buf, + ) { + // TODO: If sending the TM fails, we should also send a failure reply. + self.tm_sender + .send_tm(self.id.id(), PusTmVariant::Direct(hk_tm)) + .expect("failed to send HK TM"); + self.hk_reply_tx + .send(GenericMessage::new( + *requestor_info, + HkReply::new(hk_request.unique_id, HkReplyVariant::Ack), + )) + .expect("failed to send HK reply"); + } else { + // TODO: Send back failure reply. Need result code for this. + log::error!("TM buffer too small to generate HK data"); + } } HkRequestVariant::EnablePeriodic => todo!(), HkRequestVariant::DisablePeriodic => todo!(), diff --git a/satrs-example/src/eps/pcdu.rs b/satrs-example/src/eps/pcdu.rs index 8dce829..d51ca55 100644 --- a/satrs-example/src/eps/pcdu.rs +++ b/satrs-example/src/eps/pcdu.rs @@ -13,23 +13,20 @@ use satrs::{ pus::{EcssTmSender, PusTmVariant}, queue::{GenericSendError, GenericTargetedMessagingError}, request::{GenericMessage, MessageMetadata, UniqueApidTargetId}, - spacepackets::{ - ecss::{ - hk, - tm::{PusTmCreator, PusTmSecondaryHeader}, - }, - SpHeader, - }, + spacepackets::ByteConversionError, }; use satrs_example::{config::components::PUS_MODE_SERVICE, DeviceMode, TimestampHelper}; use satrs_minisim::{ - eps::{PcduReply, PcduRequest, PcduSwitch, SwitchMap, SwitchMapBinaryWrapper}, + eps::{ + PcduReply, PcduRequest, PcduSwitch, SwitchMap, SwitchMapBinaryWrapper, SwitchMapWrapper, + }, SerializableSimMsgPayload, SimReply, SimRequest, }; use serde::{Deserialize, Serialize}; use crate::{ acs::mgm::MpscModeLeafInterface, + hk::PusHkHelper, pus::hk::{HkReply, HkReplyVariant}, requests::CompositeRequest, }; @@ -202,6 +199,8 @@ pub struct PcduHandler { tm_sender: TmSender, pub com_interface: ComInterface, shared_switch_map: Arc>, + #[new(value = "PusHkHelper::new(id)")] + hk_helper: PusHkHelper, #[new(value = "ModeAndSubmode::new(satrs_example::DeviceMode::Off as u32, 0)")] mode_and_submode: ModeAndSubmode, #[new(default)] @@ -262,44 +261,39 @@ impl PcduHandler { if hk_request.unique_id == SetId::SwitcherSet as u32 { - self.hk_reply_tx - .send(GenericMessage::new( - *requestor_info, - HkReply::new(hk_request.unique_id, HkReplyVariant::Ack), - )) - .expect("failed to send HK reply"); - let sec_header = PusTmSecondaryHeader::new( - 3, - hk::Subservice::TmHkPacket as u8, - 0, - 0, + if let Ok(hk_tm) = self.hk_helper.generate_hk_report_packet( self.stamp_helper.stamp(), - ); - // Send TM down as JSON. - let switch_map_snapshot = self - .shared_switch_map - .lock() - .expect("failed to lock switch map") - .clone(); - let switch_map_json = serde_json::to_string(&switch_map_snapshot) - .expect("failed to serialize switch map"); - if switch_map_json.len() > self.tm_buf.len() { - log::error!("switch map JSON too large for telemetry buffer"); - return; + SetId::SwitcherSet as u32, + &mut |hk_buf| { + // Send TM down as JSON. + let switch_map_snapshot = self + .shared_switch_map + .lock() + .expect("failed to lock switch map") + .clone(); + let switch_map_json = serde_json::to_string(&switch_map_snapshot) + .expect("failed to serialize switch map"); + if switch_map_json.len() > hk_buf.len() { + log::error!("switch map JSON too large for HK buffer"); + return Err(ByteConversionError::ToSliceTooSmall { + found: hk_buf.len(), + expected: switch_map_json.len(), + }); + } + Ok(switch_map_json.len()) + }, + &mut self.tm_buf, + ) { + self.tm_sender + .send_tm(self.id.id(), PusTmVariant::Direct(hk_tm)) + .expect("failed to send HK TM"); + self.hk_reply_tx + .send(GenericMessage::new( + *requestor_info, + HkReply::new(hk_request.unique_id, HkReplyVariant::Ack), + )) + .expect("failed to send HK reply"); } - self.tm_buf[0..4].copy_from_slice(&self.id.unique_id.to_be_bytes()); - self.tm_buf[4..8].copy_from_slice(&(SetId::SwitcherSet as u32).to_be_bytes()); - self.tm_buf[8..8 + switch_map_json.len()] - .copy_from_slice(switch_map_json.as_bytes()); - let hk_tm = PusTmCreator::new( - SpHeader::new_from_apid(self.id.apid), - sec_header, - &self.tm_buf[0..8 + switch_map_json.len()], - true, - ); - self.tm_sender - .send_tm(self.id.id(), PusTmVariant::Direct(hk_tm)) - .expect("failed to send HK TM"); } } HkRequestVariant::EnablePeriodic => todo!(), @@ -369,7 +363,24 @@ impl PcduHandler { + let switch_map_wrapper = + SwitchMapWrapper::from_binary_switch_map_ref(&switch_info); + self.shared_switch_map + .lock() + .expect("failed to lock switch map") + .switch_map = switch_map_wrapper.0; + } + } + }) { + log::warn!("receiving PCDU replies failed: {:?}", e); + } + } } impl ModeProvider diff --git a/satrs-example/src/hk.rs b/satrs-example/src/hk.rs index 0852d04..bfad5e8 100644 --- a/satrs-example/src/hk.rs +++ b/satrs-example/src/hk.rs @@ -1,7 +1,9 @@ use derive_new::new; use satrs::hk::UniqueId; use satrs::request::UniqueApidTargetId; -use satrs::spacepackets::ByteConversionError; +use satrs::spacepackets::ecss::hk; +use satrs::spacepackets::ecss::tm::{PusTmCreator, PusTmSecondaryHeader}; +use satrs::spacepackets::{ByteConversionError, SpHeader}; #[derive(Debug, new, Copy, Clone)] pub struct HkUniqueId { @@ -33,3 +35,35 @@ impl HkUniqueId { Ok(8) } } + +#[derive(new)] +pub struct PusHkHelper { + component_id: UniqueApidTargetId, +} + +impl PusHkHelper { + pub fn generate_hk_report_packet< + 'a, + 'b, + HkWriter: FnMut(&mut [u8]) -> Result, + >( + &self, + timestamp: &'a [u8], + set_id: u32, + hk_data_writer: &mut HkWriter, + buf: &'b mut [u8], + ) -> Result, ByteConversionError> { + let sec_header = + PusTmSecondaryHeader::new(3, hk::Subservice::TmHkPacket as u8, 0, 0, timestamp); + buf[0..4].copy_from_slice(&self.component_id.unique_id.to_be_bytes()); + buf[4..8].copy_from_slice(&set_id.to_be_bytes()); + let (_, second_half) = buf.split_at_mut(8); + let hk_data_len = hk_data_writer(second_half)?; + Ok(PusTmCreator::new( + SpHeader::new_from_apid(self.component_id.apid), + sec_header, + &buf[0..8 + hk_data_len], + true, + )) + } +} diff --git a/satrs-example/src/pus/hk.rs b/satrs-example/src/pus/hk.rs index 0092241..2796151 100644 --- a/satrs-example/src/pus/hk.rs +++ b/satrs-example/src/pus/hk.rs @@ -12,6 +12,7 @@ use satrs::pus::{ PusPacketHandlingError, PusReplyHandler, PusServiceHelper, PusTcToRequestConverter, }; use satrs::request::{GenericMessage, UniqueApidTargetId}; +use satrs::res_code::ResultU16; use satrs::spacepackets::ecss::tc::PusTcReader; use satrs::spacepackets::ecss::{hk, PusPacket, PusServiceId}; use satrs::tmtc::{PacketAsVec, PacketSenderWithSharedPool}; @@ -34,6 +35,7 @@ pub struct HkReply { #[derive(Clone, PartialEq, Debug)] pub enum HkReplyVariant { Ack, + Failed(ResultU16), } #[derive(Default)] @@ -69,6 +71,15 @@ impl PusReplyHandler for HkReplyHandler { .completion_success(tm_sender, started_token, time_stamp) .expect("sending completion success verification failed"); } + HkReplyVariant::Failed(failure_code) => { + verification_handler + .completion_failure( + tm_sender, + started_token, + FailParams::new(time_stamp, &failure_code, &[]), + ) + .expect("sending completion success verification failed"); + } }; Ok(true) }