gondola_core/packets/
telemetry_packet.rs

1//! Wrapper for all telemetry data - original implementation in 
2//! bfsw
3// The following file is part of gaps-online-software and published 
4// under the GPLv3 license
5
6use crate::prelude::*;
7
8/// A wrapper for packets from the telemetry stream
9///
10/// This is very compact and mostly used as an 
11/// intermediary
12#[derive(Debug, Clone, PartialEq)]
13#[cfg_attr(feature = "pybindings", pyclass, pyo3(name="TelemetryPacket"))]
14pub struct TelemetryPacket {
15  pub header       : TelemetryPacketHeader,
16  pub payload      : Vec<u8>,
17  pub tof_paddles  : Arc<HashMap<u8,  TofPaddle>>, 
18  pub trk_strips   : Arc<HashMap<u32, TrackerStrip>>,
19}
20
21#[cfg(feature="pybindings")]
22#[pymethods]
23impl TelemetryPacket {
24
25  /// Get a zero copy view of the payload 
26  /// Might be mostly useful for debugging purposes
27  #[getter]
28  fn payload<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyBytes>> {
29    Ok(PyBytes::new(py, &self.payload))
30  }
31
32  #[getter]
33  fn header(&self) -> TelemetryPacketHeader {
34    // clone is fine here, since the packet header 
35    // is pretty small
36    self.header.clone()
37  }
38
39  #[getter]
40  fn packet_type(&self) -> TelemetryPacketType {
41    TelemetryPacketType::from(self.header.packet_type)
42  }
43
44  /// Check if this is either any of the different merged event 
45  /// types 
46  #[pyo3(name="is_event_packet")]
47  fn is_event_packet_py(&self) -> bool {
48    self.is_event_packet()
49  }
50
51  #[pyo3(name="to_bytestream")]
52  fn to_bytestream_py(&self) -> Vec<u8> {
53    self.to_bytestream()
54  }
55
56  #[staticmethod]
57  #[pyo3(name="from_bytestream")]
58  fn from_bytestream_py(stream : Vec<u8>, pos : usize) -> Result<Self, SerializationError> {
59    let mut pos_ = pos;
60    Self::from_bytestream(&stream, &mut pos_)
61  }
62}
63
64impl TelemetryPacket {
65
66  pub fn new() -> Self {
67    Self {
68      header      : TelemetryPacketHeader::new(),
69      payload     : Vec::<u8>::new(),
70      tof_paddles : Arc::new(HashMap::<u8, TofPaddle>::new()),
71      trk_strips  : Arc::new(HashMap::<u32,TrackerStrip>::new()),
72    }
73  }
74 
75  pub fn is_event_packet(&self) -> bool {
76    if self.header.packet_type == TelemetryPacketType::NoTofDataEvent
77      || self.header.packet_type == TelemetryPacketType::NoGapsTriggerEvent 
78      || self.header.packet_type == TelemetryPacketType::InterestingEvent 
79      || self.header.packet_type == TelemetryPacketType::BoringEvent {
80      true 
81    } else {
82      false
83    }
84  }
85
86  /// Unpack the TelemetryPacket and return its content
87  pub fn unpack<T>(&self) -> Result<T, SerializationError>
88    where T: TelemetryPackable + Serialization {
89    if !T::TEL_PACKET_TYPES_EVENT.contains(&self.header.packet_type) &&
90      T::TEL_PACKET_TYPE != self.header.packet_type {
91      error!("This bytestream is not for a {} packet!", self.header.packet_type);
92      return Err(SerializationError::IncorrectPacketType);
93    }
94    let unpacked : T = T::from_bytestream(&self.payload, &mut 0)?;
95    Ok(unpacked)
96  }
97} 
98
99impl Serialization for TelemetryPacket {
100
101  /// No "classical" head byte marker
102  const HEAD : u16 = 0;
103  /// No "classical" tail byte marker
104  const TAIL : u16 = 0;
105  /// variable size
106  const SIZE : usize = 0;
107
108  fn from_bytestream(stream : &Vec<u8>, pos : &mut usize) -> Result<Self, SerializationError> {
109    let mut tpacket: TelemetryPacket = TelemetryPacket::new();
110    let header: TelemetryPacketHeader  = TelemetryPacketHeader::from_bytestream(stream, pos)?;
111    tpacket.header = header;
112    tpacket.payload = stream[*pos..*pos + header.length as usize - TelemetryPacketHeader::SIZE].to_vec();
113    Ok(tpacket)
114  }
115
116  fn to_bytestream(&self) -> Vec<u8> {
117    let mut stream: Vec<u8> = Vec::<u8>::new();
118    let mut s_head = self.header.to_bytestream();
119    stream.append(&mut s_head);
120    stream.extend_from_slice(self.payload.as_slice());
121    stream
122  }
123}
124
125impl Default for TelemetryPacket { 
126  fn default() -> Self {
127    Self::new()
128  }
129}
130
131impl fmt::Display for TelemetryPacket {
132  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
133    let mut repr: String = String::from("<TelemetryPacket:");
134    repr += &(format!("\n  Header      : {}",self.header));
135    repr += &(format!("\n  Payload len : {}>",self.payload.len()));
136    write!(f, "{}", repr)
137  }
138}
139
140impl Frameable for TelemetryPacket {
141  const CRFRAMEOBJECT_TYPE : CRFrameObjectType = CRFrameObjectType::TelemetryPacket;
142}
143
144
145#[cfg(feature="pybindings")]
146pythonize!(TelemetryPacket);
147
148