summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Talbot <chris@talbothome.com>2023-05-14 17:27:18 -0400
committerTeemu Ikonen <tpikonen@mailbox.org>2023-06-17 16:08:48 +0000
commit411e8b0872aa934b3ba44cea9e687bfddd85904c (patch)
tree3b335321c831ebb0134bfc0149e517dc873135b5
parent337b18a5c7b8cebb906be4f2db346d930c89c66f (diff)
gclue-location: Reject RMC sentence if it is invalid, give bounds for accuracy if unknown or old
-rw-r--r--src/gclue-location.c38
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: