Skip to main content

gondola_core/monitoring/
pa_moni_data.rs

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