gondola_core/packets/
telemetry_packet_header.rs

1//! Re-implementation of the telemetry header which is attached 
2//! to each telemetry packet.
3//! Re-implemented from bfsw
4// The following file is part of gaps-online-software and published 
5// under the GPLv3 license
6
7use crate::prelude::*;
8
9/// This gets attached to each telemetry packet 
10/// "in front" of it, conveying meta information
11#[derive(Debug, Copy, Clone, PartialEq)]
12#[cfg_attr(feature = "pybindings", pyclass, pyo3(name="TelemetryPacketHeader"))]
13pub struct TelemetryPacketHeader {
14  /// A constant identifying the start of a packet
15  pub sync      : u16,
16  /// A unique identifier describing the following 
17  /// packet's content
18  pub packet_type     : TelemetryPacketType,
19  /// The timestap from the gcu (flight computer) (NOT GPS!)
20  /// when this packet header has been created
21  pub timestamp : u32,
22  /// Counting packets send out by the gcu (flight computer), 
23  /// rolling over every u16::MAX
24  pub counter   : u16,
25  /// The length in bytes of the following packet
26  pub length    : u16,
27  /// A checksum to verify the integrity of the 
28  /// following packet
29  /// FIXME - currently the algorithm used is 
30  ///         unknown
31  pub checksum  : u16
32}
33
34impl TelemetryPacketHeader {
35
36  pub fn new() -> Self {
37    Self {
38      sync      : 0,
39      packet_type     : TelemetryPacketType::Unknown,
40      timestamp : 0,
41      counter   : 0,
42      length    : 0,
43      checksum  : 0,
44    }
45  }
46
47  /// A re-implementation of make_packet_stub
48  pub fn forge(packet_type : TelemetryPacketType) -> Self {
49    let mut header = Self::new();
50    header.sync    = 0x90EB;
51    header.packet_type   = packet_type;
52    header
53  }
54
55  /// Blatent copy of bfsw's timestamp_to_double
56  pub fn get_gcutime(&self) -> f64 {
57    (self.timestamp as f64) * 0.064 + 1631030675.0
58  }
59}
60
61// methods which should be available through python, but 
62// just need to be wrapped
63#[cfg(feature="pybindings")]
64#[pymethods]
65impl TelemetryPacketHeader {
66  
67  #[getter]
68  fn gcutime(&self) -> f64 {
69    self.get_gcutime()
70  }
71
72  #[getter]
73  fn get_packet_type(&self) -> TelemetryPacketType {
74    self.packet_type
75  }
76
77  #[getter]
78  fn get_timestamp(&self) -> u32 {
79    self.timestamp 
80  }
81
82  #[getter]
83  fn get_counter(&self) -> u16 {
84    self.counter 
85  }
86
87  #[getter]
88  fn get_length(&self) -> u16 {
89    self.length
90  } 
91
92  #[getter] 
93  fn get_checksum(&self) -> u16 {
94    self.checksum 
95  }
96}
97
98// Trait implementations
99
100impl Serialization for TelemetryPacketHeader {
101  
102  const HEAD : u16 = 0x90eb;
103  const TAIL : u16 = 0x0000; // there is no tail for telemetry packets
104  const SIZE : usize = 13; 
105
106  fn from_bytestream(stream : &Vec<u8>,
107                     pos    : &mut usize)
108    -> Result<Self, SerializationError> {
109    if stream.len() < *pos + Self::SIZE {
110      return Err(SerializationError::StreamTooShort);
111    }
112    if parse_u16(stream, pos) != 0x90eb {
113      error!("The given position {} does not point to a valid header signature of {}", pos, 0x90eb);
114      return Err(SerializationError::HeadInvalid {});
115    }
116    let mut thead   = TelemetryPacketHeader::new();
117    thead.sync      = 0x90eb;
118    thead.packet_type     = TelemetryPacketType::from(parse_u8 (stream, pos));
119    thead.timestamp = parse_u32(stream, pos);
120    thead.counter   = parse_u16(stream, pos);
121    thead.length    = parse_u16(stream, pos);
122    thead.checksum  = parse_u16(stream, pos);
123    Ok(thead)
124  }
125  
126  fn to_bytestream(&self) -> Vec<u8> {
127    let mut stream = Vec::<u8>::new();
128    //let head : u16 = 0x90eb;
129    // "SYNC" is the header signature
130    stream.extend_from_slice(&self.sync.to_le_bytes());
131    stream.extend_from_slice(&(self.packet_type as u8).to_le_bytes());
132    stream.extend_from_slice(&self.timestamp.to_le_bytes());
133    stream.extend_from_slice(&self.counter.to_le_bytes());
134    stream.extend_from_slice(&self.length.to_le_bytes());
135    stream.extend_from_slice(&self.checksum.to_le_bytes());
136    stream
137  }
138}
139
140impl fmt::Display for TelemetryPacketHeader {
141  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
142    let mut repr = String::from("<TelemetryPacketHeader:");
143    repr += &(format!("\n  Header      : {}",self.sync));
144    repr += &(format!("\n  Packet Type : {}",self.packet_type));
145    repr += &(format!("\n  Timestamp   : {}",self.timestamp));
146    repr += &(format!("\n  Counter     : {}",self.counter));
147    repr += &(format!("\n  Length      : {}",self.length));
148    repr += &(format!("\n  Checksum    : {}>",self.checksum));
149    write!(f, "{}", repr)
150  }
151}
152
153#[cfg(feature="pybindings")]
154pythonize!(TelemetryPacketHeader);