aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugin_gps.c379
1 files changed, 248 insertions, 131 deletions
diff --git a/plugin_gps.c b/plugin_gps.c
index d5b2349..cb4900b 100644
--- a/plugin_gps.c
+++ b/plugin_gps.c
@@ -1,7 +1,7 @@
/* $Id$
* $URL$
*
- * gps plugin, code by michu / www.neophob.com, based on nmeap, http://sourceforge.net/projects/nmeap/
+ * gps plugin (nmea), code by michu / www.neophob.com, based on nmeap, http://sourceforge.net/projects/nmeap/
*
* Copyright (C) 2007 michu
* Copyright (C) 2004, 2005, 2006, 2007 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
@@ -25,11 +25,47 @@
*/
/*
- * exported functions:
+ * GPS Plugin for lcd4linux, by michael vogt / http://www.neophob.com
+ * contact: michu@neophob.com
*
- * int plugin_init_gps (void)
- * adds various functions
+ * based on nmeap by daveh, http://www.dmh2000.com/ or http://sourceforge.net/projects/nmeap/
+ * you need a compiled libnmeap to compile this plugin.
*
+ * History:
+ * v0.1 initial release
+ *
+ * TODO:
+ * -update direction only when speed > 5 kmh
+ * -add more data fields
+ * -dump nmea string to external file
+ *
+ * Exported functions:
+ * int plugin_init_gps (void) - default plugin initialisation
+ * void parse(SHOW-OPTIONS, DISPLAY-OPTIONS)
+ * display option define, what the plugin should display
+ *
+ * OPTION: EXAMPLE:
+ * ------- --------
+ *
+ * PARAMETER 1:
+ * #define SHOW_ALTITUDE 0x000000001 alt:500
+ * #define SHOW_SPEED 0x000000010 spd:30
+ * #define SHOW_COURSE 0x000000100 dir:NO
+ * #define SHOW_SATELLITES 0x000001000 sat:4
+ * #define SHOW_QUALITY 0x000010000 qua:1
+ * #define SHOW_STATUS 0x000100000 sta:V
+ * #define SHOW_TIME_UTC 0x001000000 utc:113459
+ * #define SHOW_DATE 0x010000000 dat:190204 (19.02.2004)
+ *
+ * PARAMETER 2:
+ * #define DISPLAY_NO_PREFIX 0x000000001 disable prefix (example, instead of "alt:500" it displays "500"
+ * #define DISPLAY_SPEED_IN_KNOTS 0x000000010 when use the SHOW_SPEED option, display speed in knots instead in km/h
+ *
+ * Examples:
+ * - gps::parse('0x011','0') will display the altitude and speed -> alt:500 spd:43
+ * - gps::parse('0x01100','0') will display the course and the numbers of satellites -> dir:NO sat:3
+ * - gps::parse('0x01','0x01') will display the speed without prefix -> 50
+ * - gps::parse('0x01','0x01') will display the speed in knots without prefix -> 27
*/
@@ -41,13 +77,6 @@
#include <string.h>
#include <ctype.h>
#include <unistd.h>
-#include <fcntl.h>
-#include <termios.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <sys/io.h>
/* these should always be included */
#include "debug.h"
@@ -59,39 +88,61 @@
#include "nmeap.h"
+//#define EMULATE //remove comment to enable gps data emulation...
+
+#define SHOW_ALTITUDE 0x000000001
+#define SHOW_SPEED 0x000000010
+#define SHOW_COURSE 0x000000100
+#define SHOW_SATELLITES 0x000001000
+#define SHOW_QUALITY 0x000010000
+#define SHOW_STATUS 0x000100000
+#define SHOW_TIME_UTC 0x001000000
+#define SHOW_DATE 0x010000000
-#define SHOW_ALTITUDE 0x0000001
-#define SHOW_SPEED 0x0000010
-#define SHOW_COURSE 0x0000100
-#define SHOW_SATELLITES 0x0001000
-#define SHOW_QUALITY 0x0010000
-#define SHOW_WARN 0x0100000
+#define DISPLAY_NO_PREFIX 0x000000001
+#define DISPLAY_SPEED_IN_KNOTS 0x000000010
-nmeap_gga_t g_gga;
+static float course = 0.f; //degrees
+static float altitude = 0.f;
+static float speed = 0.f; //Speed over ground in KNOTS!!
+static int satellites = 0; //Number of satellites in use (00-12)
+static int quality = 0; //GPS quality indicator (0 - fix not valid, 1 - GPS fix, 2 - DGPS fix)
+static char gpsStatus = 'V'; //A=active or V=Void
+static unsigned long gpsTime = 0; //UTC of position fix in hhmmss format
+static unsigned long gpsDate = 0; //Date in ddmmyy format
+static int msgCounter = 0; //debug counter
/* ---------------------------------------------------------------------------------------*/
/* STEP 1 : allocate the data structures. be careful if you put them on the stack because */
/* they need to be live for the duration of the parser */
/* ---------------------------------------------------------------------------------------*/
-
static nmeap_context_t nmea; /* parser context */
static nmeap_gga_t gga; /* this is where the data from GGA messages will show up */
static nmeap_rmc_t rmc; /* this is where the data from RMC messages will show up */
static int user_data; /* user can pass in anything. typically it will be a pointer to some user data */
-static int fd;
+static int fd_g; /* port handler */
+
+
+#ifdef EMULATE
+char test_vector[] = {
+ "$GPGGA,123519,3929.946667,N,11946.086667,E,1,08,0.9,545.4,M,46.9,M,,*4A\r\n" /* good */
+ "$xyz,1234,asdfadfasdfasdfljsadfkjasdfk\r\n" /* junk */
+ "$GPRMC,225446,A,4916.45,N,12311.12,W,000.5,054.7,191194,020.3,E*68\r\n" /* good */
+ "$GPRMC,225446,A,4916.45,N,12311.12,W,000.5,054.7,191194,020.3,E*48\r\n" /* checksum error */
+};
+#endif
/*************************************************************************
- * LINUX IO
- */
/*
* open the specified serial port for read/write
* @return port file descriptor or -1
*/
+#ifndef EMULATE
static int openPort(const char *tty, int baud)
{
int status;
@@ -134,133 +185,56 @@ static int openPort(const char *tty, int baud)
}
return fd;
}
+#endif
-
-
-static void printGps(nmeap_gga_t * gga, nmeap_rmc_t * rmc)
+/** called when a gpgga message is received and parsed */
+static void gpgga_callout( __attribute__ ((unused)) nmeap_context_t * context, void *data, __attribute__ ((unused))
+ void *user_data)
{
- float myCourse = rmc->course; /* I assume 0 degree = North */
-
- char courses[8][3] = { "N ", "NO", "O ", "SO", "S ", "SW", "W ", "NW" };
- float degrees[8] = { 22.5f, 67.5f, 112.5f, 157.5f, 202.5f, 247.5f, 292.5f, 337.5f };
- int selectedDegree = 0;
- int n;
-
- for (n = 0; n < 8; n++) {
- if (myCourse < degrees[n]) {
- selectedDegree = n;
- break;
- }
- }
-
- debug("alt:%.0f speed:%.0f course:%s sat:%d quali:%d, warn:%c\n", gga->altitude, rmc->speed * 1.852f, /* knots -> km/h */
- courses[selectedDegree], gga->satellites, gga->quality, rmc->warn /* A=active or V=Void */
- );
+ nmeap_gga_t *gga = (nmeap_gga_t *) data;
+ altitude = gga->altitude;
+ satellites = gga->satellites;
+ quality = gga->quality;
+ msgCounter++;
}
-
-/*
-#define SHOW_ALTITUDE 0x0000001
-#define SHOW_SPEED 0x0000010
-#define SHOW_COURSE 0x0000100
-#define SHOW_SATELLITES 0x0001000
-#define SHOW_QUALITY 0x0010000
-#define SHOW_WARN 0x0100000
-*/
-
-static void parse(RESULT * result, RESULT * theOptions)
+/** called when a gprmc message is received and parsed */
+static void gprmc_callout( __attribute__ ((unused)) nmeap_context_t * context, void *data, __attribute__ ((unused))
+ void *user_data)
{
- char *value = " ";
- int finito = 0;
-
- int rem;
- int offset;
- int status;
- int len;
- int lame;
- long options;
- char buffer[32];
-
- options = R2N(theOptions);
- if (options & SHOW_ALTITUDE)
-
- while (finito == 0) {
-
- /* ---------------------------------------- */
- /* STEP 6 : get a buffer of input */
- /* --------------------------------------- */
- len = rem = read(fd, buffer, sizeof(buffer));
- if (len <= 0) {
- error("GPS Plugin, Error read from port");
- break;
- }
-
- /* ---------------------------------------------- */
- /* STEP 7 : process input until buffer is used up */
- /* ---------------------------------------------- */
-
- offset = 0;
- lame = 0;
-
- while (rem > 0) {
- status = nmeap_parseBuffer(&nmea, &buffer[offset], &rem);
- offset += (len - rem);
-
- switch (status) {
- case NMEAP_GPGGA:
- /* GOT A GPGGA MESSAGE */
- lame++;
- break;
- case NMEAP_GPRMC:
- /* GOT A GPRMC MESSAGE */
- lame++;
- break;
- default:
- debug("unhandled status: %d", status);
- break;
- }
- if (lame > 1) {
- finito = 1;
- printGps(&gga, &rmc);
- }
- }
-
- }
+ nmeap_rmc_t *rmc = (nmeap_rmc_t *) data;
-
- /* store result */
- SetResult(&result, R_STRING, value);
-
- free(value);
+ speed = rmc->speed;
+ gpsStatus = rmc->warn;
+ gpsTime = rmc->time;
+ gpsDate = rmc->date;
+ msgCounter++;
}
-
-/* plugin initialization */
-/* MUST NOT be declared 'static'! */
-int plugin_init_gps(void)
+static int prepare_gps_parser()
{
- int fd;
int status;
- char *port = "/dev/usb/tty/1";
+ char *port = "/dev/usb/tts/1";
char *test;
if ((test = getenv("GPS_PORT"))) { /* define your port via env variable */
port = test;
}
-
/* --------------------------------------- */
/* open the serial port device */
/* using default 4800 baud for most GPS */
/* --------------------------------------- */
- fd = openPort(port, B4800);
- if (fd < 0) {
+#ifndef EMULATE
+ fd_g = openPort(port, B4800);
+ if (fd_g < 0) {
/* open failed */
- error("GPS PLUGIN, Error: openPort %d", fd);
- return fd;
+ error("GPS PLUGIN, Error: openPort %d", fd_g);
+ return fd_g;
}
+#endif
/* --------------------------------------- */
/*STEP 2 : initialize the nmea context */
@@ -274,7 +248,7 @@ int plugin_init_gps(void)
/* --------------------------------------- */
/*STEP 3 : add standard GPGGA parser */
/* -------------------------------------- */
- status = nmeap_addParser(&nmea, "GPGGA", nmeap_gpgga, 0, &gga);
+ status = nmeap_addParser(&nmea, "GPGGA", nmeap_gpgga, gpgga_callout, &gga);
if (status != 0) {
error("GPS PLUGIN, Error: nmeap_add GPGGA parser, error:%d", status);
return -1;
@@ -284,24 +258,167 @@ int plugin_init_gps(void)
/*STEP 4 : add standard GPRMC parser */
/* -------------------------------------- */
/* status = nmeap_addParser(&nmea,"GPRMC",nmeap_gprmc,gprmc_callout,&rmc); */
- status = nmeap_addParser(&nmea, "GPRMC", nmeap_gprmc, 0, &rmc);
+ status = nmeap_addParser(&nmea, "GPRMC", nmeap_gprmc, gprmc_callout, &rmc);
if (status != 0) {
error("GPS PLUGIN, Error: nmeap_add GPRMC parser, error:%d", status);
return -1;
}
+ return fd_g;
+}
+
+
+
+static void parse(RESULT * result, RESULT * theOptions, RESULT * displayOptions)
+{
+// char *value = " ";
+// int finito = 0;
+
+ int rem;
+ int offset;
+ int status;
+ int len;
+ long options;
+ long dispOptions;
+#ifndef EMULATE
+ char buffer[128];
+#endif
+
+ options = R2N(theOptions);
+ dispOptions = R2N(displayOptions);
+ //error("options: %x\n",options);
+
+ /* ---------------------------------------- */
+ /* STEP 6 : get a buffer of input */
+ /* --------------------------------------- */
+#ifdef EMULATE
+ len = rem = sizeof(test_vector);
+#else
+ len = rem = read(fd_g, buffer, sizeof(buffer));
+
+ /* --------------------------------------- */
+ /*STEP 7 : pass it to the parser */
+ /* status indicates whether a complete msg */
+ /* arrived for this byte */
+ /* NOTE : in addition to the return status */
+ /* the message callout will be fired when */
+ /* a complete message is processed */
+ /* --------------------------------------- */
+ if (len <= 0) {
+ error("GPS Plugin, Error read from port, try using the GPS_PORT env variable (export GPS_PORT=/dev/mydev)");
+ //break;
+ }
+#endif
+
+ /* ---------------------------------------------- */
+ /* STEP 7 : process input until buffer is used up */
+ /* ---------------------------------------------- */
+ offset = 0;
+ while (rem > 0) {
+#ifdef EMULATE
+ status = nmeap_parseBuffer(&nmea, &test_vector[offset], &rem);
+#else
+ status = nmeap_parseBuffer(&nmea, &buffer[offset], &rem);
+// error("loop, remaining=%d, read bytes=%d\n",rem,offset);
+#endif
+ offset += (len - rem);
+ }
+
+ /* --------------------------------------- */
+ /* DISPLAY stuff comes here... */
+ /* --------------------------------------- */
+ char *value = " ";
+ char outputStr[80];
+ memset(outputStr, 0, 80);
+
+ if (options & SHOW_ALTITUDE) {
+ if (dispOptions & DISPLAY_NO_PREFIX)
+ sprintf(outputStr, "%s%.0f ", outputStr, altitude);
+ else
+ sprintf(outputStr, "%salt:%.0f ", outputStr, altitude);
+ }
+ if (options & SHOW_SPEED) {
+ float knotsConvert = 1.852f; //default speed display=km/h
+ if (dispOptions & DISPLAY_SPEED_IN_KNOTS)
+ knotsConvert = 1.0f; //use knots
+
+ if (dispOptions & DISPLAY_NO_PREFIX)
+ sprintf(outputStr, "%s%.0f ", outputStr, speed * knotsConvert);
+ else
+ sprintf(outputStr, "%sspd:%.0f ", outputStr, speed * knotsConvert);
+ }
+ if (options & SHOW_COURSE) {
+ char courses[8][3] = { "N ", "NO", "O ", "SO", "S ", "SW", "W ", "NW" };
+ float degrees[8] = { 22.5f, 67.5f, 112.5f, 157.5f, 202.5f, 247.5f, 292.5f, 337.5f };
+ int selectedDegree = 0;
+ int n;
+
+ for (n = 0; n < 8; n++) {
+ if (course < degrees[n]) {
+ selectedDegree = n;
+ break;
+ }
+ }
+ if (dispOptions & DISPLAY_NO_PREFIX)
+ sprintf(outputStr, "%s%s ", outputStr, courses[selectedDegree]);
+ else
+ sprintf(outputStr, "%sdir:%s ", outputStr, courses[selectedDegree]);
+ }
+ if (options & SHOW_SATELLITES) {
+ if (dispOptions & DISPLAY_NO_PREFIX)
+ sprintf(outputStr, "%s%d ", outputStr, satellites);
+ else
+ sprintf(outputStr, "%ssat:%d ", outputStr, satellites);
+ }
+ if (options & SHOW_QUALITY) {
+ if (dispOptions & DISPLAY_NO_PREFIX)
+ sprintf(outputStr, "%s%d ", outputStr, quality);
+ else
+ sprintf(outputStr, "%squa:%d ", outputStr, quality);
+ }
+ if (options & SHOW_STATUS) {
+ if (dispOptions & DISPLAY_NO_PREFIX)
+ sprintf(outputStr, "%s%c ", outputStr, gpsStatus);
+ else
+ sprintf(outputStr, "%ssta:%c ", outputStr, gpsStatus);
+ }
+ if (options & SHOW_TIME_UTC) {
+ if (dispOptions & DISPLAY_NO_PREFIX)
+ sprintf(outputStr, "%s%ld ", outputStr, gpsTime);
+ else
+ sprintf(outputStr, "%sutc:%ld ", outputStr, gpsTime);
+ }
+ if (options & SHOW_DATE) {
+ if (dispOptions & DISPLAY_NO_PREFIX)
+ sprintf(outputStr, "%s%ld ", outputStr, gpsDate);
+ else
+ sprintf(outputStr, "%sdat:%ld ", outputStr, gpsDate);
+ }
+
+ value = strdup(outputStr);
+ SetResult(&result, R_STRING, value);
+ free(value);
+}
+
+
+/* plugin initialization */
+/* MUST NOT be declared 'static'! */
+int plugin_init_gps(void)
+{
+ printf("PLUGIN INIT\n");
+ prepare_gps_parser();
/* register all our cool functions */
/* the second parameter is the number of arguments */
/* -1 stands for variable argument list */
- AddFunction("gps::parse", 0, parse);
+ AddFunction("gps::parse", 2, parse);
return 0;
}
void plugin_exit_gps(void)
{
- /* close the serial port */
- close(fd);
-
+#ifndef EMULATE
+ close(fd_g);
+#endif
}