Skip to main content

radar_server/plugins/
source_data.rs

1use std::time::{Duration, SystemTime, UNIX_EPOCH};
2use bytemuck::bytes_of;
3use num_complex::Complex;
4use hdf5_metno::{File};
5use crate::plugins::radar_packet::*;
6
7/// Organizational struct for DummyData.
8#[allow(unused)]
9pub struct DummyData;
10
11/// A simple struct to sore info to calculate da/dt
12#[derive(Copy, Clone)]
13struct AntennaState {
14    last_a: Option<f64>,
15    last_t: Option<f64>,
16    last_da_dt: Option<f64>,
17    dt: f64,
18}
19impl AntennaState {
20    pub fn new() -> AntennaState {
21        AntennaState {
22            last_a: None,
23            last_t: None,
24            last_da_dt: None,
25            dt: 0.0,
26        }
27    }
28    /// In the data we were provided, the angle time and antenna values are all over the place,
29    ///  this makes sense of them. returning a da/dt value and setting dt to be used for the delay
30    pub fn update(&mut self, angle: f64, time: f64) -> f64 {
31        match self.last_a {
32            None => {
33                self.last_a = Some(angle);
34                self.last_t = Some(time);
35                self.dt = 0.0;
36                4.2915
37            }
38            Some(prev_a) if angle == prev_a => {
39                if self.last_da_dt.is_some() {
40                    self.dt = 0.0;
41                    self.last_da_dt.unwrap()
42                }else {
43                    self.dt = 0.0;
44                    4.2915
45                }
46            }
47            Some(prev_a) => {
48                if let Some(prev_t) = self.last_t{
49                    let dt = time - prev_t;
50                    if dt > 0.0 {
51                        let rate = (angle - prev_a) / dt;
52                        self.last_t = Some(time);
53                        self.last_a = Some(angle);
54                        self.last_da_dt = Some(rate);
55                        self.dt = dt;
56                        rate + 4.2915 / 2f64
57                    } else {
58                        self.last_a = None;
59                        self.last_t = None;
60                        self.dt = 0.0;
61                        4.2915
62                    }
63                } else {
64                    self.last_a = None;
65                    self.last_t = None;
66                    self.dt = 0.0;
67                    4.2915
68                }
69            }
70        }
71    }
72}
73
74/// A struct to contain demo data info.
75pub struct DemoData{
76    pub manual_delay: bool,
77    pub delay:u16,
78    idx:usize,
79    data_offset:u8,
80    antenna_state: [AntennaState; 4],
81    angle_ds: Vec<f64>,
82    antenna_ds: Vec<f64>,
83    real_ds:Vec<Vec<i32>>,
84    imag_ds:Vec<Vec<i32>>,
85    enable_ds:Vec<f64>,
86    time_ds:Vec<f64>,
87    pub state:State,
88}
89
90impl DemoData{
91    /// Initialize DemoData
92    pub fn new() -> DemoData{
93        let file = File::open("demo/20260519_dabob_first.hdf5").expect("Failed to open demo file!");
94        let angle_ds:Vec<f64> = file.dataset("angle").expect("Failed to open angle dataset")
95            .read_1d::<f64>().expect("Failed to read angle dataset").to_vec();
96        let antenna_ds:Vec<f64> = file.dataset("antenna").expect("Failed to open antenna data")
97            .read_1d::<f64>().expect("Failed to read antenna dataset").to_vec();
98        let real_ds:Vec<Vec<i32>> = file.dataset("data_r").expect("Failed to open real data")
99            .read_2d::<i32>().expect("failed to read real dataset")
100            .rows().into_iter().map(|row| row.to_vec()).collect();
101        let imag_ds:Vec<Vec<i32>> = file.dataset("data_i").expect("Failed to open imaginary data")
102            .read_2d::<i32>().expect("failed to read imaginary dataset")
103            .rows().into_iter().map(|row| row.to_vec()).collect();
104        let enable_ds:Vec<f64> = file.dataset("enable").expect("Failed to open enable data")
105            .read_1d::<f64>().expect("failed to read enable data").to_vec();
106        let time_ds :Vec<f64>= file.dataset("time").expect("Failed to open time data")
107            .read_1d::<f64>().expect("failed to read time data").to_vec();
108        if angle_ds.is_empty() || antenna_ds.is_empty() || real_ds.is_empty() || imag_ds.is_empty() || enable_ds.is_empty() || time_ds.is_empty() {
109            panic!("Invalid data length!");
110        }
111        DemoData{
112            manual_delay: false,
113            delay: 0,
114            idx:0,
115            data_offset:0,
116            antenna_state: [AntennaState::new(),AntennaState::new(),AntennaState::new(),AntennaState::new()],
117            angle_ds,
118            antenna_ds,
119            real_ds,
120            imag_ds,
121            enable_ds,
122            time_ds,
123            state: State{
124                angle: 0.0,
125                antenna: 0,
126                enabled: true,
127                samples: 1024u64,
128                rotation_rate: 0.0,
129            }
130        }
131    }
132    /// This would be used to demonstrate changing settings if the archiver were correctly forwarding them. ToDo: have the archiver forward settings
133    pub fn update_state(&mut self, conf: SettingData){
134        if conf.playback_delay.is_some() {
135            let pd = conf.playback_delay.unwrap();
136            if pd != 0 {
137                println!("Setting manual delay to {pd}");
138                self.manual_delay = true;
139                self.delay = pd;
140            } else {
141                println!("Setting manual delay to auto");
142                self.manual_delay = false;
143            }
144        }
145    }
146}
147
148pub trait ComplexDataSource {
149    fn source_complex_data(&mut self) -> ComPacket;
150    #[allow(unused)]
151    fn get_state(&self) -> State{
152        State{
153            angle: 0.0,
154            antenna: 0,
155            enabled: true,
156            samples:1024u64,
157            rotation_rate: 0.0,
158        }
159    }
160}
161
162/// This is a relic of before we were given data for DemoData
163impl ComplexDataSource for DummyData {
164    fn source_complex_data(&mut self) -> ComPacket {
165        let mut byte_vec: Vec<u8> = Vec::with_capacity(1024);
166        print!("nums:[");
167        for _ in 0..1024 {
168            let c = Complex::new(fastrand::i32(i32::MIN..=i32::MAX),fastrand::i32(i32::MIN..=i32::MAX));
169            print!("({}, {}), ",c.re,c.im);
170            byte_vec.extend_from_slice(bytes_of(&c));
171        }
172        print!("]\n");
173
174        ComPacket {
175            identity: Identity{
176                net_type: NetType::Server,
177                version: VERSION.to_string(),
178            },
179            timestamp: SystemTime::now().duration_since(UNIX_EPOCH)
180                .expect("Time before EPOCH not supported")
181                .as_secs_f64(),
182            state: self.get_state(),
183            data:byte_vec,
184        }
185    }
186}
187
188/// Pull data out of the data loaded into memory from the demo data file. Prepair it for send.
189impl ComplexDataSource for DemoData {
190    fn source_complex_data(&mut self) -> ComPacket {
191        let identity = Identity{
192            net_type: NetType::Server,
193            version: VERSION.to_string(),
194        };
195        let timestamp = self.time_ds[self.idx];
196        let angle = self.angle_ds[self.idx];
197        let antenna = self.antenna_ds[self.idx] as usize;
198
199        self.state.rotation_rate = self.antenna_state[antenna].update(angle, timestamp);
200        self.state.angle = angle;
201        self.state.antenna = antenna as u8;
202        self.state.enabled = self.enable_ds[self.idx] as u8 != 0;
203        self.state.samples = 1024u64;
204        let mut data: Vec<u8> = Vec::with_capacity(1024);
205
206        for i in (self.data_offset as usize * 1024)..1024 + (self.data_offset as usize * 1024) {
207            //let noise = 25;
208            let c =
209                Complex::new(self.real_ds[self.idx][i], self.imag_ds[self.idx][i]);
210                    //+ Complex::new(fastrand::i32(-noise..=noise), fastrand::i32(-noise..=noise));
211            data.extend_from_slice(bytes_of(&c));
212        }
213        self.data_offset = (self.data_offset + 1) % 2;
214
215        if !self.manual_delay {self.delay = Duration::from_secs_f64(self.antenna_state[antenna].dt).as_millis() as u16;}
216
217        self.idx = (self.idx + 1) % self.real_ds.len();
218        ComPacket{identity,timestamp,state:self.state,data}
219    }
220}