nom_teltonika/
protocol.rs

1use chrono::{DateTime, Utc};
2
3#[cfg(feature = "serde")]
4use serde::{Deserialize, Serialize};
5
6use crate::parser::{tcp_frame, udp_datagram};
7
8/// Represent the device Codec
9///
10/// | TCP/UDP | GPRS |
11/// |---------|------|
12/// | C8      | C12  |
13/// | C8Ext   | C13  |
14/// | C16     | C14  |
15#[derive(Debug, PartialEq, Copy, Clone)]
16#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
17pub enum Codec {
18    C8,
19    C8Ext,
20    C16,
21    C12,
22    C13,
23    C14,
24}
25
26impl From<u8> for Codec {
27    fn from(value: u8) -> Self {
28        match value {
29            0x08 => Self::C8,
30            0x8E => Self::C8Ext,
31            0x10 => Self::C16,
32            0x0C => Self::C12,
33            0x0D => Self::C13,
34            0x0E => Self::C14,
35            _ => panic!("Unknown value: {}", value),
36        }
37    }
38}
39
40impl From<Codec> for u8 {
41    fn from(value: Codec) -> u8 {
42        match value {
43            Codec::C8 => 0x08,
44            Codec::C8Ext => 0x8E,
45            Codec::C16 => 0x10,
46            Codec::C12 => 0x0C,
47            Codec::C13 => 0x0D,
48            Codec::C14 => 0x0E,
49        }
50    }
51}
52
53/// Record priority
54///
55/// Indicates based on configuration how important the record is
56#[derive(Debug, PartialEq, Copy, Clone)]
57#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
58pub enum Priority {
59    Low,
60    High,
61    Panic,
62}
63
64impl From<u8> for Priority {
65    fn from(value: u8) -> Self {
66        match value {
67            0x00 => Self::Low,
68            0x01 => Self::High,
69            0x02 => Self::Panic,
70            _ => panic!("Unknown value: {}", value),
71        }
72    }
73}
74
75/// Event generation
76///
77/// Indicates the cause for the event trigger see [`AVLRecord`]
78#[derive(Debug, PartialEq, Copy, Clone)]
79#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
80pub enum EventGenerationCause {
81    None,
82    OnExit,
83    OnEntrance,
84    OnBoth,
85    Reserved,
86    Hysteresis,
87    OnChange,
88    Eventual,
89    Periodical,
90}
91
92impl From<u8> for EventGenerationCause {
93    fn from(value: u8) -> Self {
94        match value {
95            0 => Self::OnExit,
96            1 => Self::OnEntrance,
97            2 => Self::OnBoth,
98            3 => Self::Reserved,
99            4 => Self::Hysteresis,
100            5 => Self::OnChange,
101            6 => Self::Eventual,
102            7 => Self::Periodical,
103            _ => panic!("Unknown value: {}", value),
104        }
105    }
106}
107
108/// UDP Datagram sent by the device
109///
110/// Represent the whole channel information
111#[derive(Debug, PartialEq, Clone)]
112#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
113pub struct AVLDatagram {
114    /// The udp channel packet id
115    pub packet_id: u16,
116    /// The actual id of the AVL packet
117    pub avl_packet_id: u8,
118    pub imei: String,
119    pub codec: Codec,
120    /// All the records sent with this datagram
121    pub records: Vec<AVLRecord>,
122}
123
124impl<'a> TryFrom<&'a [u8]> for AVLDatagram {
125    type Error = nom::Err<nom::error::Error<&'a [u8]>>;
126
127    fn try_from(value: &'a [u8]) -> Result<Self, Self::Error> {
128        match udp_datagram(value) {
129            Ok((_, datagram)) => Ok(datagram),
130            Err(e) => Err(e),
131        }
132    }
133}
134
135/// Frame sent by the device when sending records
136#[derive(Debug, PartialEq, Clone)]
137#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
138pub struct AVLFrame {
139    pub codec: Codec,
140    /// All the records sent with this frame
141    pub records: Vec<AVLRecord>,
142    /// CRC16 Calculated using [IBM/CRC16][super::crc16] algorithm and 0xA001 polynomial
143    pub crc16: u32,
144}
145
146impl<'a> TryFrom<&'a [u8]> for AVLFrame {
147    type Error = nom::Err<nom::error::Error<&'a [u8]>>;
148
149    fn try_from(value: &'a [u8]) -> Result<Self, Self::Error> {
150        match tcp_frame(value) {
151            Ok((_, TeltonikaFrame::AVL(frame))) => Ok(frame),
152            Err(e) => Err(e),
153            _ => Err(nom::Err::Failure(nom::error::Error::new(
154                value,
155                nom::error::ErrorKind::Fail,
156            ))),
157        }
158    }
159}
160
161/// Location and IO Status information at a certain point in time
162#[derive(Debug, PartialEq, Clone)]
163#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
164pub struct AVLRecord {
165    /// In Utc Dates
166    pub timestamp: DateTime<Utc>,
167    /// How important this record is, see [`Priority`]
168    pub priority: Priority,
169    pub longitude: f64,
170    pub latitude: f64,
171    pub altitude: u16,
172    /// Degrees
173    pub angle: u16,
174    /// How many satellites were connected
175    pub satellites: u8,
176    /// Km/h
177    pub speed: u16,
178    /// Which event triggered the recording
179    pub trigger_event_id: u16,
180    /// How was the event generated see [`EventGenerationCause`]
181    pub generation_type: Option<EventGenerationCause>,
182    /// Current IO Event statuses
183    pub io_events: Vec<AVLEventIO>,
184}
185
186/// IO event status
187#[derive(Debug, PartialEq, Clone)]
188#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
189pub struct AVLEventIO {
190    /// Event ID
191    pub id: u16,
192    /// Raw event value.
193    ///
194    /// Should be mapped to the real values using a AVL IO ID List
195    pub value: AVLEventIOValue,
196}
197
198#[derive(Debug, PartialEq, Clone)]
199#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
200pub enum AVLEventIOValue {
201    U8(u8),
202    U16(u16),
203    U32(u32),
204    U64(u64),
205    #[cfg_attr(feature = "serde", serde(with = "serde_bytes"))]
206    Variable(Vec<u8>),
207}
208
209/// Frame sent by the device when sending command responses
210#[derive(Debug, PartialEq, Clone)]
211#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
212pub struct GPRSFrame {
213    pub codec: Codec,
214    /// All the commands to send with this buffer
215    pub command_responses: Vec<String>,
216    /// CRC16 Calculated using [IBM/CRC16][super::crc16] algorithm and 0xA001 polynomial
217    pub crc16: u32,
218}
219
220/// Frame sent by the device
221///
222/// Based on [Teltonika Protocol Wiki](https://wiki.teltonika-gps.com/view/Teltonika_Data_Sending_Protocols#)
223#[derive(Debug, PartialEq, Clone)]
224#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
225pub enum TeltonikaFrame {
226    AVL(AVLFrame),
227    GPRS(GPRSFrame),
228}
229
230impl TeltonikaFrame {
231    pub fn unwrap_avl(self) -> AVLFrame {
232        if let Self::AVL(frame) = self {
233            return frame;
234        }
235        panic!("Frame is GPRS!")
236    }
237
238    pub fn unwrap_gprs(self) -> GPRSFrame {
239        if let Self::GPRS(frame) = self {
240            return frame;
241        }
242        panic!("Frame is AVL!")
243    }
244}