Typed NMEA 0183 parsing, diagnostics, and evidence toolkit
let record = @nmea.parse_sentence(
"$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47\r\n",
).unwrap()
guard record is @nmea.GgaRecordValue(gga) else { abort("expected GGA") }
println(gga.satellites())pub(all) struct BatchSummary {
total_value : Int
successes_value : Int
failures_value : Int
formatter_entries_value : Array[StringCountEntry]
talker_entries_value : Array[StringCountEntry]
checksum_entries_value : Array[ChecksumCountEntry]
error_entries_value : Array[StringCountEntry]
} derive(Eq, Debug)fn BoundingBox::new(minimum_latitude : Double, maximum_latitude : Double, minimum_longitude : Double, maximum_longitude : Double) -> Result[BoundingBox, NmeaError]pub(all) struct ChecksumCountEntry {
status_value : ChecksumStatus
count_value : Int
} derive(Eq, Debug)pub(all) struct Coordinate {
axis_value : CoordinateAxis
degrees_value : Double
wire_value : ExactDecimal
hemisphere_value : UInt16
} derive(Eq, Debug)fn Diagnostic::new(code : NmeaErrorCode, severity : Severity, message : String, source : SourceRef) -> Diagnosticfn FieldCursor::decimal(self : FieldCursor, index : Int, max_scale? : Int) -> Result[ExactDecimal, NmeaError]fn FieldCursor::integer(self : FieldCursor, index : Int, min? : Int, max? : Int) -> Result[Int, NmeaError]pub(all) struct FieldProvenance {
field_value : String
source_value : FusionSource
record_index_value : Int
} derive(Eq, Debug)pub(all) struct FusedFix {
time_value : UtcTime
date_value : UtcDate?
latitude_value : Double?
longitude_value : Double?
altitude_value : ExactDecimal?
quality_value : GgaFixQuality?
satellites_value : Int?
speed_knots_value : ExactDecimal?
course_value : ExactDecimal?
usable_value : Bool
provenance_value : Array[FieldProvenance]
diagnostics_value : Array[Diagnostic]
source_record_indexes_value : Array[Int]
} derive(Eq, Debug)pub(all) struct GgaRecord {
talker_value : String
time_value : UtcTime
latitude_value : Coordinate?
longitude_value : Coordinate?
quality_value : GgaFixQuality
satellites_value : Int
hdop_value : ExactDecimal?
altitude_value : ExactDecimal?
geoid_separation_value : ExactDecimal?
dgps_age_value : ExactDecimal?
dgps_station_value : String?
} derive(Eq, Debug)pub(all) struct GllRecord {
talker_value : String
latitude_value : Coordinate
longitude_value : Coordinate
time_value : UtcTime
status_value : RmcStatus
mode_value : String?
} 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 GsvAssembler::push(self : GsvAssembler, record : GsvRecord, record_index~ : Int) -> Result[GsvAssembly?, NmeaError]pub(all) struct GsvAssembly {
talker_value : String
signal_id_value : String?
total_messages_value : Int
total_satellites_value : Int
observations_value : Array[SatelliteObservation]
source_record_indexes_value : Array[Int]
} derive(Eq, Debug)pub(all) struct GsvRecord {
talker_value : String
total_messages_value : Int
message_number_value : Int
total_satellites_value : Int
observations_value : Array[SatelliteObservation]
signal_id_value : String?
} derive(Eq, Debug)pub(all) struct NmeaBatch {
items_value : Array[SentenceResult[NmeaRecord]]
summary_value : BatchSummary
} derive(Eq, Debug)pub(all) struct NmeaChecksum {
value : Int
}pub(all) enum NmeaErrorCode {
FramingMissingStart
FramingInvalidPrefix
FramingMissingChecksumDelimiter
FramingTooLong
ChecksumMissing
ChecksumMalformed
ChecksumMismatch
FieldMissing
FieldEmpty
FieldInvalidInteger
FieldInvalidDecimal
CoordinateInvalid
DateInvalid
TimeInvalid
SentenceUnsupported
SentenceInvalid
StreamLimitExceeded
GsvAssemblyInvalid
FusionConflict
GeographicInvalid
TrackQualityIssue
IntegrityInvalid
} derive(Eq, Debug)pub(all) struct NmeaFrame {
prefix_value : UInt16
talker_value : String
formatter_value : String
fields_value : Array[String]
checksum_status_value : ChecksumStatus
checksum_value : Int?
} derive(Eq, Debug)fn QualityThresholds::new(max_gap_millis? : Int64, max_segment_distance_meters? : Double, max_speed_mps? : Double, max_speed_mismatch_mps? : Double, minimum_satellites? : Int, minimum_fix_quality_rank? : Int) -> Result[QualityThresholds, NmeaError]pub(all) struct RmcRecord {
talker_value : String
time_value : UtcTime
status_value : RmcStatus
latitude_value : Coordinate?
longitude_value : Coordinate?
speed_knots_value : ExactDecimal?
course_value : ExactDecimal?
date_value : UtcDate
magnetic_variation_value : ExactDecimal?
magnetic_direction_value : String?
mode_value : String?
} derive(Eq, Debug)pub struct SentenceResult[T] {
record_index_value : Int
formatter_value : String?
checksum_status_value : ChecksumStatus
value_value : T?
error_value : NmeaError?
} derive(Eq, Debug)fn[T] SentenceResult::err(record_index : Int, checksum_status : ChecksumStatus, error : NmeaError) -> SentenceResult[T]fn[T] SentenceResult::ok(record_index : Int, formatter : String, checksum_status : ChecksumStatus, value? : T?) -> SentenceResult[T]pub struct StreamDecoder {
policy_value : ParsePolicy
limits_value : StreamLimits
buffer_value : Array[Byte]
record_index_value : Int
discarding_value : Bool
skip_lf_value : Bool
}pub(all) struct StreamLimits {
max_buffer_bytes_value : Int
frame_limits_value : FrameLimits
} derive(Eq, Debug)fn StreamLimits::new(max_buffer_bytes : Int, frame_limits? : FrameLimits) -> Result[StreamLimits, NmeaError]pub(all) struct Track {
points_value : Array[TrackPoint]
segments_value : Array[TrackSegment]
summary_value : TrackSummary
} derive(Eq, Debug)pub(all) struct TrackFilter {
start_time_value : UtcDateTime?
end_time_value : UtcDateTime?
bounds_value : BoundingBox?
minimum_fix_quality_rank_value : Int?
maximum_severity_value : Severity?
} derive(Eq, Debug)fn TrackFilter::new(start_time? : UtcDateTime?, end_time? : UtcDateTime?, bounds? : BoundingBox?, minimum_fix_quality_rank? : Int?, maximum_severity? : Severity?) -> Result[TrackFilter, NmeaError]pub(all) struct TrackFinding {
kind_value : TrackFindingKind
severity_value : Severity
point_index_value : Int?
segment_index_value : Int?
diagnostic_value : Diagnostic
} derive(Eq, Debug)pub(all) struct TrackPoint {
latitude_value : Double
longitude_value : Double
altitude_value : ExactDecimal?
datetime_value : UtcDateTime?
reported_speed_knots_value : ExactDecimal?
quality_value : GgaFixQuality?
satellites_value : Int?
usable_value : Bool
source_record_indexes_value : Array[Int]
} derive(Eq, Debug)fn TrackPoint::new(latitude : Double, longitude : Double, altitude? : ExactDecimal?, datetime? : UtcDateTime?, reported_speed_knots? : ExactDecimal?, quality? : GgaFixQuality?, satellites? : Int?, usable? : Bool, source_record_indexes? : Array[Int]) -> Result[TrackPoint, NmeaError]pub(all) struct TrackSummary {
point_count_value : Int
segment_count_value : Int
total_distance_meters_value : Double
total_duration_millis_value : Int64?
bounds_value : BoundingBox?
} derive(Eq, Debug)pub(all) struct UtcTime {
hour_value : Int
minute_value : Int
second_value : Int
nanosecond_value : Int
second_wire_value : ExactDecimal
} derive(Eq, Debug)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 filter_track(track : Track, filter : TrackFilter, report? : TrackQualityReport?) -> Result[Track, NmeaError]fn haversine_distance_meters(latitude1 : Double, longitude1 : Double, latitude2 : Double, longitude2 : Double) -> Result[Double, NmeaError]fn initial_bearing_degrees(latitude1 : Double, longitude1 : Double, latitude2 : Double, longitude2 : Double) -> Result[Double, NmeaError]fn parse_frame(input : String, policy? : ParsePolicy, limits? : FrameLimits) -> Result[NmeaFrame, NmeaError]fn parse_latitude(value : String, hemisphere : String, source : SourceRef) -> Result[Coordinate, NmeaError]fn parse_longitude(value : String, hemisphere : String, source : SourceRef) -> Result[Coordinate, NmeaError]fn parse_sentence(input : String, policy? : ParsePolicy, limits? : FrameLimits) -> Result[NmeaRecord, NmeaError]fn speed_meters_per_second(distance_meters : Double, elapsed_millis~ : Int64) -> Result[Double, NmeaError]Typed NMEA 0183 parsing, diagnostics, and evidence toolkit