1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
use chrono::NaiveTime;
use nom::bytes::complete::take_until;
use nom::character::complete::{char, one_of};
use nom::combinator::{map, opt};
use nom::sequence::terminated;
use nom::IResult;
use crate::parse::NmeaSentence;
use crate::sentences::utils::{do_parse_lat_lon, parse_hms};
pub fn parse_gll(s: &NmeaSentence) -> Result<GllData, String> {
if s.message_id != b"GLL" {
return Err("GLL message should starts with $..GLL".into());
}
let ret = do_parse_gll(s.data)
.map(|(_, data)| data)
.map_err(|err| match err {
nom::Err::Incomplete(_) => "Incomplete nmea sentence".to_string(),
nom::Err::Error((_, kind)) | nom::Err::Failure((_, kind)) => {
kind.description().to_string()
}
})?;
Ok(ret)
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum PosSystemIndicator {
Autonomous,
Differential,
EstimatedMode,
ManualInput,
DataNotValid,
}
impl From<char> for PosSystemIndicator {
fn from(b: char) -> Self {
match b {
'A' => PosSystemIndicator::Autonomous,
'D' => PosSystemIndicator::Differential,
'E' => PosSystemIndicator::EstimatedMode,
'M' => PosSystemIndicator::ManualInput,
'N' => PosSystemIndicator::DataNotValid,
_ => PosSystemIndicator::DataNotValid,
}
}
}
#[derive(Debug, PartialEq)]
pub struct GllData {
pub latitude: f64,
pub longitude: f64,
pub fix_time: NaiveTime,
pub mode: Option<PosSystemIndicator>,
}
fn do_parse_gll(i: &[u8]) -> IResult<&[u8], GllData> {
let (i, (latitude, longitude)) = do_parse_lat_lon(i)?;
let (i, _) = char(',')(i)?;
let (i, fix_time) = parse_hms(i)?;
let (i, _) = take_until(",")(i)?;
let (i, _) = char(',')(i)?;
let (i, _valid) = char('A')(i)?;
let (i, _) = char(',')(i)?;
let (i, mode) = opt(terminated(
map(one_of("ADEM"), PosSystemIndicator::from),
char(','),
))(i)?;
Ok((
i,
GllData {
latitude,
longitude,
fix_time,
mode,
},
))
}