unittests are working well
Some checks failed
Rust/sat-rs/pipeline/pr-main There was a failure building this commit
Some checks failed
Rust/sat-rs/pipeline/pr-main There was a failure building this commit
This commit is contained in:
parent
c9f71125a3
commit
3dd6ad6155
@ -4,7 +4,7 @@ use asynchronix::{
|
|||||||
model::{Model, Output},
|
model::{Model, Output},
|
||||||
time::Scheduler,
|
time::Scheduler,
|
||||||
};
|
};
|
||||||
use satrs::power::SwitchState;
|
use satrs::power::{SwitchState, SwitchStateBinary};
|
||||||
use satrs_minisim::{
|
use satrs_minisim::{
|
||||||
acs::{MgmSensorValues, MgtDipole, MGT_GEN_MAGNETIC_FIELD},
|
acs::{MgmSensorValues, MgtDipole, MGT_GEN_MAGNETIC_FIELD},
|
||||||
SimDevice, SimReply,
|
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
|
/// a general purpose OS, but self self-sampling at a relatively high rate (20-40 ms) might
|
||||||
/// stil lbe possible.
|
/// stil lbe possible.
|
||||||
pub struct MagnetometerModel {
|
pub struct MagnetometerModel {
|
||||||
pub switch_state: SwitchState,
|
pub switch_state: SwitchStateBinary,
|
||||||
pub periodicity: Duration,
|
pub periodicity: Duration,
|
||||||
pub external_mag_field: Option<MgmSensorValues>,
|
pub external_mag_field: Option<MgmSensorValues>,
|
||||||
pub reply_sender: mpsc::Sender<SimReply>,
|
pub reply_sender: mpsc::Sender<SimReply>,
|
||||||
@ -41,14 +41,14 @@ pub struct MagnetometerModel {
|
|||||||
impl MagnetometerModel {
|
impl MagnetometerModel {
|
||||||
pub fn new(periodicity: Duration, reply_sender: mpsc::Sender<SimReply>) -> Self {
|
pub fn new(periodicity: Duration, reply_sender: mpsc::Sender<SimReply>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
switch_state: SwitchState::Off,
|
switch_state: SwitchStateBinary::Off,
|
||||||
periodicity,
|
periodicity,
|
||||||
external_mag_field: None,
|
external_mag_field: None,
|
||||||
reply_sender,
|
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;
|
self.switch_state = switch_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ impl MagnetometerModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn calculate_current_mgm_tuple(&mut self, time_ms: u64) -> MgmSensorValues {
|
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 {
|
if let Some(ext_field) = self.external_mag_field {
|
||||||
return ext_field;
|
return ext_field;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
use std::{sync::mpsc, time::Duration};
|
use std::{
|
||||||
|
sync::mpsc,
|
||||||
|
time::{Duration, SystemTime},
|
||||||
|
};
|
||||||
|
|
||||||
use asynchronix::{
|
use asynchronix::{
|
||||||
simulation::{Address, Simulation},
|
simulation::{Address, Mailbox, SimInit, Simulation},
|
||||||
time::{Clock, MonotonicTime, SystemClock},
|
time::{Clock, MonotonicTime, SystemClock},
|
||||||
};
|
};
|
||||||
use satrs_minisim::{acs::MgmRequest, SimRequest};
|
use satrs_minisim::{acs::MgmRequest, SimRequest};
|
||||||
@ -21,6 +24,22 @@ pub struct SimController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SimController {
|
impl SimController {
|
||||||
|
pub fn new(
|
||||||
|
sys_clock: SystemClock,
|
||||||
|
request_receiver: mpsc::Receiver<SimRequest>,
|
||||||
|
simulation: Simulation,
|
||||||
|
mgm_addr: Address<MagnetometerModel>,
|
||||||
|
pcdu_addr: Address<PcduModel>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
sys_clock,
|
||||||
|
request_receiver,
|
||||||
|
simulation,
|
||||||
|
mgm_addr,
|
||||||
|
pcdu_addr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn run(&mut self, start_time: MonotonicTime) {
|
pub fn run(&mut self, start_time: MonotonicTime) {
|
||||||
let mut t = start_time + Duration::from_millis(1);
|
let mut t = start_time + Duration::from_millis(1);
|
||||||
self.sys_clock.synchronize(t);
|
self.sys_clock.synchronize(t);
|
||||||
@ -39,10 +58,10 @@ impl SimController {
|
|||||||
pub fn handle_sim_requests(&mut self) {
|
pub fn handle_sim_requests(&mut self) {
|
||||||
loop {
|
loop {
|
||||||
match self.request_receiver.try_recv() {
|
match self.request_receiver.try_recv() {
|
||||||
Ok(request) => match request.device {
|
Ok(request) => match request.device() {
|
||||||
satrs_minisim::SimDevice::Mgm => self.handle_mgm_request(&request.request),
|
satrs_minisim::SimDevice::Mgm => self.handle_mgm_request(request.request()),
|
||||||
satrs_minisim::SimDevice::Mgt => self.handle_mgt_request(&request.request),
|
satrs_minisim::SimDevice::Mgt => self.handle_mgt_request(request.request()),
|
||||||
satrs_minisim::SimDevice::Pcdu => self.handle_pcdu_request(&request.request),
|
satrs_minisim::SimDevice::Pcdu => self.handle_pcdu_request(request.request()),
|
||||||
},
|
},
|
||||||
Err(e) => match e {
|
Err(e) => match e {
|
||||||
mpsc::TryRecvError::Empty => break,
|
mpsc::TryRecvError::Empty => break,
|
||||||
@ -83,6 +102,7 @@ impl SimController {
|
|||||||
let pcdu_request = pcdu_request.unwrap();
|
let pcdu_request = pcdu_request.unwrap();
|
||||||
match pcdu_request {
|
match pcdu_request {
|
||||||
PcduRequest::RequestSwitchInfo => todo!(),
|
PcduRequest::RequestSwitchInfo => todo!(),
|
||||||
|
PcduRequest::SwitchDevice => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,19 @@
|
|||||||
use asynchronix::model::{Model, Output};
|
use std::{sync::mpsc, time::Duration};
|
||||||
use satrs::power::{SwitchState, SwitchStateBinary};
|
|
||||||
|
use asynchronix::{
|
||||||
|
model::{Model, Output},
|
||||||
|
time::Scheduler,
|
||||||
|
};
|
||||||
|
use satrs::power::SwitchStateBinary;
|
||||||
|
use satrs_minisim::{SimDevice, SimReply};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize)]
|
pub const SWITCH_INFO_DELAY_MS: u64 = 10;
|
||||||
pub struct PcduTuple {}
|
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Serialize)]
|
||||||
|
pub struct SwitchInfo(Vec<SwitchStateBinary>);
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub enum PcduSwitches {
|
pub enum PcduSwitches {
|
||||||
Mgm = 0,
|
Mgm = 0,
|
||||||
Mgt = 1,
|
Mgt = 1,
|
||||||
@ -12,17 +21,45 @@ pub enum PcduSwitches {
|
|||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
|
||||||
pub enum PcduRequest {
|
pub enum PcduRequest {
|
||||||
|
SwitchDevice,
|
||||||
RequestSwitchInfo,
|
RequestSwitchInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PcduModel {
|
pub struct PcduModel {
|
||||||
pub switcher_list: Output<Vec<SwitchStateBinary>>,
|
pub current_switch_info: Vec<SwitchStateBinary>,
|
||||||
pub mgm_switch: Output<SwitchState>,
|
pub mgm_switch: Output<SwitchStateBinary>,
|
||||||
pub mgt_switch: Output<SwitchState>,
|
pub mgt_switch: Output<SwitchStateBinary>,
|
||||||
|
pub reply_sender: mpsc::Sender<SimReply>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PcduModel {
|
impl PcduModel {
|
||||||
pub async fn switch_device(&mut self, switch: PcduSwitches, switch_state: SwitchState) {
|
pub fn new(reply_sender: mpsc::Sender<SimReply>) -> 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<Self>) {
|
||||||
|
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 {
|
match switch {
|
||||||
PcduSwitches::Mgm => {
|
PcduSwitches::Mgm => {
|
||||||
self.mgm_switch.send(switch_state).await;
|
self.mgm_switch.send(switch_state).await;
|
||||||
|
@ -9,8 +9,25 @@ pub enum SimDevice {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct SimRequest {
|
pub struct SimRequest {
|
||||||
pub device: SimDevice,
|
device: SimDevice,
|
||||||
pub request: String,
|
request: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SimRequest {
|
||||||
|
pub fn new<T: Serialize>(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)]
|
#[derive(Serialize, Deserialize)]
|
||||||
@ -19,6 +36,19 @@ pub struct SimReply {
|
|||||||
pub reply: String,
|
pub reply: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SimReply {
|
||||||
|
pub fn new<T: Serialize>(device: SimDevice, reply: T) -> Self {
|
||||||
|
Self {
|
||||||
|
device,
|
||||||
|
reply: serde_json::to_string(&reply).unwrap(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reply(&self) -> &String {
|
||||||
|
&self.reply
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub mod acs {
|
pub mod acs {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
@ -2,6 +2,8 @@ use acs::MagnetometerModel;
|
|||||||
use asynchronix::simulation::{Mailbox, SimInit};
|
use asynchronix::simulation::{Mailbox, SimInit};
|
||||||
use asynchronix::time::{MonotonicTime, SystemClock};
|
use asynchronix::time::{MonotonicTime, SystemClock};
|
||||||
use controller::SimController;
|
use controller::SimController;
|
||||||
|
use eps::PcduModel;
|
||||||
|
use satrs_minisim::{SimReply, SimRequest};
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::{Duration, SystemTime};
|
use std::time::{Duration, SystemTime};
|
||||||
@ -13,35 +15,57 @@ mod eps;
|
|||||||
mod time;
|
mod time;
|
||||||
mod udp;
|
mod udp;
|
||||||
|
|
||||||
fn main() {
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
let shared_socket_addr = SharedSocketAddr::default();
|
pub enum ThreadingModel {
|
||||||
let (request_sender, request_receiver) = mpsc::channel();
|
Default = 0,
|
||||||
let (reply_sender, reply_receiver) = mpsc::channel();
|
Single = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_sim_controller(
|
||||||
|
threading_model: ThreadingModel,
|
||||||
|
start_time: MonotonicTime,
|
||||||
|
reply_sender: mpsc::Sender<SimReply>,
|
||||||
|
request_receiver: mpsc::Receiver<SimRequest>,
|
||||||
|
) -> SimController {
|
||||||
// Instantiate models and their mailboxes.
|
// 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_mailbox = Mailbox::new();
|
||||||
let mgm_addr = mgm_mailbox.address();
|
let mgm_addr = mgm_mailbox.address();
|
||||||
let pcdu_mailbox = Mailbox::new();
|
let pcdu_mailbox = Mailbox::new();
|
||||||
let pcdu_addr = pcdu_mailbox.address();
|
let pcdu_addr = pcdu_mailbox.address();
|
||||||
|
|
||||||
// Instantiate the simulator
|
let mut pcdu_model = PcduModel::new(reply_sender.clone());
|
||||||
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 sim_controller = SimController {
|
pcdu_model
|
||||||
sys_clock,
|
.mgm_switch
|
||||||
request_receiver,
|
.connect(MagnetometerModel::switch_device, &mgm_addr);
|
||||||
simulation,
|
|
||||||
mgm_addr,
|
// Instantiate the simulator
|
||||||
pcdu_addr,
|
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.
|
// This thread schedules the simulator.
|
||||||
let sim_thread = thread::spawn(move || {
|
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();
|
let mut server = UdpTcServer::new(request_sender, shared_socket_addr.clone()).unwrap();
|
||||||
@ -69,6 +93,8 @@ mod tests {
|
|||||||
SimDevice, SimReply, SimRequest,
|
SimDevice, SimReply, SimRequest,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::eps::PcduRequest;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
struct SimTestbench {
|
struct SimTestbench {
|
||||||
@ -81,29 +107,12 @@ mod tests {
|
|||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
let (request_sender, request_receiver) = mpsc::channel();
|
let (request_sender, request_receiver) = mpsc::channel();
|
||||||
let (reply_sender, reply_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 t0 = MonotonicTime::EPOCH;
|
||||||
let sys_clock = SystemClock::from_system_time(t0, SystemTime::now());
|
let sim_ctrl =
|
||||||
let simulation = SimInit::with_num_threads(1)
|
create_sim_controller(ThreadingModel::Single, t0, reply_sender, request_receiver);
|
||||||
.add_model(mgm_sim, mgm_mailbox)
|
|
||||||
.init(t0);
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
sim_controller: SimController {
|
sim_controller: sim_ctrl,
|
||||||
sys_clock,
|
|
||||||
request_receiver,
|
|
||||||
simulation,
|
|
||||||
mgm_addr,
|
|
||||||
pcdu_addr,
|
|
||||||
},
|
|
||||||
reply_receiver,
|
reply_receiver,
|
||||||
request_sender,
|
request_sender,
|
||||||
}
|
}
|
||||||
@ -140,10 +149,7 @@ mod tests {
|
|||||||
fn test_basic_mgm_request() {
|
fn test_basic_mgm_request() {
|
||||||
let mut sim_testbench = SimTestbench::new();
|
let mut sim_testbench = SimTestbench::new();
|
||||||
let mgm_request = MgmRequest::RequestSensorData;
|
let mgm_request = MgmRequest::RequestSensorData;
|
||||||
let request = SimRequest {
|
let request = SimRequest::new(SimDevice::Mgm, mgm_request);
|
||||||
device: SimDevice::Mgm,
|
|
||||||
request: serde_json::to_string(&mgm_request).unwrap(),
|
|
||||||
};
|
|
||||||
sim_testbench
|
sim_testbench
|
||||||
.send_request(request)
|
.send_request(request)
|
||||||
.expect("sending MGM request failed");
|
.expect("sending MGM request failed");
|
||||||
@ -161,5 +167,9 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,15 @@ impl TryFrom<SwitchState> for SwitchStateBinary {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: Into<u64>> From<T> for SwitchStateBinary {
|
||||||
|
fn from(value: T) -> Self {
|
||||||
|
if value.into() == 0 {
|
||||||
|
return SwitchStateBinary::Off;
|
||||||
|
}
|
||||||
|
SwitchStateBinary::On
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<SwitchStateBinary> for SwitchState {
|
impl From<SwitchStateBinary> for SwitchState {
|
||||||
fn from(value: SwitchStateBinary) -> Self {
|
fn from(value: SwitchStateBinary) -> Self {
|
||||||
match value {
|
match value {
|
||||||
|
Loading…
Reference in New Issue
Block a user