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