use chrono::NaiveTime;
use nom::{character::complete::char, combinator::opt, number::complete::float, IResult};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use crate::{
parse::NmeaSentence,
sentences::utils::{number, parse_hms, parse_lat_lon},
Error, SentenceType,
};
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "defmt-03", derive(defmt::Format))]
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct GbsData {
#[cfg_attr(feature = "defmt-03", 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)(i)?;
let (i, _) = char(',')(i)?;
let (i, lat_lon_errors) = parse_lat_lon(i)?;
let (i, _) = char(',')(i)?;
let (i, alt_error) = opt(float)(i)?;
let (i, _) = char(',')(i)?;
let (i, most_likely_failed_sat) = opt(number::<u8>)(i)?;
let (i, _) = char(',')(i)?;
let (i, missed_probability) = opt(float)(i)?;
let (i, _) = char(',')(i)?;
let (i, bias_estimate) = opt(float)(i)?;
let (i, _) = char(',')(i)?;
let (i, bias_standard_deviation) = opt(float)(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)
}
}