Skip to content

Commit fe5c3f5

Browse files
committed
Controller server
1 parent 4046fdd commit fe5c3f5

File tree

13 files changed

+478
-134
lines changed

13 files changed

+478
-134
lines changed

antares/Cargo.lock

Lines changed: 300 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

antares/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ edition = "2021"
77
chrono = "0.4.38"
88
rand = "0.8.5"
99
tokio = { version = "1", features = ["full"] }
10+
hyper = { version = "1", features = ["full"] }
1011
serde = { version = "1", features = ["derive"] }
1112
toml = "0.8.19"
1213
async-trait = "0.1.88"
1314
tokio-tungstenite = "0.26.2"
1415
futures-util = "0.3.31"
1516
futures = "0.3.31"
17+
axum = "0.8.4"

antares/assets/config.toml

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,36 @@
1-
[radar]
1+
[simulation]
2+
emission_interval = 20
3+
controller_bind_addr = "127.0.0.1:18900"
4+
5+
[[simulation.initial_ships]]
6+
initial_position = [-50.0, 50.0]
7+
type = "line"
8+
angle = 0.785
9+
speed = 5.0
10+
11+
[[simulation.initial_ships]]
12+
initial_position = [50.0, -50.0]
13+
type = "circle"
14+
radius = 20.0
15+
speed = 5.0
16+
17+
[[simulation.initial_ships]]
18+
initial_position = [-50.0, -50.0]
19+
type = "random"
20+
max_speed = 20.0
221

3-
[radar.protocol]
4-
host = "0.0.0.0"
5-
num_workers_tci = 1
6-
num_workers_tdi = 1
22+
[[simulation.initial_ships]]
23+
initial_position = [50.0, 50.0]
24+
type = "stationary"
25+
26+
[radar]
27+
bind_addr = "127.0.0.1:18950"
728

829
[radar.detector]
930
range = 100.0
1031
speed = 0.0
1132
angle = 0.0
1233
start_coordinates = [4.0, -72.0]
1334

14-
[simulation]
15-
emission_interval = 20
16-
17-
[simulation.ships]
18-
line = [{ initial_position = [-50.0, 50.0], angle = 0.785, speed = 5.0 }]
19-
circle = [{ initial_position = [50.0, -50.0], radius = 20.0, speed = 5.0 }]
20-
random = [{ initial_position = [-50.0, -50.0], max_speed = 20.0 }]
21-
stationary = [{ initial_position = [50.0, 50.0] }]
35+
[radar.broadcast]
36+
type = "tcp"

antares/src/controller.rs

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,47 @@
33
//! This module contains the Controller struct which is responsible for starting the simulation and radar.
44
//!
55
6-
use super::{Config, Radar, Simulation};
6+
use super::{Config, Radar, ShipConfig, Simulation};
7+
use std::sync::Arc;
78
use tokio::sync::mpsc;
89

910
pub struct Controller {
10-
radar: Radar,
11-
simulation: Simulation,
11+
radar: Arc<Radar>,
12+
simulation: Arc<Simulation>,
1213
}
1314

