gondola_core/packets/
magnetometer.rs

1// This file is part of gaps-online-software and published 
2// under the GPLv3 license
3
4use crate::prelude::*;
5
6#[cfg_attr(feature="pybindings", pyclass)]
7pub struct MagnetoMeter {
8  pub telemetry_header : TelemetryPacketHeader,
9  pub temp             : u16, 
10  pub mag_x            : u16, 
11  pub mag_y            : u16, 
12  pub mag_z            : u16, 
13  pub acc_x            : u16, 
14  pub acc_y            : u16, 
15  pub acc_z            : u16, 
16  pub roll             : u16, 
17  pub pitch            : u16, 
18  pub yaw              : u16, 
19  pub mag_roll         : u16, 
20  pub mag_field        : u16, 
21  pub grav_field       : u16, 
22  pub expected_size    : u64, // technically usize
23  pub end_byte         : u16, 
24  pub zero             : u8, 
25  pub ndata            : u8, 
26}
27
28impl MagnetoMeter {
29  pub fn new() -> Self {
30    Self {
31     telemetry_header  : TelemetryPacketHeader::new(),
32     temp              : 0, 
33     mag_x             : 0, 
34     mag_y             : 0, 
35     mag_z             : 0, 
36     acc_x             : 0, 
37     acc_y             : 0, 
38     acc_z             : 0, 
39     roll              : 0, 
40     pitch             : 0, 
41     yaw               : 0, 
42     mag_roll          : 0, 
43     mag_field         : 0, 
44     grav_field        : 0, 
45     expected_size     : 0, // technically usize
46     end_byte          : 0, 
47     zero              : 0, 
48     ndata             : 0, 
49    }
50  }
51}
52
53impl Default for MagnetoMeter {
54  fn default() -> Self {
55    Self::new()
56  }
57}
58
59impl fmt::Display for MagnetoMeter {
60  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
61    let mut repr = String::from("<MagnetoMeter: ");
62    repr += &(format!("\n {}", self.telemetry_header));
63    repr += &(format!("\n temp          : {}", self.temp            ));   
64    repr += &(format!("\n mag_x         : {}", self.mag_x           ));   
65    repr += &(format!("\n mag_y         : {}", self.mag_y           ));   
66    repr += &(format!("\n mag_z         : {}", self.mag_z           ));   
67    repr += &(format!("\n acc_x         : {}", self.acc_x           ));   
68    repr += &(format!("\n acc_y         : {}", self.acc_y           ));   
69    repr += &(format!("\n acc_z         : {}", self.acc_z           ));   
70    repr += &(format!("\n roll          : {}", self.roll            ));   
71    repr += &(format!("\n pitch         : {}", self.pitch           ));   
72    repr += &(format!("\n yaw           : {}", self.yaw             ));   
73    repr += &(format!("\n mag_roll      : {}", self.mag_roll        ));   
74    repr += &(format!("\n mag_field     : {}", self.mag_field       ));   
75    repr += &(format!("\n grav_field    : {}", self.grav_field      ));   
76    repr += &(format!("\n expected_size : {}", self.expected_size   ));   
77    repr += &(format!("\n end_byte      : {}", self.end_byte        ));   
78    repr += &(format!("\n zero          : {}", self.zero            ));   
79    repr += &(format!("\n ndata         : {}", self.ndata           ));   
80    write!(f, "{}", repr)
81  }
82}
83
84impl Serialization for MagnetoMeter {
85  
86  const HEAD : u16   = 0x90eb;
87  const TAIL : u16   = 0x0000; // there is no tail for telemetry packets
88  const SIZE : usize = 57; 
89  
90  fn from_bytestream(stream : &Vec<u8>,
91                     pos    : &mut usize)
92    -> Result<Self, SerializationError> {
93    let mut mag = Self::new();
94    if stream.len() < Self::SIZE {
95      error!("We got {} bytes, but need {}!", stream.len(),Self::SIZE);
96      return Err(SerializationError::StreamTooShort);
97    }
98    mag.telemetry_header  = TelemetryPacketHeader::from_bytestream(stream, pos)?;
99    // we do have to deal with a bunch of empty bytes
100    *pos += 1;
101    let mut n_data = parse_u8(stream, pos);
102    if n_data != 16 {
103      error!("Decoding of magnetometer packet faILed! We expected 16 data bytes, but got {} instead!", n_data);
104      return Err(SerializationError::WrongByteSize);
105    }
106    //*pos += n_empty as usize;
107    mag.mag_x = parse_u16_be(stream, pos);
108    mag.acc_x = parse_u16_be(stream, pos);
109    mag.mag_y = parse_u16_be(stream, pos);
110    mag.acc_y = parse_u16_be(stream, pos);
111    mag.mag_z = parse_u16_be(stream, pos);
112    mag.acc_z = parse_u16_be(stream, pos);
113    mag.temp  = parse_u16(stream, pos);
114    //i += from_bytes(&bytes[i],temp);
115    //i +=2; // the other temp we do not understand
116    *pos += 2; // ALEX - "the other temp we do not understand"
117    //i += from_bytes(&bytes[i],zero);
118    mag.zero  = parse_u8(stream, pos);
119    if mag.zero != 0 {
120      // FIXME - better error type
121      error!("Decoding of magnetometer packet failed! Byte whcih should be zero is not zero!");
122      return Err(SerializationError::WrongByteSize);
123    }
124    *pos += 1; // ALEX - "the checksum we are not checking"
125    mag.end_byte = parse_u16_be(stream, pos);
126    if mag.end_byte != 32767 {
127      error!("Decoding of magnetormeter packet faailed! Tail incorrect!");
128      return Err(SerializationError::TailInvalid);
129    }
130    *pos += 1; // empty bytes that we do not care about from the first magnetometer packet
131    n_data     = parse_u8(stream, pos);
132    if n_data != 16 {
133      error!("The second magnetometer data chunk seems to have the wrong size! ({} instead of 16)", n_data);
134      return Err(SerializationError::WrongByteSize);
135    };
136    mag.roll        = parse_u16_be(stream, pos); 
137    mag.mag_roll    = parse_u16_be(stream, pos); 
138    mag.pitch       = parse_u16_be(stream, pos); 
139    mag.mag_field   = parse_u16_be(stream, pos); 
140    mag.yaw         = parse_u16_be(stream, pos); 
141    mag.grav_field  = parse_u16_be(stream, pos); 
142    *pos += 4; // ALEX - "more temp data we are not reading out"
143    mag.zero = parse_u8(stream, pos);
144    if mag.zero != 0 {
145      // FIXME - better error type
146      error!("Decoding of magnetometer packet failed! Byte whcih should be zero is not zero!");
147      return Err(SerializationError::WrongByteSize);
148    }
149    *pos += 1; // ALEX  - "another checksum (from second packet) we are not checking"
150    mag.end_byte = parse_u16_be(stream, pos);
151    if mag.end_byte != 32767 {
152      error!("Decoding of magnetormeter packet faailed! Tail incorrect!");
153      return Err(SerializationError::TailInvalid);
154    }
155    Ok(mag)
156  }
157}
158
159#[cfg(feature="pybindings")]
160#[pymethods]
161impl MagnetoMeter {
162
163  #[getter]
164  fn get_temp         (&self) -> u16 { 
165    self.temp
166  }
167  
168  #[getter]
169  fn get_mag_x        (&self) -> u16 { 
170    self.mag_x
171  }
172  
173  #[getter]
174  fn get_mag_y        (&self) -> u16 { 
175    self.mag_y
176  }
177  
178  #[getter]
179  fn get_mag_z        (&self) -> u16 { 
180    self.mag_z
181  }
182  
183  //#[getter]
184  //fn mag_tot        (&self) -> u16 { 
185  //  self.mag.mag_z
186  //}
187  
188  #[getter]
189  fn get_acc_x        (&self) -> u16 { 
190    self.acc_x
191  }
192  
193  #[getter]
194  fn get_acc_y        (&self) -> u16 { 
195    self.acc_y
196  }
197  
198  #[getter]
199  fn get_acc_z        (&self) -> u16 { 
200    self.acc_z
201  }
202  
203  #[getter]
204  fn get_roll         (&self) -> u16 { 
205    self.roll
206  }
207  
208  #[getter]
209  fn get_pitch        (&self) -> u16 { 
210    self.pitch
211  }
212  
213  #[getter]
214  fn get_yaw          (&self) -> u16 { 
215    self.yaw
216  }
217  
218  #[getter]
219  fn get_mag_roll     (&self) -> u16 { 
220    self.mag_roll
221  }
222  
223  #[getter]
224  fn get_mag_field    (&self) -> u16 { 
225    self.mag_field
226  }
227  
228  #[getter]
229  fn get_grav_field   (&self) -> u16 { 
230    self.grav_field
231  }
232 
233 //fn expected_size(&self) -> u64 { 
234 //fn end_byte     (&self) -> u16 { 
235 //fn zero         (&self) -> u8  { 
236 //fn ndata        (&self) -> u8  { 
237}
238
239#[cfg(feature="pybindings")]
240pythonize_telemetry!(MagnetoMeter);
241