1use super::*;
17
18#[derive(Clone, Debug, PartialEq, Serialize)]
20pub struct GsvData {
21 pub source: NavigationSystem,
23
24 pub prn_number: u8,
26
27 pub elevation: Option<f32>,
29
30 pub azimuth: Option<f32>,
32
33 pub snr: Option<f32>,
35}
36
37pub(crate) fn handle(
41 sentence: &str,
42 nav_system: NavigationSystem,
43 store: &mut NmeaParser,
44) -> Result<ParsedMessage, ParseError> {
45 let split: Vec<&str> = sentence.split(',').collect();
46
47 let msg_type = split.first().unwrap_or(&"");
48 let msg_count = pick_number_field(&split, 1)?.unwrap_or(0);
49 let msg_num = pick_number_field(&split, 2)?.unwrap_or(0);
50 store.push_string(make_gsv_key(msg_type, msg_count, msg_num), sentence.into());
51
52 let mut found_count = 0;
53 for i in 1..(msg_count + 1) {
54 if store.contains_key(make_gsv_key(msg_type, msg_count, i)) {
55 found_count += 1;
56 }
57 }
58
59 if found_count == msg_count {
60 let mut v = Vec::new();
61 for i in 1..(msg_count + 1) {
62 if let Some(sentence) = store.pull_string(make_gsv_key(msg_type, msg_count, i)) {
63 let split: Vec<&str> = sentence.split(',').collect();
64 for j in 0..4 {
65 if let Some(prn) = pick_number_field(&split, 4 + 4 * j as usize)
66 .ok()
67 .unwrap_or(None)
68 {
69 v.push(GsvData {
70 source: nav_system,
71 prn_number: prn,
72 elevation: pick_number_field(&split, 4 + 4 * j as usize + 1)
73 .ok()
74 .unwrap_or(None),
75 azimuth: pick_number_field(&split, 4 + 4 * j as usize + 2)
76 .ok()
77 .unwrap_or(None),
78 snr: pick_number_field(&split, 4 + 4 * j as usize + 3)
79 .ok()
80 .unwrap_or(None),
81 });
82 }
83 }
84 }
85 }
86
87 Ok(ParsedMessage::Gsv(v))
88 } else {
89 Ok(ParsedMessage::Incomplete)
90 }
91}
92
93fn make_gsv_key(sentence_type: &str, msg_count: u32, msg_num: u32) -> String {
95 format!("{},{},{}", sentence_type, msg_count, msg_num)
96}
97
98#[cfg(test)]
101mod test {
102 use super::*;
103
104 #[test]
109 fn test_parse_cpgsv() {
110 let mut p = NmeaParser::new();
111
112 match p
113 .parse_sentence("$GPGSV,3,1,11,03,03,111,00,04,15,270,00,06,01,010,00,13,06,292,00*74")
114 {
115 Ok(ps) => match ps {
116 ParsedMessage::Incomplete => {}
117 _ => {
118 assert!(false);
119 }
120 },
121 Err(e) => {
122 assert_eq!(e.to_string(), "OK");
123 }
124 }
125 assert_eq!(p.strings_count(), 1);
126
127 match p
128 .parse_sentence("$GPGSV,3,2,11,14,25,170,00,16,57,208,39,18,67,296,40,19,40,246,00*74")
129 {
130 Ok(ps) => match ps {
131 ParsedMessage::Incomplete => {}
132 _ => {
133 assert!(false);
134 }
135 },
136 Err(e) => {
137 assert_eq!(e.to_string(), "OK");
138 }
139 }
140 assert_eq!(p.strings_count(), 2);
141
142 match p.parse_sentence("$GPGSV,3,3,11,22,42,067,42,24,14,311,43,27,05,244,00,,,,*4D") {
143 Ok(ps) => {
144 match ps {
145 ParsedMessage::Gsv(v) => {
147 assert_eq!(v.len(), 11);
148
149 let s2 = v.get(1).unwrap();
151 assert_eq!(s2.elevation, Some(15.0));
152 assert_eq!(s2.azimuth, Some(270.0));
153 assert_eq!(s2.snr, Some(0.0));
154
155 let s5 = v.get(4).unwrap();
157 assert_eq!(s5.elevation, Some(25.0));
158 assert_eq!(s5.azimuth, Some(170.0));
159 assert_eq!(s5.snr, Some(0.0));
160
161 let s11 = v.get(10).unwrap();
163 assert_eq!(s11.elevation, Some(5.0));
164 assert_eq!(s11.azimuth, Some(244.0));
165 assert_eq!(s11.snr, Some(0.0));
166 }
167 _ => {
168 assert_eq!(p.strings_count(), 3);
169 assert!(false);
170 }
171 }
172 }
173 Err(e) => {
174 assert_eq!(e.to_string(), "OK");
175 }
176 }
177 assert_eq!(p.strings_count(), 0);
178 }
179}