2023-07-06 00:49:18 +02:00
|
|
|
use crate::requests::{Request, RequestWithToken};
|
|
|
|
use log::{error, warn};
|
2024-02-12 15:51:37 +01:00
|
|
|
use satrs::hk::{CollectionIntervalFactor, HkRequest};
|
|
|
|
use satrs::pool::{SharedStaticMemoryPool, StoreAddr};
|
|
|
|
use satrs::pus::verification::{
|
2024-02-07 18:10:47 +01:00
|
|
|
FailParams, StdVerifReporterWithSender, VerificationReporterWithSender,
|
|
|
|
};
|
2024-02-12 15:51:37 +01:00
|
|
|
use satrs::pus::{
|
2024-02-07 18:10:47 +01:00
|
|
|
EcssTcAndToken, EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter,
|
2024-02-08 17:42:36 +01:00
|
|
|
EcssTcReceiver, EcssTmSender, MpscTcReceiver, MpscTmAsVecSender, MpscTmInSharedPoolSender,
|
2024-02-03 13:41:51 +01:00
|
|
|
PusPacketHandlerResult, PusPacketHandlingError, PusServiceBase, PusServiceHelper,
|
2023-07-06 00:49:18 +02:00
|
|
|
};
|
2024-02-12 15:51:37 +01:00
|
|
|
use satrs::spacepackets::ecss::{hk, PusPacket};
|
|
|
|
use satrs::tmtc::tm_helper::SharedTmPool;
|
|
|
|
use satrs::ChannelId;
|
2024-02-07 18:10:47 +01:00
|
|
|
use satrs_example::config::{hk_err, tmtc_err, TcReceiverId, TmSenderId, PUS_APID};
|
|
|
|
use satrs_example::TargetIdWithApid;
|
2023-07-06 00:49:18 +02:00
|
|
|
use std::collections::HashMap;
|
2024-02-07 18:10:47 +01:00
|
|
|
use std::sync::mpsc::{self, Sender};
|
|
|
|
|
|
|
|
pub fn create_hk_service_static(
|
2024-02-08 17:42:36 +01:00
|
|
|
shared_tm_store: SharedTmPool,
|
2024-02-07 18:10:47 +01:00
|
|
|
tm_funnel_tx: mpsc::Sender<StoreAddr>,
|
|
|
|
verif_reporter: VerificationReporterWithSender,
|
|
|
|
tc_pool: SharedStaticMemoryPool,
|
|
|
|
pus_hk_rx: mpsc::Receiver<EcssTcAndToken>,
|
|
|
|
request_map: HashMap<TargetIdWithApid, mpsc::Sender<RequestWithToken>>,
|
|
|
|
) -> Pus3Wrapper<EcssTcInSharedStoreConverter> {
|
2024-02-08 17:42:36 +01:00
|
|
|
let hk_srv_tm_sender = MpscTmInSharedPoolSender::new(
|
2024-02-07 18:10:47 +01:00
|
|
|
TmSenderId::PusHk as ChannelId,
|
|
|
|
"PUS_3_TM_SENDER",
|
|
|
|
shared_tm_store.clone(),
|
|
|
|
tm_funnel_tx.clone(),
|
|
|
|
);
|
|
|
|
let hk_srv_receiver =
|
|
|
|
MpscTcReceiver::new(TcReceiverId::PusHk as ChannelId, "PUS_8_TC_RECV", pus_hk_rx);
|
|
|
|
let pus_3_handler = PusService3HkHandler::new(
|
|
|
|
Box::new(hk_srv_receiver),
|
|
|
|
Box::new(hk_srv_tm_sender),
|
|
|
|
PUS_APID,
|
|
|
|
verif_reporter.clone(),
|
|
|
|
EcssTcInSharedStoreConverter::new(tc_pool, 2048),
|
|
|
|
request_map,
|
|
|
|
);
|
|
|
|
Pus3Wrapper { pus_3_handler }
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn create_hk_service_dynamic(
|
|
|
|
tm_funnel_tx: mpsc::Sender<Vec<u8>>,
|
|
|
|
verif_reporter: VerificationReporterWithSender,
|
|
|
|
pus_hk_rx: mpsc::Receiver<EcssTcAndToken>,
|
|
|
|
request_map: HashMap<TargetIdWithApid, mpsc::Sender<RequestWithToken>>,
|
|
|
|
) -> Pus3Wrapper<EcssTcInVecConverter> {
|
|
|
|
let hk_srv_tm_sender = MpscTmAsVecSender::new(
|
|
|
|
TmSenderId::PusHk as ChannelId,
|
|
|
|
"PUS_3_TM_SENDER",
|
|
|
|
tm_funnel_tx.clone(),
|
|
|
|
);
|
|
|
|
let hk_srv_receiver =
|
|
|
|
MpscTcReceiver::new(TcReceiverId::PusHk as ChannelId, "PUS_8_TC_RECV", pus_hk_rx);
|
|
|
|
let pus_3_handler = PusService3HkHandler::new(
|
|
|
|
Box::new(hk_srv_receiver),
|
|
|
|
Box::new(hk_srv_tm_sender),
|
|
|
|
PUS_APID,
|
|
|
|
verif_reporter.clone(),
|
|
|
|
EcssTcInVecConverter::default(),
|
|
|
|
request_map,
|
|
|
|
);
|
|
|
|
Pus3Wrapper { pus_3_handler }
|
|
|
|
}
|
2023-07-05 21:10:45 +02:00
|
|
|
|
2024-01-31 12:09:55 +01:00
|
|
|
pub struct PusService3HkHandler<TcInMemConverter: EcssTcInMemConverter> {
|
2024-02-03 13:41:51 +01:00
|
|
|
psb: PusServiceHelper<TcInMemConverter>,
|
2023-08-15 08:49:54 +02:00
|
|
|
request_handlers: HashMap<TargetIdWithApid, Sender<RequestWithToken>>,
|
2023-07-06 00:49:18 +02:00
|
|
|
}
|
|
|
|
|
2024-01-31 12:09:55 +01:00
|
|
|
impl<TcInMemConverter: EcssTcInMemConverter> PusService3HkHandler<TcInMemConverter> {
|
2023-07-06 00:49:18 +02:00
|
|
|
pub fn new(
|
2023-07-10 00:29:31 +02:00
|
|
|
tc_receiver: Box<dyn EcssTcReceiver>,
|
2023-07-09 17:04:18 +02:00
|
|
|
tm_sender: Box<dyn EcssTmSender>,
|
2023-07-06 00:49:18 +02:00
|
|
|
tm_apid: u16,
|
|
|
|
verification_handler: StdVerifReporterWithSender,
|
2024-01-31 12:09:55 +01:00
|
|
|
tc_in_mem_converter: TcInMemConverter,
|
2023-08-15 08:49:54 +02:00
|
|
|
request_handlers: HashMap<TargetIdWithApid, Sender<RequestWithToken>>,
|
2023-07-06 00:49:18 +02:00
|
|
|
) -> Self {
|
|
|
|
Self {
|
2024-02-03 13:41:51 +01:00
|
|
|
psb: PusServiceHelper::new(
|
2023-07-10 00:29:31 +02:00
|
|
|
tc_receiver,
|
|
|
|
tm_sender,
|
|
|
|
tm_apid,
|
|
|
|
verification_handler,
|
2024-01-31 12:09:55 +01:00
|
|
|
tc_in_mem_converter,
|
2023-07-10 00:29:31 +02:00
|
|
|
),
|
2023-07-06 00:49:18 +02:00
|
|
|
request_handlers,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-30 01:18:48 +01:00
|
|
|
fn handle_one_tc(&mut self) -> Result<PusPacketHandlerResult, PusPacketHandlingError> {
|
2024-01-30 09:59:45 +01:00
|
|
|
let possible_packet = self.psb.retrieve_and_accept_next_packet()?;
|
2024-01-30 01:18:48 +01:00
|
|
|
if possible_packet.is_none() {
|
|
|
|
return Ok(PusPacketHandlerResult::Empty);
|
|
|
|
}
|
2024-01-31 01:32:03 +01:00
|
|
|
let ecss_tc_and_token = possible_packet.unwrap();
|
2024-01-31 12:09:55 +01:00
|
|
|
let tc = self
|
|
|
|
.psb
|
|
|
|
.tc_in_mem_converter
|
2024-02-03 13:41:51 +01:00
|
|
|
.convert_ecss_tc_in_memory_to_reader(&ecss_tc_and_token.tc_in_memory)?;
|
2023-07-06 00:49:18 +02:00
|
|
|
let subservice = tc.subservice();
|
|
|
|
let mut partial_error = None;
|
2024-01-31 12:09:55 +01:00
|
|
|
let time_stamp = PusServiceBase::get_current_timestamp(&mut partial_error);
|
2023-07-11 00:28:28 +02:00
|
|
|
let user_data = tc.user_data();
|
|
|
|
if user_data.is_empty() {
|
2023-07-06 00:49:18 +02:00
|
|
|
self.psb
|
2024-01-31 12:09:55 +01:00
|
|
|
.common
|
2023-07-06 00:49:18 +02:00
|
|
|
.verification_handler
|
|
|
|
.borrow_mut()
|
|
|
|
.start_failure(
|
2024-01-31 01:32:03 +01:00
|
|
|
ecss_tc_and_token.token,
|
2023-07-06 00:49:18 +02:00
|
|
|
FailParams::new(Some(&time_stamp), &tmtc_err::NOT_ENOUGH_APP_DATA, None),
|
|
|
|
)
|
|
|
|
.expect("Sending start failure TM failed");
|
|
|
|
return Err(PusPacketHandlingError::NotEnoughAppData(
|
|
|
|
"Expected at least 8 bytes of app data".into(),
|
|
|
|
));
|
|
|
|
}
|
|
|
|
if user_data.len() < 8 {
|
|
|
|
let err = if user_data.len() < 4 {
|
|
|
|
&hk_err::TARGET_ID_MISSING
|
|
|
|
} else {
|
|
|
|
&hk_err::UNIQUE_ID_MISSING
|
|
|
|
};
|
|
|
|
self.psb
|
2024-01-31 12:09:55 +01:00
|
|
|
.common
|
2023-07-06 00:49:18 +02:00
|
|
|
.verification_handler
|
|
|
|
.borrow_mut()
|
2024-01-31 01:32:03 +01:00
|
|
|
.start_failure(
|
|
|
|
ecss_tc_and_token.token,
|
|
|
|
FailParams::new(Some(&time_stamp), err, None),
|
|
|
|
)
|
2023-07-06 00:49:18 +02:00
|
|
|
.expect("Sending start failure TM failed");
|
|
|
|
return Err(PusPacketHandlingError::NotEnoughAppData(
|
|
|
|
"Expected at least 8 bytes of app data".into(),
|
|
|
|
));
|
|
|
|
}
|
2023-08-15 08:49:54 +02:00
|
|
|
let target_id = TargetIdWithApid::from_tc(&tc).expect("invalid tc format");
|
|
|
|
let unique_id = u32::from_be_bytes(tc.user_data()[0..4].try_into().unwrap());
|
2023-08-15 21:07:15 +02:00
|
|
|
if !self.request_handlers.contains_key(&target_id) {
|
2023-07-06 00:49:18 +02:00
|
|
|
self.psb
|
2024-01-31 12:09:55 +01:00
|
|
|
.common
|
2023-07-06 00:49:18 +02:00
|
|
|
.verification_handler
|
|
|
|
.borrow_mut()
|
|
|
|
.start_failure(
|
2024-01-31 01:32:03 +01:00
|
|
|
ecss_tc_and_token.token,
|
2023-07-06 00:49:18 +02:00
|
|
|
FailParams::new(Some(&time_stamp), &hk_err::UNKNOWN_TARGET_ID, None),
|
|
|
|
)
|
|
|
|
.expect("Sending start failure TM failed");
|
|
|
|
return Err(PusPacketHandlingError::NotEnoughAppData(format!(
|
2023-08-15 08:49:54 +02:00
|
|
|
"Unknown target ID {target_id}"
|
2023-07-06 00:49:18 +02:00
|
|
|
)));
|
|
|
|
}
|
2023-08-15 08:49:54 +02:00
|
|
|
let send_request = |target: TargetIdWithApid, request: HkRequest| {
|
2023-08-15 21:07:15 +02:00
|
|
|
let sender = self.request_handlers.get(&target).unwrap();
|
2023-07-06 00:49:18 +02:00
|
|
|
sender
|
2024-01-31 01:32:03 +01:00
|
|
|
.send(RequestWithToken::new(
|
|
|
|
target,
|
|
|
|
Request::Hk(request),
|
|
|
|
ecss_tc_and_token.token,
|
|
|
|
))
|
2023-07-06 00:49:18 +02:00
|
|
|
.unwrap_or_else(|_| panic!("Sending HK request {request:?} failed"));
|
|
|
|
};
|
|
|
|
if subservice == hk::Subservice::TcEnableHkGeneration as u8 {
|
2023-08-15 21:07:15 +02:00
|
|
|
send_request(target_id, HkRequest::Enable(unique_id));
|
2023-07-06 00:49:18 +02:00
|
|
|
} else if subservice == hk::Subservice::TcDisableHkGeneration as u8 {
|
2023-08-15 21:07:15 +02:00
|
|
|
send_request(target_id, HkRequest::Disable(unique_id));
|
2023-07-06 00:49:18 +02:00
|
|
|
} else if subservice == hk::Subservice::TcGenerateOneShotHk as u8 {
|
2023-08-15 21:07:15 +02:00
|
|
|
send_request(target_id, HkRequest::OneShot(unique_id));
|
2023-07-06 00:49:18 +02:00
|
|
|
} else if subservice == hk::Subservice::TcModifyHkCollectionInterval as u8 {
|
|
|
|
if user_data.len() < 12 {
|
|
|
|
self.psb
|
2024-01-31 12:09:55 +01:00
|
|
|
.common
|
2023-07-06 00:49:18 +02:00
|
|
|
.verification_handler
|
|
|
|
.borrow_mut()
|
|
|
|
.start_failure(
|
2024-01-31 01:32:03 +01:00
|
|
|
ecss_tc_and_token.token,
|
2023-07-06 00:49:18 +02:00
|
|
|
FailParams::new(
|
|
|
|
Some(&time_stamp),
|
|
|
|
&hk_err::COLLECTION_INTERVAL_MISSING,
|
|
|
|
None,
|
|
|
|
),
|
|
|
|
)
|
|
|
|
.expect("Sending start failure TM failed");
|
|
|
|
return Err(PusPacketHandlingError::NotEnoughAppData(
|
|
|
|
"Collection interval missing".into(),
|
|
|
|
));
|
|
|
|
}
|
|
|
|
send_request(
|
2023-08-15 08:49:54 +02:00
|
|
|
target_id,
|
2023-07-06 00:49:18 +02:00
|
|
|
HkRequest::ModifyCollectionInterval(
|
2023-08-15 08:49:54 +02:00
|
|
|
unique_id,
|
2023-07-06 00:49:18 +02:00
|
|
|
CollectionIntervalFactor::from_be_bytes(user_data[8..12].try_into().unwrap()),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
Ok(PusPacketHandlerResult::RequestHandled)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-07 18:10:47 +01:00
|
|
|
pub struct Pus3Wrapper<TcInMemConverter: EcssTcInMemConverter> {
|
|
|
|
pub(crate) pus_3_handler: PusService3HkHandler<TcInMemConverter>,
|
2023-07-06 00:49:18 +02:00
|
|
|
}
|
|
|
|
|
2024-02-07 18:10:47 +01:00
|
|
|
impl<TcInMemConverter: EcssTcInMemConverter> Pus3Wrapper<TcInMemConverter> {
|
2023-07-06 00:49:18 +02:00
|
|
|
pub fn handle_next_packet(&mut self) -> bool {
|
2024-01-30 01:18:48 +01:00
|
|
|
match self.pus_3_handler.handle_one_tc() {
|
2023-07-06 00:49:18 +02:00
|
|
|
Ok(result) => match result {
|
|
|
|
PusPacketHandlerResult::RequestHandled => {}
|
|
|
|
PusPacketHandlerResult::RequestHandledPartialSuccess(e) => {
|
|
|
|
warn!("PUS 3 partial packet handling success: {e:?}")
|
|
|
|
}
|
|
|
|
PusPacketHandlerResult::CustomSubservice(invalid, _) => {
|
|
|
|
warn!("PUS 3 invalid subservice {invalid}");
|
|
|
|
}
|
|
|
|
PusPacketHandlerResult::SubserviceNotImplemented(subservice, _) => {
|
|
|
|
warn!("PUS 3 subservice {subservice} not implemented");
|
|
|
|
}
|
|
|
|
PusPacketHandlerResult::Empty => {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
Err(error) => {
|
|
|
|
error!("PUS packet handling error: {error:?}")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|