1415
impl Controller {
1516
pub fn new(config: Config) -> Controller {
1617
Controller {
17-
radar: Radar::new(config.radar),
18-
simulation: Simulation::new(config.simulation),
18+
radar: Arc::new(Radar::new(config.radar)),
19+
simulation: Arc::new(Simulation::new(config.simulation)),
1920
}
2021
}
2122

22-
pub async fn run(self) {
23+
pub async fn run(&self) {
2324
let (wave_sender, wave_receiver) = mpsc::channel(100);
24-
let Controller { radar, simulation } = self;
2525

26-
tokio::spawn(simulation.start(wave_sender));
27-
tokio::spawn(radar.start(wave_receiver));
26+
let simulation = Arc::clone(&self.simulation);
27+
let radar = Arc::clone(&self.radar);
28+
29+
tokio::spawn(async move {
30+
simulation.start(wave_sender).await;
31+
});
32+
33+
tokio::spawn(async move {
34+
radar.start(wave_receiver).await;
35+
});
2836

2937
tokio::signal::ctrl_c()
3038
.await
3139
.expect("failed to listen for Ctrl+C");
3240
}
41+
42+
pub fn reset_simulation(&self) {
43+
self.simulation.reset();
44+
}
45+
46+
pub fn add_ship(&self, ship_data: ShipConfig) {
47+
self.simulation.add_ship(ship_data);
48+
}
3349
}

antares/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ use simulation::{Simulation, SimulationConfig, Wave};
1313

1414
pub use config::Config;
1515
pub use controller::Controller;
16+
pub use simulation::ShipConfig;

antares/src/main.rs

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1+
use antares::ShipConfig;
12
use antares::{Config, Controller};
2-
use std::{env, fs, process};
3+
use axum::{extract::State, routing::post, Json, Router};
4+
use std::{env, fs, net::SocketAddr, process, sync::Arc};
5+
use tokio::task;
36

4-
fn main() {
7+
#[tokio::main]
8+
async fn main() {
59
let args: Vec<String> = env::args().collect();
610

711
if args.len() != 2 {
@@ -19,6 +23,31 @@ fn main() {
1923
process::exit(1);
2024
});
2125

22-
let controller = Controller::new(config);
23-
controller.run();
26+
let controller_bind_addr = config.simulation.controller_bind_addr.clone();
27+
let controller = Arc::new(Controller::new(config));
28+
29+
let controller_clone = Arc::clone(&controller);
30+
task::spawn(async move {
31+
controller_clone.run().await;
32+
});
33+
34+
let app = Router::new()
35+
.route("/simulation/reset", post(reset_simulation))
36+
.route("/simulation/ships", post(add_ship))
37+
.with_state(controller);
38+
39+
let addr: SocketAddr = controller_bind_addr.parse().unwrap();
40+
let listener = tokio::net::TcpListener::bind(&addr).await.unwrap();
41+
println!("🚢 Controller server running on {addr}");
42+
axum::serve(listener, app.into_make_service())
43+
.await
44+
.unwrap();
45+
}
46+
47+
async fn reset_simulation(State(controller): State<Arc<Controller>>) {
48+
controller.reset_simulation();
49+
}
50+
51+
async fn add_ship(State(controller): State<Arc<Controller>>, Json(payload): Json<ShipConfig>) {
52+
controller.add_ship(payload);
2453
}

antares/src/radar/config.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use serde::Deserialize;
44
pub struct RadarConfig {
55
pub detector: DetectorConfig,
66
pub broadcast: BroadcastConfig,
7+
pub bind_addr: String,
78
}
89

910
#[derive(Debug, Deserialize, Clone)]
@@ -17,6 +18,6 @@ pub struct DetectorConfig {
1718
#[derive(Debug, Deserialize)]
1819
#[serde(tag = "type", rename_all = "lowercase")]
1920
pub enum BroadcastConfig {
20-
Tcp { bind_addr: String },
21-
WebSocket { bind_addr: String },
21+
Tcp,
22+
WebSocket,
2223
}

antares/src/radar/radar.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ impl Radar {
1313
Self { config }
1414
}
1515

16-
pub async fn start(self, wave_receiver: mpsc::Receiver<Wave>) {
16+
pub async fn start(&self, wave_receiver: mpsc::Receiver<Wave>) {
1717
let (plot_sender, plot_receiver) = mpsc::channel(100);
1818
let (track_sender, mut track_receiver) = mpsc::channel(100);
1919

@@ -22,9 +22,9 @@ impl Radar {
2222
Tracker::start(plot_receiver, track_sender);
2323

2424
let broadcaster: Arc<dyn Broadcaster> = match &self.config.broadcast {
25-
BroadcastConfig::Tcp { bind_addr } => Arc::new(TcpBroadcaster::new(bind_addr.clone())),
26-
BroadcastConfig::WebSocket { bind_addr } => {
27-
Arc::new(WebSocketBroadcaster::new(bind_addr.clone()))
25+
BroadcastConfig::Tcp => Arc::new(TcpBroadcaster::new(self.config.bind_addr.clone())),
26+
BroadcastConfig::WebSocket => {
27+
Arc::new(WebSocketBroadcaster::new(self.config.bind_addr.clone()))
2828
}
2929
};
3030

antares/src/simulation/config.rs

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,45 @@
1+
use super::{
2+
CircleMovement, LineMovement, MovementStrategy, RandomMovement, Ship, StationaryMovement,
3+
};
14
use serde::Deserialize;
25

36
#[derive(Debug, Deserialize)]
47
pub struct SimulationConfig {
58
pub emission_interval: u64,
6-
pub ships: ShipsConfig,
9+
pub initial_ships: Vec<ShipConfig>,
10+
pub controller_bind_addr: String,
711
}
812

913
#[derive(Debug, Deserialize)]
10-
pub struct ShipsConfig {
11-
pub line: Vec<LineMovementConfig>,
12-
pub circle: Vec<CircleMovementConfig>,
13-
pub random: Vec<RandomMovementConfig>,
14-
pub stationary: Vec<StationaryMovementConfig>,
15-
}
16-
17-
#[derive(Debug, Deserialize)]
18-
pub struct LineMovementConfig {
14+
pub struct ShipConfig {
1915
pub initial_position: (f64, f64),
20-
pub angle: f64,
21-
pub speed: f64,
16+
#[serde(flatten)]
17+
pub movement: MovementType,
2218
}
2319

2420
#[derive(Debug, Deserialize)]
25-
pub struct CircleMovementConfig {
26-
pub initial_position: (f64, f64),
27-
pub radius: f64,
28-
pub speed: f64,
21+
#[serde(tag = "type", rename_all = "lowercase")]
22+
pub enum MovementType {
23+
Line { angle: f64, speed: f64 },
24+
Circle { radius: f64, speed: f64 },
25+
Random { max_speed: f64 },
26+
Stationary,
2927
}
3028

31-
#[derive(Debug, Deserialize)]
32-
pub struct RandomMovementConfig {
33-
pub initial_position: (f64, f64),
34-
pub max_speed: f64,
35-
}
29+
pub fn build_ship_from_config(id: u64, config: ShipConfig, emission_interval: u64) -> Ship {
30+
let movement_strategy: Box<dyn MovementStrategy> = match config.movement {
31+
MovementType::Line { angle, speed } => Box::new(LineMovement::new(angle, speed)),
32+
MovementType::Circle { radius, speed } => {
33+
Box::new(CircleMovement::new(radius, speed, emission_interval))
34+
}
35+
MovementType::Random { max_speed } => Box::new(RandomMovement::new(max_speed)),
36+
MovementType::Stationary => Box::new(StationaryMovement {}),
37+
};
3638

37-
#[derive(Debug, Deserialize)]
38-
pub struct StationaryMovementConfig {
39-
pub initial_position: (f64, f64),
39+
Ship {
40+
id,
41+
position: config.initial_position,
42+
emission_interval,
43+
movement_strategy,
44+
}
4045
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::Wave;
22

33
pub trait Emitter {
4-
fn emit(&mut self) -> Wave;
4+
fn emit(&self) -> Wave;
55
}

0 commit comments

Comments
 (0)