143 lines
5.0 KiB
Rust
143 lines
5.0 KiB
Rust
use num_enum::TryFromPrimitive;
|
|
use satrs::{
|
|
action::ActionRequest,
|
|
pus::action::{ActionReplyPus, ActionReplyVariant},
|
|
request::{GenericMessage, MessageMetadata},
|
|
};
|
|
use std::{
|
|
env::temp_dir,
|
|
path::{Path, PathBuf},
|
|
sync::{atomic::AtomicBool, mpsc, Arc},
|
|
};
|
|
|
|
use ops_sat_rs::config::{action_err::INVALID_ACTION_ID, HOME_PATH, STOP_FILE_NAME, TO_GROUND_FOLDER_EXPERIMENT};
|
|
use crate::logger::LOGFILE_PATH;
|
|
|
|
use crate::requests::CompositeRequest;
|
|
|
|
#[derive(Debug, Clone, Copy, TryFromPrimitive)]
|
|
#[repr(u32)]
|
|
pub enum ActionId {
|
|
StopExperiment = 1,
|
|
DownlinkLogfile = 2,
|
|
}
|
|
|
|
pub struct ExperimentController {
|
|
pub composite_request_rx: mpsc::Receiver<GenericMessage<CompositeRequest>>,
|
|
pub action_reply_tx: mpsc::Sender<GenericMessage<ActionReplyPus>>,
|
|
pub stop_signal: Arc<AtomicBool>,
|
|
home_path_stop_file: PathBuf,
|
|
tmp_path_stop_file: PathBuf,
|
|
}
|
|
|
|
impl ExperimentController {
|
|
pub fn new(
|
|
composite_request_rx: mpsc::Receiver<GenericMessage<CompositeRequest>>,
|
|
action_reply_tx: mpsc::Sender<GenericMessage<ActionReplyPus>>,
|
|
stop_signal: Arc<AtomicBool>,
|
|
) -> Self {
|
|
let mut home_path_stop_file = PathBuf::new();
|
|
home_path_stop_file.push(HOME_PATH.as_path());
|
|
home_path_stop_file.push(STOP_FILE_NAME);
|
|
let mut tmp_path_stop_file = temp_dir();
|
|
tmp_path_stop_file.push(STOP_FILE_NAME);
|
|
Self {
|
|
composite_request_rx,
|
|
action_reply_tx,
|
|
stop_signal,
|
|
home_path_stop_file,
|
|
tmp_path_stop_file,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ExperimentController {
|
|
pub fn perform_operation(&mut self) {
|
|
match self.composite_request_rx.try_recv() {
|
|
Ok(msg) => match msg.message {
|
|
CompositeRequest::Hk(_) => {
|
|
log::warn!("hk request handling unimplemented")
|
|
}
|
|
CompositeRequest::Action(action_req) => {
|
|
self.handle_action_request(msg.requestor_info, action_req);
|
|
}
|
|
},
|
|
Err(e) => {
|
|
if e != mpsc::TryRecvError::Empty {
|
|
log::error!("composite request rx error: {:?}", e);
|
|
}
|
|
}
|
|
}
|
|
self.check_stop_file();
|
|
}
|
|
|
|
pub fn handle_action_request(&mut self, requestor: MessageMetadata, action_req: ActionRequest) {
|
|
let action_id = ActionId::try_from(action_req.action_id);
|
|
if action_id.is_err() {
|
|
let result = self.action_reply_tx.send(GenericMessage::new_action_reply(
|
|
requestor,
|
|
action_req.action_id,
|
|
ActionReplyVariant::CompletionFailed {
|
|
error_code: INVALID_ACTION_ID,
|
|
params: None,
|
|
},
|
|
));
|
|
if result.is_err() {
|
|
log::error!("sending action reply failed");
|
|
}
|
|
return;
|
|
}
|
|
let action_id = action_id.unwrap();
|
|
match action_id {
|
|
ActionId::StopExperiment => {
|
|
self.stop_signal
|
|
.store(true, std::sync::atomic::Ordering::Relaxed);
|
|
let result = self.action_reply_tx.send(GenericMessage::new_action_reply(
|
|
requestor,
|
|
action_req.action_id,
|
|
ActionReplyVariant::Completed,
|
|
));
|
|
if result.is_err() {
|
|
log::error!("Sending action reply failed");
|
|
}
|
|
}
|
|
ActionId::DownlinkLogfile => {
|
|
if let Some(logfile_path) = LOGFILE_PATH.get() {
|
|
if let Ok(logfile_path) = <PathBuf as Clone>::clone(logfile_path).into_os_string().into_string() {
|
|
let ground_folder_path = TO_GROUND_FOLDER_EXPERIMENT.to_string();
|
|
if std::fs::copy(logfile_path.as_str(), ground_folder_path.as_str()).is_err() {
|
|
log::error!("Copying logfile into downlink path failed")
|
|
}
|
|
}
|
|
} else {
|
|
log::error!("Downlink path emtpy")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn check_stop_file(&self) {
|
|
let check_at_path = |path: &Path| {
|
|
if path.exists() {
|
|
log::warn!(
|
|
"Detected stop file name at {:?}. Initiating experiment shutdown",
|
|
path
|
|
);
|
|
// By default, clear the stop file.
|
|
let result = std::fs::remove_file(path);
|
|
if result.is_err() {
|
|
log::error!(
|
|
"failed to remove stop file at {:?}: {}",
|
|
path,
|
|
result.unwrap_err()
|
|
);
|
|
}
|
|
self.stop_signal
|
|
.store(true, std::sync::atomic::Ordering::Relaxed);
|
|
}
|
|
};
|
|
check_at_path(self.tmp_path_stop_file.as_path());
|
|
check_at_path(self.home_path_stop_file.as_path());
|
|
}
|
|
}
|