introduce new HK helper
All checks were successful
Rust/sat-rs/pipeline/pr-main This commit looks good

This commit is contained in:
Robin Müller 2024-05-25 12:29:44 +02:00
parent 2a2a3a3eab
commit 29783b2b07
4 changed files with 131 additions and 81 deletions

View File

@ -2,9 +2,6 @@ use derive_new::new;
use satrs::hk::{HkRequest, HkRequestVariant}; use satrs::hk::{HkRequest, HkRequestVariant};
use satrs::power::{PowerSwitchInfo, PowerSwitcherCommandSender}; use satrs::power::{PowerSwitchInfo, PowerSwitcherCommandSender};
use satrs::queue::{GenericSendError, GenericTargetedMessagingError}; 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_example::{DeviceMode, TimestampHelper};
use satrs_minisim::acs::lis3mdl::{ use satrs_minisim::acs::lis3mdl::{
MgmLis3MdlReply, MgmLis3RawValues, FIELD_LSB_PER_GAUSS_4_SENS, GAUSS_TO_MICROTESLA_FACTOR, 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::request::{GenericMessage, MessageMetadata, UniqueApidTargetId};
use satrs_example::config::components::PUS_MODE_SERVICE; use satrs_example::config::components::PUS_MODE_SERVICE;
use crate::hk::PusHkHelper;
use crate::pus::hk::{HkReply, HkReplyVariant}; use crate::pus::hk::{HkReply, HkReplyVariant};
use crate::requests::CompositeRequest; use crate::requests::CompositeRequest;
@ -179,6 +177,8 @@ pub struct MgmHandlerLis3Mdl<
tm_sender: TmSender, tm_sender: TmSender,
pub com_interface: ComInterface, pub com_interface: ComInterface,
shared_mgm_set: Arc<Mutex<MgmData>>, shared_mgm_set: Arc<Mutex<MgmData>>,
#[new(value = "PusHkHelper::new(id)")]
hk_helper: PusHkHelper,
#[new(default)] #[new(default)]
mode_helpers: ModeHelpers, mode_helpers: ModeHelpers,
#[new(default)] #[new(default)]
@ -237,39 +237,33 @@ impl<
pub fn handle_hk_request(&mut self, requestor_info: &MessageMetadata, hk_request: &HkRequest) { pub fn handle_hk_request(&mut self, requestor_info: &MessageMetadata, hk_request: &HkRequest) {
match hk_request.variant { match hk_request.variant {
HkRequestVariant::OneShot => { 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(); 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()); if let Ok(hk_tm) = self.hk_helper.generate_hk_report_packet(
self.bufs.tm_buf[4..8].copy_from_slice(&(SetId::SensorData as u32).to_be_bytes()); self.stamp_helper.stamp(),
// Use binary serialization here. We want the data to be tightly packed. SetId::SensorData as u32,
self.bufs.tm_buf[8] = mgm_snapshot.valid as u8; &mut |hk_buf| {
self.bufs.tm_buf[9..13].copy_from_slice(&mgm_snapshot.x.to_be_bytes()); hk_buf[0] = mgm_snapshot.valid as u8;
self.bufs.tm_buf[13..17].copy_from_slice(&mgm_snapshot.y.to_be_bytes()); hk_buf[1..5].copy_from_slice(&mgm_snapshot.x.to_be_bytes());
self.bufs.tm_buf[17..21].copy_from_slice(&mgm_snapshot.z.to_be_bytes()); hk_buf[5..9].copy_from_slice(&mgm_snapshot.y.to_be_bytes());
let hk_tm = PusTmCreator::new( hk_buf[9..13].copy_from_slice(&mgm_snapshot.z.to_be_bytes());
SpHeader::new_from_apid(self.id.apid), Ok(13)
sec_header, },
&self.bufs.tm_buf[0..21], &mut self.bufs.tm_buf,
true, ) {
); // TODO: If sending the TM fails, we should also send a failure reply.
self.tm_sender self.tm_sender
.send_tm(self.id.id(), PusTmVariant::Direct(hk_tm)) .send_tm(self.id.id(), PusTmVariant::Direct(hk_tm))
.expect("failed to send 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::EnablePeriodic => todo!(),
HkRequestVariant::DisablePeriodic => todo!(), HkRequestVariant::DisablePeriodic => todo!(),

View File

@ -13,23 +13,20 @@ use satrs::{
pus::{EcssTmSender, PusTmVariant}, pus::{EcssTmSender, PusTmVariant},
queue::{GenericSendError, GenericTargetedMessagingError}, queue::{GenericSendError, GenericTargetedMessagingError},
request::{GenericMessage, MessageMetadata, UniqueApidTargetId}, request::{GenericMessage, MessageMetadata, UniqueApidTargetId},
spacepackets::{ spacepackets::ByteConversionError,
ecss::{
hk,
tm::{PusTmCreator, PusTmSecondaryHeader},
},
SpHeader,
},
}; };
use satrs_example::{config::components::PUS_MODE_SERVICE, DeviceMode, TimestampHelper}; use satrs_example::{config::components::PUS_MODE_SERVICE, DeviceMode, TimestampHelper};
use satrs_minisim::{ use satrs_minisim::{
eps::{PcduReply, PcduRequest, PcduSwitch, SwitchMap, SwitchMapBinaryWrapper}, eps::{
PcduReply, PcduRequest, PcduSwitch, SwitchMap, SwitchMapBinaryWrapper, SwitchMapWrapper,
},
SerializableSimMsgPayload, SimReply, SimRequest, SerializableSimMsgPayload, SimReply, SimRequest,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
acs::mgm::MpscModeLeafInterface, acs::mgm::MpscModeLeafInterface,
hk::PusHkHelper,
pus::hk::{HkReply, HkReplyVariant}, pus::hk::{HkReply, HkReplyVariant},
requests::CompositeRequest, requests::CompositeRequest,
}; };
@ -202,6 +199,8 @@ pub struct PcduHandler<ComInterface: SerialInterface, TmSender: EcssTmSender> {
tm_sender: TmSender, tm_sender: TmSender,
pub com_interface: ComInterface, pub com_interface: ComInterface,
shared_switch_map: Arc<Mutex<SwitchSet>>, shared_switch_map: Arc<Mutex<SwitchSet>>,
#[new(value = "PusHkHelper::new(id)")]
hk_helper: PusHkHelper,
#[new(value = "ModeAndSubmode::new(satrs_example::DeviceMode::Off as u32, 0)")] #[new(value = "ModeAndSubmode::new(satrs_example::DeviceMode::Off as u32, 0)")]
mode_and_submode: ModeAndSubmode, mode_and_submode: ModeAndSubmode,
#[new(default)] #[new(default)]
@ -262,44 +261,39 @@ impl<ComInterface: SerialInterface, TmSender: EcssTmSender> PcduHandler<ComInter
match hk_request.variant { match hk_request.variant {
HkRequestVariant::OneShot => { HkRequestVariant::OneShot => {
if hk_request.unique_id == SetId::SwitcherSet as u32 { if hk_request.unique_id == SetId::SwitcherSet as u32 {
self.hk_reply_tx if let Ok(hk_tm) = self.hk_helper.generate_hk_report_packet(
.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(), self.stamp_helper.stamp(),
); SetId::SwitcherSet as u32,
// Send TM down as JSON. &mut |hk_buf| {
let switch_map_snapshot = self // Send TM down as JSON.
.shared_switch_map let switch_map_snapshot = self
.lock() .shared_switch_map
.expect("failed to lock switch map") .lock()
.clone(); .expect("failed to lock switch map")
let switch_map_json = serde_json::to_string(&switch_map_snapshot) .clone();
.expect("failed to serialize switch map"); let switch_map_json = serde_json::to_string(&switch_map_snapshot)
if switch_map_json.len() > self.tm_buf.len() { .expect("failed to serialize switch map");
log::error!("switch map JSON too large for telemetry buffer"); if switch_map_json.len() > hk_buf.len() {
return; 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!(), HkRequestVariant::EnablePeriodic => todo!(),
@ -369,7 +363,24 @@ impl<ComInterface: SerialInterface, TmSender: EcssTmSender> PcduHandler<ComInter
} }
} }
pub fn poll_and_handle_replies(&mut self) {} pub fn poll_and_handle_replies(&mut self) {
if let Err(e) = self.com_interface.try_recv_replies(|reply| {
let sim_reply: SimReply = serde_json::from_slice(reply).expect("invalid reply format");
let pcdu_reply = PcduReply::from_sim_message(&sim_reply).expect("invalid reply format");
match pcdu_reply {
PcduReply::SwitchInfo(switch_info) => {
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<ComInterface: SerialInterface, TmSender: EcssTmSender> ModeProvider impl<ComInterface: SerialInterface, TmSender: EcssTmSender> ModeProvider

View File

@ -1,7 +1,9 @@
use derive_new::new; use derive_new::new;
use satrs::hk::UniqueId; use satrs::hk::UniqueId;
use satrs::request::UniqueApidTargetId; 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)] #[derive(Debug, new, Copy, Clone)]
pub struct HkUniqueId { pub struct HkUniqueId {
@ -33,3 +35,35 @@ impl HkUniqueId {
Ok(8) 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<usize, ByteConversionError>,
>(
&self,
timestamp: &'a [u8],
set_id: u32,
hk_data_writer: &mut HkWriter,
buf: &'b mut [u8],
) -> Result<PusTmCreator<'a, 'b>, 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,
))
}
}

View File

@ -12,6 +12,7 @@ use satrs::pus::{
PusPacketHandlingError, PusReplyHandler, PusServiceHelper, PusTcToRequestConverter, PusPacketHandlingError, PusReplyHandler, PusServiceHelper, PusTcToRequestConverter,
}; };
use satrs::request::{GenericMessage, UniqueApidTargetId}; use satrs::request::{GenericMessage, UniqueApidTargetId};
use satrs::res_code::ResultU16;
use satrs::spacepackets::ecss::tc::PusTcReader; use satrs::spacepackets::ecss::tc::PusTcReader;
use satrs::spacepackets::ecss::{hk, PusPacket, PusServiceId}; use satrs::spacepackets::ecss::{hk, PusPacket, PusServiceId};
use satrs::tmtc::{PacketAsVec, PacketSenderWithSharedPool}; use satrs::tmtc::{PacketAsVec, PacketSenderWithSharedPool};
@ -34,6 +35,7 @@ pub struct HkReply {
#[derive(Clone, PartialEq, Debug)] #[derive(Clone, PartialEq, Debug)]
pub enum HkReplyVariant { pub enum HkReplyVariant {
Ack, Ack,
Failed(ResultU16),
} }
#[derive(Default)] #[derive(Default)]
@ -69,6 +71,15 @@ impl PusReplyHandler<ActivePusRequestStd, HkReply> for HkReplyHandler {
.completion_success(tm_sender, started_token, time_stamp) .completion_success(tm_sender, started_token, time_stamp)
.expect("sending completion success verification failed"); .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) Ok(true)
} }