diff --git a/satrs-minisim/Cargo.toml b/satrs-minisim/Cargo.toml index c272fee..53910e1 100644 --- a/satrs-minisim/Cargo.toml +++ b/satrs-minisim/Cargo.toml @@ -6,10 +6,15 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -asynchronix = "0.2" serde = { version = "1", features = ["derive"] } serde_json = "1" log = "0.4" +[dependencies.asynchronix] +version = "0.2" +path = "../../asynchronix/asynchronix" +# git = "https://github.com/us-irs/asynchronix.git" +# branch = "clock-not-sendable" + [dependencies.satrs] path = "../satrs" diff --git a/satrs-minisim/src/main.rs b/satrs-minisim/src/main.rs index 88d6b69..ad39ab1 100644 --- a/satrs-minisim/src/main.rs +++ b/satrs-minisim/src/main.rs @@ -1,6 +1,6 @@ use asynchronix::model::{Model, Output}; -use asynchronix::simulation::{EventSlot, Mailbox, SimInit}; -use asynchronix::time::{MonotonicTime, Scheduler}; +use asynchronix::simulation::{EventSlot, Mailbox, SimInit, Simulation}; +use asynchronix::time::{MonotonicTime, Scheduler, SystemClock}; use log::{info, warn}; use satrs::power::{SwitchState, SwitchStateBinary}; use serde::{Deserialize, Serialize}; @@ -8,7 +8,7 @@ use std::f64::consts::PI; use std::future::Future; use std::net::{SocketAddr, UdpSocket}; use std::sync::{mpsc, Arc, Mutex}; -use std::time::Duration; +use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; use std::{io, thread}; // Normally, small magnetometers generate their output as a signed 16 bit raw format or something @@ -219,17 +219,11 @@ impl MagnetorquerModel { impl Model for MagnetorquerModel {} -// A UDP server which handles all TC received by a client application. -pub struct UdpTcServer { - socket: UdpSocket, - last_sender: Arc>>, -} - // A helper object which sends back all replies to the UDP client. // // This helper is scheduled separately to minimize the delay between the requests and replies. pub struct UdpTmSender { - reply_receiver: mpsc::Receiver, + reply_receiver: mpsc::Receiver, last_sender: Arc>>, } @@ -247,21 +241,30 @@ pub struct SimRequest { } #[derive(Serialize, Deserialize)] -pub struct ValueReply { +pub struct SimReply { device: SimDevice, reply: String, } -struct ReplyHandler { - reply_sender: mpsc::Sender, +pub type SharedSocketAddr = Arc>>; + +// A UDP server which handles all TC received by a client application. +pub struct UdpTcServer { + socket: UdpSocket, + request_sender: mpsc::Sender, + last_sender: SharedSocketAddr, } impl UdpTcServer { - pub fn new(reply_receiver: mpsc::Receiver) -> io::Result { + pub fn new( + request_sender: mpsc::Sender, + last_sender: SharedSocketAddr, + ) -> io::Result { let socket = UdpSocket::bind("0.0.0.0:7303")?; Ok(Self { socket, - // reply_receiver, + request_sender, + last_sender, }) } @@ -288,6 +291,9 @@ impl UdpTcServer { ); continue; } + self.request_sender.send(sim_req.unwrap()).unwrap(); + self.last_sender.lock().unwrap().replace(src); + /* let sim_req = sim_req.unwrap(); match sim_req.device { SimDevice::Mgm => { @@ -298,6 +304,7 @@ impl UdpTcServer { self.handle_pcdu_request(&src, &sim_req); } } + */ } } @@ -327,11 +334,23 @@ impl UdpTcServer { } } +// The simulation controller processes requests and drives the simulation. +// TODO: How do we process requests and drive the simulation at the same time? +pub struct SimController { + pub request_receiver: mpsc::Receiver, + pub simulation: Simulation, +} + +impl SimController {} + pub fn current_millis(time: MonotonicTime) -> u64 { (time.as_secs() as u64 * 1000) + (time.subsec_nanos() as u64 / 1_000_000) } fn main() { + let shared_socket_addr = SharedSocketAddr::default(); + let (req_sender, req_receiver) = mpsc::channel(); + // Instantiate models and their mailboxes. let mut mgm_sim = MagnetometerModel::new(Duration::from_millis(50)); @@ -339,24 +358,19 @@ fn main() { let mgm_input_addr = mgm_mailbox.address(); // Keep handles to the main input and output. - let output_slot = mgm_sim.sensor_values.connect_slot().0; + // let output_slot = mgm_sim.sensor_values.connect_slot().0; // let output_slot_2 = mgm_sim.sensor_values.connect_slot().0; - + let t0 = MonotonicTime::EPOCH; + let clock = SystemClock::from_system_time(t0, SystemTime::now()); // Instantiate the simulator - let t0 = MonotonicTime::EPOCH; // arbitrary start time - let mut simu = SimInit::new().add_model(mgm_sim, mgm_mailbox).init(t0); + let mut simu = SimInit::new() + .add_model(mgm_sim, mgm_mailbox) + .init_with_clock(t0, clock); // This thread schedules the simulator. let sim_thread = thread::spawn(move || { // The magnetometer will schedule itself at fixed intervals. simu.send_event(MagnetometerModel::start, (), &mgm_input_addr); - /* - for _ in 0..100 { - simu.step(); - let tuple = output_slot_2.take().expect("expected output"); - println!("output at {:?}: {tuple:?}", simu.time()); - } - */ loop { simu.step(); } @@ -364,7 +378,7 @@ fn main() { // This thread manages the simulator UDP server. let udp_thread = thread::spawn(move || { - let mut server = UdpTcServer::new(output_slot).unwrap(); + let mut server = UdpTcServer::new(req_sender, shared_socket_addr).unwrap(); server.run(); });