Merge pull request 'update nexosim to v1' (#289) from update-nexosim into main
Reviewed-on: #289
This commit was merged in pull request #289.
This commit is contained in:
@@ -15,7 +15,7 @@ strum = { version = "0.28", features = ["derive"] }
|
||||
num_enum = "0.7"
|
||||
humantime = "2"
|
||||
tai-time = { version = "0.3", features = ["serde"] }
|
||||
nexosim = { version = "0.3.1" }
|
||||
nexosim = "1"
|
||||
|
||||
satrs = { path = "../../satrs" }
|
||||
types = { path = "../types" }
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
use std::{f32::consts::PI, sync::mpsc};
|
||||
use std::f32::consts::PI;
|
||||
|
||||
use nexosim::model::{Context, Model};
|
||||
use nexosim::{
|
||||
model::{Context, Model},
|
||||
ports::Output,
|
||||
};
|
||||
use satrs_minisim::{acs::mgm, SimReply};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use types::pcdu::SwitchStateBinary;
|
||||
|
||||
use crate::time::current_millis;
|
||||
@@ -19,22 +23,24 @@ const PHASE_Z: f32 = 0.2;
|
||||
/// An ideal sensor would sample the magnetic field at a high fixed rate. This might not be
|
||||
/// possible for a general purpose OS, but self self-sampling at a relatively high rate (20-40 ms)
|
||||
/// might still be possible and is probably sufficient for many OBSW needs.
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct MgmModel {
|
||||
pub id: mgm::Id,
|
||||
pub switch_state: SwitchStateBinary,
|
||||
pub external_mag_field: Option<mgm::SensorValuesMicroTesla>,
|
||||
pub spi_fault: mgm::SpiFault,
|
||||
pub reply_sender: mpsc::Sender<SimReply>,
|
||||
id: mgm::Id,
|
||||
switch_state: SwitchStateBinary,
|
||||
external_mag_field: Option<mgm::SensorValuesMicroTesla>,
|
||||
spi_fault: mgm::SpiFault,
|
||||
pub reply: Output<SimReply>,
|
||||
}
|
||||
|
||||
#[Model]
|
||||
impl MgmModel {
|
||||
pub fn new(mgm_id: mgm::Id, reply_sender: mpsc::Sender<SimReply>) -> Self {
|
||||
pub fn new(mgm_id: mgm::Id) -> Self {
|
||||
Self {
|
||||
id: mgm_id,
|
||||
switch_state: SwitchStateBinary::Off,
|
||||
external_mag_field: None,
|
||||
spi_fault: mgm::SpiFault::default(),
|
||||
reply_sender,
|
||||
reply: Output::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,18 +56,16 @@ impl MgmModel {
|
||||
self.spi_fault = fault;
|
||||
}
|
||||
|
||||
pub async fn send_sensor_values(&mut self, _: (), scheduler: &mut Context<Self>) {
|
||||
pub async fn send_sensor_values(&mut self, _: (), cx: &Context<Self>) {
|
||||
let reply = SimReply::Mgm {
|
||||
id: self.id,
|
||||
reply: mgm::Reply::new(
|
||||
self.switch_state,
|
||||
self.calculate_current_mgm_tuple(current_millis(scheduler.time())),
|
||||
self.calculate_current_mgm_tuple(current_millis(cx.time())),
|
||||
self.spi_fault.mode,
|
||||
),
|
||||
};
|
||||
self.reply_sender
|
||||
.send(reply)
|
||||
.expect("sending MGM sensor values failed");
|
||||
self.reply.send(reply).await;
|
||||
}
|
||||
|
||||
// Devices like magnetorquers generate a strong magnetic field which overrides the default
|
||||
@@ -94,8 +98,6 @@ impl MgmModel {
|
||||
}
|
||||
}
|
||||
|
||||
impl Model for MgmModel {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::time::Duration;
|
||||
|
||||
@@ -1,45 +1,48 @@
|
||||
use nexosim::{
|
||||
model::{Context, Model},
|
||||
model::{schedulable, Context, Model},
|
||||
ports::Output,
|
||||
};
|
||||
use satrs_minisim::{
|
||||
acs::{mgm, mgt},
|
||||
SimReply,
|
||||
};
|
||||
use std::{sync::mpsc, time::Duration};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::time::Duration;
|
||||
use types::pcdu::SwitchStateBinary;
|
||||
|
||||
/// Simple magnetorquer simulation model.
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct MgtModel {
|
||||
switch_state: SwitchStateBinary,
|
||||
torquing: bool,
|
||||
torque_dipole: mgt::Dipole,
|
||||
pub gen_magnetic_field: Output<mgm::SensorValuesMicroTesla>,
|
||||
pub clear_magnetic_field: Output<()>,
|
||||
reply_sender: mpsc::Sender<SimReply>,
|
||||
pub reply: Output<SimReply>,
|
||||
}
|
||||
|
||||
#[Model]
|
||||
impl MgtModel {
|
||||
pub fn new(reply_sender: mpsc::Sender<SimReply>) -> Self {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
switch_state: SwitchStateBinary::Off,
|
||||
torquing: false,
|
||||
torque_dipole: mgt::Dipole::default(),
|
||||
gen_magnetic_field: Output::new(),
|
||||
clear_magnetic_field: Output::new(),
|
||||
reply_sender,
|
||||
reply: Output::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn apply_torque(
|
||||
&mut self,
|
||||
duration_and_dipole: (Duration, mgt::Dipole),
|
||||
cx: &mut Context<Self>,
|
||||
cx: &Context<Self>,
|
||||
) {
|
||||
self.torque_dipole = duration_and_dipole.1;
|
||||
self.torquing = true;
|
||||
if cx
|
||||
.schedule_event(duration_and_dipole.0, Self::clear_torque, ())
|
||||
.schedule_event(duration_and_dipole.0, schedulable!(Self::clear_torque), ())
|
||||
.is_err()
|
||||
{
|
||||
log::warn!("torque clearing can only be set for a future time.");
|
||||
@@ -47,7 +50,8 @@ impl MgtModel {
|
||||
self.generate_magnetic_field(()).await;
|
||||
}
|
||||
|
||||
pub async fn clear_torque(&mut self, _: ()) {
|
||||
#[nexosim(schedulable)]
|
||||
async fn clear_torque(&mut self) {
|
||||
self.torque_dipole = mgt::Dipole::default();
|
||||
self.torquing = false;
|
||||
self.clear_magnetic_field.send(()).await;
|
||||
@@ -57,25 +61,30 @@ impl MgtModel {
|
||||
self.switch_state = switch_state;
|
||||
match switch_state {
|
||||
SwitchStateBinary::On => self.generate_magnetic_field(()).await,
|
||||
SwitchStateBinary::Off => self.clear_torque(()).await,
|
||||
SwitchStateBinary::Off => self.clear_torque().await,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn request_housekeeping_data(&mut self, _: (), cx: &mut Context<Self>) {
|
||||
pub async fn request_housekeeping_data(&mut self, _: (), cx: &Context<Self>) {
|
||||
if self.switch_state != SwitchStateBinary::On {
|
||||
return;
|
||||
}
|
||||
cx.schedule_event(Duration::from_millis(15), Self::send_housekeeping_data, ())
|
||||
.expect("requesting housekeeping data failed")
|
||||
cx.schedule_event(
|
||||
Duration::from_millis(15),
|
||||
schedulable!(Self::send_housekeeping_data),
|
||||
(),
|
||||
)
|
||||
.expect("requesting housekeeping data failed")
|
||||
}
|
||||
|
||||
pub fn send_housekeeping_data(&mut self) {
|
||||
self.reply_sender
|
||||
#[nexosim(schedulable)]
|
||||
async fn send_housekeeping_data(&mut self) {
|
||||
self.reply
|
||||
.send(SimReply::from(mgt::Reply::Hk(mgt::HkSet {
|
||||
dipole: self.torque_dipole,
|
||||
torquing: self.torquing,
|
||||
})))
|
||||
.unwrap();
|
||||
.await;
|
||||
}
|
||||
|
||||
fn calc_magnetic_field(&self, _: mgt::Dipole) -> mgm::SensorValuesMicroTesla {
|
||||
@@ -96,8 +105,6 @@ impl MgtModel {
|
||||
}
|
||||
}
|
||||
|
||||
impl Model for MgtModel {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::time::Duration;
|
||||
|
||||
@@ -4,14 +4,16 @@ use std::{
|
||||
};
|
||||
|
||||
use nexosim::{
|
||||
simulation::{Address, Mailbox, SimInit, Simulation},
|
||||
time::{Clock, MonotonicTime, SystemClock},
|
||||
ports::{event_queue, EventQueueReader, EventSinkReader, EventSource, SinkState},
|
||||
simulation::{EventId, ExecutionError, Mailbox, SimInit, Simulation},
|
||||
time::{Clock, Deadline, MonotonicTime, SystemClock},
|
||||
};
|
||||
use satrs_minisim::{
|
||||
acs::{mgm, mgt},
|
||||
eps::PcduRequest,
|
||||
SimCtrlReply, SimCtrlRequest, SimReply, SimRequest, SimRequestWithTime,
|
||||
};
|
||||
use types::pcdu::{SwitchId, SwitchStateBinary};
|
||||
|
||||
use crate::{
|
||||
acs::{mgm::MgmModel, mgt::MgtModel},
|
||||
@@ -31,11 +33,32 @@ pub enum ThreadingModel {
|
||||
Single = 1,
|
||||
}
|
||||
|
||||
struct ModelAddresses {
|
||||
mgm_0: Address<MgmModel>,
|
||||
mgm_1: Address<MgmModel>,
|
||||
pcdu: Address<PcduModel>,
|
||||
mgt: Address<MgtModel>,
|
||||
struct MgmInputs {
|
||||
send_sensor_values: EventId<()>,
|
||||
set_spi_fault: EventId<mgm::SpiFault>,
|
||||
}
|
||||
|
||||
impl MgmInputs {
|
||||
fn register(sim_init: &mut SimInit, mailbox: &Mailbox<MgmModel>) -> Self {
|
||||
Self {
|
||||
send_sensor_values: EventSource::new()
|
||||
.connect(MgmModel::send_sensor_values, mailbox)
|
||||
.register(sim_init),
|
||||
set_spi_fault: EventSource::new()
|
||||
.connect(MgmModel::set_spi_fault, mailbox)
|
||||
.register(sim_init),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Model inputs which are driven by simulation requests.
|
||||
struct ModelInputs {
|
||||
mgm_0: MgmInputs,
|
||||
mgm_1: MgmInputs,
|
||||
pcdu_request_switch_info: EventId<()>,
|
||||
pcdu_switch_device: EventId<(SwitchId, SwitchStateBinary)>,
|
||||
mgt_apply_torque: EventId<(Duration, mgt::Dipole)>,
|
||||
mgt_request_hk: EventId<()>,
|
||||
}
|
||||
|
||||
// The simulation controller processes requests and drives the simulation.
|
||||
@@ -43,8 +66,9 @@ pub struct SimController {
|
||||
sys_clock: SystemClock,
|
||||
request_receiver: mpsc::Receiver<SimRequestWithTime>,
|
||||
reply_sender: mpsc::Sender<SimReply>,
|
||||
pub simulation: Simulation,
|
||||
addrs: ModelAddresses,
|
||||
simulation: Simulation,
|
||||
inputs: ModelInputs,
|
||||
model_replies: EventQueueReader<SimReply>,
|
||||
}
|
||||
|
||||
impl SimController {
|
||||
@@ -54,50 +78,66 @@ impl SimController {
|
||||
reply_sender: mpsc::Sender<SimReply>,
|
||||
request_receiver: mpsc::Receiver<SimRequestWithTime>,
|
||||
) -> Self {
|
||||
let mgm_0_model = MgmModel::new(mgm::Id::Mgm0, reply_sender.clone());
|
||||
let mgm_1_model = MgmModel::new(mgm::Id::Mgm1, reply_sender.clone());
|
||||
let mut pcdu_model = PcduModel::new(reply_sender.clone());
|
||||
let mut mgt_model = MgtModel::new(reply_sender.clone());
|
||||
let mut mgm_0_model = MgmModel::new(mgm::Id::Mgm0);
|
||||
let mut mgm_1_model = MgmModel::new(mgm::Id::Mgm1);
|
||||
let mut pcdu_model = PcduModel::new();
|
||||
let mut mgt_model = MgtModel::new();
|
||||
|
||||
let mgm_0_mailbox = Mailbox::new();
|
||||
let mgm_1_mailbox = Mailbox::new();
|
||||
let pcdu_mailbox = Mailbox::new();
|
||||
let mgt_mailbox = Mailbox::new();
|
||||
let addrs = ModelAddresses {
|
||||
mgm_0: mgm_0_mailbox.address(),
|
||||
mgm_1: mgm_1_mailbox.address(),
|
||||
pcdu: pcdu_mailbox.address(),
|
||||
mgt: mgt_mailbox.address(),
|
||||
};
|
||||
|
||||
pcdu_model
|
||||
.mgm_0_switch
|
||||
.connect(MgmModel::switch_device, &addrs.mgm_0);
|
||||
.connect(MgmModel::switch_device, &mgm_0_mailbox);
|
||||
pcdu_model
|
||||
.mgm_1_switch
|
||||
.connect(MgmModel::switch_device, &addrs.mgm_1);
|
||||
.connect(MgmModel::switch_device, &mgm_1_mailbox);
|
||||
pcdu_model
|
||||
.mgt_switch
|
||||
.connect(MgtModel::switch_device, &addrs.mgt);
|
||||
.connect(MgtModel::switch_device, &mgt_mailbox);
|
||||
mgt_model
|
||||
.gen_magnetic_field
|
||||
.connect(MgmModel::apply_external_magnetic_field, &addrs.mgm_0);
|
||||
.connect(MgmModel::apply_external_magnetic_field, &mgm_0_mailbox);
|
||||
mgt_model
|
||||
.gen_magnetic_field
|
||||
.connect(MgmModel::apply_external_magnetic_field, &addrs.mgm_1);
|
||||
.connect(MgmModel::apply_external_magnetic_field, &mgm_1_mailbox);
|
||||
mgt_model
|
||||
.clear_magnetic_field
|
||||
.connect(MgmModel::clear_external_magnetic_field, &addrs.mgm_0);
|
||||
.connect(MgmModel::clear_external_magnetic_field, &mgm_0_mailbox);
|
||||
mgt_model
|
||||
.clear_magnetic_field
|
||||
.connect(MgmModel::clear_external_magnetic_field, &addrs.mgm_1);
|
||||
.connect(MgmModel::clear_external_magnetic_field, &mgm_1_mailbox);
|
||||
|
||||
let sim_init = if threading_model == ThreadingModel::Single {
|
||||
let (reply_sink, model_replies) = event_queue(SinkState::Enabled);
|
||||
mgm_0_model.reply.connect_sink(reply_sink.clone());
|
||||
mgm_1_model.reply.connect_sink(reply_sink.clone());
|
||||
pcdu_model.reply.connect_sink(reply_sink.clone());
|
||||
mgt_model.reply.connect_sink(reply_sink);
|
||||
|
||||
let mut sim_init = if threading_model == ThreadingModel::Single {
|
||||
SimInit::with_num_threads(1)
|
||||
} else {
|
||||
SimInit::new()
|
||||
};
|
||||
let (simulation, _scheduler) = sim_init
|
||||
let inputs = ModelInputs {
|
||||
mgm_0: MgmInputs::register(&mut sim_init, &mgm_0_mailbox),
|
||||
mgm_1: MgmInputs::register(&mut sim_init, &mgm_1_mailbox),
|
||||
pcdu_request_switch_info: EventSource::new()
|
||||
.connect(PcduModel::request_switch_info, &pcdu_mailbox)
|
||||
.register(&mut sim_init),
|
||||
pcdu_switch_device: EventSource::new()
|
||||
.connect(PcduModel::switch_device, &pcdu_mailbox)
|
||||
.register(&mut sim_init),
|
||||
mgt_apply_torque: EventSource::new()
|
||||
.connect(MgtModel::apply_torque, &mgt_mailbox)
|
||||
.register(&mut sim_init),
|
||||
mgt_request_hk: EventSource::new()
|
||||
.connect(MgtModel::request_housekeeping_data, &mgt_mailbox)
|
||||
.register(&mut sim_init),
|
||||
};
|
||||
let simulation = sim_init
|
||||
.add_model(mgm_0_model, mgm_0_mailbox, "MGM 0 model")
|
||||
.add_model(mgm_1_model, mgm_1_mailbox, "MGM 1 model")
|
||||
.add_model(pcdu_model, pcdu_mailbox, "PCDU model")
|
||||
@@ -109,7 +149,29 @@ impl SimController {
|
||||
request_receiver,
|
||||
reply_sender,
|
||||
simulation,
|
||||
addrs,
|
||||
inputs,
|
||||
model_replies,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn step(&mut self) -> Result<(), ExecutionError> {
|
||||
self.simulation.step()?;
|
||||
self.forward_model_replies();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn step_until(&mut self, deadline: impl Deadline) -> Result<(), ExecutionError> {
|
||||
self.simulation.step_until(deadline)?;
|
||||
self.forward_model_replies();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn forward_model_replies(&mut self) {
|
||||
while let Some(reply) = self.model_replies.try_read() {
|
||||
self.reply_sender
|
||||
.send(reply)
|
||||
.expect("sending model reply failed");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,9 +184,7 @@ impl SimController {
|
||||
t += Duration::from_millis(udp_polling_interval_ms);
|
||||
let _synch_status = self.sys_clock.synchronize(t);
|
||||
self.handle_sim_requests(t_old);
|
||||
self.simulation
|
||||
.step_until(t)
|
||||
.expect("simulation step failed");
|
||||
self.step_until(t).expect("simulation step failed");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,6 +210,7 @@ impl SimController {
|
||||
},
|
||||
}
|
||||
}
|
||||
self.forward_model_replies();
|
||||
}
|
||||
|
||||
fn handle_ctrl_request(&mut self, sim_ctrl_request: SimCtrlRequest) {
|
||||
@@ -167,9 +228,9 @@ impl SimController {
|
||||
}
|
||||
|
||||
fn handle_mgm_request(&mut self, mgm_id: mgm::Id, mgm_request: mgm::Request) {
|
||||
let addr = match mgm_id {
|
||||
mgm::Id::Mgm0 => &self.addrs.mgm_0,
|
||||
mgm::Id::Mgm1 => &self.addrs.mgm_1,
|
||||
let inputs = match mgm_id {
|
||||
mgm::Id::Mgm0 => &self.inputs.mgm_0,
|
||||
mgm::Id::Mgm1 => &self.inputs.mgm_1,
|
||||
};
|
||||
if MGM_REQ_WIRETAPPING {
|
||||
log::info!("received {mgm_id:?} request: {mgm_request:?}");
|
||||
@@ -177,13 +238,13 @@ impl SimController {
|
||||
match mgm_request {
|
||||
mgm::Request::RequestSensorData => {
|
||||
self.simulation
|
||||
.process_event(MgmModel::send_sensor_values, (), addr)
|
||||
.process_event(&inputs.send_sensor_values, ())
|
||||
.expect("event execution error for mgm");
|
||||
}
|
||||
mgm::Request::SetSpiFault(fault_mode) => {
|
||||
log::info!("{mgm_id:?}: setting SPI fault mode to {fault_mode:?}");
|
||||
self.simulation
|
||||
.process_event(MgmModel::set_spi_fault, fault_mode, addr)
|
||||
.process_event(&inputs.set_spi_fault, fault_mode)
|
||||
.expect("event execution error for mgm");
|
||||
}
|
||||
}
|
||||
@@ -196,12 +257,12 @@ impl SimController {
|
||||
match pcdu_request {
|
||||
PcduRequest::RequestSwitchInfo => {
|
||||
self.simulation
|
||||
.process_event(PcduModel::request_switch_info, (), &self.addrs.pcdu)
|
||||
.process_event(&self.inputs.pcdu_request_switch_info, ())
|
||||
.unwrap();
|
||||
}
|
||||
PcduRequest::SwitchDevice { switch, state } => {
|
||||
self.simulation
|
||||
.process_event(PcduModel::switch_device, (switch, state), &self.addrs.pcdu)
|
||||
.process_event(&self.inputs.pcdu_switch_device, (switch, state))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
@@ -214,11 +275,11 @@ impl SimController {
|
||||
match mgt_request {
|
||||
mgt::Request::ApplyTorque { duration, dipole } => self
|
||||
.simulation
|
||||
.process_event(MgtModel::apply_torque, (duration, dipole), &self.addrs.mgt)
|
||||
.process_event(&self.inputs.mgt_apply_torque, (duration, dipole))
|
||||
.unwrap(),
|
||||
mgt::Request::RequestHk => self
|
||||
.simulation
|
||||
.process_event(MgtModel::request_housekeeping_data, (), &self.addrs.mgt)
|
||||
.process_event(&self.inputs.mgt_request_hk, ())
|
||||
.unwrap(),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,45 +1,49 @@
|
||||
use std::{sync::mpsc, time::Duration};
|
||||
use std::time::Duration;
|
||||
|
||||
use nexosim::{
|
||||
model::{Context, Model},
|
||||
model::{schedulable, Context, Model},
|
||||
ports::Output,
|
||||
};
|
||||
use satrs_minisim::{eps::PcduReply, SimReply};
|
||||
use types::pcdu::{SwitchId, SwitchMapBinaryWrapper, SwitchStateBinary};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use types::pcdu::{SwitchId, SwitchMapBinary, SwitchMapBinaryWrapper, SwitchStateBinary};
|
||||
|
||||
pub const SWITCH_INFO_DELAY_MS: u64 = 10;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct PcduModel {
|
||||
pub switcher_map: SwitchMapBinaryWrapper,
|
||||
switcher_map: SwitchMapBinary,
|
||||
pub mgm_0_switch: Output<SwitchStateBinary>,
|
||||
pub mgm_1_switch: Output<SwitchStateBinary>,
|
||||
pub mgt_switch: Output<SwitchStateBinary>,
|
||||
pub reply_sender: mpsc::Sender<SimReply>,
|
||||
pub reply: Output<SimReply>,
|
||||
}
|
||||
|
||||
#[Model]
|
||||
impl PcduModel {
|
||||
pub fn new(reply_sender: mpsc::Sender<SimReply>) -> Self {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
switcher_map: Default::default(),
|
||||
switcher_map: SwitchMapBinaryWrapper::default().0,
|
||||
mgm_0_switch: Output::new(),
|
||||
mgm_1_switch: Output::new(),
|
||||
mgt_switch: Output::new(),
|
||||
reply_sender,
|
||||
reply: Output::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn request_switch_info(&mut self, _: (), cx: &mut Context<Self>) {
|
||||
pub async fn request_switch_info(&mut self, _: (), cx: &Context<Self>) {
|
||||
cx.schedule_event(
|
||||
Duration::from_millis(SWITCH_INFO_DELAY_MS),
|
||||
Self::send_switch_info,
|
||||
schedulable!(Self::send_switch_info),
|
||||
(),
|
||||
)
|
||||
.expect("requesting switch info failed");
|
||||
}
|
||||
|
||||
pub fn send_switch_info(&mut self) {
|
||||
let reply = SimReply::from(PcduReply::SwitchInfo(self.switcher_map.0.clone()));
|
||||
self.reply_sender.send(reply).unwrap();
|
||||
#[nexosim(schedulable)]
|
||||
async fn send_switch_info(&mut self) {
|
||||
let reply = SimReply::from(PcduReply::SwitchInfo(self.switcher_map.clone()));
|
||||
self.reply.send(reply).await;
|
||||
}
|
||||
|
||||
pub async fn switch_device(&mut self, switch_and_target_state: (SwitchId, SwitchStateBinary)) {
|
||||
@@ -50,7 +54,6 @@ impl PcduModel {
|
||||
);
|
||||
let val = self
|
||||
.switcher_map
|
||||
.0
|
||||
.get_mut(&switch_and_target_state.0)
|
||||
.unwrap_or_else(|| panic!("switch {:?} not found", switch_and_target_state.0));
|
||||
*val = switch_and_target_state.1;
|
||||
@@ -68,8 +71,6 @@ impl PcduModel {
|
||||
}
|
||||
}
|
||||
|
||||
impl Model for PcduModel {}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) mod tests {
|
||||
use super::*;
|
||||
|
||||
@@ -36,8 +36,6 @@ impl SimTestbench {
|
||||
delegate! {
|
||||
to self.sim_controller {
|
||||
pub fn handle_sim_requests(&mut self, old_timestamp: MonotonicTime);
|
||||
}
|
||||
to self.sim_controller.simulation {
|
||||
pub fn step(&mut self) -> Result<(), ExecutionError>;
|
||||
pub fn step_until(&mut self, duration: impl Deadline) -> Result<(), ExecutionError>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user