1#![cfg_attr(not(test), no_std)]
2
3pub mod fast_packet;
28pub mod nmea_id;
29pub mod pgn_types;
30pub mod pgns;
31use fast_packet::{AddFrame, FastPacket};
32use heapless::Entry;
33use heapless::{FnvIndexMap, Vec};
34use nmea_id::NmeaId;
35use pgns::get_pgn_type::get_pgn_type;
36use pgns::pgn::Pgn;
37pub mod date;
38pub mod nmea_option;
39pub mod parse;
40
41#[derive(Debug)]
42pub struct NmeaParser {
43 pub fast_packet_map: FnvIndexMap<u32, FastPacket, 16>,
44}
45
46impl NmeaParser {
47 pub fn new() -> NmeaParser {
48 let fast_packet_map = FnvIndexMap::<u32, FastPacket, 16>::new();
49 NmeaParser { fast_packet_map }
50 }
51
52 pub fn parse(&mut self, id: u32, data: &[u8]) -> Option<Pgn> {
53 let pgn = NmeaId(id);
54 let pgn_type = get_pgn_type(pgn.get_pgn());
55 match pgn_type {
56 pgn_types::PgnType::Fast => {
57 if let Some(data) = self.parse_fast_packet(id, data) {
58 parse::get_nmea_message(pgn.get_pgn(), data.as_slice())
59 } else {
60 None
61 }
62 }
63 pgn_types::PgnType::Single => parse::get_nmea_message(pgn.get_pgn(), data),
64 _ => None,
65 }
66 }
67
68 pub fn parse_fast_packet(&mut self, id: u32, data: &[u8]) -> Option<Vec<u8, 128>> {
69 let nmea_message = NmeaId(id);
70 let pgn = nmea_message.get_pgn();
71 let fp = FastPacket::new(data);
72
73 if let Some(fp) = fp {
74 match self.fast_packet_map.entry(pgn) {
75 Entry::Vacant(packet) => {
76 packet.insert(fp).unwrap();
77 None
78 }
79 Entry::Occupied(mut packet) => {
80 let current_packet = packet.get_mut();
81 match current_packet.add_frame(data) {
82 AddFrame::Error => {
84 packet.remove();
85 let _ = self.fast_packet_map.insert(pgn, fp);
86 None
87 }
88 _ => None,
89 }
90 }
91 }
92 } else {
93 match self.fast_packet_map.entry(pgn) {
94 Entry::Vacant(_) => None,
95 Entry::Occupied(mut packet) => {
96 let fp = packet.get_mut();
97 match fp.add_frame(data) {
98 AddFrame::Error => {
100 packet.remove();
101 None
102 }
103 AddFrame::Complete => {
104 let (_, complete_packet) = packet.remove_entry();
105 Some(complete_packet.data)
106 }
107 _ => None,
108 }
109 }
110 }
111 }
112 }
113}
114
115#[cfg(test)]
116mod tests {
117
118 use chrono::Datelike;
119
120 use super::*;
121
122 #[test]
123 fn matches_pgn_correctly() {
124 let id = 233836644;
125 let data: &[u8] = &[255, 255, 79, 78, 144, 3, 32, 46];
126 let mut parser = NmeaParser::new();
127 let data = parser.parse(id, data);
128 let date = match data.unwrap() {
129 Pgn::SystemTime(time) => {
130 println!("{:?}", time);
131 Some(time)
132 }
133 _ => None,
134 };
135
136 assert_eq!(date.unwrap().date().datetime.year(), 2018);
137 }
138}