Skip to main content

radar_server/
main.rs

1//! # Radar Server
2//!
3//! The one binary to rule them all for all things related to Professor John Mower's radar system.
4//!
5//! ## Goals:
6//!
7//! ### When running as a Server:
8//! - Source radar data from the radar hardware in such a way that adding support for new radar systems is easy.
9//! - Source simulated radar data from a random function and / or a sample file.
10//! - Send radar data to clients through a ZMQ Publisher Subscriber connection.
11//! - Listen as a ZMQ router, and adjust radar control commands from authorized clients.
12//!
13//! ### When running as an Archiver:
14//! - Subscribe to a Server's published data.
15//! - Archive that data in an HDF5 file.
16//! - Send live data to the appropriate clients as a ZMQ router.
17//! - Listen as a ZMQ router for requests for archived data.
18//! - Respond as a ZMQ router with archived data.
19//! - Listen as a ZMQ router and forward server commands as a dealer.
20//!
21//! ## Current ToDos
22//! - Improve Archiver Performance, the data is copied a few times and I don't like that.
23//! - Fix radar control, decide if the client should ever be allowed to connect to the server, or if all communication should pass through the Archiver
24//! - Acquire hardware/hardware simulation
25//! - Source Real Server data. (Blocked by Acquire hardware/hardware simulation)
26//! - Implement Radar Blanking. (Blocked by Acquire hardware/hardware simulation)
27//! - Implement radar control. security.
28//! - Finalize radar control (PBlocked by Implement radar control security)
29//! - Implement true Server mode. (Blocked by Sourcing Real Server Data and Implement radar control)
30use std::{env, fs, thread};
31use std::collections::HashSet;
32use std::time::{Duration};
33use hdf5_metno::File;
34
35/// The plugins module contains all logic and datastructure submodules
36mod plugins;
37mod consts;
38
39use crate::plugins::radar_packet::*;
40use crate::plugins::publish_data::*;
41use crate::plugins::source_data::*;
42use crate::consts::*;
43
44
45/// Main handles argument parsing and calling the necessary submodules.
46fn main() {
47    //!
48    //! The main function takes the following arguments:\
49    //!     -h, --help      Print this help message and exit\
50    //!     -s, --server    Run in Server mode\
51    //!     -d, --dummy     Run in Dummy Server mode\
52    //!     -a, --archive   Run in Archiver mode\
53    //!
54    //! ## Server Mode
55    //! Sources real radar data and sends it to the DATA_ADDRESS.
56    //!
57    //! ToDo: needs to be implemented
58    //!
59    //! ## Dummy Mode
60    //! Sources simulated radar data and sends it to the DATA_ADDRESS.
61    //!
62    //! ## Archive Mode
63    //! Sources radar packets from the SUBSCRIPTION_ADDRESS, archives each packet and forwards the live data the DATA_ADDRESS.
64    //! Additionally will send archived data to individual clients on request.
65    //!
66    //! ToDo: Sending archived data as well as forwarding live data is not yet implemented
67    let args: Vec<String> = env::args().collect();
68
69    if args.contains(&String::from("--server")) || args.contains(&String::from("-s")) {
70        println!("Server mode is not yet implemented.");
71        todo!();
72    }
73
74    if args.contains(&String::from("--dummy")) || args.contains(&String::from("-d")) {
75        println!("Running Dummy Server mode.");
76        let identity = Identity {
77            net_type: NetType::Server,
78            version: VERSION.to_string(),
79        };
80        let mut demo = DemoData::new();
81        let mut server: Connection = Server::new_broadcast([WORLD_ADDRESS, RADAR_PORT].concat().as_str());
82        let mut settings_channel: Connection = SettingsChannel::new_dealer([ARCHIVER_ADDRESS,CONTROL_PORT].concat().as_str());
83        let mut settings_check;
84        settings_channel.send_settings(
85            "".as_bytes(),
86            SettingsPacket {
87                identity: identity.clone(),
88                controls: SettingType::SettingInfo(SettingInfo::get_server_settings()),
89            });
90        let mut i = 0;
91        while i < 200 {
92            settings_check = settings_channel.check_settings();
93            if settings_check.is_some() {
94                let message = settings_check.unwrap();
95                match serde_json::from_slice::<SettingsPacket>(message[1].as_slice()) {
96                    Ok(p) => match p.controls {
97                        SettingType::SettingData(s) => {
98                            demo.update_state(s);
99                        }
100                        _ => {}
101                    }
102                    _ => {}
103                }
104            }
105            server.broadcast(demo.source_complex_data());
106            thread::sleep(Duration::from_millis(demo.delay as u64));
107            i-=1;
108        }
109    }
110
111    if args.contains(&String::from("--archive")) || args.contains(&String::from("-a")) {
112        let identity = Identity {
113            net_type: NetType::Archiver,
114            version: VERSION.to_string(),
115        };
116        let mut subscription: Connection = Subscriber::new_subscription([RADAR_ADDRESS, RADAR_PORT].concat().as_str());
117        let mut client: Connection = Server::new_broadcast([WORLD_ADDRESS, CLIENT_PORT].concat().as_str());
118        let mut settings_channel: Connection = SettingsChannel::new_router([WORLD_ADDRESS,CONTROL_PORT].concat().as_str());
119        let mut clients = HashSet::new();
120        let mut servers = HashSet::new();
121        let mut settings_check;
122        let mut setting_info = SettingInfo::get_archiver_settings();
123        let mut data_path = dirs::home_dir().expect("Failed to get home directory");
124        data_path.push(DATA_ARCHIVE_DIR);
125        let mut file = File::open([DATA_ARCHIVE_DIR, "radar-data.h5"].concat()).unwrap_or_else(|_| {
126            fs::create_dir_all(data_path.to_str().unwrap()).expect("Failed to create data dir"); // creates the data dir or does nothing
127            File::create([data_path.to_str().unwrap(),"radar-data.h5"].concat()).expect("Couldn't create radar-data.h5 file")
128        });
129
130        let mut idx = 0;
131        loop {
132            settings_check = settings_channel.check_settings();
133            if settings_check.is_some() {
134                let message = settings_check.unwrap();
135                match serde_json::from_slice::<SettingsPacket>(message[1].as_slice()) {
136                    Ok(p) => match p.clone().controls{
137                        SettingType::SettingInfo(s) => if p.identity.net_type == NetType::Server {
138                            setting_info.extend_from_slice(s.as_slice());
139
140                            println!("Adding server {:?} to known servers.", message[0]);
141                            servers.insert(message[0].clone());
142                        }
143                        #[allow(unused)]
144                        SettingType::SettingData(s) => {
145                            for s_id in servers.clone(){
146                                settings_channel.send_settings(s_id.as_slice(),p.clone());
147                                //ToDo: update archiver settings
148                            }
149                        }
150                    }
151                    _ => {
152                        if message[1].len() == 0 {
153                            settings_channel.send_settings(
154                                message[0].as_slice(),
155                                SettingsPacket{
156                                    identity: identity.clone(),
157                                    controls: SettingType::SettingInfo(setting_info.clone()),
158                                });
159                            println!("Adding client {:?} to known clients.", message[0]);
160                            clients.insert(message[0].clone());
161                        }
162                    }
163                }
164                for i in 1..message.len(){
165                    println!("Message: {}", std::str::from_utf8(message[i].as_slice()).unwrap());
166                }
167
168                for c_id in clients.clone() {
169                    settings_channel.send_settings(
170                        c_id.as_slice(),
171                        SettingsPacket{
172                            identity: identity.clone(),
173                            controls: SettingType::SettingInfo(setting_info.clone()),
174                        });
175                }
176            }
177            let receive_packet = subscription.subscribe_check();
178            if receive_packet.is_some() {
179                let p = receive_packet.unwrap();
180                p.to_hdf5(&mut file).expect("Failed to write packet");
181                ComPacket::from_hdf5(idx,&file).expect("Failed to read packet");
182                client.broadcast(p);
183                idx +=1;
184            }
185        }
186    }
187
188    println!("Only one of the following args is required: \n\n\
189    -h, --help\t Print this help message and exit\n\
190    -s, --server\t Run in Server mode\n\
191    -d, --dummy\t Run in Dummy Server mode\n\
192    -a, --archive\t Run in Archiver mode\n\
193    ");
194}