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;
11
12use std::collections::HashMap;
13use std::collections::VecDeque;
14
15use tui_logger::TuiLoggerWidget;
16use ratatui::{
17 style::{
18 Color,
19 Style,
20 },
21 widgets::{
22 Block,
23 Borders,
24 },
25};
26
27pub use crate::tabs::*;
28pub use crate::layout::*;
29
30use crate::colors::ColorTheme;
31use gondola_core::prelude::*;
32
33//use tof_dataclasses::packets::TofPacket;
34//use tof_dataclasses::packets::PacketType;
35//use tof_dataclasses::events::MasterTriggerEvent;
36//use tof_dataclasses::events::TofEventSummary;
37//use tof_dataclasses::events::TofHit;
38//use tof_dataclasses::serialization::Packable;
39//use tof_dataclasses::serialization::Serialization;
40//use tof_dataclasses::io::TofPacketWriter;
41
42use crossbeam_channel::{
43 Sender,
44 Receiver
45};
46
47/// A map which keeps track of the types of telemetry packets
48/// received
49pub fn telly_packet_counter(pack_map : &mut HashMap<&str, usize>, packet_type : &TelemetryPacketType) {
50 let pack_key : &str;
51 match packet_type {
52 TelemetryPacketType::Unknown => pack_key = "Unknown",
53 TelemetryPacketType::CardHKP => pack_key = "CardHKP",
54 TelemetryPacketType::CoolingHK => pack_key = "CoolingHKP",
55 TelemetryPacketType::PDUHK => pack_key = "PDUHK",
56 TelemetryPacketType::Tracker => pack_key = "Tracker",
57 TelemetryPacketType::TrackerDAQCntr => pack_key = "TrakcerDAQCntr",
58 TelemetryPacketType::GPS => pack_key = "GPS",
59 TelemetryPacketType::TrkTempLeak => pack_key = "TrkTempLeak",
60 TelemetryPacketType::BoringEvent => pack_key = "BoringEvent",
61 TelemetryPacketType::RBWaveform => pack_key = "RBWaveform",
62 TelemetryPacketType::AnyTofHK => pack_key = "AnyTofHK",
63 TelemetryPacketType::GcuEvtBldSettings => pack_key = "GcuEvtBldSettings",
64 TelemetryPacketType::LabJackHK => pack_key = "LabJackHK",
65 TelemetryPacketType::MagHK => pack_key = "MagHK",
66 TelemetryPacketType::GcuMon => pack_key = "GcuMon",
67 TelemetryPacketType::InterestingEvent => pack_key = "InterestingEvent",
68 TelemetryPacketType::NoGapsTriggerEvent => pack_key = "NoGapsTriggerEvent",
69 TelemetryPacketType::NoTofDataEvent => pack_key = "NoTofDataEvent",
70 TelemetryPacketType::Ack => pack_key = "Ack",
71 TelemetryPacketType::AnyTrackerHK => pack_key = "AnyTrackerHK",
72 TelemetryPacketType::TmP33 => pack_key = "TmP33",
73 TelemetryPacketType::TmP34 => pack_key = "TmP34",
74 TelemetryPacketType::TmP37 => pack_key = "TmP37",
75 TelemetryPacketType::TmP38 => pack_key = "TmP38",
76 TelemetryPacketType::TmP55 => pack_key = "TmP55",
77 TelemetryPacketType::TmP64 => pack_key = "TmP64",
78 TelemetryPacketType::TmP96 => pack_key = "TmP96",
79 TelemetryPacketType::TmP214 => pack_key = "TmP214",
80 //_ => pack_key = "Unknown",
81 }
82 if pack_map.get(pack_key).is_some() {
83 *pack_map.get_mut(pack_key).unwrap() += 1;
84 } else {
85 pack_map.insert(pack_key, 0);
86 }
87}
88
89/// Use the TuiLoggerWidget to display
90/// the most recent log messages
91///
92///
93pub fn render_logs<'a>(theme : ColorTheme) -> TuiLoggerWidget<'a> {
94 TuiLoggerWidget::default()
95 .style_error(Style::default().fg(Color::Red))
96 .style_debug(Style::default().fg(Color::Green))
97 .style_warn(Style::default().fg(Color::Yellow))
98 .style_trace(Style::default().fg(Color::Gray))
99 .style_info(Style::default().fg(Color::Blue))
100 .block(
101 Block::default()
102 .title("Logs")
103 .border_style(theme.style())
104 .borders(Borders::ALL),
105 )
106 .style(theme.style())
107}
108
109/// Count the different types of tofpackets and store the result
110/// in a HashMap
111///
112/// # Arguments:
113///
114/// * packet_type : TofPacket type to llokup it's position in
115/// the map
116/// * packet_map : An arc/mutex to the HashMap we use to store
117/// the counted values in.
118fn packet_sorter(packet_type : &TofPacketType,
119 packet_map : &Arc<Mutex<HashMap<&str,usize>>>) {
120 match packet_map.lock() {
121 Ok(mut pm) => {
122 let pack_key : &str;
123 //let pt = packet_type.cl
124 //let pt = packet_type.clone();
125 //let pack_key = pt.as_ref();
126 match packet_type {
127 TofPacketType::Unknown => pack_key = "Unknown",
128 TofPacketType::RBEvent => pack_key = "RBEvent",
129 TofPacketType::TofEvent => pack_key = "TofEvent",
130 TofPacketType::RBWaveform => pack_key = "RBWaveform",
131 TofPacketType::TofEventDeprecated => pack_key = "TofEventDeprecated",
132 TofPacketType::DataSinkHB => pack_key = "DataSinkHB",
133 TofPacketType::MasterTrigger => pack_key = "MasterTrigger",
134 TofPacketType::TriggerConfig => pack_key = "TriggerConfig",
135 TofPacketType::MasterTriggerHB => pack_key = "MasterTriggerHHB",
136 TofPacketType::EventBuilderHB => pack_key = "EventBuilderHB",
137 TofPacketType::RBChannelMaskConfig => pack_key = "RBChannelMaskConfig",
138 TofPacketType::TofRBConfig => pack_key = "TofRBConfig",
139 TofPacketType::AnalysisEngineConfig => pack_key = "AnalysisEngineConfig",
140 TofPacketType::RBEventHeader => pack_key = "RBEventHeader", // needs to go away
141 TofPacketType::TOFEventBuilderConfig => pack_key = "TOFEventBuilderConfig",
142 TofPacketType::DataPublisherConfig => pack_key = "DataPublisherConfig",
143 TofPacketType::TofRunConfig => pack_key = "TofRunConfig",
144 TofPacketType::CPUMoniData => pack_key = "CPUMoniData",
145 TofPacketType::MtbMoniData => pack_key = "MtbMoniData",
146 TofPacketType::RBMoniData => pack_key = "RBMoniData",
147 TofPacketType::PBMoniData => pack_key = "PBMoniData",
148 TofPacketType::LTBMoniData => pack_key = "LTBMoniData",
149 TofPacketType::PAMoniData => pack_key = "PAMoniData",
150 TofPacketType::RBEventMemoryView => pack_key = "RBEventMemoryView", // We'll keep it for now - indicates that the event
151 TofPacketType::RBCalibration => pack_key = "RBCalibration",
152 TofPacketType::TofCommand => pack_key = "TofCommand",
153 TofPacketType::TofCommandV2 => pack_key = "TofCommandV2",
154 TofPacketType::TofResponse => pack_key = "TofResponse",
155 TofPacketType::RBCommand => pack_key = "RBCommand",
156 TofPacketType::RBPing => pack_key = "RBPing",
157 TofPacketType::PreampBiasConfig => pack_key = "PreampBiasConfig",
158 TofPacketType::RunConfig => pack_key = "RunConfig",
159 TofPacketType::LTBThresholdConfig => pack_key = "LTBThresholdConfig",
160 TofPacketType::TofDetectorStatus => pack_key = "TofDetectorStatus",
161 TofPacketType::ConfigBinary => pack_key = "ConfigBinary",
162 TofPacketType::LiftofRBBinary => pack_key = "LiftofRBBinary",
163 TofPacketType::LiftofBinaryService => pack_key = "LiftofBinaryService",
164 TofPacketType::LiftofCCBinary => pack_key = "LiftofCCBinary",
165 TofPacketType::RBCalibrationFlightV => pack_key = "RBCalibrationFlightV",
166 TofPacketType::RBCalibrationFlightT => pack_key = "RBCalibrationFlightT",
167 TofPacketType::BfswAckPacket => pack_key = "BfswAckPacket",
168 TofPacketType::MultiPacket => pack_key = "MultiPacket",
169 }
170 if pm.get(pack_key).is_some() {
171 *pm.get_mut(pack_key).unwrap() += 1;
172 } else {
173 pm.insert(pack_key, 0);
174 }
175 }
176 Err(err) => {
177 error!("Can't lock shared memory! {err}");
178 }
179 }
180}
181
182/// Receive packets from an incoming stream
183/// and distrubute them to their receivers
184/// while taking notes of everything
185///
186/// This is a Pablo Pubsub kind of persona
187/// (see a fantastic talk at RustConf 2023)
188pub fn packet_distributor(tp_from_sock : Receiver<TofPacket>,
189 tp_sender_mt : Sender<TofPacket>,
190 tp_sender_rb : Sender<TofPacket>,
191 tp_sender_ev : Sender<TofPacket>,
192 tp_sender_cp : Sender<TofPacket>,
193 tp_sender_tr : Sender<TofPacket>,
194 rbwf_sender : Sender<TofPacket>,
195 ts_send : Sender<TofEvent>,
196 th_send : Sender<TofHit>,
197 tp_sender_hb : Sender<TofPacket>,
198 str_list : Arc<Mutex<VecDeque<String>>>,
199 pck_map : Arc<Mutex<HashMap<&str, usize>>>,
200 mut writer : Option<TofPacketWriter>) {
201 let mut n_pack = 0usize;
202 // per default, we create master trigger packets from TofEventSummary,
203 // except we have "real" mtb packets
204 let craft_mte_packets = true;
205
206 loop {
207 //match data_socket.recv_bytes(0) {
208 match tp_from_sock.recv() {
209 Err(err) => error!("Can't receive TofPacket! {err}"),
210 Ok(tp) => {
211 //println!("{:?}", pck_map);
212 packet_sorter(&tp.packet_type, &pck_map);
213 n_pack += 1;
214 //println!("Got TP {}", tp);
215 match str_list.lock() {
216 Err(err) => error!("Can't lock shared memory! {err}"),
217 Ok(mut _list) => {
218 //let prefix = String::from_utf8(payload[0..4].to_vec()).expect("Can't get prefix!");
219 //let message = format!("{}-{} {}", n_pack,prefix, tp.to_string());
220 let message = format!("{} : {}", n_pack, tp);
221 _list.push_back(message);
222 }
223 }
224 // if captured, write file
225 if writer.is_some() {
226 writer.as_mut().unwrap().add_tof_packet(&tp);
227 }
228 match tp.packet_type {
229 TofPacketType::TofResponse => {
230 match tp_sender_tr.send(tp) {
231 Err(err) => error!("Can't send TP! {err}"),
232 Ok(_) => (),
233 }
234 }
235 TofPacketType::MtbMoniData |
236 //TofPacketType::MasterTrigger => {
237 // // apparently, we are getting MasterTriggerEvents,
238 // // sow we won't be needing to craft them from
239 // // TofEventSummary packets
240 // if tp.packet_type == TofPacketType::MasterTrigger {
241 // craft_mte_packets = false;
242 // }
243 // match tp_sender_mt.send(tp) {
244 // Err(err) => error!("Can't send TP! {err}"),
245 // Ok(_) => (),
246 // }
247 //},
248 TofPacketType::RBWaveform => {
249 match rbwf_sender.send(tp) {
250 Err(err) => error!("Can't send TP! {err}"),
251 Ok(_) => (),
252 }
253 }
254 TofPacketType::TofEvent => {
255 //match TofEvent::from_tofpacket(&tp) {
256 match tp.unpack::<TofEvent>() {
257 Err(err) => {
258 error!("Unable to unpack TofEvent! {err}");
259 }
260 Ok(ts) => {
261 // FIXME - this is not needed anymore
262 if craft_mte_packets {
263 //let mte = MasterTriggerEvent::from(&ts);
264 //let mte_tp = mte.pack();
265 //error!("We are sending the following tp {}", mte_tp);
266 match tp_sender_mt.send(tp.clone()) {
267 //match tp_sender_mt.send(mte_tp) {
268 Err(err) => error!("Can't send MTE TP! {err}"),
269 Ok(_) => ()
270 }
271 }
272 for h in &ts.hits {
273 match th_send.send(*h) {
274 Err(err) => error!("Can't send TP! {err}"),
275 Ok(_) => (),
276 }
277 }
278 match ts_send.send(ts) {
279 Err(err) => error!("Can't send TP! {err}"),
280 Ok(_) => (),
281 }
282 match tp_sender_ev.send(tp.clone()) {
283 Err(err) => error!("Can't send TP! {err}"),
284 Ok(_) => (),
285 }
286 }
287 }
288 }
289 //TofPacketType::TofEvent => {
290 // // since the tof event contains MTEs, we don't need
291 // // to craft them
292 // craft_mte_packets = false;
293 // match tp_sender_ev.send(tp) {
294 // Err(err) => error!("Can't send TP! {err}"),
295 // Ok(_) => (),
296 // }
297 // // Disasemble the packets
298 // //match TofEvent::from_bytestream(tp.payload, &mut 0) {
299 // // Err(err) => {
300 // // error!("Can't decode TofEvent");
301 // // },
302 // // Ok(ev) => {
303 // // //for rbev in ev.rb_events {
304 // // // let
305 // // // match tp_sender_rb.send
306 // // //}
307 // // }
308 // //}
309 //}
310 TofPacketType::RBEvent |
311 TofPacketType::RBEventMemoryView |
312 TofPacketType::LTBMoniData |
313 TofPacketType::PAMoniData |
314 TofPacketType::PBMoniData |
315 TofPacketType::RBMoniData => {
316 match tp_sender_rb.send(tp) {
317 Err(err) => error!("Can't send TP! {err}"),
318 Ok(_) => (),
319 }
320 }
321 TofPacketType::CPUMoniData => {
322 match tp_sender_cp.send(tp) {
323 Err(err) => error!("Can't send TP! {err}"),
324 Ok(_) => (),
325 }
326 }
327 TofPacketType::DataSinkHB |
328 TofPacketType::EventBuilderHB |
329 TofPacketType::MasterTriggerHB => {
330 match tp_sender_hb.send(tp) {
331 Err(err) => error!("Can't send TP! {err}"),
332 Ok(_) => {
333 },
334 }
335 }
336 _ => ()
337 }
338 }
339 }
340 }
341}
342
343///// ZMQ socket wrapper for the zmq socket which is
344///// supposed to receive data from the TOF system.
345//pub fn socket_wrap_tofstream(address : &str,
346// tp_sender : Sender<TofPacket>) {
347// let ctx = zmq::Context::new();
348// // FIXME - don't hardcode this IP
349// let socket = ctx.socket(zmq::SUB).expect("Unable to create 0MQ SUB socket!");
350// socket.connect(address).expect("Unable to connect to data (PUB) socket {adress}");
351// socket.set_subscribe(b"").expect("Can't subscribe to any message on 0MQ socket!");
352// //let mut n_pack = 0usize;
353// info!("0MQ SUB socket connected to address {address}");
354// // per default, we create master trigger packets from TofEventSummary,
355// // except we have "real" mtb packets
356// //let mut craft_mte_packets = true;
357// loop {
358// match socket.recv_bytes(0) {
359// Err(err) => error!("Can't receive TofPacket! {err}"),
360// Ok(payload) => {
361// match TofPacket::from_bytestream(&payload, &mut 0) {
362// Ok(tp) => {
363// match tp_sender.send(tp) {
364// Ok(_) => (),
365// Err(err) => error!("Can't send TofPacket over channel! {err}")
366// }
367// }
368// Err(err) => {
369// debug!("Can't decode payload! {err}");
370// // that might have an RB prefix, forward
371// // it
372// match TofPacket::from_bytestream(&payload, &mut 4) {
373// Err(err) => {
374// error!("Don't understand bytestream! {err}");
375// },
376// Ok(tp) => {
377// match tp_sender.send(tp) {
378// Ok(_) => (),
379// Err(err) => error!("Can't send TofPacket over channel! {err}")
380// }
381// }
382// }
383// }
384// }
385// }
386// }
387// }
388//}
389//
390////use telemetry_dataclasses::packets::{
391//// TelemetryPacketHeader,
392//// TelemetryPacket,
393////};
394//
395///// Get the GAPS merged event telemetry stream and
396///// broadcast it to the relevant tab
397/////
398///// # Arguments
399/////
400///// * address : Address to susbscribe to for telemetry
401///// stream (must be zmq.PUB) on the Sender
402///// side
403///// * cachesize : Getting the packets from the funneled stream leads
404///// to duplicates. To eliminate these, we store the
405///// packet counter variable in a Dequee of a given
406///// size
407///// * tele_sender : Channel to forward the received telemetry
408///// packets
409//pub fn socket_wrap_telemetry(address : &str,
410// cachesize : usize,
411// tele_sender : Sender<TelemetryPacket>) {
412// let ctx = zmq::Context::new();
413// // FIXME - don't hardcode this IP
414// // typically how it is done is that this program runs either on a gse
415// // or there is a local forwarding of the port thrugh ssh
416// //let address : &str = "tcp://127.0.0.1:55555";
417// let socket = ctx.socket(zmq::SUB).expect("Unable to create 0MQ SUB socket!");
418// match socket.connect(&address) {
419// Err(err) => {
420// error!("Unable to connect to data (PUB) socket {address}! {err}");
421// panic!("Can not connect to zmq PUB socket!");
422// }
423// Ok(_) => ()
424// }
425// let mut cache = VecDeque::<u16>::with_capacity(cachesize);
426// socket.set_subscribe(b"") .expect("Can't subscribe to any message on 0MQ socket! {err}");
427// loop {
428// match socket.recv_bytes(0) {
429// Err(err) => error!("Can't receive TofPacket! {err}"),
430// Ok(mut payload) => {
431// match TelemetryPacketHeader::from_bytestream(&payload, &mut 0) {
432// Err(err) => {
433// error!("Can not decode telemtry header! {err}");
434// //for k in pos - 5 .. pos + 5 {
435// // println!("{}",stream[k]);
436// //}
437// }
438// Ok(header) => {
439// let mut packet = TelemetryPacket::new();
440// if payload.len() > TelemetryPacketHeader::SIZE {
441// payload.drain(0..TelemetryPacketHeader::SIZE);
442// }
443// if cache.contains(&header.counter) {
444// // drop this packet
445// continue;
446// } else {
447// cache.push_back(header.counter);
448// }
449// if cache.len() == cachesize {
450// cache.pop_front();
451// }
452//
453// packet.header = header;
454// packet.payload = payload;
455// match tele_sender.send(packet) {
456// Err(err) => error!("Can not send telemetry packet to downstream! {err}"),
457// Ok(_) => ()
458// }
459// }
460// }
461// }
462// }
463// }
464//}
465