1use crate::ParsingError;
2use byteorder::{ReadBytesExt, LE};
3use itertools::Itertools;
4use serde::{Deserialize, Serialize};
5use std::convert::TryFrom;
6use std::fmt;
7use std::io::{BufRead, Cursor};
8use std::mem::size_of;
9
10use async_graphql::{Enum, SimpleObject};
11
12#[cfg(feature = "pumqry")]
13use clap::ValueEnum;
14
15#[cfg(test)]
16use rand::rngs::SmallRng;
17
18use super::DEFAULT_RESPONSE_DELAY;
19
20#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, Enum)]
21#[repr(u8)]
22pub enum DataType {
24 Str = b'S',
25 Char = b'c',
26 UINT8 = b'u',
27 INT8 = b't',
28 UINT16 = b's',
29 INT16 = b'n',
30 UINT32 = b'i',
31 INT32 = b'd',
32 UINT64 = b'l',
33 INT64 = b'k',
34 Float = b'f',
35 Double = b'F',
36 Hex8 = b'x',
37 Hex16 = b'z',
38}
39
40impl Into<char> for DataType {
42 fn into(self) -> char {
43 self as u8 as char
44 }
45}
46
47impl TryFrom<char> for DataType {
48 type Error = ParsingError;
49
50 fn try_from(c: char) -> Result<Self, ParsingError> {
51 match c {
52 'S' => Ok(DataType::Str),
53 'c' => Ok(DataType::Char),
54 'u' => Ok(DataType::UINT8),
55 't' => Ok(DataType::INT8),
56 's' => Ok(DataType::UINT16),
57 'n' => Ok(DataType::INT16),
58 'i' => Ok(DataType::UINT32),
59 'd' => Ok(DataType::INT32),
60 'l' => Ok(DataType::UINT64),
61 'k' => Ok(DataType::INT64),
62 'f' => Ok(DataType::Float),
63 'F' => Ok(DataType::Double),
64 'x' => Ok(DataType::Hex8),
65 'X' => Ok(DataType::Hex8),
66 'z' => Ok(DataType::Hex16),
67 'Z' => Ok(DataType::Hex16),
68 _ => Err(ParsingError::InvalidFormatCharacter(c)),
69 }
70 }
71}
72
73impl DataType {
74 pub fn get_byte_length(&self) -> Option<usize> {
76 match self {
77 DataType::Str => None,
78 DataType::Char => Some(1),
79 DataType::UINT8 => Some(size_of::<u8>()),
80 DataType::INT8 => Some(size_of::<i8>()),
81 DataType::UINT16 => Some(size_of::<u16>()),
82 DataType::INT16 => Some(size_of::<i16>()),
83 DataType::UINT32 => Some(size_of::<u32>()),
84 DataType::INT32 => Some(size_of::<i32>()),
85 DataType::UINT64 => Some(size_of::<u64>()),
86 DataType::INT64 => Some(size_of::<i64>()),
87 DataType::Float => Some(size_of::<f32>()),
88 DataType::Double => Some(size_of::<f64>()),
89 DataType::Hex8 => Some(1),
90 DataType::Hex16 => Some(2),
91 }
92 }
93}
94
95#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, SimpleObject)]
96pub struct SupMCUFormat {
98 format: Vec<DataType>,
99}
100
101impl IntoIterator for SupMCUFormat {
102 type Item = DataType;
103 type IntoIter = std::vec::IntoIter<Self::Item>;
104
105 fn into_iter(self) -> Self::IntoIter {
106 self.format.into_iter()
107 }
108}
109
110impl SupMCUFormat {
111 pub fn new(fmt_str: &str) -> Self {
113 let mut format = vec![];
114 for c in fmt_str.chars() {
115 if let Ok(t) = DataType::try_from(c) {
116 format.push(t);
117 }
118 }
119 SupMCUFormat { format }
120 }
121
122 pub fn get_byte_length(&self) -> Option<usize> {
125 let mut sum: usize = 0;
126 for b in self.format.as_slice() {
127 if let Some(l) = b.get_byte_length() {
128 sum += l;
129 } else {
130 return None;
131 }
132 }
133 Some(sum)
134 }
135
136 pub fn get_format_str(&self) -> String {
138 let mut s = String::new();
139 for c in self.format.as_slice() {
140 s.push((*c).into());
141 }
142 s
143 }
144
145 pub fn parse_data(
147 &self,
148 rdr: &mut Cursor<&Vec<u8>>,
149 ) -> Result<Vec<SupMCUValue>, ParsingError> {
150 let mut out = vec![];
151
152 for dt in self.format.as_slice() {
153 out.push(match dt {
154 DataType::Str => {
155 let mut buf = vec![];
156 rdr.read_until(0, &mut buf)?;
157 buf.pop();
158 SupMCUValue::Str(String::from_utf8(buf)?)
159 }
160 DataType::Char => SupMCUValue::Char(rdr.read_u8()? as char),
161 DataType::UINT8 => SupMCUValue::U8(rdr.read_u8()?),
162 DataType::INT8 => SupMCUValue::I8(rdr.read_i8()?),
163 DataType::UINT16 => SupMCUValue::U16(rdr.read_u16::<LE>()?),
164 DataType::INT16 => SupMCUValue::I16(rdr.read_i16::<LE>()?),
165 DataType::UINT32 => SupMCUValue::U32(rdr.read_u32::<LE>()?),
166 DataType::INT32 => SupMCUValue::I32(rdr.read_i32::<LE>()?),
167 DataType::UINT64 => SupMCUValue::U64(rdr.read_u64::<LE>()?),
168 DataType::INT64 => SupMCUValue::I64(rdr.read_i64::<LE>()?),
169 DataType::Float => SupMCUValue::Float(rdr.read_f32::<LE>()?),
170 DataType::Double => SupMCUValue::Double(rdr.read_f64::<LE>()?),
171 DataType::Hex8 => SupMCUValue::Hex8(rdr.read_u8()?),
172 DataType::Hex16 => SupMCUValue::Hex16(rdr.read_u16::<LE>()?),
173 });
174 }
175 Ok(out)
176 }
177
178 #[cfg(test)]
180 pub fn random_data(&self, rng: &mut SmallRng) -> Vec<SupMCUValue> {
181 use rand::Rng;
182
183 let mut out = vec![];
184
185 for dt in self.format.as_slice() {
186 out.push(match dt {
187 DataType::Str => SupMCUValue::Str("A random string".into()),
188 DataType::Char => SupMCUValue::Char(rng.gen::<u8>() as char),
189 DataType::UINT8 => SupMCUValue::U8(rng.gen()),
190 DataType::INT8 => SupMCUValue::I8(rng.gen()),
191 DataType::UINT16 => SupMCUValue::U16(rng.gen()),
192 DataType::INT16 => SupMCUValue::I16(rng.gen()),
193 DataType::UINT32 => SupMCUValue::U32(rng.gen()),
194 DataType::INT32 => SupMCUValue::I32(rng.gen()),
195 DataType::UINT64 => SupMCUValue::U64(rng.gen()),
196 DataType::INT64 => SupMCUValue::I64(rng.gen()),
197 DataType::Float => SupMCUValue::Float(rng.gen()),
198 DataType::Double => SupMCUValue::Double(rng.gen()),
199 DataType::Hex8 => SupMCUValue::Hex8(rng.gen()),
200 DataType::Hex16 => SupMCUValue::Hex16(rng.gen()),
201 });
202 }
203 out
204 }
205}
206
207#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
208#[serde(tag = "type", content = "value")]
209pub enum SupMCUValue {
210 Str(String),
211 Char(char),
212 U8(u8),
213 I8(i8),
214 U16(u16),
215 I16(i16),
216 U32(u32),
217 I32(i32),
218 U64(u64),
219 I64(i64),
220 Float(f32),
221 Double(f64),
222 Hex8(u8),
223 Hex16(u16),
224}
225
226impl fmt::Display for SupMCUValue {
227 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
228 match self {
229 SupMCUValue::Str(i) => write!(f, "{i}"),
230 SupMCUValue::Char(i) => write!(f, "{i}"),
231 SupMCUValue::U8(i) => write!(f, "{i}"),
232 SupMCUValue::I8(i) => write!(f, "{i}"),
233 SupMCUValue::U16(i) => write!(f, "{i}"),
234 SupMCUValue::I16(i) => write!(f, "{i}"),
235 SupMCUValue::U32(i) => write!(f, "{i}"),
236 SupMCUValue::I32(i) => write!(f, "{i}"),
237 SupMCUValue::U64(i) => write!(f, "{i}"),
238 SupMCUValue::I64(i) => write!(f, "{i}"),
239 SupMCUValue::Float(i) => write!(f, "{i}"),
240 SupMCUValue::Double(i) => write!(f, "{i}"),
241 SupMCUValue::Hex8(i) => write!(f, "0x{i:x}"),
242 SupMCUValue::Hex16(i) => write!(f, "0x{i:x}"),
243 }
244 }
245}
246
247impl Into<Vec<u8>> for SupMCUValue {
248 fn into(self) -> Vec<u8> {
249 match self {
250 SupMCUValue::Str(i) => i.into_bytes(),
251 SupMCUValue::Char(i) => (i as u8).to_le_bytes().to_vec(),
252 SupMCUValue::U8(i) => i.to_le_bytes().to_vec(),
253 SupMCUValue::I8(i) => i.to_le_bytes().to_vec(),
254 SupMCUValue::U16(i) => i.to_le_bytes().to_vec(),
255 SupMCUValue::I16(i) => i.to_le_bytes().to_vec(),
256 SupMCUValue::U32(i) => i.to_le_bytes().to_vec(),
257 SupMCUValue::I32(i) => i.to_le_bytes().to_vec(),
258 SupMCUValue::U64(i) => i.to_le_bytes().to_vec(),
259 SupMCUValue::I64(i) => i.to_le_bytes().to_vec(),
260 SupMCUValue::Float(i) => i.to_le_bytes().to_vec(),
261 SupMCUValue::Double(i) => i.to_le_bytes().to_vec(),
262 SupMCUValue::Hex8(i) => i.to_le_bytes().to_vec(),
263 SupMCUValue::Hex16(i) => i.to_le_bytes().to_vec(),
264 }
265 }
266}
267
268#[derive(Debug, Serialize, Deserialize)]
269pub struct SupMCUHDR {
270 pub ready: bool,
271 pub timestamp: u32,
272}
273
274impl TryFrom<&mut Cursor<&Vec<u8>>> for SupMCUHDR {
275 type Error = ParsingError;
276
277 fn try_from(rdr: &mut Cursor<&Vec<u8>>) -> Result<Self, Self::Error> {
278 Ok(SupMCUHDR {
279 ready: rdr.read_u8()? & 0b01 == 1,
280 timestamp: rdr.read_u32::<LE>()?,
281 })
282 }
283}
284
285#[cfg(test)]
286impl Into<Vec<u8>> for SupMCUHDR {
287 fn into(self) -> Vec<u8> {
288 let mut buf = vec![self.ready as u8];
289 buf.extend(self.timestamp.to_le_bytes());
290 buf
291 }
292}
293
294pub type SupMCUTelemetryData = Vec<SupMCUValue>;
295
296#[derive(Debug, Serialize, Deserialize)]
297pub struct SupMCUTelemetry {
298 pub definition: SupMCUTelemetryDefinition,
299 pub header: SupMCUHDR,
300 pub data: SupMCUTelemetryData,
301}
302
303impl SupMCUTelemetry {
304 pub fn from_bytes(
305 buff: Vec<u8>,
306 def: &SupMCUTelemetryDefinition,
307 ) -> Result<Self, ParsingError> {
308 let mut rdr = Cursor::new(&buff);
309
310 Ok(SupMCUTelemetry {
311 definition: def.clone(),
312 header: SupMCUHDR::try_from(&mut rdr)?,
313 data: def.format.parse_data(&mut rdr)?,
314 })
315 }
316}
317
318#[cfg(test)]
319impl<'a> Into<&'a [u8]> for SupMCUTelemetry {
320 fn into(self) -> &'a [u8] {
321 todo!()
322 }
323}
324
325#[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize, Default, Copy, Enum)]
326#[cfg_attr(feature = "pumqry", derive(ValueEnum))]
327#[cfg_attr(feature = "pumqry", clap(rename_all = "lower"))]
328pub enum TelemetryType {
329 #[default]
330 SupMCU,
331 Module,
332}
333
334impl fmt::Display for TelemetryType {
335 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
336 match self {
337 TelemetryType::SupMCU => write!(f, "SupMCU"),
338 TelemetryType::Module => write!(f, "Module"),
339 }
340 }
341}
342
343#[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize, Copy, Enum, Default)]
344pub enum McuType {
345 #[default]
346 UNKNOWN,
347 PIC24EP256MC206,
348 PIC24EP512MC206,
349}
350
351impl fmt::Display for McuType {
352 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
353 match self {
354 McuType::UNKNOWN => write!(f, "UKNOWN"),
355 McuType::PIC24EP256MC206 => write!(f, "PIC24EP256MC206"),
356 McuType::PIC24EP512MC206 => write!(f, "PIC24EP512MC206"),
357 }
358 }
359}
360
361impl TryFrom<&u8> for McuType {
362 type Error = ParsingError;
363 fn try_from(value: &u8) -> Result<Self, Self::Error> {
364 match value {
365 1 => Ok(Self::PIC24EP256MC206),
366 2 => Ok(Self::PIC24EP512MC206),
367 _ => Err(ParsingError::McuIdParsingError(*value)),
368 }
369 }
370}
371
372#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, SimpleObject)]
373pub struct SupMCUTelemetryDefinition {
374 pub name: String,
375 #[serde(flatten)]
376 pub format: SupMCUFormat,
377 pub length: Option<usize>,
378 #[graphql(skip)]
379 pub default_sim_value: Option<Vec<SupMCUValue>>,
380 pub idx: usize,
381 pub telemetry_type: TelemetryType,
382}
383
384impl Default for SupMCUTelemetryDefinition {
385 fn default() -> Self {
386 SupMCUTelemetryDefinition {
387 name: "".into(),
388 format: SupMCUFormat::new(""),
389 length: None,
390 default_sim_value: None,
391 idx: 0,
392 telemetry_type: TelemetryType::SupMCU,
393 }
394 }
395}
396
397impl SupMCUTelemetryDefinition {
398 pub fn simulatable(&self) -> bool {
399 self.default_sim_value.is_some()
400 }
401}
402
403#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, SimpleObject)]
404pub struct SupMCUCommand {
405 pub name: String,
406 pub idx: u16,
407}
408
409#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, SimpleObject)]
410pub struct SupMCUModuleDefinition {
411 pub name: String,
413 pub address: u16,
414 pub simulatable: bool,
415 pub telemetry: Vec<SupMCUTelemetryDefinition>,
416 pub commands: Vec<SupMCUCommand>,
417 pub mcu: McuType,
418 pub response_delay: f32,
419}
420
421impl Default for SupMCUModuleDefinition {
422 fn default() -> Self {
423 SupMCUModuleDefinition {
424 name: "".into(),
425 address: 0,
426 simulatable: false,
427 telemetry: vec![],
428 commands: vec![],
429 mcu: McuType::UNKNOWN,
430 response_delay: DEFAULT_RESPONSE_DELAY,
431 }
432 }
433}
434
435impl fmt::Display for SupMCUModuleDefinition {
436 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
437 write!(f, "{} @ {}", self.name, self.address)
438 }
439}
440
441impl SupMCUModuleDefinition {
442 pub fn get_supmcu_telemetry(&self) -> Vec<SupMCUTelemetryDefinition> {
443 self.telemetry
444 .clone()
445 .into_iter()
446 .filter(|def| def.telemetry_type == TelemetryType::SupMCU)
447 .sorted_by_key(|def| def.idx)
448 .collect()
449 }
450
451 pub fn get_module_telemetry(&self) -> Vec<SupMCUTelemetryDefinition> {
452 self.telemetry
453 .clone()
454 .into_iter()
455 .filter(|def| def.telemetry_type == TelemetryType::Module)
456 .sorted_by_key(|def| def.idx)
457 .collect()
458 }
459}