introduce new HK helper
All checks were successful
Rust/sat-rs/pipeline/pr-main This commit looks good
All checks were successful
Rust/sat-rs/pipeline/pr-main This commit looks good
This commit is contained in:
parent
2a2a3a3eab
commit
29783b2b07
@ -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<Mutex<MgmData>>,
|
||||
#[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.
|
||||
let mgm_snapshot = *self.shared_mgm_set.lock().unwrap();
|
||||
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");
|
||||
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");
|
||||
} 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!(),
|
||||
|
@ -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<ComInterface: SerialInterface, TmSender: EcssTmSender> {
|
||||
tm_sender: TmSender,
|
||||
pub com_interface: ComInterface,
|
||||
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)")]
|
||||
mode_and_submode: ModeAndSubmode,
|
||||
#[new(default)]
|
||||
@ -262,19 +261,10 @@ impl<ComInterface: SerialInterface, TmSender: EcssTmSender> PcduHandler<ComInter
|
||||
match hk_request.variant {
|
||||
HkRequestVariant::OneShot => {
|
||||
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(),
|
||||
);
|
||||
SetId::SwitcherSet as u32,
|
||||
&mut |hk_buf| {
|
||||
// Send TM down as JSON.
|
||||
let switch_map_snapshot = self
|
||||
.shared_switch_map
|
||||
@ -283,23 +273,27 @@ impl<ComInterface: SerialInterface, TmSender: EcssTmSender> PcduHandler<ComInter
|
||||
.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;
|
||||
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(),
|
||||
});
|
||||
}
|
||||
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,
|
||||
);
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
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
|
||||
|
@ -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<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,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
@ -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<ActivePusRequestStd, HkReply> 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)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user