liftof_tui/
lib.rs

1#[macro_use] extern crate log;
2
3pub mod menu;
4pub mod colors;
5pub mod widgets;
6pub mod tabs;
7pub mod layout;
8
9use std::sync::Mutex;
10use std::sync::Arc;
11use std::path::PathBuf;
12
13use std::collections::HashMap;
14use std::collections::VecDeque;
15
16use tui_logger::TuiLoggerWidget;
17use ratatui::{
18  style::{
19    Color,
20    Style,
21  },
22  widgets::{
23    Block,
24    Borders,
25  },
26};
27
28pub use crate::tabs::*;
29pub use crate::layout::*;
30
31use crate::colors::ColorTheme;
32use gondola_core::prelude::*;
33
34use crossbeam_channel::{
35  Sender,
36  Receiver
37};
38
39use toml;
40use toml::{
41  Value
42};
43
44pub type WaveformCache = HashMap<u8,HashMap<u8, Arc<Mutex<VecDeque<RBWaveform>>>>>;
45
46/// Create a global storage for RBWaveforms 
47pub fn global_waveform_cache() -> WaveformCache {
48  let mut cache = WaveformCache::new();
49  //let rbs   = ReadoutBoard::all();
50  //let paddles = TofPaddle::all_as_dict();
51  for k in 1..50 {
52    let ch_dict = HashMap::<u8, Arc<Mutex<VecDeque<RBWaveform>>>>::new();
53    cache.insert(k as u8, ch_dict);
54    for j in 1..10 {
55      let wfs     = Arc::new(Mutex::new(VecDeque::<RBWaveform>::new()));
56      cache.get_mut(&k).unwrap().insert(j as u8, wfs); 
57    }
58  }
59  cache
60}
61
62/// A map which keeps track of the types of telemetry packets 
63/// received
64pub fn telly_packet_counter(pack_map : &mut HashMap<&str, usize>, packet_type : &TelemetryPacketType) {
65  let pack_key : &str;
66  match packet_type {
67    TelemetryPacketType::Unknown            => pack_key = "Unknown",
68    TelemetryPacketType::CardHKP            => pack_key = "CardHKP",
69    TelemetryPacketType::CoolingHK          => pack_key = "CoolingHKP",
70    TelemetryPacketType::PDUHK              => pack_key = "PDUHK",
71    TelemetryPacketType::Tracker            => pack_key = "Tracker",
72    TelemetryPacketType::TrackerDAQCntr     => pack_key = "TrakcerDAQCntr",
73    TelemetryPacketType::GPS                => pack_key = "GPS",
74    TelemetryPacketType::TrkTempLeak        => pack_key = "TrkTempLeak",
75    TelemetryPacketType::BoringEvent        => pack_key = "BoringEvent",
76    TelemetryPacketType::RBWaveform         => pack_key = "RBWaveform",
77    TelemetryPacketType::AnyTofHK           => pack_key = "AnyTofHK",
78    TelemetryPacketType::GcuEvtBldSettings  => pack_key = "GcuEvtBldSettings",
79    TelemetryPacketType::LabJackHK          => pack_key = "LabJackHK",
80    TelemetryPacketType::MagHK              => pack_key = "MagHK",
81    TelemetryPacketType::GcuMon             => pack_key = "GcuMon",
82    TelemetryPacketType::InterestingEvent   => pack_key = "InterestingEvent",
83    TelemetryPacketType::NoGapsTriggerEvent => pack_key = "NoGapsTriggerEvent",
84    TelemetryPacketType::NoTofDataEvent     => pack_key = "NoTofDataEvent",
85    TelemetryPacketType::Ack                => pack_key = "Ack",     
86    TelemetryPacketType::AnyTrackerHK       => pack_key = "AnyTrackerHK",
87    TelemetryPacketType::TmP33              => pack_key = "TmP33",
88    TelemetryPacketType::TmP34              => pack_key = "TmP34",
89    TelemetryPacketType::TmP37              => pack_key = "TmP37",
90    TelemetryPacketType::TmP38              => pack_key = "TmP38",
91    TelemetryPacketType::TmP55              => pack_key = "TmP55",
92    TelemetryPacketType::TmP64              => pack_key = "TmP64",
93    TelemetryPacketType::TmP96              => pack_key = "TmP96",
94    TelemetryPacketType::TmP214             => pack_key = "TmP214",
95    _                                       => pack_key = "Unknown",
96  }
97  if pack_map.get(pack_key).is_some() {
98    *pack_map.get_mut(pack_key).unwrap() += 1;
99  } else {
100    pack_map.insert(pack_key, 1);
101  }
102}
103
104/// Use the TuiLoggerWidget to display 
105/// the most recent log messages
106///
107///
108pub fn render_logs<'a>(theme : ColorTheme) -> TuiLoggerWidget<'a> {
109  TuiLoggerWidget::default()
110    .style_error(Style::default().fg(Color::Red))
111    .style_debug(Style::default().fg(Color::Green))
112    .style_warn(Style::default().fg(Color::Yellow))
113    .style_trace(Style::default().fg(Color::Gray))
114    .style_info(Style::default().fg(Color::Blue))
115    .block(
116      Block::default()
117        .title("Logs")
118        .border_style(theme.style())
119        .borders(Borders::ALL),
120    )   
121    .style(theme.style())
122}
123
124/// Count the different types of tofpackets and store the result 
125/// in a HashMap
126///
127/// # Arguments:
128///
129///   * packet_type : TofPacket type to llokup it's position in 
130///                   the map
131///   * packet_size : The size of the packet including header in bytes
132///   * packet_map  : An arc/mutex to the HashMap we use to store
133///                   the counted values in.
134fn packet_sorter(packet_type : &TofPacketType,
135                 packet_size : usize,
136                 packet_map  : &Arc<Mutex<HashMap<&str,(usize,usize)>>>) {
137  match packet_map.lock() {
138    Ok(mut pm) => {
139      let pack_key : &str;
140      //let pt = packet_type.cl
141      //let pt = packet_type.clone();
142      //let pack_key = pt.as_ref();
143      match packet_type {
144        TofPacketType::Unknown               => pack_key = "Unknown", 
145        TofPacketType::RBEvent               => pack_key = "RBEvent",
146        TofPacketType::TofEvent              => pack_key = "TofEvent",
147        TofPacketType::RBWaveform            => pack_key = "RBWaveform",
148        TofPacketType::TofEventDeprecated    => pack_key = "TofEventDeprecated",
149        TofPacketType::DataSinkHB            => pack_key = "DataSinkHB",    
150        TofPacketType::MasterTrigger         => pack_key = "MasterTrigger",
151        TofPacketType::TriggerConfig         => pack_key = "TriggerConfig",
152        TofPacketType::MasterTriggerHB       => pack_key = "MasterTriggerHHB", 
153        TofPacketType::EventBuilderHB        => pack_key = "EventBuilderHB",
154        TofPacketType::RBChannelMaskConfig   => pack_key = "RBChannelMaskConfig",
155        TofPacketType::TofRBConfig           => pack_key = "TofRBConfig",
156        TofPacketType::AnalysisEngineConfig  => pack_key = "AnalysisEngineConfig",
157        TofPacketType::RBEventHeader         => pack_key = "RBEventHeader",    // needs to go away
158        TofPacketType::TOFEventBuilderConfig => pack_key = "TOFEventBuilderConfig",
159        TofPacketType::DataPublisherConfig   => pack_key = "DataPublisherConfig",
160        TofPacketType::TofRunConfig          => pack_key = "TofRunConfig",
161        TofPacketType::CPUMoniData           => pack_key = "CPUMoniData",
162        TofPacketType::MtbMoniData           => pack_key = "MtbMoniData",
163        TofPacketType::RBMoniData            => pack_key = "RBMoniData",
164        TofPacketType::PBMoniData            => pack_key = "PBMoniData",
165        TofPacketType::LTBMoniData           => pack_key = "LTBMoniData",
166        TofPacketType::PAMoniData            => pack_key = "PAMoniData",
167        TofPacketType::RBEventMemoryView     => pack_key = "RBEventMemoryView", // We'll keep it for now - indicates that the event
168        TofPacketType::RBCalibration         => pack_key = "RBCalibration",
169        TofPacketType::TofCommand            => pack_key = "TofCommand",
170        TofPacketType::TofCommandV2          => pack_key = "TofCommandV2",
171        TofPacketType::TofResponse           => pack_key = "TofResponse",
172        TofPacketType::RBCommand             => pack_key = "RBCommand",
173        TofPacketType::RBPing                => pack_key = "RBPing",
174        TofPacketType::PreampBiasConfig      => pack_key = "PreampBiasConfig",
175        TofPacketType::RunConfig             => pack_key = "RunConfig",
176        TofPacketType::LTBThresholdConfig    => pack_key = "LTBThresholdConfig",
177        TofPacketType::TofDetectorStatus     => pack_key = "TofDetectorStatus",
178        TofPacketType::ConfigBinary          => pack_key = "ConfigBinary",
179        TofPacketType::LiftofRBBinary        => pack_key = "LiftofRBBinary",
180        TofPacketType::LiftofBinaryService   => pack_key = "LiftofBinaryService",
181        TofPacketType::LiftofCCBinary        => pack_key = "LiftofCCBinary",
182        TofPacketType::LiftofSettings        => pack_key = "LiftofSettings",
183        TofPacketType::LiftofSettingsDiff    => pack_key = "LiftofSettingsDiff",
184        TofPacketType::RBCalibrationFlightV  => pack_key = "RBCalibrationFlightV",
185        TofPacketType::RBCalibrationFlightT  => pack_key = "RBCalibrationFlightT",
186        TofPacketType::BfswAckPacket         => pack_key = "BfswAckPacket",
187        TofPacketType::MultiPacket           => pack_key = "MultiPacket",
188        TofPacketType::PanicPacket           => pack_key = "PanicPacket",
189      }
190      if pm.get(pack_key).is_some() {
191        pm.get_mut(pack_key).unwrap().0 += 1;
192        pm.get_mut(pack_key).unwrap().1 += packet_size;
193      } else {
194        pm.insert(pack_key, (1, packet_size));
195      }
196    }
197    Err(err) => {
198      error!("Can't lock shared memory! {err}");
199    }
200  }
201}
202
203/// Receive packets from an incoming stream
204/// and distrubute them to their receivers
205/// while taking notes of everything
206///
207/// This is a Pablo Pubsub kind of persona
208/// (see a fantastic talk at RustConf 2023)
209pub fn packet_distributor(tp_from_sock       : Receiver<TofPacket>,
210                          tp_sender_mt       : Sender<TofPacket>,
211                          tp_sender_rb       : Sender<TofPacket>,
212                          tp_sender_cp       : Sender<TofPacket>,
213                          tp_sender_tr       : Sender<TofPacket>,
214                          ts_send            : Sender<TofPacket>,
215                          tp_sender_hb       : Sender<TofPacket>,
216                          str_list           : Arc<Mutex<VecDeque<String>>>,
217                          pck_map            : Arc<Mutex<HashMap<&str, (usize, usize)>>>,
218                          mut writer         : Option<TofPacketWriter>,
219                          mut wf_cache       : Box<WaveformCache>,
220                          latest_config      : Arc<Mutex<String>>) {
221  let mut n_pack = 0usize;
222
223  loop {
224    match tp_from_sock.recv() {
225      Err(err) => error!("Can't receive TofPacket! {err}"),
226      Ok(tp) => {
227        let packet_size = tp.payload.len() + 9; // 9 is overhead for TofPacket 
228        packet_sorter(&tp.packet_type, packet_size, &pck_map);
229        n_pack += 1;
230        match str_list.lock() {
231          Err(err) => error!("Can't lock shared memory! {err}"),
232          Ok(mut _list)    => {
233            //let prefix  = String::from_utf8(payload[0..4].to_vec()).expect("Can't get prefix!");
234            //let message = format!("{}-{} {}", n_pack,prefix, tp.to_string());
235            let message = format!("{} : {}", n_pack, tp);
236            _list.push_back(message);
237          }
238        }
239        //continue; 
240        // if --capture, write file
241        if writer.is_some() {
242          writer.as_mut().unwrap().add_tof_packet(&tp);
243        }
244        match tp.packet_type {
245          TofPacketType::TofResponse => { 
246            match tp_sender_tr.send(tp) {
247              Err(err) => error!("Can't send TP! {err}"),
248              Ok(_)    => (),
249            }
250          }
251          TofPacketType::MtbMoniData => {
252            match tp_sender_mt.send(tp) {
253              Err(err) => error!("Can't send TP! {err}"),
254              Ok(_)    => (),
255            }
256          }
257          TofPacketType::RBWaveform => {
258            match tp.unpack::<RBWaveform>() {
259              Ok(wf) => {
260                 
261                let rb_id = wf.rb_id;
262                let ch_a  = wf.rb_channel_a + 1;
263                let ch_b  = wf.rb_channel_b + 1;
264                debug!("Successfully unpacked RBWaveform! {} {} {}", rb_id, ch_a, ch_b);
265                //if rb_id != 25 {
266                //  continue;
267                //} 
268                //if ch_a != 3 {
269                //  continue
270                //}
271                //println!("{wf}");
272                if rb_id > 50 || rb_id == 0 {
273                  continue;
274                }
275                if ch_a > 9 || ch_a == 0 {
276                  error!("Invalid channel B {}", ch_a);
277                  continue;
278                }
279                if ch_b > 9 || ch_b == 0 {
280                  error!("Invalid channel A {}", ch_b);
281                  continue;
282                }
283                //error!("1 : Pushing wf with rb id {} to {}", wf.rb_id, rb_id);
284                match wf_cache.get_mut(&wf.rb_id).unwrap().get_mut(&ch_a).unwrap().lock() {
285                  Err(err)  => {
286                    error!("Unable to lock waveform cache! {err}");
287                  }
288                  Ok(mut cache) => {
289                    //error!("2 : Pushing wf with rb id {} to {}", wf.rb_id, rb_id);
290                    cache.push_back(wf.clone());
291                    //error!("3 : Pushing wf with rb id {} to {}", wf.rb_id, rb_id);
292                    debug!("Last wf in cache has rb id {}", cache.back().unwrap().rb_id); 
293                    if cache.len() > 1000 {
294                      cache.pop_front();
295                    }
296                  }
297                }
298                match wf_cache.get_mut(&wf.rb_id).unwrap().get_mut(&ch_b).unwrap().lock() {
299                  Err(err)  => {
300                    error!("Unable to lock waveform cache! {err}");
301                  }
302                  Ok(mut cache) => {
303                    cache.push_back(wf.clone());
304                    if cache.len() > 1000 {
305                      cache.pop_front();
306                    }
307                   // println!("Pushing waveform for {rb_id} - {ch_b} to cache of len {}", cache.len());
308                  }
309                }
310              }
311              Err(err) => {
312                error!("Unable to unpack RBWaveform! {err}");
313              }
314            }
315            //match rbwf_sender.send(tp) {
316            //  Err(err) => error!("Can't send TP! {err}"),
317            //  Ok(_)    => (),
318            //}
319          }
320          TofPacketType::LiftofSettings => {
321            info!("Saving received liftof-config.toml data!");
322            let output_file_path = PathBuf::from("latest-liftof-config.toml");
323            match decompress_toml(&tp.payload.as_slice(), &output_file_path) {
324              Err(err) => {
325                error!("Unable to decompressed the received bytes into a valid .toml file! {err}")
326              }
327              Ok(_)    => ()
328            }
329            let contents     = fs::read_to_string(output_file_path).unwrap();
330            let value: Value = toml::from_str(&contents).unwrap();
331            match latest_config.lock() {
332              Ok(mut cfg) => {
333                *cfg = toml::to_string_pretty(&value).unwrap();
334              }
335              Err(err) => {
336                error!("Can not lock String to save config! {err}");
337              }
338            }
339            //latest_config    = Arc::new(toml::to_string_pretty(&value).unwrap());
340            //println!("{:?}", latest_config);
341          }
342          TofPacketType::TofEvent => {
343            match ts_send.send(tp) {
344              Err(err) => error!("Can't send TP! {err}"),
345              Ok(_)    => (),
346            }
347          }
348          TofPacketType::RBEvent |
349          TofPacketType::RBEventMemoryView | 
350          TofPacketType::LTBMoniData |
351          TofPacketType::PAMoniData  |
352          TofPacketType::PBMoniData  |
353          TofPacketType::RBMoniData => {
354            match tp_sender_rb.send(tp) {
355              Err(err) => error!("Can't send TP! {err}"),
356              Ok(_)    => (),
357            }
358          }
359          TofPacketType::CPUMoniData => {
360            match tp_sender_cp.send(tp) {
361              Err(err) => error!("Can't send TP! {err}"),
362              Ok(_)    => (),
363            }
364          }
365          TofPacketType::DataSinkHB      |
366          TofPacketType::EventBuilderHB  | 
367          TofPacketType::MasterTriggerHB => {
368            match tp_sender_hb.send(tp) {
369              Err(err) => error!("Can't send TP! {err}"),
370              Ok(_)    => {
371              },
372            }
373          }
374          _ => () 
375        }
376      }
377    } 
378  }
379}
380
381