...
 
Commits (7)
......@@ -351,23 +351,18 @@ gclue_location_source_set_location (GClueLocationSource *source,
{
GClueLocationSourcePrivate *priv = source->priv;
GClueLocation *cur_location;
GeocodeLocation *gloc;
gdouble speed, heading;
gloc = GEOCODE_LOCATION (location);
cur_location = priv->location;
priv->location = gclue_location_new_with_description
(geocode_location_get_latitude (gloc),
geocode_location_get_longitude (gloc),
geocode_location_get_accuracy (gloc),
geocode_location_get_description (gloc));
priv->location = gclue_location_duplicate (location);
speed = gclue_location_get_speed (location);
if (speed == GCLUE_LOCATION_SPEED_UNKNOWN) {
if (cur_location != NULL && priv->compute_movement) {
guint64 cur_timestamp, timestamp;
timestamp = geocode_location_get_timestamp (gloc);
timestamp = geocode_location_get_timestamp
(GEOCODE_LOCATION (location));
cur_timestamp = geocode_location_get_timestamp
(GEOCODE_LOCATION (cur_location));
......
......@@ -25,6 +25,8 @@
#include "gclue-location.h"
#include <math.h>
#include <string.h>
#include <stdlib.h>
struct _GClueLocationPrivate {
gdouble speed;
......@@ -236,6 +238,59 @@ parse_altitude_string (const char *altitude,
return g_ascii_strtod (altitude, NULL);
}
static gint64
parse_nmea_timestamp (const char *nmea_ts)
{
char parts[3][3];
int i, hours, minutes, seconds;
GDateTime *now, *ts = NULL;
guint64 ret;
now = g_date_time_new_now_utc ();
ret = g_date_time_to_unix (now);
if (strlen (nmea_ts) < 6) {
g_warning ("Failed to parse NMEA timestamp '%s'", nmea_ts);
goto parse_error;
}
for (i = 0; i < 3; i++) {
memmove (parts[i], nmea_ts + (i * 2), 2);
parts[i][2] = '\0';
}
hours = atoi (parts[0]);
minutes = atoi (parts[1]);
seconds = atoi (parts[2]);
ts = g_date_time_new_utc (g_date_time_get_year (now),
g_date_time_get_month (now),
g_date_time_get_day_of_month (now),
hours,
minutes,
seconds);
if (g_date_time_difference (now, ts) < 0) {
g_debug ("NMEA timestamp '%s' in future. Assuming yesterday's.",
nmea_ts);
g_date_time_unref (ts);
ts = g_date_time_new_utc (g_date_time_get_year (now),
g_date_time_get_month (now),
g_date_time_get_day_of_month (now) - 1,
hours,
minutes,
seconds);
}
ret = g_date_time_to_unix (ts);
g_date_time_unref (ts);
parse_error:
g_date_time_unref (now);
return ret;
}
/**
* gclue_location_new:
* @latitude: a valid latitude
......@@ -299,6 +354,7 @@ gclue_location_create_from_gga (const char *gga, GError **error)
GClueLocation *location = NULL;
gdouble latitude, longitude, accuracy, altitude;
gdouble hdop; /* Horizontal Dilution Of Precision */
guint64 timestamp;
char **parts;
parts = g_strsplit (gga, ",", -1);
......@@ -313,6 +369,7 @@ gclue_location_create_from_gga (const char *gga, GError **error)
/* For syntax of GGA sentences:
* http://www.gpsinformation.org/dale/nmea.htm#GGA
*/
timestamp = parse_nmea_timestamp (parts[1]);
latitude = parse_coordinate_string (parts[2], parts[3]);
longitude = parse_coordinate_string (parts[4], parts[5]);
if (latitude == INVALID_COORDINATE || longitude == INVALID_COORDINATE) {
......@@ -330,7 +387,12 @@ gclue_location_create_from_gga (const char *gga, GError **error)
hdop = g_ascii_strtod (parts[8], NULL);
accuracy = get_accuracy_from_hdop (hdop);
location = gclue_location_new (latitude, longitude, accuracy);
location = g_object_new (GCLUE_TYPE_LOCATION,
"latitude", latitude,
"longitude", longitude,
"accuracy", accuracy,
"timestamp", timestamp,
NULL);
if (altitude != GEOCODE_LOCATION_ALTITUDE_UNKNOWN)
g_object_set (location, "altitude", altitude, NULL);
......@@ -339,6 +401,33 @@ out:
return location;
}
/**
* gclue_location_duplicate:
* @location: the #GClueLocation instance to duplicate.
*
* Creates a new copy of @location object.
*
* Returns: a new #GClueLocation object. Use g_object_unref() when done.
**/
GClueLocation *
gclue_location_duplicate (GClueLocation *location)
{
GeocodeLocation *gloc = GEOCODE_LOCATION (location);
return g_object_new
(GCLUE_TYPE_LOCATION,
"description", geocode_location_get_description (gloc),
"latitude", geocode_location_get_latitude (gloc),
"longitude", geocode_location_get_longitude (gloc),
"accuracy", geocode_location_get_accuracy (gloc),
"altitude", geocode_location_get_altitude (gloc),
"crs", geocode_location_get_crs (gloc),
"timestamp", geocode_location_get_timestamp (gloc),
"speed", location->priv->speed,
"heading", location->priv->heading,
NULL);
}
/**
* gclue_location_get_speed:
* @location: a #GClueLocation
......@@ -393,9 +482,9 @@ gclue_location_set_speed_from_prev_location (GClueLocation *location,
GCLUE_IS_LOCATION (prev_location));
if (prev_location == NULL) {
location->priv->speed = GCLUE_LOCATION_SPEED_UNKNOWN;
speed = GCLUE_LOCATION_SPEED_UNKNOWN;
return;
goto out;
}
gloc = GEOCODE_LOCATION (location);
......@@ -404,11 +493,16 @@ gclue_location_set_speed_from_prev_location (GClueLocation *location,
timestamp = geocode_location_get_timestamp (gloc);
prev_timestamp = geocode_location_get_timestamp (prev_gloc);
g_return_if_fail (timestamp != prev_timestamp);
if (timestamp <= prev_timestamp) {
speed = GCLUE_LOCATION_SPEED_UNKNOWN;
goto out;
}
speed = geocode_location_get_distance_from (gloc, prev_gloc) *
1000.0 / (timestamp - prev_timestamp);
out:
location->priv->speed = speed;
g_object_notify (G_OBJECT (location), "speed");
......
......@@ -89,6 +89,9 @@ GClueLocation *gclue_location_create_from_gga
(const char *gga,
GError **error);
GClueLocation *gclue_location_duplicate
(GClueLocation *location);
void gclue_location_set_speed (GClueLocation *loc,
gdouble speed);
......
......@@ -88,17 +88,24 @@ set_location (GClueLocator *locator,
g_debug ("New location available");
if (cur_location != NULL &&
geocode_location_get_distance_from (gloc, cur_gloc) * 1000 <
geocode_location_get_accuracy (gloc) &&
geocode_location_get_accuracy (gloc) >
geocode_location_get_accuracy (cur_gloc)) {
/* We only take the new location if either the previous one
* lies outside its accuracy circle or its more or as
* accurate as previous one.
*/
g_debug ("Ignoring less accurate new location");
return;
if (cur_location != NULL) {
if (geocode_location_get_timestamp (gloc) <
geocode_location_get_timestamp (cur_gloc)) {
g_debug ("New location older than current, ignoring.");
return;
}
if (geocode_location_get_distance_from (gloc, cur_gloc) * 1000 <
geocode_location_get_accuracy (gloc) &&
geocode_location_get_accuracy (gloc) >
geocode_location_get_accuracy (cur_gloc)) {
/* We only take the new location if either the previous one
* lies outside its accuracy circle or its more or as
* accurate as previous one.
*/
g_debug ("Ignoring less accurate new location");
return;
}
}
gclue_location_source_set_location (GCLUE_LOCATION_SOURCE (locator),
......
......@@ -156,6 +156,22 @@ geocode_location_set_crs(GeocodeLocation *loc,
loc->priv->crs = crs;
}
static void
geocode_location_set_timestamp (GeocodeLocation *location,
guint64 timestamp)
{
if (timestamp != 0) {
location->priv->timestamp = timestamp;
} else {
GTimeVal tv;
g_get_current_time (&tv);
location->priv->timestamp = tv.tv_sec;
}
g_print ("\nset location ts to '%lu'\n",
location->priv->timestamp);
}
static void
geocode_location_set_property(GObject *object,
guint property_id,
......@@ -195,6 +211,11 @@ geocode_location_set_property(GObject *object,
g_value_get_enum (value));
break;
case PROP_TIMESTAMP:
geocode_location_set_timestamp (location,
g_value_get_uint64 (value));
break;
default:
/* We don't have any other property... */
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
......@@ -587,7 +608,8 @@ geocode_location_class_init (GeocodeLocationClass *klass)
0,
G_MAXINT64,
0,
G_PARAM_READABLE |
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
g_object_class_install_property (glocation_class, PROP_TIMESTAMP, pspec);
}
......@@ -595,14 +617,10 @@ geocode_location_class_init (GeocodeLocationClass *klass)
static void
geocode_location_init (GeocodeLocation *location)
{
GTimeVal tv;
location->priv = G_TYPE_INSTANCE_GET_PRIVATE ((location),
GEOCODE_TYPE_LOCATION,
GeocodeLocationPrivate);
g_get_current_time (&tv);
location->priv->timestamp = tv.tv_sec;
location->priv->altitude = GEOCODE_LOCATION_ALTITUDE_UNKNOWN;
location->priv->accuracy = GEOCODE_LOCATION_ACCURACY_UNKNOWN;
location->priv->crs = GEOCODE_LOCATION_CRS_WGS84;
......