Skip to main content

tuxar_modes/
lib.rs

1use crate::adsb::AdsbMessage;
2
3pub mod adsb;
4
5#[derive(Clone, PartialEq, Eq)]
6pub struct DF17Message {
7    pub capability: u8,
8    pub icao: u32,
9    pub tc: u8,
10    pub msg: AdsbMessage,
11}
12
13impl std::fmt::Debug for DF17Message {
14    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
15        f.debug_struct("DF17Message")
16            .field("capability", &self.capability)
17            .field("icao", &format_args!("{:06X}", self.icao))
18            .field("tc", &self.tc)
19            .field("msg", &self.msg)
20            .finish()
21    }
22}
23
24impl DF17Message {
25    pub fn decode(data: Vec<u8>) -> DF17Message {
26        let capability = data[0] & 0x07;
27        let icao = u32::from_be_bytes([0, data[1], data[2], data[3]]);
28        let tc = (data[4] >> 3) & 0x1F;
29        let msg = AdsbMessage::decode(data);
30        DF17Message { capability, icao, tc, msg }
31    }
32}
33
34#[derive(Clone, PartialEq, Eq)]
35pub struct DF18Message {
36    pub control: u8,
37    pub icao: u32,
38    pub tc: Option<u8>,
39    pub msg: Option<AdsbMessage>,
40}
41
42impl std::fmt::Debug for DF18Message {
43    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
44        f.debug_struct("DF18Message")
45            .field("control", &self.control)
46            .field("icao", &format_args!("{:06X}", self.icao))
47            .field("tc", &self.tc)
48            .field("msg", &self.msg)
49            .finish()
50    }
51}
52
53impl DF18Message {
54    pub fn decode(data: Vec<u8>) -> DF18Message {
55        let control = data[0] & 0x07;
56        let icao = u32::from_be_bytes([0, data[1], data[2], data[3]]);
57        let (tc, msg) = if control == 0 {
58            let tc = (data[4] >> 3) & 0x1F;
59            let msg = AdsbMessage::decode(data);
60            (Some(tc), Some(msg))
61        } else {
62            (None, None)
63        };
64        DF18Message { control, icao, tc, msg }
65    }
66}
67
68#[derive(Clone, PartialEq, Eq)]
69pub struct DF19Message {
70    pub application: u8,
71    pub icao: u32,
72    pub tc: Option<u8>,
73    pub msg: Option<AdsbMessage>,
74}
75
76impl std::fmt::Debug for DF19Message {
77    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
78        f.debug_struct("DF19Message")
79            .field("application", &self.application)
80            .field("icao", &format_args!("{:06X}", self.icao))
81            .field("tc", &self.tc)
82            .field("msg", &self.msg)
83            .finish()
84    }
85}
86
87impl DF19Message {
88    pub fn decode(data: Vec<u8>) -> DF19Message {
89        let application = data[0] & 0x07;
90        let icao = u32::from_be_bytes([0, data[1], data[2], data[3]]);
91        let (tc, msg) = if application == 0 {
92            let tc = (data[4] >> 3) & 0x1F;
93            let msg = AdsbMessage::decode(data);
94            (Some(tc), Some(msg))
95        } else {
96            (None, None)
97        };
98        DF19Message { application, icao, tc, msg }
99    }
100}
101
102#[derive(Debug, Clone, PartialEq, Eq)]
103pub enum ModeSMessage {
104    DF17(DF17Message),
105    DF18(DF18Message),
106    DF19(DF19Message),
107    Other(Vec<u8>),
108}
109
110impl ModeSMessage {
111    pub fn decode(data: Vec<u8>) -> Option<ModeSMessage> {
112        if !matches!(data.len(), 7 | 14) {
113            return None;
114        }
115
116        let df: u8 = (data[0] & 0xF8) >> 3;
117
118        match df {
119            17 => Some(ModeSMessage::DF17(DF17Message::decode(data))),
120            18 => Some(ModeSMessage::DF18(DF18Message::decode(data))),
121            19 => Some(ModeSMessage::DF19(DF19Message::decode(data))),
122            _ => Some(ModeSMessage::Other(data)),
123        }
124    }
125}