From 3dd6ad61553a98b4fac738a3f2b6dc535e6ec50b Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 7 Mar 2024 17:11:24 +0100 Subject: [PATCH] unittests are working well --- satrs-minisim/src/acs.rs | 10 ++-- satrs-minisim/src/controller.rs | 32 +++++++++--- satrs-minisim/src/eps.rs | 53 ++++++++++++++++--- satrs-minisim/src/lib.rs | 34 +++++++++++- satrs-minisim/src/main.rs | 92 ++++++++++++++++++--------------- satrs/src/power.rs | 9 ++++ 6 files changed, 168 insertions(+), 62 deletions(-) diff --git a/satrs-minisim/src/acs.rs b/satrs-minisim/src/acs.rs index 45dc7b6..e09a77a 100644 --- a/satrs-minisim/src/acs.rs +++ b/satrs-minisim/src/acs.rs @@ -4,7 +4,7 @@ use asynchronix::{ model::{Model, Output}, time::Scheduler, }; -use satrs::power::SwitchState; +use satrs::power::{SwitchState, SwitchStateBinary}; use satrs_minisim::{ acs::{MgmSensorValues, MgtDipole, MGT_GEN_MAGNETIC_FIELD}, SimDevice, SimReply, @@ -32,7 +32,7 @@ const PHASE_Z: f32 = 0.2; /// a general purpose OS, but self self-sampling at a relatively high rate (20-40 ms) might /// stil lbe possible. pub struct MagnetometerModel { - pub switch_state: SwitchState, + pub switch_state: SwitchStateBinary, pub periodicity: Duration, pub external_mag_field: Option, pub reply_sender: mpsc::Sender, @@ -41,14 +41,14 @@ pub struct MagnetometerModel { impl MagnetometerModel { pub fn new(periodicity: Duration, reply_sender: mpsc::Sender) -> Self { Self { - switch_state: SwitchState::Off, + switch_state: SwitchStateBinary::Off, periodicity, external_mag_field: None, reply_sender, } } - pub async fn switch_device(&mut self, switch_state: SwitchState) { + pub async fn switch_device(&mut self, switch_state: SwitchStateBinary) { self.switch_state = switch_state; } @@ -72,7 +72,7 @@ impl MagnetometerModel { } fn calculate_current_mgm_tuple(&mut self, time_ms: u64) -> MgmSensorValues { - if let SwitchState::On = self.switch_state { + if SwitchStateBinary::On == self.switch_state { if let Some(ext_field) = self.external_mag_field { return ext_field; } diff --git a/satrs-minisim/src/controller.rs b/satrs-minisim/src/controller.rs index 3c1e91a..e21247f 100644 --- a/satrs-minisim/src/controller.rs +++ b/satrs-minisim/src/controller.rs @@ -1,7 +1,10 @@ -use std::{sync::mpsc, time::Duration}; +use std::{ + sync::mpsc, + time::{Duration, SystemTime}, +}; use asynchronix::{ - simulation::{Address, Simulation}, + simulation::{Address, Mailbox, SimInit, Simulation}, time::{Clock, MonotonicTime, SystemClock}, }; use satrs_minisim::{acs::MgmRequest, SimRequest}; @@ -21,6 +24,22 @@ pub struct SimController { } impl SimController { + pub fn new( + sys_clock: SystemClock, + request_receiver: mpsc::Receiver, + simulation: Simulation, + mgm_addr: Address, + pcdu_addr: Address, + ) -> Self { + Self { + sys_clock, + request_receiver, + simulation, + mgm_addr, + pcdu_addr, + } + } + pub fn run(&mut self, start_time: MonotonicTime) { let mut t = start_time + Duration::from_millis(1); self.sys_clock.synchronize(t); @@ -39,10 +58,10 @@ impl SimController { pub fn handle_sim_requests(&mut self) { loop { match self.request_receiver.try_recv() { - Ok(request) => match request.device { - satrs_minisim::SimDevice::Mgm => self.handle_mgm_request(&request.request), - satrs_minisim::SimDevice::Mgt => self.handle_mgt_request(&request.request), - satrs_minisim::SimDevice::Pcdu => self.handle_pcdu_request(&request.request), + Ok(request) => match request.device() { + satrs_minisim::SimDevice::Mgm => self.handle_mgm_request(request.request()), + satrs_minisim::SimDevice::Mgt => self.handle_mgt_request(request.request()), + satrs_minisim::SimDevice::Pcdu => self.handle_pcdu_request(request.request()), }, Err(e) => match e { mpsc::TryRecvError::Empty => break, @@ -83,6 +102,7 @@ impl SimController { let pcdu_request = pcdu_request.unwrap(); match pcdu_request { PcduRequest::RequestSwitchInfo => todo!(), + PcduRequest::SwitchDevice => todo!(), } } diff --git a/satrs-minisim/src/eps.rs b/satrs-minisim/src/eps.rs index aa16afa..544038c 100644 --- a/satrs-minisim/src/eps.rs +++ b/satrs-minisim/src/eps.rs @@ -1,10 +1,19 @@ -use asynchronix::model::{Model, Output}; -use satrs::power::{SwitchState, SwitchStateBinary}; +use std::{sync::mpsc, time::Duration}; + +use asynchronix::{ + model::{Model, Output}, + time::Scheduler, +}; +use satrs::power::SwitchStateBinary; +use satrs_minisim::{SimDevice, SimReply}; use serde::{Deserialize, Serialize}; -#[derive(Debug, Clone, PartialEq, Serialize)] -pub struct PcduTuple {} +pub const SWITCH_INFO_DELAY_MS: u64 = 10; +#[derive(Debug, Clone, PartialEq, Serialize)] +pub struct SwitchInfo(Vec); + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)] pub enum PcduSwitches { Mgm = 0, Mgt = 1, @@ -12,17 +21,45 @@ pub enum PcduSwitches { #[derive(Debug, Copy, Clone, Serialize, Deserialize)] pub enum PcduRequest { + SwitchDevice, RequestSwitchInfo, } pub struct PcduModel { - pub switcher_list: Output>, - pub mgm_switch: Output, - pub mgt_switch: Output, + pub current_switch_info: Vec, + pub mgm_switch: Output, + pub mgt_switch: Output, + pub reply_sender: mpsc::Sender, } impl PcduModel { - pub async fn switch_device(&mut self, switch: PcduSwitches, switch_state: SwitchState) { + pub fn new(reply_sender: mpsc::Sender) -> Self { + Self { + current_switch_info: vec![SwitchStateBinary::Off; 2], + mgm_switch: Output::new(), + mgt_switch: Output::new(), + reply_sender, + } + } + + pub async fn request_switch_info(&mut self, _: (), scheduler: &Scheduler) { + scheduler + .schedule_event( + Duration::from_millis(SWITCH_INFO_DELAY_MS), + Self::send_switch_info, + (), + ) + .expect("requesting switch info failed"); + } + + pub fn send_switch_info(&mut self) { + let switch_info = SwitchInfo(self.current_switch_info.clone()); + let reply = SimReply::new(SimDevice::Pcdu, switch_info); + self.reply_sender.send(reply).unwrap(); + } + + pub async fn switch_device(&mut self, switch: PcduSwitches, switch_state: SwitchStateBinary) { + self.current_switch_info[switch as usize] = switch_state; match switch { PcduSwitches::Mgm => { self.mgm_switch.send(switch_state).await; diff --git a/satrs-minisim/src/lib.rs b/satrs-minisim/src/lib.rs index 8731a31..0723910 100644 --- a/satrs-minisim/src/lib.rs +++ b/satrs-minisim/src/lib.rs @@ -9,8 +9,25 @@ pub enum SimDevice { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct SimRequest { - pub device: SimDevice, - pub request: String, + device: SimDevice, + request: String, +} + +impl SimRequest { + pub fn new(device: SimDevice, reply: T) -> Self { + Self { + device, + request: serde_json::to_string(&reply).unwrap(), + } + } + + pub fn device(&self) -> SimDevice { + self.device + } + + pub fn request(&self) -> &String { + &self.request + } } #[derive(Serialize, Deserialize)] @@ -19,6 +36,19 @@ pub struct SimReply { pub reply: String, } +impl SimReply { + pub fn new(device: SimDevice, reply: T) -> Self { + Self { + device, + reply: serde_json::to_string(&reply).unwrap(), + } + } + + pub fn reply(&self) -> &String { + &self.reply + } +} + pub mod acs { use super::*; diff --git a/satrs-minisim/src/main.rs b/satrs-minisim/src/main.rs index 4c5f1f6..3aa03ec 100644 --- a/satrs-minisim/src/main.rs +++ b/satrs-minisim/src/main.rs @@ -2,6 +2,8 @@ use acs::MagnetometerModel; use asynchronix::simulation::{Mailbox, SimInit}; use asynchronix::time::{MonotonicTime, SystemClock}; use controller::SimController; +use eps::PcduModel; +use satrs_minisim::{SimReply, SimRequest}; use std::sync::mpsc; use std::thread; use std::time::{Duration, SystemTime}; @@ -13,35 +15,57 @@ mod eps; mod time; mod udp; -fn main() { - let shared_socket_addr = SharedSocketAddr::default(); - let (request_sender, request_receiver) = mpsc::channel(); - let (reply_sender, reply_receiver) = mpsc::channel(); +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum ThreadingModel { + Default = 0, + Single = 1, +} +fn create_sim_controller( + threading_model: ThreadingModel, + start_time: MonotonicTime, + reply_sender: mpsc::Sender, + request_receiver: mpsc::Receiver, +) -> SimController { // Instantiate models and their mailboxes. - let mgm_sim = MagnetometerModel::new(Duration::from_millis(50), reply_sender.clone()); + let mgm_model = MagnetometerModel::new(Duration::from_millis(50), reply_sender.clone()); let mgm_mailbox = Mailbox::new(); let mgm_addr = mgm_mailbox.address(); let pcdu_mailbox = Mailbox::new(); let pcdu_addr = pcdu_mailbox.address(); - // Instantiate the simulator - let t0 = MonotonicTime::EPOCH; - let sys_clock = SystemClock::from_system_time(t0, SystemTime::now()); - let simulation = SimInit::new().add_model(mgm_sim, mgm_mailbox).init(t0); + let mut pcdu_model = PcduModel::new(reply_sender.clone()); - let mut sim_controller = SimController { - sys_clock, - request_receiver, - simulation, - mgm_addr, - pcdu_addr, + pcdu_model + .mgm_switch + .connect(MagnetometerModel::switch_device, &mgm_addr); + + // Instantiate the simulator + let sys_clock = SystemClock::from_system_time(start_time, SystemTime::now()); + let sim_init = if threading_model == ThreadingModel::Single { + SimInit::with_num_threads(1) + } else { + SimInit::new() }; + let simulation = sim_init + .add_model(mgm_model, mgm_mailbox) + .add_model(pcdu_model, pcdu_mailbox) + .init(start_time); + SimController::new(sys_clock, request_receiver, simulation, mgm_addr, pcdu_addr) +} + +fn main() { + let shared_socket_addr = SharedSocketAddr::default(); + let (request_sender, request_receiver) = mpsc::channel(); + let (reply_sender, reply_receiver) = mpsc::channel(); + let t0 = MonotonicTime::EPOCH; + let mut sim_ctrl = + create_sim_controller(ThreadingModel::Default, t0, reply_sender, request_receiver); // This thread schedules the simulator. let sim_thread = thread::spawn(move || { - sim_controller.run(t0); + sim_ctrl.run(t0); }); let mut server = UdpTcServer::new(request_sender, shared_socket_addr.clone()).unwrap(); @@ -69,6 +93,8 @@ mod tests { SimDevice, SimReply, SimRequest, }; + use crate::eps::PcduRequest; + use super::*; struct SimTestbench { @@ -81,29 +107,12 @@ mod tests { fn new() -> Self { let (request_sender, request_receiver) = mpsc::channel(); let (reply_sender, reply_receiver) = mpsc::channel(); - // Instantiate models and their mailboxes. - let mgm_sim = MagnetometerModel::new(Duration::from_millis(50), reply_sender.clone()); - - let mgm_mailbox = Mailbox::new(); - let mgm_addr = mgm_mailbox.address(); - let pcdu_mailbox = Mailbox::new(); - let pcdu_addr = pcdu_mailbox.address(); - - // Instantiate the simulator let t0 = MonotonicTime::EPOCH; - let sys_clock = SystemClock::from_system_time(t0, SystemTime::now()); - let simulation = SimInit::with_num_threads(1) - .add_model(mgm_sim, mgm_mailbox) - .init(t0); + let sim_ctrl = + create_sim_controller(ThreadingModel::Single, t0, reply_sender, request_receiver); Self { - sim_controller: SimController { - sys_clock, - request_receiver, - simulation, - mgm_addr, - pcdu_addr, - }, + sim_controller: sim_ctrl, reply_receiver, request_sender, } @@ -140,10 +149,7 @@ mod tests { fn test_basic_mgm_request() { let mut sim_testbench = SimTestbench::new(); let mgm_request = MgmRequest::RequestSensorData; - let request = SimRequest { - device: SimDevice::Mgm, - request: serde_json::to_string(&mgm_request).unwrap(), - }; + let request = SimRequest::new(SimDevice::Mgm, mgm_request); sim_testbench .send_request(request) .expect("sending MGM request failed"); @@ -161,5 +167,9 @@ mod tests { } #[test] - fn test_basic_mgm_request_switched_on() {} + fn test_basic_mgm_request_switched_on() { + let mut sim_testbench = SimTestbench::new(); + let pcdu_request = PcduRequest::RequestSwitchInfo; + let request = SimRequest::new(SimDevice::Pcdu, pcdu_request); + } } diff --git a/satrs/src/power.rs b/satrs/src/power.rs index 7786651..1e1fda1 100644 --- a/satrs/src/power.rs +++ b/satrs/src/power.rs @@ -42,6 +42,15 @@ impl TryFrom for SwitchStateBinary { } } +impl> From for SwitchStateBinary { + fn from(value: T) -> Self { + if value.into() == 0 { + return SwitchStateBinary::Off; + } + SwitchStateBinary::On + } +} + impl From for SwitchState { fn from(value: SwitchStateBinary) -> Self { match value {