aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorreinelt <>2004-05-22 18:30:02 +0000
committerreinelt <>2004-05-22 18:30:02 +0000
commit54a3ddf9b4ab1b2f739700268de2f09014ecd95c (patch)
tree1d68a2aab7e852c1500c9c2417114e1d787db966
parent8f9e1a5296018e0729343eea686970bfc917c699 (diff)
downloadlcd4linux-54a3ddf9b4ab1b2f739700268de2f09014ecd95c.tar.gz
[lcd4linux @ 2004-05-22 18:30:01 by reinelt]
added plugin 'uptime'
-rw-r--r--Makefile.am1
-rw-r--r--Makefile.in9
-rw-r--r--config.h.in3
-rwxr-xr-xconfigure12
-rw-r--r--lcd4linux.conf.sample17
-rw-r--r--plugin.c14
-rw-r--r--plugin_uptime.c237
-rw-r--r--plugins.m48
8 files changed, 292 insertions, 9 deletions
diff --git a/Makefile.am b/Makefile.am
index 84710b7..badf184 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -88,6 +88,7 @@ plugin_ppp.c \
plugin_proc_stat.c \
plugin_seti.c \
plugin_uname.c \
+plugin_uptime.c \
plugin_wireless.c \
plugin_xmms.c
diff --git a/Makefile.in b/Makefile.in
index f95b582..2a7bbfb 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -101,7 +101,7 @@ lcd4linux_SOURCES = lcd4linux.c cfg.c cfg.h deb
#liblcd4linux_la_SOURCES =
-EXTRA_lcd4linux_SOURCES = drv_generic_text.c drv_generic_text.h drv_generic_graphic.c drv_generic_graphic.h drv_generic_serial.c drv_generic_serial.h drv_generic_parport.c drv_generic_parport.h BeckmannEgle.c drv_Crystalfontz.c drv_Cwlinux.c drv_HD44780.c drv_M50530.c drv_T6963.c drv_USBLCD.c drv_MatrixOrbital.c MilfordInstruments.c PalmPilot.c Raster.c drv_X11.c Text.c font_6x8.h plugin_apm.c plugin_cpuinfo.c plugin_dvb.c plugin_exec.c plugin_i2c_sensors.c plugin_imon.c plugin_isdn.c plugin_loadavg.c plugin_meminfo.c plugin_mysql.c plugin_netdev.c plugin_pop3.c plugin_ppp.c plugin_proc_stat.c plugin_seti.c plugin_uname.c plugin_wireless.c plugin_xmms.c
+EXTRA_lcd4linux_SOURCES = drv_generic_text.c drv_generic_text.h drv_generic_graphic.c drv_generic_graphic.h drv_generic_serial.c drv_generic_serial.h drv_generic_parport.c drv_generic_parport.h BeckmannEgle.c drv_Crystalfontz.c drv_Cwlinux.c drv_HD44780.c drv_M50530.c drv_T6963.c drv_USBLCD.c drv_MatrixOrbital.c MilfordInstruments.c PalmPilot.c Raster.c drv_X11.c Text.c font_6x8.h plugin_apm.c plugin_cpuinfo.c plugin_dvb.c plugin_exec.c plugin_i2c_sensors.c plugin_imon.c plugin_isdn.c plugin_loadavg.c plugin_meminfo.c plugin_mysql.c plugin_netdev.c plugin_pop3.c plugin_ppp.c plugin_proc_stat.c plugin_seti.c plugin_uname.c plugin_uptime.c plugin_wireless.c plugin_xmms.c
EXTRA_DIST = lcd4linux.conf.sample lcd4kde.conf lcd4linux.kdelnk lcd4linux.xpm lcd4linux.lsm curses.m4 AUTHORS CREDITS FAQ NEWS TODO README README.Rows README.Tokens README.Drivers README.Plugins README.KDE plugin_sample.c
@@ -154,9 +154,10 @@ DEP_FILES = .deps/BeckmannEgle.P .deps/MilfordInstruments.P \
.deps/plugin_mysql.P .deps/plugin_netdev.P .deps/plugin_pop3.P \
.deps/plugin_ppp.P .deps/plugin_proc_stat.P .deps/plugin_seti.P \
.deps/plugin_string.P .deps/plugin_time.P .deps/plugin_uname.P \
-.deps/plugin_wireless.P .deps/plugin_xmms.P .deps/qprintf.P \
-.deps/thread.P .deps/timer.P .deps/udelay.P .deps/widget.P \
-.deps/widget_bar.P .deps/widget_icon.P .deps/widget_text.P
+.deps/plugin_uptime.P .deps/plugin_wireless.P .deps/plugin_xmms.P \
+.deps/qprintf.P .deps/thread.P .deps/timer.P .deps/udelay.P \
+.deps/widget.P .deps/widget_bar.P .deps/widget_icon.P \
+.deps/widget_text.P
SOURCES = $(lcd4linux_SOURCES) $(EXTRA_lcd4linux_SOURCES)
OBJECTS = $(lcd4linux_OBJECTS)
diff --git a/config.h.in b/config.h.in
index ab5b2b7..b1e163f 100644
--- a/config.h.in
+++ b/config.h.in
@@ -278,6 +278,9 @@
/* uname plugin */
#undef PLUGIN_UNAME
+/* uptime plugin */
+#undef PLUGIN_UPTIME
+
/* wireless plugin */
#undef PLUGIN_WIRELESS
diff --git a/configure b/configure
index 68d071c..ebf9082 100755
--- a/configure
+++ b/configure
@@ -5748,6 +5748,7 @@ echo "$as_me: error: run ./configure --with-plugins=..." >&2;}
PLUGIN_PROC_STAT="yes"
PLUGIN_SETI="yes"
PLUGIN_UNAME="yes"
+ PLUGIN_UPTIME="yes"
PLUGIN_WIRELESS="yes"
PLUGIN_XMMS="yes"
;;
@@ -5799,6 +5800,9 @@ echo "$as_me: error: run ./configure --with-plugins=..." >&2;}
uname)
PLUGIN_UNAME=$val
;;
+ uptime)
+ PLUGIN_UPTIME=$val
+ ;;
wireless)
PLUGIN_WIRELESS=$val
;;
@@ -6641,6 +6645,14 @@ cat >>confdefs.h <<\_ACEOF
_ACEOF
fi
+if test "$PLUGIN_UPTIME" = "yes"; then
+ PLUGINS="$PLUGINS plugin_uptime.o"
+
+cat >>confdefs.h <<\_ACEOF
+#define PLUGIN_UPTIME 1
+_ACEOF
+
+fi
if test "$PLUGIN_WIRELESS" = "yes"; then
PLUGINS="$PLUGINS plugin_wireless.o"
diff --git a/lcd4linux.conf.sample b/lcd4linux.conf.sample
index 9367805..9f57059 100644
--- a/lcd4linux.conf.sample
+++ b/lcd4linux.conf.sample
@@ -247,6 +247,15 @@ Widget MySQLtest2 {
update minute
}
+Widget Uptime {
+ class 'Text'
+ expression uptime('%d days %H:%M:%S')
+ width 20
+ align 'R'
+ prefix 'Up '
+ update 1000
+}
+
Widget Heartbeat {
class 'Icon'
speed 800
@@ -457,17 +466,17 @@ Layout testMySQL {
#Display 'LK204'
-Display 'HD44780-20x4'
+#Display 'HD44780-20x4'
#Display 'M50530-24x8'
#Display 'CF631'
#Display 'CF632'
#Display 'CF633'
-#Display 'USBLCD'
+Display 'USBLCD'
#Display 'T6963-240x64'
#Display 'XWindow'
-#Layout 'Default'
-Layout 'L16x2'
+Layout 'Default'
+#ayout 'L16x2'
#Layout 'Test'
diff --git a/plugin.c b/plugin.c
index 5e2a58e..69a6212 100644
--- a/plugin.c
+++ b/plugin.c
@@ -1,4 +1,4 @@
-/* $Id: plugin.c,v 1.29 2004/05/20 07:47:51 reinelt Exp $
+/* $Id: plugin.c,v 1.30 2004/05/22 18:30:02 reinelt Exp $
*
* plugin handler for the Evaluator
*
@@ -22,6 +22,10 @@
*
*
* $Log: plugin.c,v $
+ * Revision 1.30 2004/05/22 18:30:02 reinelt
+ *
+ * added plugin 'uptime'
+ *
* Revision 1.29 2004/05/20 07:47:51 reinelt
* added plugin_time
*
@@ -209,6 +213,8 @@ int plugin_init_seti(void);
void plugin_exit_seti(void);
int plugin_init_uname (void);
void plugin_exit_uname (void);
+int plugin_init_uptime (void);
+void plugin_exit_uptime (void);
int plugin_init_wireless(void);
void plugin_exit_wireless(void);
int plugin_init_xmms (void);
@@ -270,6 +276,9 @@ int plugin_init (void)
#ifdef PLUGIN_UNAME
plugin_init_uname();
#endif
+#ifdef PLUGIN_UPTIME
+ plugin_init_uptime();
+#endif
#ifdef PLUGIN_WIRELESS
plugin_init_wireless();
#endif
@@ -330,6 +339,9 @@ void plugin_exit(void) {
#ifdef PLUGIN_UNAME
plugin_exit_uname();
#endif
+#ifdef PLUGIN_UPTIME
+ plugin_exit_uptime();
+#endif
#ifdef PLUGIN_WIRELESS
plugin_exit_wireless();
#endif
diff --git a/plugin_uptime.c b/plugin_uptime.c
new file mode 100644
index 0000000..1519ad1
--- /dev/null
+++ b/plugin_uptime.c
@@ -0,0 +1,237 @@
+/* $Id: plugin_uptime.c,v 1.1 2004/05/22 18:30:02 reinelt Exp $
+ *
+ * plugin for uptime
+ *
+ * Copyright 2003 Michael Reinelt <reinelt@eunet.at>
+ * Copyright 2004 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
+ *
+ * This file is part of LCD4Linux.
+ *
+ * LCD4Linux is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * LCD4Linux 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * $Log: plugin_uptime.c,v $
+ * Revision 1.1 2004/05/22 18:30:02 reinelt
+ *
+ * added plugin 'uptime'
+ *
+ */
+
+/*
+ * exported functions:
+ *
+ * int plugin_init_uptime (void)
+ * adds functions for uptime
+ *
+ */
+
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <fcntl.h>
+
+#include "debug.h"
+#include "plugin.h"
+
+static int fd = -2;
+
+
+static char *itoa(char* buffer, size_t size, unsigned int value)
+{
+ char *p;
+
+ // sanity checks
+ if (buffer==NULL || size<2) return (NULL);
+
+ // p points to last char
+ p = buffer+size-1;
+
+ // set terminating zero
+ *p='\0';
+
+ do {
+ *--p = value%10 + '0';
+ value = value/10;
+ } while (value!=0 && p>buffer);
+
+ return p;
+}
+
+
+char *struptime (unsigned int uptime, char *format)
+{
+ static char string[256];
+ const char *src;
+ char *dst;
+ int len, size;
+
+ src = format;
+ dst = string;
+ len = 0;
+
+ // leave room for terminating zero
+ size = sizeof(string) - 1;
+
+ while (len < size) {
+
+ if (*src == '%') {
+ src++;
+
+ if (strchr ("sSmMhHd", *src) != NULL) {
+ char buffer[12], *s;
+ unsigned int value = 0;
+ int leading_zero = 0;
+ switch (*src++) {
+ case 's':
+ value = uptime;
+ break;
+ case 'S':
+ value = uptime % 60;
+ leading_zero = 1;
+ break;
+ case 'm':
+ value = uptime / 60;
+ break;
+ case 'M':
+ value = (uptime / 60) % 60;
+ leading_zero = 1;
+ break;
+ case 'h':
+ value = uptime / 60 / 60;
+ break;
+ case 'H':
+ value = (uptime / 60 / 60) % 24;
+ leading_zero = 1;
+ break;
+ case 'd':
+ value = uptime / 60 / 60 / 24;
+ break;
+ }
+
+ if (leading_zero && value < 10) {
+ len++;
+ *dst++ = '0';
+ }
+
+ s = itoa (buffer, sizeof(buffer), value);
+ while (len < size && *s != '\0') {
+ len++;
+ *dst++ = *s++;
+ }
+
+ } else if (*src == '%') {
+ len++;
+ *dst++ = '%';
+
+ } else {
+ len += 2;
+ *dst++ = '%';
+ *dst++ = *src++;
+ }
+
+ } else {
+ len++;
+ *dst++ = *src;
+ if (*src++ == '\0') break;
+ }
+ }
+
+ // enforce terminating zero
+ if (len >= size && *(dst-1) != '\0') {
+ len++;
+ *dst = '\0';
+ }
+
+ return string;
+}
+
+
+double getuptime (void)
+{
+ char buffer[36];
+ int i;
+
+ if (fd == -2) fd = open ("/proc/uptime", O_RDONLY);
+ if (fd < 0) return -1;
+
+ lseek(fd, 0, SEEK_SET);
+
+ i = read (fd, buffer, sizeof(buffer) - 1);
+ if (i < 0) return -1;
+
+ buffer[i-1] = '\0';
+
+ // ignore the 2nd value from /proc/uptime
+ return strtod(buffer, NULL);
+}
+
+
+static void my_uptime (RESULT *result, int argc, RESULT *argv[])
+{
+ int age;
+ static double uptime = 0.0;
+ static struct timeval last_value;
+ struct timeval now;
+
+ if (argc>1) {
+ error ("uptime(): wrong number of parameters");
+ SetResult(&result, R_STRING, "");
+ return;
+ }
+
+ gettimeofday(&now,NULL);
+
+ age = (now.tv_sec - last_value.tv_sec)*1000 + (now.tv_usec - last_value.tv_usec)/1000;
+ // reread every 100 msec only
+ if (fd == -2 || age == 0 || age > 100) {
+ uptime = getuptime();
+ if (uptime < 0.0) {
+ error ("parse(/proc/uptime) failed!");
+ SetResult(&result, R_STRING, "");
+ return;
+ }
+
+ last_value = now;
+ }
+
+ if (argc == 0) {
+ SetResult (&result, R_NUMBER, &uptime);
+ } else {
+ SetResult (&result, R_STRING, struptime(uptime, R2S(argv[0])));
+ }
+
+ return;
+
+}
+
+int plugin_init_uptime (void)
+{
+ AddFunction ("uptime", -1, my_uptime);
+ return 0;
+}
+
+void plugin_exit_uptime(void)
+{
+ if (fd > 0) close(fd);
+ fd = -2;
+}
diff --git a/plugins.m4 b/plugins.m4
index 4e97005..547fc57 100644
--- a/plugins.m4
+++ b/plugins.m4
@@ -46,6 +46,7 @@ for plugin in $plugins; do
PLUGIN_PROC_STAT="yes"
PLUGIN_SETI="yes"
PLUGIN_UNAME="yes"
+ PLUGIN_UPTIME="yes"
PLUGIN_WIRELESS="yes"
PLUGIN_XMMS="yes"
;;
@@ -97,6 +98,9 @@ for plugin in $plugins; do
uname)
PLUGIN_UNAME=$val
;;
+ uptime)
+ PLUGIN_UPTIME=$val
+ ;;
wireless)
PLUGIN_WIRELESS=$val
;;
@@ -199,6 +203,10 @@ if test "$PLUGIN_UNAME" = "yes"; then
PLUGINS="$PLUGINS plugin_uname.o"
AC_DEFINE(PLUGIN_UNAME,1,[uname plugin])
fi
+if test "$PLUGIN_UPTIME" = "yes"; then
+ PLUGINS="$PLUGINS plugin_uptime.o"
+ AC_DEFINE(PLUGIN_UPTIME,1,[uptime plugin])
+fi
if test "$PLUGIN_WIRELESS" = "yes"; then
PLUGINS="$PLUGINS plugin_wireless.o"
AC_DEFINE(PLUGIN_WIRELESS,1,[wireless plugin])
>(phid); phid->sckbuf_read=0; phid->sckbuf_write=0; ZEROMEM(phid->sckbuf, 256); phid->lastFix = PUNK_BOOL; phid->lastLatitude = PUNK_DBL; phid->lastLongitude = PUNK_DBL; phid->lastAltitude = PUNK_DBL; phid->fix = PUNK_BOOL; phid->heading = PUNK_DBL; phid->velocity = PUNK_DBL; phid->altitude = PUNK_DBL; phid->latitude = PUNK_DBL; phid->longitude = PUNK_DBL; phid->haveTime = PUNK_BOOL; phid->haveDate = PUNK_BOOL; //clean out the NMEA sentences ZEROMEM(&phid->GPSData, sizeof(NMEAData)); //Examples for sending data. buffer[0] is dataLength, other spots are data // continue in multiple packets if needed. Wait for ACK between sends //set factory defaults and reboot /*buffer[0]=0x02;buffer[1]=0x04;buffer[2]=0x01; CUSBSendPacket((CPhidgetHandle)phid, buffer);*/ //set 10Hz update rate /*buffer[0]=0x03;buffer[1]=0x0e;buffer[2]=0x0a;buffer[3]=0x00; CUSBSendPacket((CPhidgetHandle)phid, buffer);*/ //Get Ephemeris /*buffer[0]=0x02;buffer[1]=0x30;buffer[2]=0x00; CUSBSendPacket((CPhidgetHandle)phid, buffer);*/ //Enable WAAS buffer[0]=0x03;buffer[1]=0x37;buffer[2]=0x01;buffer[2]=0x01; CUSBSendPacket((CPhidgetHandle)phid, buffer); //Query WAAS /*buffer[0]=0x01;buffer[1]=0x38; CUSBSendPacket((CPhidgetHandle)phid, buffer);*/ //read some initial data - rate is 10Hz so we shouldn't have to wait long //This ensures we have received at least one GGA and one RMC readtries = 30; //250ms while((phid->fix==PUNK_BOOL || phid->haveTime==PUNK_BOOL || phid->haveDate==PUNK_BOOL) && readtries) { CPhidget_read((CPhidgetHandle)phid); readtries--; } if(phid->fix==PUNK_BOOL) phid->fix=PFALSE; return EPHIDGET_OK; } //dataInput - parses device packets CPHIDGETDATA(GPS) int i=0; if (length < 0) return EPHIDGET_INVALIDARG; TESTPTR(phid); TESTPTR(buffer); //LOG(PHIDGET_LOG_DEBUG, "GPS Packet size: %d", buffer[0]); /* stick it in a buffer */ for (i=0; i<buffer[0]; i++) { phid->sckbuf[phid->sckbuf_write++] = buffer[i+1]; } parse_GPS_packets(phid); return EPHIDGET_OK; } //eventsAfterOpen - sends out an event for all valid data, used during attach initialization CPHIDGETINITEVENTS(GPS) if(phid->fix != PUNK_BOOL) FIRE(PositionFixStatusChange, phid->fix); if (phid->fix == PTRUE && (phid->latitude != PUNK_DBL || phid->longitude != PUNK_DBL || phid->altitude != PUNK_DBL)) FIRE(PositionChange, phid->latitude, phid->longitude, phid->altitude); return EPHIDGET_OK; } //getPacket - not used for GPS CGETPACKET(GPS) return EPHIDGET_UNEXPECTED; } /* checks a CRC */ static int checkcrc(char *data, int crc) { unsigned int i=0; unsigned char check=0; for(i=1;i<strlen(data);i++) check^=data[i]; if(check == crc) return 0; return 1; } /* this parses a full NMEA sentence */ static int parse_NMEA_data(char *data, CPhidgetGPSInfo *phid) { char *dataarray[50]; int numfields = 0; int i,j,crc=0; double dintpart, decpart; int intpart; double tempD; //LOG(PHIDGET_LOG_DEBUG,"%s\n",data); /* fist check CRC if there is one */ j = (int)strlen(data); for(i=0;i<j;i++) { if(data[i] == '*') { crc = strtol(data+i+1,NULL,16); data[i] = '\0'; if(checkcrc(data, crc)) { /* This will usually be caused by blocking in an event handler, which causes some packets to be dropped. Safe to ignore. */ LOG(PHIDGET_LOG_WARNING,"CRC Error parsing NMEA sentence."); return 1; } break; } } /* seperate out by commas */ dataarray[0] = data; j = (int)strlen(data); for(i=0;i<j;i++) { if(data[i] == ',') { numfields++; dataarray[numfields] = data+i+1; data[i] = '\0'; } } if(strlen(dataarray[0]) != 6) { LOG(PHIDGET_LOG_WARNING,"Bad sentence type."); return 1; } /* find the type of sentence */ if(!strncmp("GGA",dataarray[0]+3,3)) { //time: HHMMSS.milliseconds if(strlen(dataarray[1]) >= 6) { decpart = modf(strtod(dataarray[1], NULL), &dintpart); intpart = (int)dintpart; phid->GPSData.GGA.time.tm_hour = (short)(intpart/10000); phid->GPSData.GGA.time.tm_min = (short)(intpart/100%100); phid->GPSData.GGA.time.tm_sec = (short)(intpart%100); phid->GPSData.GGA.time.tm_ms = (short)round(decpart*1000); phid->haveTime = PTRUE; } else phid->haveTime = PFALSE; /* convert lat/long to signed decimal degree format */ if(strlen(dataarray[2])) { tempD = (int)(strtol(dataarray[2], NULL, 10) / 100) + (strtod((dataarray[2]+2),NULL) / 60); if(dataarray[3][0] == 'S') phid->GPSData.GGA.latitude = -tempD; else phid->GPSData.GGA.latitude = tempD; } else phid->GPSData.GGA.latitude = 0; if(strlen(dataarray[4])) { tempD = (int)(strtol(dataarray[4], NULL, 10) / 100) + (strtod((dataarray[4]+3),NULL) / 60); if(dataarray[5][0] == 'W') phid->GPSData.GGA.longitude = -tempD; else phid->GPSData.GGA.longitude = tempD; } else phid->GPSData.GGA.longitude = 0; phid->GPSData.GGA.fixQuality = (short)strtol(dataarray[6],NULL,10); phid->GPSData.GGA.numSatellites = (short)strtol(dataarray[7],NULL,10); phid->GPSData.GGA.horizontalDilution = strtod(dataarray[8],NULL); phid->GPSData.GGA.altitude = strtod(dataarray[9],NULL); phid->GPSData.GGA.heightOfGeoid = strtod(dataarray[11],NULL); //Set local variables for getters/events phid->fix = (phid->GPSData.GGA.fixQuality == 0) ? PFALSE : PTRUE; if(phid->fix) { phid->altitude = phid->GPSData.GGA.altitude; phid->latitude = phid->GPSData.GGA.latitude; phid->longitude = phid->GPSData.GGA.longitude; } else { phid->altitude = PUNK_DBL; phid->latitude = PUNK_DBL; phid->longitude = PUNK_DBL; } //Fix status changed if(phid->fix != phid->lastFix) { FIRE(PositionFixStatusChange, phid->fix); phid->lastFix = phid->fix; } /* only sends event if the fix is valid, and position has changed a bit */ if (phid->fix == PTRUE && (phid->latitude != phid->lastLatitude || phid->longitude != phid->lastLongitude || phid->altitude != phid->lastAltitude) ) { FIRE(PositionChange, phid->latitude, phid->longitude, phid->altitude); phid->lastLatitude = phid->latitude; phid->lastLongitude = phid->longitude; phid->lastAltitude = phid->altitude; } } else if(!strncmp("GSA",dataarray[0]+3,3)) { phid->GPSData.GSA.mode = dataarray[1][0]; phid->GPSData.GSA.fixType = (short)strtol(dataarray[2],NULL,10); for(i=0;i<12;i++) phid->GPSData.GSA.satUsed[i] = (short)strtol(dataarray[i+3],NULL,10); phid->GPSData.GSA.posnDilution = strtod(dataarray[15],NULL); phid->GPSData.GSA.horizDilution = strtod(dataarray[16],NULL); phid->GPSData.GSA.vertDilution = strtod(dataarray[17],NULL); } else if(!strncmp("GSV",dataarray[0]+3,3)) { int numSentences, sentenceNumber, numSats; numSentences = strtol(dataarray[1],NULL,10); sentenceNumber = strtol(dataarray[2],NULL,10); numSats = strtol(dataarray[3],NULL,10); phid->GPSData.GSV.satsInView = (short)numSats; for(i=0;i<(numSentences==sentenceNumber?numSats-(4*(numSentences-1)):4);i++) { phid->GPSData.GSV.satInfo[i+((sentenceNumber-1)*4)].ID = (short)strtol(dataarray[4+(i*4)],NULL,10); phid->GPSData.GSV.satInfo[i+((sentenceNumber-1)*4)].elevation = (short)strtol(dataarray[5+(i*4)],NULL,10); phid->GPSData.GSV.satInfo[i+((sentenceNumber-1)*4)].azimuth = strtol(dataarray[6+(i*4)],NULL,10); phid->GPSData.GSV.satInfo[i+((sentenceNumber-1)*4)].SNR = (short)strtol(dataarray[7+(i*4)],NULL,10); } } else if(!strncmp("RMC",dataarray[0]+3,3)) { if(strlen(dataarray[1])>=6) { decpart = modf(strtod(dataarray[1], NULL), &dintpart); intpart = (int)dintpart; phid->GPSData.RMC.time.tm_hour = (short)(intpart/10000); phid->GPSData.RMC.time.tm_min = (short)(intpart/100%100); phid->GPSData.RMC.time.tm_sec = (short)(intpart%100); phid->GPSData.RMC.time.tm_ms = (short)round(decpart*1000); } phid->GPSData.RMC.status = dataarray[2][0]; /* convert lat/long to signed decimal degree format */ if(strlen(dataarray[3])) { tempD = (int)(strtol(dataarray[3], NULL, 10) / 100) + (strtod((dataarray[3]+2),NULL) / 60); if(dataarray[4][0] == 'S') phid->GPSData.RMC.latitude = -tempD; else phid->GPSData.RMC.latitude = tempD; } else phid->GPSData.RMC.latitude = 0; if(strlen(dataarray[5])) { tempD = (int)(strtol(dataarray[5], NULL, 10) / 100) + (strtod((dataarray[5]+3),NULL) / 60); if(dataarray[6][0] == 'W') phid->GPSData.RMC.longitude = -tempD; else phid->GPSData.RMC.longitude = tempD; } else phid->GPSData.RMC.longitude = 0; phid->GPSData.RMC.speedKnots = strtod(dataarray[7],NULL); phid->GPSData.RMC.heading = strtod(dataarray[8],NULL); if(strlen(dataarray[9])>=6) { intpart = strtol(dataarray[9], NULL, 10); phid->GPSData.RMC.date.tm_mday = (short)(intpart/10000); phid->GPSData.RMC.date.tm_mon = (short)(intpart/100%100); phid->GPSData.RMC.date.tm_year = (short)(intpart%100) + 2000; //2-digit year, add 2000 years phid->haveDate = PTRUE; } else phid->haveDate = PFALSE; tempD = strtod(dataarray[10],NULL); if(dataarray[11][0] == 'W') phid->GPSData.RMC.magneticVariation = -tempD; else phid->GPSData.RMC.magneticVariation = tempD; phid->GPSData.RMC.mode = dataarray[12][0]; if(phid->GPSData.RMC.status == 'A') { phid->velocity = phid->GPSData.RMC.speedKnots * 1.852; //convert to km/h phid->heading = phid->GPSData.RMC.heading; } else { phid->velocity = PUNK_DBL; phid->heading = PUNK_DBL; } } else if(!strncmp("VTG",dataarray[0]+3,3)) { phid->GPSData.VTG.trueHeading = strtod(dataarray[1],NULL); phid->GPSData.VTG.magneticHeading = strtod(dataarray[3],NULL); phid->GPSData.VTG.speedKnots = strtod(dataarray[5],NULL); phid->GPSData.VTG.speed = strtod(dataarray[7],NULL); phid->GPSData.VTG.mode = dataarray[9][0]; } else { LOG(PHIDGET_LOG_INFO,"Unrecognized sentence type: %s", dataarray[0]+3); } return 0; } /* this parses a full sentence */ static int parse_SkyTraq_response(unsigned char *data, CPhidgetGPSInfo *phid) { int msgLength = data[3]; int crc = data[msgLength + 4]; int i, crccheck=0; char buffer[256]; for(i=0;i<msgLength;i++) { crccheck^=data[i+4]; } if(crc != crccheck) { LOG(PHIDGET_LOG_WARNING,"CRC Error parsing SkyTraq response."); return -1; } switch(data[4]) { case 0x83: //ACK LOG(PHIDGET_LOG_INFO, "SkyTraq ACK: 0x%02x", data[5]); break; case 0x84: //NACK LOG(PHIDGET_LOG_INFO, "SkyTraq NACK: 0x%02x", data[5]); break; default: LOG(PHIDGET_LOG_INFO, "Got a SkyTraq message: 0x%02x", data[4]); buffer[0]=0; for(i=0;i<msgLength-1;i++) { if(i%8==0 && i!=0) { LOG(PHIDGET_LOG_INFO, "%s", buffer); buffer[0]=0; } sprintf(buffer+strlen(buffer)," 0x%02x", data[i+5]); } if(buffer[0]) LOG(PHIDGET_LOG_INFO, "%s", buffer); } return 0; } /* this parses out the packets */ static int parse_GPS_packets(CPhidgetGPSInfo *phid) { unsigned char current_queuesize, msgsize, temp; int result, i=0; do { result = 0; /* Not known if packetsize is valid yet... */ /* advance read ptr to '$' or 0xa0 */ i=0; while ((i < 255) && (phid->sckbuf_read != phid->sckbuf_write)) { if(phid->sckbuf[phid->sckbuf_read] == '$' || phid->sckbuf[phid->sckbuf_read] == 0xa0) break; i++; phid->sckbuf_read++; } current_queuesize = phid->sckbuf_write - phid->sckbuf_read; //response msg from skytraq - size is in posn 3 if(phid->sckbuf[phid->sckbuf_read] == 0xa0) { unsigned char tempbuffer[256]; if(current_queuesize < 4) break; msgsize = 7 + phid->sckbuf[(unsigned char)(phid->sckbuf_read + 3)]; if(current_queuesize < msgsize) break; for (i = 0; i<msgsize; i++) tempbuffer[i] = phid->sckbuf[phid->sckbuf_read++]; /* We know that we have at least a full sentence here... look for another */ result=1; /* here we'll actually parse this sentence */ if(parse_SkyTraq_response(tempbuffer, phid)) { LOG(PHIDGET_LOG_WARNING,"Error parsing SkyTraq response."); } } else //NMEA/Other { char tempbuffer[256]; /* find the end of the sentence */ temp = phid->sckbuf_read; msgsize = 0; for (i=0; i < current_queuesize; i++,temp++) { if(phid->sckbuf[temp] == '\n') { msgsize = i; break; } } if(!msgsize) break; //couldn't find it for (i = 0; i<msgsize; i++) tempbuffer[i] = phid->sckbuf[phid->sckbuf_read++]; tempbuffer[i] = 0; /* We know that we have at least a full sentence here... look for another */ result=1; //NMEA - always starts with '$GP' if (current_queuesize >= 6 && tempbuffer[1] == 'G' && tempbuffer[2] == 'P') { /* here we'll actually parse this sentence */ if(parse_NMEA_data(tempbuffer, phid)) { LOG(PHIDGET_LOG_WARNING,"Error parsing NMEA sentence."); } } else //Something else that starts with a '$' { LOG(PHIDGET_LOG_INFO, "GPS Message: %s", tempbuffer); } } } while(result); return 0; } // === Exported Functions === // //create and initialize a device structure CCREATE(GPS, PHIDCLASS_GPS) //event setup functions CFHANDLE(GPS, PositionChange, double, double, double) CFHANDLE(GPS, PositionFixStatusChange, int) CGET(GPS,Latitude,double) TESTPTRS(phid,pVal) TESTDEVICETYPE(PHIDCLASS_GPS) TESTATTACHED TESTMASGN(latitude, PUNK_DBL) MASGN(latitude) } CGET(GPS,Longitude,double) TESTPTRS(phid,pVal) TESTDEVICETYPE(PHIDCLASS_GPS) TESTATTACHED TESTMASGN(longitude, PUNK_DBL) MASGN(longitude) } CGET(GPS,Altitude,double) TESTPTRS(phid,pVal) TESTDEVICETYPE(PHIDCLASS_GPS) TESTATTACHED TESTMASGN(altitude, PUNK_DBL) MASGN(altitude) } CGET(GPS,Time,GPSTime) TESTPTRS(phid,pVal) TESTDEVICETYPE(PHIDCLASS_GPS) TESTATTACHED if(phid->haveTime == PUNK_BOOL) return EPHIDGET_UNKNOWNVAL; MASGN(GPSData.GGA.time) } CGET(GPS,Date,GPSDate) TESTPTRS(phid,pVal) TESTDEVICETYPE(PHIDCLASS_GPS) TESTATTACHED if(phid->haveDate == PUNK_BOOL) return EPHIDGET_UNKNOWNVAL; MASGN(GPSData.RMC.date) } CGET(GPS,NMEAData,NMEAData) TESTPTRS(phid,pVal) TESTDEVICETYPE(PHIDCLASS_GPS) TESTATTACHED //Not uspported over webservice if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG)) return EPHIDGET_UNSUPPORTED; MASGN(GPSData) } CGET(GPS,Heading,double) TESTPTRS(phid,pVal) TESTDEVICETYPE(PHIDCLASS_GPS) TESTATTACHED TESTMASGN(heading, PUNK_DBL) MASGN(heading) } CGET(GPS,Velocity,double) TESTPTRS(phid,pVal) TESTDEVICETYPE(PHIDCLASS_GPS) TESTATTACHED TESTMASGN(velocity, PUNK_DBL) MASGN(velocity) } CGET(GPS,PositionFixStatus,int) TESTPTRS(phid,pVal) TESTDEVICETYPE(PHIDCLASS_GPS) TESTATTACHED TESTMASGN(fix, PUNK_BOOL) MASGN(fix) }