@@ -18,7 +18,7 @@ use chrono::{DateTime, Timelike, Utc};
1818
1919use crate :: {
2020 coords:: LLHDegrees ,
21- nmea:: { self } ,
21+ nmea:: { self , Source } ,
2222} ;
2323
2424/// Quality of GPS solution
@@ -31,7 +31,7 @@ pub enum GPSQuality {
3131 SPS ,
3232 /// Differential GPS, SPS Mode, fix valid
3333 DGPS ,
34- /// GPS PPS (pulse per second ), fix valid
34+ /// GPS PPS (precise positioning service, military encrypted signals ), fix valid
3535 PPS ,
3636 /// RTK (real time kinematic). System used in RTK mode with fixed integers
3737 RTK ,
@@ -61,17 +61,28 @@ impl fmt::Display for GPSQuality {
6161 }
6262}
6363
64+ #[ derive( thiserror:: Error , Debug ) ]
65+ pub enum GGAParseError {
66+ #[ error( "Invalid time format" ) ]
67+ InvalidTimeFormat ,
68+
69+ #[ error( "Invalid or missing GPS quality" ) ]
70+ InvalidGPSQuality ,
71+ }
72+
6473/// Global Positioning System Fix Data including time, position and fix related data for a GNSS
6574/// receiver
6675#[ derive( Debug , PartialEq , Clone , Builder ) ]
6776pub struct GGA {
77+ #[ builder( default ) ]
78+ pub source : Source ,
6879 /// Time of fix in UTC.
6980 #[ builder( default = Utc :: now( ) ) ]
7081 pub time : DateTime < Utc > ,
7182 /// Latitude, longitude and height in degrees.
7283 pub llh : LLHDegrees ,
7384 /// Quality of GPS solution.
74- #[ builder( default = GPSQuality :: default ( ) ) ]
85+ #[ builder( default ) ]
7586 pub gps_quality : GPSQuality ,
7687 /// Sattelites in use
7788 pub sat_in_use : Option < u8 > ,
@@ -86,10 +97,18 @@ pub struct GGA {
8697}
8798
8899impl GGA {
89- // converts the GGA struct into an NMEA sentence
90- // http://lefebure.com/articles/nmea-gga/
100+ /// converts the GGA struct into an NMEA sentence
101+ ///
102+ /// <https://gpsd.gitlab.io/gpsd/NMEA.html#_gga_global_positioning_system_fix_data>
103+ ///
104+ /// ```text
105+ /// 1 2 3 4 5 6 7 8 9 10 | 12 13 14 15
106+ /// | | | | | | | | | | | | | | |
107+ /// $--GGA,hhmmss.ss,ddmm.mm,a,ddmm.mm,a,x,xx,x.x,x.x,M,x.x,M,x.x,xxxx*hh<CR><LF>
108+ /// ```
91109 #[ must_use]
92110 pub fn to_sentence ( & self ) -> String {
111+ let talker_id = self . source . to_nmea_talker_id ( ) ;
93112 // NOTE(ted): We are formatting here a bit strange because for some ungodly reason,
94113 // chrono chose not to allow for abitrary fractional seconds precision when formatting
95114 // Construct timestamp in HHMMSS.SS format
@@ -129,7 +148,7 @@ impl GGA {
129148 . map_or ( String :: new ( ) , |id| id. to_string ( ) ) ;
130149
131150 let sentence = format ! (
132- "GPGGA ,{timestamp},{lat_deg:02}{lat_mins:010.7},{lat_hemisphere},{lon_deg:\
151+ "{talker_id}GGA ,{timestamp},{lat_deg:02}{lat_mins:010.7},{lat_hemisphere},{lon_deg:\
133152 03}{lon_mins:010.7},{lon_hemisphere},{gps_quality},{sat_in_use},{hdop},{height:.6},M,\
134153 {geoidal_separation},{age_dgps:.1},{reference_station_id}",
135154 ) ;
0 commit comments