use derive_new::new; use num_enum::TryFromPrimitive; use satrs::{ action::ActionRequest, pus::action::{ActionReplyVariant, PusActionReply}, request::{GenericMessage, MessageMetadata}, }; use std::sync::{atomic::AtomicBool, mpsc, Arc}; use ops_sat_rs::config::{action_err::INVALID_ACTION_ID, STOP_FILE_NAME}; use crate::requests::CompositeRequest; #[derive(Debug, Clone, Copy, TryFromPrimitive)] #[repr(u32)] pub enum ActionId { StopExperiment = 1, } #[derive(new)] pub struct ExperimentController { pub composite_request_rx: mpsc::Receiver>, pub action_reply_tx: mpsc::Sender>, pub stop_signal: Arc, } impl ExperimentController { pub fn perform_operation(&mut self) { match self.composite_request_rx.try_recv() { Ok(msg) => match msg.message { CompositeRequest::Hk(_) => todo!(), CompositeRequest::Action(action_req) => { self.handle_action_request(msg.requestor_info, action_req); } }, Err(_) => todo!(), } 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"); } } } } pub fn check_stop_file(&self) { if std::path::Path::new(STOP_FILE_NAME).exists() { log::warn!( "Detected stop file name at {}. Initiating experiment shutdown", STOP_FILE_NAME ); self.stop_signal .store(true, std::sync::atomic::Ordering::Relaxed); } } }