///|
pub(all) struct VtgRecord {
talker_value : String
true_course_value : ExactDecimal?
magnetic_course_value : ExactDecimal?
speed_knots_value : ExactDecimal?
speed_kph_value : ExactDecimal?
mode_value : String?
} derive(Eq, Debug)
///|
fn vtg_error(message : String) -> NmeaError {
NmeaError::from_diagnostic(
Diagnostic::new(SentenceInvalid, Error, message, SourceRef::sentence(0)),
)
}
///|
fn vtg_decimal(
cursor : FieldCursor,
index : Int,
) -> Result[ExactDecimal?, NmeaError] {
match cursor.optional(index) {
Ok(None) => Ok(None)
Ok(Some(_)) =>
match cursor.decimal(index) {
Ok(value) => Ok(Some(value))
Err(error) => Err(error)
}
Err(error) => Err(error)
}
}
///|
pub fn parse_vtg(frame : NmeaFrame) -> Result[VtgRecord, NmeaError] {
if frame.formatter() != "VTG" {
return Err(vtg_error("frame formatter is not VTG"))
}
let cursor = FieldCursor::new(frame.fields())
let true_course = match vtg_decimal(cursor, 0) {
Ok(value) => value
Err(error) => return Err(error)
}
let true_marker = match cursor.optional(1) {
Ok(value) => value
Err(error) => return Err(error)
}
let magnetic_course = match vtg_decimal(cursor, 2) {
Ok(value) => value
Err(error) => return Err(error)
}
let magnetic_marker = match cursor.optional(3) {
Ok(value) => value
Err(error) => return Err(error)
}
let speed_knots = match vtg_decimal(cursor, 4) {
Ok(value) => value
Err(error) => return Err(error)
}
let knot_marker = match cursor.optional(5) {
Ok(value) => value
Err(error) => return Err(error)
}
let speed_kph = match vtg_decimal(cursor, 6) {
Ok(value) => value
Err(error) => return Err(error)
}
let kph_marker = match cursor.optional(7) {
Ok(value) => value
Err(error) => return Err(error)
}
if (true_course is Some(_) && true_marker != Some("T")) ||
(magnetic_course is Some(_) && magnetic_marker != Some("M")) ||
(speed_knots is Some(_) && knot_marker != Some("N")) ||
(speed_kph is Some(_) && kph_marker != Some("K")) {
return Err(vtg_error("VTG value has an invalid unit marker"))
}
let mode = match cursor.optional(8) {
Ok(value) => value
Err(error) => return Err(error)
}
Ok({
talker_value: frame.talker(),
true_course_value: true_course,
magnetic_course_value: magnetic_course,
speed_knots_value: speed_knots,
speed_kph_value: speed_kph,
mode_value: mode,
})
}
///|
pub fn VtgRecord::true_course(self : VtgRecord) -> ExactDecimal? {
self.true_course_value
}
///|
pub fn VtgRecord::magnetic_course(self : VtgRecord) -> ExactDecimal? {
self.magnetic_course_value
}
///|
pub fn VtgRecord::speed_knots(self : VtgRecord) -> ExactDecimal? {
self.speed_knots_value
}
///|
pub fn VtgRecord::speed_kph(self : VtgRecord) -> ExactDecimal? {
self.speed_kph_value
}
///|
pub fn VtgRecord::mode(self : VtgRecord) -> String? {
self.mode_value
}
///|
fn vtg_decimal_text(value : ExactDecimal?) -> String {
match value {
Some(decimal) => decimal.to_string()
None => ""
}
}
///|
pub fn VtgRecord::encode(self : VtgRecord) -> Result[String, NmeaError] {
let fields = [
vtg_decimal_text(self.true_course_value),
"T",
vtg_decimal_text(self.magnetic_course_value),
"M",
vtg_decimal_text(self.speed_knots_value),
"N",
vtg_decimal_text(self.speed_kph_value),
"K",
]
match self.mode_value {
Some(mode) => fields.push(mode)
None => ()
}
Ok(NmeaFrame::new(36, self.talker_value, "VTG", fields).encode())
}