use super::*;
#[derive(Default, Clone, Debug, PartialEq)]
pub struct BaseStationReport {
pub own_vessel: bool,
pub station: Station,
pub mmsi: u32,
pub timestamp: Option<DateTime<Utc>>,
pub high_position_accuracy: bool,
pub latitude: Option<f64>,
pub longitude: Option<f64>,
pub position_fix_type: Option<PositionFixType>,
pub raim_flag: bool,
pub radio_status: u32,
}
impl LatLon for BaseStationReport {
fn latitude(&self) -> Option<f64> {
self.latitude
}
fn longitude(&self) -> Option<f64> {
self.longitude
}
}
pub(crate) fn handle(
bv: &BitVec,
station: Station,
own_vessel: bool,
) -> Result<ParsedMessage, ParseError> {
Ok(ParsedMessage::BaseStationReport(BaseStationReport {
own_vessel: { own_vessel },
station: { station },
mmsi: { pick_u64(bv, 8, 30) as u32 },
timestamp: {
Some(parse_ymdhs(
pick_u64(bv, 38, 14) as i32,
pick_u64(bv, 52, 4) as u32,
pick_u64(bv, 56, 5) as u32,
pick_u64(bv, 61, 5) as u32,
pick_u64(bv, 66, 6) as u32,
pick_u64(bv, 72, 6) as u32,
)?)
},
high_position_accuracy: { pick_u64(bv, 78, 1) != 0 },
latitude: {
let lat_raw = pick_i64(bv, 107, 27) as i32;
if lat_raw != 0x3412140 {
Some((lat_raw as f64) / 600000.0)
} else {
None
}
},
longitude: {
let lon_raw = pick_i64(bv, 79, 28) as i32;
if lon_raw != 0x6791AC0 {
Some((lon_raw as f64) / 600000.0)
} else {
None
}
},
position_fix_type: {
let raw = pick_u64(bv, 134, 4) as u8;
match raw {
0 => None,
_ => Some(PositionFixType::new(raw)),
}
},
raim_flag: { pick_u64(bv, 148, 1) != 0 },
radio_status: { pick_u64(bv, 149, 19) as u32 },
}))
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_parse_vdm_type4() {
let mut p = NmeaParser::new();
match p.parse_sentence("!AIVDM,1,1,,A,403OviQuMGCqWrRO9>E6fE700@GO,0*4D") {
Ok(ps) => {
match ps {
ParsedMessage::BaseStationReport(bsr) => {
assert_eq!(bsr.mmsi, 3669702);
assert_eq!(
bsr.timestamp,
Utc.with_ymd_and_hms(2007, 5, 14, 19, 57, 39).single()
);
assert!(bsr.high_position_accuracy);
assert::close(bsr.latitude.unwrap_or(0.0), 36.884, 0.001);
assert::close(bsr.longitude.unwrap_or(0.0), -76.352, 0.001);
assert_eq!(bsr.position_fix_type, Some(PositionFixType::Surveyed));
assert!(!bsr.raim_flag);
assert_eq!(bsr.radio_status, 67039);
}
ParsedMessage::Incomplete => {
assert!(false);
}
_ => {
assert!(false);
}
}
}
Err(e) => {
assert_eq!(e.to_string(), "OK");
}
}
}
}