use chrono::NaiveTime;
use nom::{
IResult, Parser as _, character::complete::char, combinator::opt, number::complete::float,
};
use crate::{
Error, SentenceType,
parse::NmeaSentence,
sentences::utils::{number, parse_hms, parse_lat_lon},
};
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct GbsData {
#[cfg_attr(feature = "defmt", defmt(Debug2Format))]
pub time: Option<NaiveTime>,
pub lat_error: Option<f64>,
pub lon_error: Option<f64>,
pub alt_error: Option<f32>,
pub most_likely_failed_sat: Option<u8>,
pub missed_probability: Option<f32>,
pub bias_estimate: Option<f32>,
pub bias_standard_deviation: Option<f32>,
}
fn do_parse_gbs(i: &str) -> IResult<&str, GbsData> {
let (i, time) = opt(parse_hms).parse(i)?;
let (i, _) = char(',').parse(i)?;
let (i, lat_lon_errors) = parse_lat_lon(i)?;
let (i, _) = char(',').parse(i)?;
let (i, alt_error) = opt(float).parse(i)?;
let (i, _) = char(',').parse(i)?;
let (i, most_likely_failed_sat) = opt(number::<u8>).parse(i)?;
let (i, _) = char(',').parse(i)?;
let (i, missed_probability) = opt(float).parse(i)?;
let (i, _) = char(',').parse(i)?;
let (i, bias_estimate) = opt(float).parse(i)?;
let (i, _) = char(',').parse(i)?;
let (i, bias_standard_deviation) = opt(float).parse(i)?;
Ok((
i,
GbsData {
time,
lat_error: lat_lon_errors.map(|(lat, _lon)| lat),
lon_error: lat_lon_errors.map(|(_lat, lon)| lon),
alt_error,
most_likely_failed_sat,
missed_probability,
bias_estimate,
bias_standard_deviation,
},
))
}
pub fn parse_gbs(sentence: NmeaSentence<'_>) -> Result<GbsData, Error<'_>> {
if sentence.message_id != SentenceType::GBS {
Err(Error::WrongSentenceHeader {
expected: SentenceType::GBS,
found: sentence.message_id,
})
} else {
Ok(do_parse_gbs(sentence.data)?.1)
}
}