-
Notifications
You must be signed in to change notification settings - Fork 41
/
mtw.rs
106 lines (96 loc) · 2.79 KB
/
mtw.rs
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
94
95
96
97
98
99
100
101
102
103
104
105
106
use nom::{
character::complete::{char, one_of},
combinator::opt,
number::complete::double,
sequence::preceded,
IResult,
};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use crate::{parse::NmeaSentence, Error, SentenceType};
/// MTW - Mean Temperature of Water
///
/// <https://gpsd.gitlab.io/gpsd/NMEA.html#_mtw_mean_temperature_of_water>
///
/// ```text
/// 1 2 3
/// | | |
/// $--MTW,x.x,C*hh<CR><LF>
/// ```
/// 1: Temperature, degrees
/// 2: Unit of Measurement, (only) Celsius
/// 3: Mandatory NMEA checksum
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "defmt-03", derive(defmt::Format))]
#[derive(Debug, PartialEq)]
pub struct MtwData {
pub temperature: Option<f64>,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "defmt-03", derive(defmt::Format))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MtwUnit {
Celsius,
}
/// # Parse MTW message
///
/// Information from mtw:
///
/// NMEA 0183 standard Mean Temperature of Water.
/// <https://gpsd.gitlab.io/gpsd/NMEA.html#_mtw_mean_temperature_of_water>
///
/// ## Example (Ignore the line break):
/// ```text
/// $INMTW,17.9,C*1B
///```
///
/// 1: 17.9 Temperature, degrees
/// 2: C Unit of Measurement, (only) Celsius
/// 3: *16 Mandatory NMEA checksum
pub fn parse_mtw(sentence: NmeaSentence) -> Result<MtwData, Error> {
if sentence.message_id != SentenceType::MTW {
Err(Error::WrongSentenceHeader {
expected: SentenceType::MTW,
found: sentence.message_id,
})
} else {
Ok(do_parse_mtw(sentence.data)?.1)
}
}
fn do_parse_mtw(i: &str) -> IResult<&str, MtwData> {
let (i, temperature_value) = opt(double)(i)?;
preceded(char(','), one_of("C"))(i)?;
Ok((
i,
MtwData {
temperature: temperature_value,
},
))
}
#[cfg(test)]
mod tests {
use super::*;
use crate::parse::parse_nmea_sentence;
#[test]
fn test_parse_mtw() {
let s = parse_nmea_sentence("$INMTW,17.9,C*1B").unwrap();
assert_eq!(s.checksum, s.calc_checksum());
assert_eq!(s.checksum, 0x1B);
let mtw_data = parse_mtw(s).unwrap();
assert_eq!(Some(17.9), mtw_data.temperature);
}
#[test]
fn test_parse_mtw_invalid_unit() {
let s = parse_nmea_sentence("$INMTW,17.9,x*20").unwrap();
assert_eq!(s.checksum, s.calc_checksum());
assert_eq!(s.checksum, 0x20);
assert!(parse_mtw(s).is_err());
}
#[test]
fn test_parse_mtw_invalid_temp() {
let s = parse_nmea_sentence("$INMTW,x.9,C*65").unwrap();
assert_eq!(s.checksum, s.calc_checksum());
assert_eq!(s.checksum, 0x65);
assert!(parse_mtw(s).is_err());
}
}