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::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!(),
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user