#include <string.h>
#include <stdlib.h>
#include <syslog.h>
#include <math.h>
#include <time.h>
#include <signal.h>
#include <glib.h>
#include <dbus/dbus.h>
#include <dbus/dbus-glib-lowlevel.h>
#include <dbus/dbus-glib.h>
#include <glib/gprintf.h>
DBusConnection* connection;
static char *author = "Amaury Jacquot";
static char *copyright = "GPL v 2.0";
static int intrack = 0;
static int first = 1;
static time_t tracklimit = 5; /* seconds */
static struct {
time_t old_time;
time_t time;
gint32 mode;
gdouble ept;
gdouble latitude;
gdouble longitude;
gdouble eph;
gdouble altitude;
gdouble epv;
gdouble track;
gdouble epd;
gdouble speed;
gdouble eps;
gdouble climb;
gdouble epc;
//gdouble separation;
} gpsfix;
static void print_gpx_trk_start (void) {
fprintf (stdout, " <trk>\n");
fprintf (stdout, " <trkseg>\n");
fflush (stdout);
}
static void print_gpx_trk_end (void) {
fprintf (stdout, " </trkseg>\n");
fprintf (stdout, " </trk>\n");
fflush (stdout);
}
static DBusHandlerResult handle_gps_fix (DBusMessage* message) {
DBusMessageIter iter;
DBusError error;
double temp_time;
dbus_error_init (&error);
dbus_message_get_args (message,
&error,
DBUS_TYPE_DOUBLE, &temp_time,
DBUS_TYPE_INT32, &gpsfix.mode,
DBUS_TYPE_DOUBLE, &gpsfix.ept,
DBUS_TYPE_DOUBLE, &gpsfix.latitude,
DBUS_TYPE_DOUBLE, &gpsfix.longitude,
DBUS_TYPE_DOUBLE, &gpsfix.eph,
DBUS_TYPE_DOUBLE, &gpsfix.altitude,
DBUS_TYPE_DOUBLE, &gpsfix.epv,
DBUS_TYPE_DOUBLE, &gpsfix.track,
DBUS_TYPE_DOUBLE, &gpsfix.epd,
DBUS_TYPE_DOUBLE, &gpsfix.speed,
DBUS_TYPE_DOUBLE, &gpsfix.eps,
DBUS_TYPE_DOUBLE, &gpsfix.climb,
DBUS_TYPE_DOUBLE, &gpsfix.epc,
DBUS_TYPE_INVALID);
gpsfix.time = floor(temp_time);
/*
* we have a fix there - log the point
*/
if ((gpsfix.time!=gpsfix.old_time)&&gpsfix.mode>1) {
struct tm time;
/* Make new track if the jump in time is above
* tracklimit. Handle jumps both forward and
* backwards in time. The clock sometimes jump
* backward when gpsd is submitting junk on the
* dbus. */
if (fabs(gpsfix.time - gpsfix.old_time) > tracklimit && !first) {
print_gpx_trk_end();
intrack = 0;
}
if (!intrack) {
print_gpx_trk_start();
intrack = 1;
if (first)
first = 0;
}
gpsfix.old_time = gpsfix.time;
fprintf (stdout, " <trkpt lat=\"%f\" lon=\"%f\">\n", gpsfix.latitude, gpsfix.longitude);
fprintf (stdout, " <ele>%f</ele>\n", gpsfix.altitude);
gmtime_r (&(gpsfix.time), &time);
fprintf (stdout, " <time>%04d-%02d-%02dT%02d:%02d:%02dZ</time>\n",
time.tm_year+1900, time.tm_mon+1, time.tm_mday,
time.tm_hour, time.tm_min, time.tm_sec);
if (gpsfix.mode==1)
fprintf (stdout, " <fix>none</fix>\n");
else
fprintf (stdout, " <fix>%dd</fix>\n", gpsfix.mode);
fprintf (stdout, " </trkpt>\n");
fflush (stdout);
}
return DBUS_HANDLER_RESULT_HANDLED;
}
static void print_gpx_header (void) {
fprintf (stdout, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
fprintf (stdout, "<gpx version=\"1.1\" creator=\"navsys logger\"\n");
fprintf (stdout, " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n");
fprintf (stdout, " xmlns=\"http://www.topografix.com/GPX/1.1\"\n");
fprintf (stdout, " xsi:schemaLocation=\"http://www.topografix.com/GPS/1/1\n");
fprintf (stdout, " http://www.topografix.com/GPX/1/1/gpx.xsd\">\n");
fprintf (stdout, " <metadata>\n");
fprintf (stdout, " <name>NavSys GPS logger dump</name>\n");
fprintf (stdout, " <author>%s</author>\n", author);
fprintf (stdout, " <copyright>%s</copyright>\n", copyright);
fprintf (stdout, " </metadata>\n");
fflush (stdout);
}
static void print_gpx_footer (void) {
if (intrack)
print_gpx_trk_end();
fprintf (stdout, "</gpx>\n");
fclose (stdout);
}
static void quit_handler (int signum) {
syslog (LOG_INFO, "exiting, signal %d received", signum);
print_gpx_footer ();
exit (0);
}
/*
* Message dispatching function
*
*/
static DBusHandlerResult signal_handler (
DBusConnection* connection, DBusMessage* message) {
/* dummy, need to use the variable for some reason */
connection = NULL;
if (dbus_message_is_signal (message, "org.gpsd", "fix"))
return handle_gps_fix (message);
/*
* ignore all other messages
*/
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
int main (int argc, char** argv) {
GMainLoop* mainloop;
DBusError error;
/* initializes the gpsfix data structure */
bzero (&gpsfix, sizeof(gpsfix));
/* catch all interesting signals */
signal (SIGTERM, quit_handler);
signal (SIGQUIT, quit_handler);
signal (SIGINT, quit_handler);
openlog ("gpxlogger", LOG_PID | LOG_NDELAY , LOG_DAEMON);
syslog (LOG_INFO, "---------- STARTED ----------");
if (argc<2) {
fprintf (stderr, "need the filename as an argument\n");
return 1;
}
print_gpx_header ();
mainloop = g_main_loop_new (NULL, FALSE);
dbus_error_init (&error);
connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
if (dbus_error_is_set (&error)) {
syslog (LOG_CRIT, "%s: %s", error.name, error.message);
return 3;
}
dbus_bus_add_match (connection, "type='signal'", &error);
if (dbus_error_is_set (&error)) {
syslog (LOG_CRIT, "unable to add match for signals %s: %s", error.name, error.message);
return 4;
}
if (!dbus_connection_add_filter (connection, (DBusHandleMessageFunction)signal_handler, NULL, NULL)) {
syslog (LOG_CRIT, "unable to register filter with the connection");
return 5;
}
dbus_connection_setup_with_g_main (connection, NULL);
g_main_loop_run (mainloop);
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1