1use crate::prelude::*;
5
6#[cfg(feature="tofcontrol")]
7use tof_control::helper::pa_type::{
8 PATemp,
9 PAReadBias
10};
11
12#[derive(Debug, Copy, Clone, PartialEq)]
14#[cfg_attr(feature="pybindings", pyclass)]
15pub struct PAMoniData {
16 pub board_id : u8,
17 pub temps : [f32;16],
18 pub biases : [f32;16],
19 pub timestamp : u64,
20}
21
22impl PAMoniData {
23
24 pub fn new() -> Self {
25 Self {
26 board_id : 0,
27 temps : [f32::MAX;16],
28 biases : [f32::MAX;16],
29 timestamp : 0,
30 }
31 }
32
33 #[cfg(feature = "tofcontrol")]
34 pub fn add_temps(&mut self, pt : &PATemp ) {
35 self.temps = pt.pa_temps;
36 }
37
38 #[cfg(feature = "tofcontrol")]
39 pub fn add_biases(&mut self, pb : &PAReadBias) {
40 self.biases = pb.read_biases;
41 }
42
43 pub fn get_pid_temps(&mut self, pid_map_a : &RbChPidMapping, pid_map_b : &RbChPidMapping ) -> HashMap<u8, (f32, f32)> {
46 let mut pid_temps = HashMap::<u8, (f32,f32)>::new();
47 let channels_a = pid_map_a.get(&(self.board_id as u8)).expect("There is no RB {self.board_id} in te provided mapping!");
50 let channels_b = pid_map_b.get(&(self.board_id as u8)).expect("There is no board id {self.board_id} in the provided mapping!");
51 for k in 0..16u8 {
52 if channels_a.contains_key(&(k+1) ) {
53 let pid = channels_a.get(&(k+1)).unwrap();
54 if !pid_temps.contains_key(&pid) {
55 pid_temps.insert(*pid, (-273.0, -273.0));
56 }
57 pid_temps.get_mut(&pid).unwrap().0 = self.temps[k as usize];
58 }
59 if channels_b.contains_key(&(k+1)) {
60 let pid = channels_b.get(&(k+1)).unwrap();
61 if !pid_temps.contains_key(&pid) {
62 pid_temps.insert(*pid, (-273.0, -273.0));
63 }
64 pid_temps.get_mut(&pid).unwrap().1 = self.temps[k as usize];
65 }
66 }
67 pid_temps
68 }
69}
70
71#[cfg(feature="pybindings")]
72#[pymethods]
73impl PAMoniData {
74
75 #[getter]
77 fn get_temps(&self) -> [f32;16] {
78 self.temps
79 }
80
81 #[getter]
83 fn get_biases(&self) -> [f32;16] {
84 self.biases
85 }
86
87 #[pyo3(name="get_pid_temps")]
93 fn get_pid_temps_py(&mut self, pid_map_a : RbChPidMapping, pid_map_b : RbChPidMapping) -> HashMap<u8, (f32, f32)> {
94 self.get_pid_temps(&pid_map_a, &pid_map_b)
95 }
96}
97
98impl Default for PAMoniData {
99 fn default() -> Self {
100 Self::new()
101 }
102}
103
104impl fmt::Display for PAMoniData {
105 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
106 write!(f, "<PAMoniData:
107 Board ID : {}
108 **16 Temp values**
109 T1 : {:.2} [\u{00B0}C]
110 T2 : {:.2} [\u{00B0}C]
111 T3 : {:.2} [\u{00B0}C]
112 T4 : {:.2} [\u{00B0}C]
113 T5 : {:.2} [\u{00B0}C]
114 T6 : {:.2} [\u{00B0}C]
115 T7 : {:.2} [\u{00B0}C]
116 T8 : {:.2} [\u{00B0}C]
117 T9 : {:.2} [\u{00B0}C]
118 T10 : {:.2} [\u{00B0}C]
119 T11 : {:.2} [\u{00B0}C]
120 T12 : {:.2} [\u{00B0}C]
121 T13 : {:.2} [\u{00B0}C]
122 T14 : {:.2} [\u{00B0}C]
123 T15 : {:.2} [\u{00B0}C]
124 T16 : {:.2} [\u{00B0}C]
125 **16 Bias voltages**
126 V1 : {:.3} [V]
127 V2 : {:.3} [V]
128 V3 : {:.3} [V]
129 V4 : {:.3} [V]
130 V5 : {:.3} [V]
131 V6 : {:.3} [V]
132 V7 : {:.3} [V]
133 V8 : {:.3} [V]
134 V9 : {:.3} [V]
135 V10 : {:.3} [V]
136 V11 : {:.3} [V]
137 V12 : {:.3} [V]
138 V13 : {:.3} [V]
139 V14 : {:.3} [V]
140 V15 : {:.3} [V]
141 V16 : {:.3} [V]>",
142 self.board_id,
143 if self.temps[0] != f32::MAX {self.temps[0 ].to_string()} else {String::from("f32::MAX (ERR)")},
144 if self.temps[1] != f32::MAX {self.temps[1 ].to_string()} else {String::from("f32::MAX (ERR)")},
145 if self.temps[2] != f32::MAX {self.temps[2 ].to_string()} else {String::from("f32::MAX (ERR)")},
146 if self.temps[3] != f32::MAX {self.temps[3 ].to_string()} else {String::from("f32::MAX (ERR)")},
147 if self.temps[4] != f32::MAX {self.temps[4 ].to_string()} else {String::from("f32::MAX (ERR)")},
148 if self.temps[5] != f32::MAX {self.temps[5 ].to_string()} else {String::from("f32::MAX (ERR)")},
149 if self.temps[6] != f32::MAX {self.temps[6 ].to_string()} else {String::from("f32::MAX (ERR)")},
150 if self.temps[7] != f32::MAX {self.temps[7 ].to_string()} else {String::from("f32::MAX (ERR)")},
151 if self.temps[8] != f32::MAX {self.temps[8 ].to_string()} else {String::from("f32::MAX (ERR)")},
152 if self.temps[9] != f32::MAX {self.temps[9 ].to_string()} else {String::from("f32::MAX (ERR)")},
153 if self.temps[10] != f32::MAX {self.temps[10].to_string()} else {String::from("f32::MAX (ERR)")},
154 if self.temps[11] != f32::MAX {self.temps[11].to_string()} else {String::from("f32::MAX (ERR)")},
155 if self.temps[12] != f32::MAX {self.temps[12].to_string()} else {String::from("f32::MAX (ERR)")},
156 if self.temps[13] != f32::MAX {self.temps[13].to_string()} else {String::from("f32::MAX (ERR)")},
157 if self.temps[14] != f32::MAX {self.temps[14].to_string()} else {String::from("f32::MAX (ERR)")},
158 if self.temps[15] != f32::MAX {self.temps[15].to_string()} else {String::from("f32::MAX (ERR)")},
159 self.biases[0],
160 self.biases[1],
161 self.biases[2],
162 self.biases[3],
163 self.biases[4],
164 self.biases[5],
165 self.biases[6],
166 self.biases[7],
167 self.biases[8],
168 self.biases[9],
169 self.biases[10],
170 self.biases[11],
171 self.biases[12],
172 self.biases[13],
173 self.biases[14],
174 self.biases[15])
175 }
176}
177
178impl TofPackable for PAMoniData {
179 const TOF_PACKET_TYPE : TofPacketType = TofPacketType::PAMoniData;
180}
181
182impl Serialization for PAMoniData {
183
184 const HEAD : u16 = 0xAAAA;
185 const TAIL : u16 = 0x5555;
186 const SIZE : usize = 4 + 1 + (4*16*2);
191
192 fn to_bytestream(&self) -> Vec<u8> {
193 let mut stream = Vec::<u8>::with_capacity(Self::SIZE);
194 stream.extend_from_slice(&Self::HEAD.to_le_bytes());
195 stream.extend_from_slice(&self.board_id.to_le_bytes());
196 for k in 0..16 {
197 stream.extend_from_slice(&self.temps[k].to_le_bytes());
198 }
199 for k in 0..16 {
200 stream.extend_from_slice(&self.biases[k].to_le_bytes());
201 }
202 stream.extend_from_slice(&Self::TAIL.to_le_bytes());
203 stream
204 }
205
206 fn from_bytestream(stream : &Vec<u8>, pos : &mut usize)
207 -> Result<Self, SerializationError> {
208 let mut moni_data = Self::new();
209 Self::verify_fixed(stream, pos)?;
210 moni_data.board_id = parse_u8(stream, pos);
211 for k in 0..16 {
212 moni_data.temps[k] = parse_f32(stream, pos);
213 }
214 for k in 0..16 {
215 moni_data.biases[k] = parse_f32(stream, pos);
216 }
217 *pos += 2;
218 Ok(moni_data)
219 }
220}
221
222impl MoniData for PAMoniData {
223
224 fn get_board_id(&self) -> u8 {
225 return self.board_id;
226 }
227
228 fn get_timestamp(&self) -> u64 {
229 self.timestamp
230 }
231
232 fn set_timestamp(&mut self, ts: u64) {
233 self.timestamp = ts;
234 }
235
236 fn keys() -> Vec<&'static str> {
237 vec!["board_id",
238 "temps1" , "temps2" , "temps3" , "temps4" ,
239 "temps5" , "temps6" , "temps7" , "temps8" ,
240 "temps9" , "temps10" , "temps11" , "temps12" ,
241 "temps13" , "temps14" , "temps15" , "temps16" ,
242 "biases1" , "biases2" , "biases3" , "biases4" ,
243 "biases5" , "biases6" , "biases7" , "biases8" ,
244 "biases9" , "biases10", "biases11", "biases12",
245 "biases13", "biases14", "biases15", "biases16",
246 "timestamp"]
247 }
248
249 fn get(&self, varname : &str) -> Option<f32> {
250 match varname {
251 "board_id" => Some(self.board_id as f32),
252 "temps1" => Some(self.temps[0] ),
253 "temps2" => Some(self.temps[1] ),
254 "temps3" => Some(self.temps[2] ),
255 "temps4" => Some(self.temps[3] ),
256 "temps5" => Some(self.temps[4] ),
257 "temps6" => Some(self.temps[5] ),
258 "temps7" => Some(self.temps[6] ),
259 "temps8" => Some(self.temps[7] ),
260 "temps9" => Some(self.temps[8] ),
261 "temps10" => Some(self.temps[9] ),
262 "temps11" => Some(self.temps[10] ),
263 "temps12" => Some(self.temps[11] ),
264 "temps13" => Some(self.temps[12] ),
265 "temps14" => Some(self.temps[13] ),
266 "temps15" => Some(self.temps[14] ),
267 "temps16" => Some(self.temps[15] ),
268 "biases1" => Some(self.biases[0] ),
269 "biases2" => Some(self.biases[1] ),
270 "biases3" => Some(self.biases[2] ),
271 "biases4" => Some(self.biases[3] ),
272 "biases5" => Some(self.biases[4] ),
273 "biases6" => Some(self.biases[5] ),
274 "biases7" => Some(self.biases[6] ),
275 "biases8" => Some(self.biases[7] ),
276 "biases9" => Some(self.biases[8] ),
277 "biases10" => Some(self.biases[9] ),
278 "biases11" => Some(self.biases[10]),
279 "biases12" => Some(self.biases[11]),
280 "biases13" => Some(self.biases[12]),
281 "biases14" => Some(self.biases[13]),
282 "biases15" => Some(self.biases[14]),
283 "biases16" => Some(self.biases[15]),
284 "timestamp" => Some(self.timestamp as f32),
285 _ => None
286 }
287 }
288}
289
290
291#[cfg(feature = "random")]
292impl FromRandom for PAMoniData {
293
294 fn from_random() -> Self {
295 let mut moni = Self::new();
296 let mut rng = rand::rng();
297 moni.board_id = rng.random::<u8>();
298 for k in 0..16 {
299 moni.temps[k] = rng.random::<f32>();
300 }
301 for k in 0..16 {
302 moni.biases[k] = rng.random::<f32>();
303 }
304 moni
305 }
306}
307
308#[cfg(feature="pybindings")]
311pythonize_packable_no_new!(PAMoniData);
312
313#[cfg(feature="pybindings")]
314pythonize_monidata!(PAMoniData);
315
316moniseries!(PAMoniDataSeries, PAMoniData);
317
318#[test]
321#[cfg(feature = "random")]
322fn pack_pamonidata() {
323 for _ in 0..100 {
324 let data = PAMoniData::from_random();
325 let test : PAMoniData = data.pack().unpack().unwrap();
326 assert_eq!(data, test);
327 }
328}
329