/**
* Navit, a modular navigation system.
* Copyright (C) 2005-2008 Navit Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
Plugin for new Maemo's liblocation API.
source cound be on of "any","cwp","acwp","gnss","agnss"
retry_interval could be one of "1","2","5","10","20","30","60","120" measured in seconds
*/
#include
#include
#include
#include
#include
#include
#include "debug.h"
#include "callback.h"
#include "plugin.h"
#include "coord.h"
#include "item.h"
#include "vehicle.h"
#include "event.h"
static struct vehicle_priv {
LocationGPSDControl *control;
LocationGPSDevice *device;
char *source;
guint retry_interval;
struct callback_list *cbl;
struct attr ** attrs;
int sats; // satellites_in_view
int sats_used; //satellites_in_user
int fix_type; //mode
struct coord_geo geo; //lattigute&longittude
double speed; //speed:)
double direction; //track
double height; //altitude
double hdop; //eph
time_t fix_time; //time
char fixiso8601[128];
};
static void vehicle_maemo_callback(LocationGPSDevice *device, gpointer user_data) {
struct vehicle_priv *priv=(struct vehicle_priv*)user_data;
priv->sats=device->satellites_in_view;
priv->sats_used=device->satellites_in_use;
callback_list_call_attr_0(priv->cbl, attr_position_sats);
dbg(lvl_debug,"Got update with %u/%u satellites\n",priv->sats_used,priv->sats);
if (device->fix) {
switch(device->fix->mode) {
case LOCATION_GPS_DEVICE_MODE_NOT_SEEN:
case LOCATION_GPS_DEVICE_MODE_NO_FIX:
priv->fix_type=0;
break;
case LOCATION_GPS_DEVICE_MODE_2D:
case LOCATION_GPS_DEVICE_MODE_3D:
priv->fix_type=1;
break;
}
if (device->fix->fields & LOCATION_GPS_DEVICE_LATLONG_SET) {
priv->geo.lat=device->fix->latitude;
priv->geo.lng=device->fix->longitude;
priv->hdop=device->fix->eph/100;
callback_list_call_attr_0(priv->cbl, attr_position_coord_geo);
dbg(lvl_debug,"Position: %f %f with error %f meters\n",priv->geo.lat,priv->geo.lng,priv->hdop);
}
if (device->fix->fields & LOCATION_GPS_DEVICE_SPEED_SET) {
priv->speed=device->fix->speed;
callback_list_call_attr_0(priv->cbl, attr_position_speed);
dbg(lvl_debug,"Speed: %f\n ",priv->speed);
}
if (device->fix->fields & LOCATION_GPS_DEVICE_TRACK_SET) {
priv->direction=device->fix->track;
dbg(lvl_debug,"Direction: %f\n",priv->direction);
}
if (device->fix->fields & LOCATION_GPS_DEVICE_TIME_SET) {
priv->fix_time=device->fix->time;
dbg(lvl_debug,"Time: %f\n",priv->fix_time);
}
if (device->fix->fields & LOCATION_GPS_DEVICE_ALTITUDE_SET) {
priv->height=device->fix->altitude;
dbg(lvl_debug,"Elevation: %f\n",priv->height);
}
}
return;
}
static void vehicle_maemo_error(LocationGPSDControl *control, LocationGPSDControlError error, gpointer user_data)
{
switch (error) {
case LOCATION_ERROR_USER_REJECTED_DIALOG:
dbg(lvl_error,"User didn't enable requested methods\n");
break;
case LOCATION_ERROR_USER_REJECTED_SETTINGS:
dbg(lvl_error,"User changed settings, which disabled location\n");
break;
case LOCATION_ERROR_BT_GPS_NOT_AVAILABLE:
dbg(lvl_error,"Problems with BT GPS\n");
break;
case LOCATION_ERROR_METHOD_NOT_ALLOWED_IN_OFFLINE_MODE:
dbg(lvl_error,"Requested method is not allowed in offline mode\n");
break;
case LOCATION_ERROR_SYSTEM:
dbg(lvl_error,"System error\n");
break;
}
}
/**
* Instantiate liblocation objects
*/
static void
vehicle_maemo_open(struct vehicle_priv *priv)
{
priv->control = location_gpsd_control_get_default();
priv->device = g_object_new(LOCATION_TYPE_GPS_DEVICE, NULL);
if (!strcasecmp(priv->source+8,"cwp")) {
g_object_set(G_OBJECT(priv->control), "preferred-method", LOCATION_METHOD_CWP, NULL);
dbg(lvl_debug,"Method set: CWP\n");
} else if (!strcasecmp(priv->source+8,"acwp")) {
g_object_set(G_OBJECT(priv->control), "preferred-method", LOCATION_METHOD_ACWP, NULL);
dbg(lvl_debug,"Method set: ACWP\n");
} else if (!strcasecmp(priv->source+8,"gnss")) {
g_object_set(G_OBJECT(priv->control), "preferred-method", LOCATION_METHOD_GNSS, NULL);
dbg(lvl_debug,"Method set: GNSS\n");
} else if (!strcasecmp(priv->source+8,"agnss")) {
g_object_set(G_OBJECT(priv->control), "preferred-method", LOCATION_METHOD_AGNSS, NULL);
dbg(lvl_debug,"Method set: AGNSS\n");
} else {
g_object_set(G_OBJECT(priv->control), "preferred-method", LOCATION_METHOD_USER_SELECTED, NULL);
dbg(lvl_debug,"Method set: ANY\n");
}
switch (priv->retry_interval) {
case 2:
g_object_set(G_OBJECT(priv->control), "preferred-interval", LOCATION_INTERVAL_2S, NULL);
dbg(lvl_debug,"Interval set: 2s\n");
break;
case 5:
g_object_set(G_OBJECT(priv->control), "preferred-interval", LOCATION_INTERVAL_5S, NULL);
dbg(lvl_debug,"Interval set: 5s\n");
break;
case 10:
g_object_set(G_OBJECT(priv->control), "preferred-interval", LOCATION_INTERVAL_10S, NULL);
dbg(lvl_debug,"Interval set: 10s\n");
break;
case 20:
g_object_set(G_OBJECT(priv->control), "preferred-interval", LOCATION_INTERVAL_20S, NULL);
dbg(lvl_debug,"Interval set: 20s\n");
break;
case 30:
g_object_set(G_OBJECT(priv->control), "preferred-interval", LOCATION_INTERVAL_30S, NULL);
dbg(lvl_debug,"Interval set: 30s\n");
break;
case 60:
g_object_set(G_OBJECT(priv->control), "preferred-interval", LOCATION_INTERVAL_60S, NULL);
dbg(lvl_debug,"Interval set: 60s\n");
break;
case 120:
g_object_set(G_OBJECT(priv->control), "preferred-interval", LOCATION_INTERVAL_120S, NULL);
dbg(lvl_debug,"Interval set: 120s\n");
break;
case 1:
default:
g_object_set(G_OBJECT(priv->control), "preferred-interval", LOCATION_INTERVAL_1S, NULL);
dbg(lvl_debug,"Interval set: 1s\n");
break;
}
g_signal_connect(priv->device, "changed", G_CALLBACK(vehicle_maemo_callback), priv);
g_signal_connect(priv->control, "error-verbose", G_CALLBACK(vehicle_maemo_error), priv);
location_gpsd_control_start(priv->control);
return;
}
static void
vehicle_maemo_destroy(struct vehicle_priv *priv)
{
location_gpsd_control_stop(priv->control);
g_object_unref(priv->device);
g_object_unref(priv->control);
return;
}
static int
vehicle_maemo_position_attr_get(struct vehicle_priv *priv,
enum attr_type type, struct attr *attr)
{
struct attr * active=NULL;
switch (type) {
case attr_position_fix_type:
dbg(lvl_debug,"Attr requested: position_fix_type\n");
attr->u.num = priv->fix_type;
break;
case attr_position_height:
dbg(lvl_debug,"Attr requested: position_height\n");
attr->u.numd = &priv->height;
break;
case attr_position_speed:
dbg(lvl_debug,"Attr requested: position_speed\n");
attr->u.numd = &priv->speed;
break;
case attr_position_direction:
dbg(lvl_debug,"Attr requested: position_direction\n");
attr->u.numd = &priv->direction;
break;
case attr_position_hdop:
dbg(lvl_debug,"Attr requested: position_hdop\n");
attr->u.numd = &priv->hdop;
break;
case attr_position_sats:
dbg(lvl_debug,"Attr requested: position_sats\n");
attr->u.num = priv->sats;
break;
case attr_position_sats_used:
dbg(lvl_debug,"Attr requested: position_sats_used\n");
attr->u.num = priv->sats_used;
break;
case attr_position_coord_geo:
dbg(lvl_debug,"Attr requested: position_coord_geo\n");
attr->u.coord_geo = &priv->geo;
break;
case attr_position_time_iso8601:
{
struct tm tm;
dbg(lvl_debug,"Attr requested: position_time_iso8601\n");
if (!priv->fix_time)
return 0;
if (gmtime_r(&priv->fix_time, &tm)) {
strftime(priv->fixiso8601, sizeof(priv->fixiso8601),
"%Y-%m-%dT%TZ", &tm);
attr->u.str=priv->fixiso8601;
} else
return 0;
}
break;
case attr_active:
dbg(lvl_debug,"Attr requested: position_active\n");
active = attr_search(priv->attrs,NULL,attr_active);
if(active != NULL) {
attr->u.num=active->u.num;
return 1;
} else
return 0;
break;
default:
return 0;
}
attr->type = type;
return 1;
}
struct vehicle_methods vehicle_maemo_methods = {
vehicle_maemo_destroy,
vehicle_maemo_position_attr_get,
};
static struct vehicle_priv *
vehicle_maemo_new_maemo(struct vehicle_methods
*meth, struct callback_list
*cbl, struct attr **attrs)
{
struct vehicle_priv *ret;
struct attr *source, *retry_int;
dbg(lvl_debug, "enter\n");
source = attr_search(attrs, NULL, attr_source);
ret = g_new0(struct vehicle_priv, 1);
ret->source = g_strdup(source->u.str);
retry_int = attr_search(attrs, NULL, attr_retry_interval);
if (retry_int) {
ret->retry_interval = retry_int->u.num;
if (ret->retry_interval !=1 && ret->retry_interval !=2 && ret->retry_interval !=5 && ret->retry_interval !=10 && ret->retry_interval !=20 && ret->retry_interval !=30 && ret->retry_interval !=60 && ret->retry_interval !=120 ) {
dbg(lvl_error, "Retry interval %d invalid, setting to 1\n", ret->retry_interval,1);
ret->retry_interval = 1;
}
} else {
ret->retry_interval = 1;
}
dbg(lvl_debug,"source: %s, interval: %u\n",ret->source,ret->retry_interval);
ret->cbl = cbl;
*meth = vehicle_maemo_methods;
ret->attrs = attrs;
vehicle_maemo_open(ret);
return ret;
}
void
plugin_init(void)
{
dbg(lvl_debug, "enter\n");
plugin_register_vehicle_type("maemo", vehicle_maemo_new_maemo);
}