diff options
author | Chris Talbot <chris@talbothome.com> | 2023-05-14 17:27:18 -0400 |
---|---|---|
committer | Teemu Ikonen <tpikonen@mailbox.org> | 2023-06-17 16:08:48 +0000 |
commit | 411e8b0872aa934b3ba44cea9e687bfddd85904c (patch) | |
tree | 3b335321c831ebb0134bfc0149e517dc873135b5 | |
parent | 337b18a5c7b8cebb906be4f2db346d930c89c66f (diff) |
gclue-location: Reject RMC sentence if it is invalid, give bounds for accuracy if unknown or old
-rw-r--r-- | src/gclue-location.c | 38 |
1 files changed, 27 insertions, 11 deletions
diff --git a/src/gclue-location.c b/src/gclue-location.c index 0d40ca9..06f74dd 100644 --- a/src/gclue-location.c +++ b/src/gclue-location.c @@ -32,6 +32,8 @@ #define TIME_DIFF_THRESHOLD (60 * G_USEC_PER_SEC) /* 60 seconds */ #define EARTH_RADIUS_KM 6372.795 #define KNOTS_IN_METERS_PER_SECOND 0.51444 +#define RMC_TIME_DIFF_THRESHOLD 5 /* 5 seconds */ +#define RMC_DEFAULT_ACCURACY 5 /* 5 meters */ struct _GClueLocationPrivate { char *description; @@ -647,11 +649,17 @@ gclue_location_create_from_rmc (const char *rmc, { GClueLocation *location; g_auto(GStrv) parts = NULL; + gdouble accuracy; + gdouble altitude; parts = g_strsplit (rmc, ",", -1); if (g_strv_length (parts) < 13) goto error; + /* RMC sentence is invalid */ + if (g_strcmp0 (parts[3], "A") != 0) + return NULL; + guint64 timestamp = parse_nmea_timestamp (parts[1]); gdouble lat = parse_coordinate_string (parts[3], parts[4]); gdouble lon = parse_coordinate_string (parts[5], parts[6]); @@ -673,6 +681,23 @@ gclue_location_create_from_rmc (const char *rmc, heading = GCLUE_LOCATION_HEADING_UNKNOWN; } + accuracy = RMC_DEFAULT_ACCURACY; + altitude = GCLUE_LOCATION_ALTITUDE_UNKNOWN; + if (prev_location != NULL) { + guint64 prev_loc_timestamp; + + prev_loc_timestamp = gclue_location_get_timestamp (prev_location); + + /* Sentence is older then previous location, reject */ + if (timestamp < prev_loc_timestamp) + return NULL; + + if (timestamp - prev_loc_timestamp < RMC_TIME_DIFF_THRESHOLD) { + accuracy = gclue_location_get_accuracy (prev_location); + altitude = gclue_location_get_altitude (prev_location); + } + } + location = g_object_new (GCLUE_TYPE_LOCATION, "latitude", lat, "longitude", lon, @@ -680,19 +705,10 @@ gclue_location_create_from_rmc (const char *rmc, "speed", speed, "heading", heading, "description", "GPS RMC", + "accuracy", accuracy, + "altitude", altitude, NULL); - if (prev_location != NULL) { - g_object_set (location, - "accuracy", - gclue_location_get_accuracy (prev_location), - NULL); - g_object_set (location, - "altitude", - gclue_location_get_altitude (prev_location), - NULL); - } - return location; error: |