need to think about the exchange interface again..
Some checks failed
Rust/sat-rs/pipeline/pr-main There was a failure building this commit

This commit is contained in:
Robin Müller 2024-03-05 18:10:46 +01:00
parent 9569cb76c3
commit b622e83731

View File

@ -1,12 +1,13 @@
use asynchronix::model::{Model, Output}; use asynchronix::model::{Model, Output};
use asynchronix::simulation::{EventSlot, Mailbox, SimInit}; use asynchronix::simulation::{EventSlot, Mailbox, SimInit};
use asynchronix::time::{MonotonicTime, Scheduler}; use asynchronix::time::{MonotonicTime, Scheduler};
use log::warn; use log::{info, warn};
use satrs::power::{SwitchState, SwitchStateBinary}; use satrs::power::{SwitchState, SwitchStateBinary};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::f64::consts::PI; use std::f64::consts::PI;
use std::future::Future; use std::future::Future;
use std::net::UdpSocket; use std::net::{SocketAddr, UdpSocket};
use std::sync::{mpsc, Arc, Mutex};
use std::time::Duration; use std::time::Duration;
use std::{io, thread}; use std::{io, thread};
@ -127,6 +128,11 @@ pub enum PcduSwitches {
Mgt = 1, Mgt = 1,
} }
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
pub enum PcduRequest {
RequestSwitchInfo,
}
pub struct PcduModel { pub struct PcduModel {
pub switcher_list: Output<Vec<SwitchStateBinary>>, pub switcher_list: Output<Vec<SwitchStateBinary>>,
pub mgm_switch: Output<SwitchState>, pub mgm_switch: Output<SwitchState>,
@ -213,29 +219,50 @@ impl MagnetorquerModel {
impl Model for MagnetorquerModel {} impl Model for MagnetorquerModel {}
// A UDP server which exposes all values generated by the simulator. // A UDP server which handles all TC received by a client application.
pub struct UdpServer { pub struct UdpTcServer {
socket: UdpSocket, socket: UdpSocket,
mgm_out: EventSlot<MgmTuple>, last_sender: Arc<Mutex<Option<SocketAddr>>>,
} }
#[derive(Serialize, Deserialize)] // A helper object which sends back all replies to the UDP client.
pub struct ValueRequest { //
device: String, // This helper is scheduled separately to minimize the delay between the requests and replies.
pub struct UdpTmSender {
reply_receiver: mpsc::Receiver<ValueReply>,
last_sender: Arc<Mutex<Option<SocketAddr>>>,
}
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
pub enum SimDevice {
Mgm,
Mgt,
Pcdu,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SimRequest {
device: SimDevice,
request: String,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct ValueReply { pub struct ValueReply {
device: String, device: SimDevice,
reply: String, reply: String,
} }
const MGM_DEV_STR: &str = "mgm"; struct ReplyHandler {
reply_sender: mpsc::Sender<ValueReply>,
}
impl UdpServer { impl UdpTcServer {
pub fn new(mgm_out: EventSlot<MgmTuple>) -> io::Result<Self> { pub fn new(reply_receiver: mpsc::Receiver<ValueReply>) -> io::Result<Self> {
let socket = UdpSocket::bind("0.0.0.0:7303")?; let socket = UdpSocket::bind("0.0.0.0:7303")?;
Ok(Self { socket, mgm_out }) Ok(Self {
socket,
// reply_receiver,
})
} }
pub fn run(&mut self) { pub fn run(&mut self) {
@ -253,28 +280,51 @@ impl UdpServer {
let req_string = std::str::from_utf8(&buffer[..bytes_read]) let req_string = std::str::from_utf8(&buffer[..bytes_read])
.expect("Could not write buffer as string"); .expect("Could not write buffer as string");
println!("Received from {}: {}", src, req_string); println!("Received from {}: {}", src, req_string);
let value_result: serde_json::Result<ValueRequest> = serde_json::from_str(req_string); let sim_req: serde_json::Result<SimRequest> = serde_json::from_str(req_string);
match value_result { if sim_req.is_err() {
Ok(value) => { warn!(
if value.device == MGM_DEV_STR { "received UDP request with invalid format: {}",
let tuple = self.mgm_out.take().expect("expected output"); sim_req.unwrap_err()
let reply = ValueReply { );
device: MGM_DEV_STR.to_string(), continue;
reply: serde_json::to_string(&tuple).unwrap(), }
}; let sim_req = sim_req.unwrap();
let reply_string = match sim_req.device {
serde_json::to_string(&reply).expect("generating reply string failed"); SimDevice::Mgm => {
self.socket self.handle_mgm_request(&src, &sim_req);
.send_to(reply_string.as_bytes(), src)
.expect("could not send data");
}
} }
Err(e) => { SimDevice::Mgt => {}
warn!("received UDP request with invalid format: {e}"); SimDevice::Pcdu => {
self.handle_pcdu_request(&src, &sim_req);
} }
} }
} }
} }
fn handle_mgm_request(&mut self, sender: &SocketAddr, sim_req: &SimRequest) {
/*
let tuple = self.mgm_out.take().expect("expected output");
let reply = ValueReply {
device: sim_req.device,
reply: serde_json::to_string(&tuple).unwrap(),
};
let reply_string = serde_json::to_string(&reply).expect("generating reply string failed");
self.socket
.send_to(reply_string.as_bytes(), sender)
.expect("could not send data");
*/
}
fn handle_pcdu_request(&mut self, sender: &SocketAddr, sim_req: &SimRequest) {
let pcdu_request: serde_json::Result<PcduRequest> = serde_json::from_str(&sim_req.request);
if pcdu_request.is_err() {
warn!(
"received invalid PCDU request: {}",
pcdu_request.unwrap_err()
);
return;
}
}
} }
pub fn current_millis(time: MonotonicTime) -> u64 { pub fn current_millis(time: MonotonicTime) -> u64 {
@ -314,7 +364,7 @@ fn main() {
// This thread manages the simulator UDP server. // This thread manages the simulator UDP server.
let udp_thread = thread::spawn(move || { let udp_thread = thread::spawn(move || {
let mut server = UdpServer::new(output_slot).unwrap(); let mut server = UdpTcServer::new(output_slot).unwrap();
server.run(); server.run();
}); });