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};
#[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,
}
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());
}
}