///|
pub(all) enum GsaSelection {
AutomaticSelection
ManualSelection
} derive(Eq, Debug)
///|
pub(all) enum GsaFixMode {
NoDimensionalFix
TwoDimensional
ThreeDimensional
} derive(Eq, Debug)
///|
pub(all) struct GsaRecord {
talker_value : String
selection_value : GsaSelection
fix_mode_value : GsaFixMode
satellite_ids_value : Array[String]
pdop_value : ExactDecimal?
hdop_value : ExactDecimal?
vdop_value : ExactDecimal?
} derive(Eq, Debug)
///|
fn gsa_error(message : String) -> NmeaError {
NmeaError::from_diagnostic(
Diagnostic::new(SentenceInvalid, Error, message, SourceRef::sentence(0)),
)
}
///|
fn gsa_optional_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_gsa(frame : NmeaFrame) -> Result[GsaRecord, NmeaError] {
if frame.formatter() != "GSA" {
return Err(gsa_error("frame formatter is not GSA"))
}
let cursor = FieldCursor::new(frame.fields())
let selection_text = match cursor.required(0) {
Ok(value) => value
Err(error) => return Err(error)
}
let selection = if selection_text == "A" {
AutomaticSelection
} else if selection_text == "M" {
ManualSelection
} else {
return Err(gsa_error("GSA selection must be A or M"))
}
let mode = match cursor.integer(1, min=1, max=3) {
Ok(1) => NoDimensionalFix
Ok(2) => TwoDimensional
Ok(3) => ThreeDimensional
Ok(_) => return Err(gsa_error("GSA fix mode is invalid"))
Err(error) => return Err(error)
}
let satellites : Array[String] = []
for index = 2; index < 14; index = index + 1 {
match cursor.optional(index) {
Ok(Some(value)) => satellites.push(value)
Ok(None) => ()
Err(error) => return Err(error)
}
}
let pdop = match gsa_optional_decimal(cursor, 14) {
Ok(value) => value
Err(error) => return Err(error)
}
let hdop = match gsa_optional_decimal(cursor, 15) {
Ok(value) => value
Err(error) => return Err(error)
}
let vdop = match gsa_optional_decimal(cursor, 16) {
Ok(value) => value
Err(error) => return Err(error)
}
Ok({
talker_value: frame.talker(),
selection_value: selection,
fix_mode_value: mode,
satellite_ids_value: satellites,
pdop_value: pdop,
hdop_value: hdop,
vdop_value: vdop,
})
}
///|
pub fn GsaRecord::selection(self : GsaRecord) -> GsaSelection {
self.selection_value
}
///|
pub fn GsaRecord::fix_mode(self : GsaRecord) -> GsaFixMode {
self.fix_mode_value
}
///|
pub fn GsaRecord::satellite_ids(self : GsaRecord) -> Array[String] {
self.satellite_ids_value.copy()
}
///|
pub fn GsaRecord::pdop(self : GsaRecord) -> ExactDecimal? {
self.pdop_value
}
///|
pub fn GsaRecord::hdop(self : GsaRecord) -> ExactDecimal? {
self.hdop_value
}
///|
pub fn GsaRecord::vdop(self : GsaRecord) -> ExactDecimal? {
self.vdop_value
}
///|
fn gsa_decimal_text(value : ExactDecimal?) -> String {
match value {
Some(decimal) => decimal.to_string()
None => ""
}
}
///|
pub fn GsaRecord::encode(self : GsaRecord) -> Result[String, NmeaError] {
if self.satellite_ids_value.length() > 12 {
return Err(gsa_error("GSA cannot encode more than 12 satellite slots"))
}
let fields = [
match self.selection_value {
AutomaticSelection => "A"
ManualSelection => "M"
},
match self.fix_mode_value {
NoDimensionalFix => "1"
TwoDimensional => "2"
ThreeDimensional => "3"
},
]
for satellite in self.satellite_ids_value {
fields.push(satellite)
}
while fields.length() < 14 {
fields.push("")
}
fields.push(gsa_decimal_text(self.pdop_value))
fields.push(gsa_decimal_text(self.hdop_value))
fields.push(gsa_decimal_text(self.vdop_value))
Ok(NmeaFrame::new(36, self.talker_value, "GSA", fields).encode())
}