diff options
author | Chris Kuethe <chris.kuethe@gmail.com> | 2005-08-16 22:00:27 +0000 |
---|---|---|
committer | Chris Kuethe <chris.kuethe@gmail.com> | 2005-08-16 22:00:27 +0000 |
commit | 02dfd5956eaca5ced6cb5b3ece06f263f5d158f2 (patch) | |
tree | 07aed359c4414a3927d3d3ff6c8d40bb2ba8f7be /contrib | |
parent | 4d7a2de4c441ef13e68dc1b6aa9dafe8e4dd2697 (diff) | |
download | gpsd-02dfd5956eaca5ced6cb5b3ece06f263f5d158f2.tar.gz |
>From Jeff Francis:
I don't generally run X on the car (truck) computer, so I threw
together a quick, dirty, and nasty little C/curses program that does
basically the same thing as xgps, minus the "x" part. I unashamedly
pillaged xgps.c for some of the code, and unashamedly hard-coded it
for English units (mph and ft). It's probably not perfect, nor is it
totally bug-free (for example, ^C doesn't work - got that wrong
somewhere). I don't feel it's up to snuff yet for include/, but I
thought I'd offer it up for use and abuse for anyone who needs a
text-only display. I'll clean it up as I go (for example, remove the
zillion #ifdefs for curses/non-curses).
Diffstat (limited to 'contrib')
-rw-r--r-- | contrib/gpsdspewcurses.c | 475 |
1 files changed, 475 insertions, 0 deletions
diff --git a/contrib/gpsdspewcurses.c b/contrib/gpsdspewcurses.c new file mode 100644 index 00000000..8fac8001 --- /dev/null +++ b/contrib/gpsdspewcurses.c @@ -0,0 +1,475 @@ +/* + * Copyright (c) 2005 Jeff Francis <jeff@gritch.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + Jeff Francis + jeff@gritch.org + $Id: gpsdspewcurses.c,v 1.11 2005/08/16 20:32:27 jfrancis Exp $ + + Kind of a curses version of xgps for use with gpsd. +*/ + + +/* Do ya want curses, or just straight text? */ +#define WITH_CURSES yep +/* #undef WITH_CURSES */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <unistd.h> +#include <math.h> +#include <errno.h> + +#ifdef WITH_CURSES +#include <ncurses.h> +#include <signal.h> +#endif + +#include "gps.h" + +/* Macro for declaring function arguments unused. */ +#if defined(__GNUC__) +# define UNUSED __attribute__((unused)) /* Flag variable as unused */ +#else /* not __GNUC__ */ +# define UNUSED +#endif + +static struct gps_data_t *gpsdata; +static time_t timer; /* time of last state change */ +static int state = 0; /* or MODE_NO_FIX=1, MODE_2D=2, MODE_3D=3 */ + +#ifdef WITH_CURSES +/* Function to call when we're all done. Does a bit of clean-up. */ +static void die() { + + /* Ignore signals. */ + signal(SIGINT,SIG_IGN); + + /* Move the cursor to the bottom left corner. */ + mvcur(0,COLS-1,LINES-1,0); + + /* Put input attributes back the way they were. */ + echo(); + noraw(); + + /* Done with curses. */ + endwin(); + + /* We're done talking to gpsd. */ + (void)gps_close(gpsdata); + + /* Bye! */ + exit(0); +} +#endif + +/* This gets called once for each new sentence. */ +static void update_panel(struct gps_data_t *gpsdata, + char *message, + size_t len UNUSED, + int level UNUSED) +{ + unsigned int i; + int newstate; + char s[128]; + + float altunits=METERS_TO_FEET; + float speedunits=MPS_TO_MPH; + +#ifdef WITH_CURSES + /* Do the initial field label setup. */ + move(0,5); + printw("Time:"); + move(1,5); + printw("Latitude:"); + move(2,5); + printw("Longitude:"); + move(3,5); + printw("Altitude:"); + move(4,5); + printw("Speed:"); + move(5,5); + printw("Heading:"); + move(6,5); + printw("HPE:"); + move(7,5); + printw("VPE:"); + move(8,5); + printw("Climb:"); + move(9,5); + printw("Status:"); + move(10,5); + printw("Change:"); + move(0,45); + printw("PRN: Elev: Azim: SNR: Used:"); +#endif + +#ifndef WITH_CURSES + printf("PRN: Elev: Azim: SNR: Used:\n"); +#endif + + /* This is for the satellite status display. Lifted almost verbatim + from xgps.c. */ + if (gpsdata->satellites) { + for (i = 0; i < MAXCHANNELS; i++) { + if (i < (unsigned int)gpsdata->satellites) { +#ifdef WITH_CURSES + move(i+1,45); + printw(" %3d %02d %03d %02d %c ", + gpsdata->PRN[i], + gpsdata->elevation[i], gpsdata->azimuth[i], + gpsdata->ss[i], gpsdata->used[i] ? 'Y' : 'N'); +#else + printf(" %3d %02d %03d %02d %c\n", + gpsdata->PRN[i], + gpsdata->elevation[i], gpsdata->azimuth[i], + gpsdata->ss[i], gpsdata->used[i] ? 'Y' : 'N'); +#endif + } else { +#ifdef WITH_CURSES + move(i+1,45); + printw(" "); +#else + printf(" \n"); +#endif + } + } + } + +/* TODO: Make this work. */ + if (isnan(gpsdata->fix.time)==0) { +#ifdef WITH_CURSES + move(0,17); + printw("%s",unix_to_iso8601(gpsdata->fix.time, s, (int)sizeof(s))); +#else + printf("%s\n",unix_to_iso8601(gpsdata->fix.time, s, (int)sizeof(s))); +#endif + } else { +#ifdef WITH_CURSES + move(0,17); + printw("n/a "); +#else + printf("n/a\n"); +#endif + } + + /* Fill in the latitude. */ + if (gpsdata->fix.mode >= MODE_2D) { +#ifdef WITH_CURSES + move(1,17); + printw("%lf %c ", fabs(gpsdata->fix.latitude), (gpsdata->fix.latitude < 0) ? 'S' : 'N'); +#else + printf("lat: %lf %c\n", fabs(gpsdata->fix.latitude), (gpsdata->fix.latitude < 0) ? 'S' : 'N'); +#endif + } else { +#ifdef WITH_CURSES + move(1,17); + printw("n/a "); +#else + printf("n/a\n"); +#endif + } + + /* Fill in the longitude. */ + if (gpsdata->fix.mode >= MODE_2D) { +#ifdef WITH_CURSES + move(2,17); + printw("%lf %c ", fabs(gpsdata->fix.longitude), (gpsdata->fix.longitude < 0) ? 'W' : 'E'); +#else + printf("lon: %lf %c\n", fabs(gpsdata->fix.longitude), (gpsdata->fix.longitude < 0) ? 'W' : 'E'); +#endif + } else { +#ifdef WITH_CURSES + move(2,17); + printw("n/a "); +#else + printf("n/a\n"); +#endif + } + + /* Fill in the altitude. */ + if (gpsdata->fix.mode == MODE_3D) { +#ifdef WITH_CURSES + move(3,17); + printw("%.1f ft ",gpsdata->fix.altitude*altunits); +#else + printf("alt: %f ft\n",gpsdata->fix.altitude*altunits); +#endif + } else { +#ifdef WITH_CURSES + move(3,17); + printw("n/a "); +#else + printf("n/a\n"); +#endif + } + + /* Fill in the speed */ + if (gpsdata->fix.mode >= MODE_2D && isnan(gpsdata->fix.track)==0) { +#ifdef WITH_CURSES + move(4,17); + printw("%.1f mph ", gpsdata->fix.speed*speedunits); +#else + printf("spd: %f mph\n", gpsdata->fix.speed*speedunits); +#endif + } else { +#ifdef WITH_CURSES + move(4,17); + printw("n/a "); +#else + printf("n/a\n"); +#endif + } + + /* Fill in the heading. */ + if (gpsdata->fix.mode >= MODE_2D && isnan(gpsdata->fix.track)==0) { +#ifdef WITH_CURSES + move(5,17); + printw("%.1f degrees \n", gpsdata->fix.track); +#else + printf("crs: %f degrees\n", gpsdata->fix.track); +#endif + } else { +#ifdef WITH_CURSES + move(5,17); + printw("n/a "); +#else + printf("n/a\n"); +#endif + } + + /* Fill in the estimated horizontal position error. */ + if (isnan(gpsdata->fix.eph)==0) { +#ifdef WITH_CURSES + move(6,17); + printw("%d ft ", (int) (gpsdata->fix.eph * altunits)); +#else + printf("alterr: %f\n", gpsdata->fix.eph * altunits); +#endif + } else { +#ifdef WITH_CURSES + move(6,17); + printw("n/a "); +#else + printf("n/a\n"); +#endif + } + + /* Fill in the estimated vertical position error. */ + if (isnan(gpsdata->fix.epv)==0) { +#ifdef WITH_CURSES + move(7,17); + printw("%d ft ", (int)(gpsdata->fix.epv * altunits)); +#else + printf("poserr: %f\n", gpsdata->fix.epv * altunits); +#endif + } else { +#ifdef WITH_CURSES + move(7,17); + printw("n/a "); +#else + printf("n/a\n"); +#endif + } + + /* Fill in the rate of climb. */ + /* TODO: Units are probably wrong. */ + if (gpsdata->fix.mode == MODE_3D && isnan(gpsdata->fix.climb)==0) { +#ifdef WITH_CURSES + move(8,17); + printw("%.1f ft/min ", gpsdata->fix.climb * METERS_TO_FEET * 60); +#else + printf("cli: %f ft/min\n", gpsdata->fix.climb * METERS_TO_FEET * 60); +#endif + } else { +#ifdef WITH_CURSES + move(8,17); + printw("n/a "); +#else + printf("n/a\n"); +#endif + } + + /* Fill in the GPS status */ + if (gpsdata->online == 0) { + newstate = 0; +#ifdef WITH_CURSES + move(9,17); + printw("OFFLINE "); +#else + printf("OFFLINE\n"); +#endif + } else { + newstate = gpsdata->fix.mode; + switch (gpsdata->fix.mode) { + case MODE_2D: +#ifdef WITH_CURSES + move(9,17); + printw("2D %sFIX ",(gpsdata->status==STATUS_DGPS_FIX)?"DIFF ":""); +#else + printf("2D %sFIX\n",(gpsdata->status==STATUS_DGPS_FIX)?"DIFF ":""); +#endif + break; + case MODE_3D: +#ifdef WITH_CURSES + move(9,17); + printw("3D %sFIX ",(gpsdata->status==STATUS_DGPS_FIX)?"DIFF ":""); +#else + printf("3D %sFIX\n",(gpsdata->status==STATUS_DGPS_FIX)?"DIFF ":""); +#endif + break; + default: +#ifdef WITH_CURSES + move(9,17); + printw("NO FIX "); +#else + printf("NO FIX\n"); +#endif + break; + } + } + + /* Fill in the time since the last state change. */ + if (newstate != state) { + timer = time(NULL); + state = newstate; + } +#ifdef WITH_CURSES + move(10,17); + printw("(%d secs) ", (int) (time(NULL) - timer)); +#else + printf("(%d secs)\n", (int) (time(NULL) - timer)); +#endif + + /* Update the screen. */ +#ifdef WITH_CURSES + refresh(); +#else + printf("\n"); +#endif +} + +int main(int argc, char *argv[]) +{ + int option; + char *arg = NULL, *colon1, *colon2, *device = NULL, *server = NULL, *port = DEFAULT_GPSD_PORT; + char *err_str = NULL; + + /* Process the options. Print help or version, if requested. */ + while ((option = getopt(argc, argv, "hv")) != -1) { + switch (option) { + case 'v': + (void)printf("thing $Id: gpsdspewcurses.c,v 1.11 2005/08/16 20:32:27 jfrancis Exp $\n"); + exit(0); + case 'h': default: + (void)fputs("usage: thing [-hv] [server[:port:[device]]]\n", stderr); + exit(1); + } + } + + /* Grok the server, port, and device. */ + if (optind < argc) { + arg = strdup(argv[optind]); + colon1 = strchr(arg, ':'); + server = arg; + if (colon1 != NULL) { + if (colon1 == arg) + server = NULL; + else + *colon1 = '\0'; + port = colon1 + 1; + colon2 = strchr(port, ':'); + if (colon2 != NULL) { + if (colon2 == port) + port = NULL; + else + *colon2 = '\0'; + device = colon2 + 1; + } + } + colon1 = colon2 = NULL; + } + + /* Open the stream to gpsd. */ + gpsdata = gps_open(server, port); + if (!gpsdata) { + switch ( errno ) { + case NL_NOSERVICE: err_str = "can't get service entry"; break; + case NL_NOHOST: err_str = "can't get host entry"; break; + case NL_NOPROTO: err_str = "can't get protocol entry"; break; + case NL_NOSOCK: err_str = "can't create socket"; break; + case NL_NOSOCKOPT: err_str = "error SETSOCKOPT SO_REUSEADDR"; break; + case NL_NOCONNECT: err_str = "can't connect to host"; break; + default: err_str = "Unknown"; break; + } + (void)fprintf( stderr, + "xgps: no gpsd running or network error: %d, %s\n", + errno, err_str); + exit(2); + } + + /* Update the timestamp (used to keep track of time since last state + change). */ + timer = time(NULL); + + /* Set up the curses screen (if using curses). */ +#ifdef WITH_CURSES + initscr(); + raw(); + noecho(); + /* signal(SIGINT,die); */ +#endif + + /* Here's where updates go. */ + gps_set_raw_hook(gpsdata, update_panel); + + /* If the user requested a specific device, try to change to it. */ + if (device) { + char *channelcmd = (char *)malloc(strlen(device)+3); + + if (channelcmd) { + (void)strcpy(channelcmd, "F="); + (void)strcpy(channelcmd+2, device); + (void)gps_query(gpsdata, channelcmd); + (void)free(channelcmd); + } + } + + /* Request "w+x" data from gpsd. */ + (void)gps_query(gpsdata, "w+x\n"); + + /* Loop and poll once per second (this could be less than optimal + for a receiver that updates > 1hz, or for a user using a *really* + slow ancient serial terminal). */ + while(1) { + gps_poll(gpsdata); + sleep(1); + } + +#ifdef WITH_CURSES + die(); +#else + /* We're done talking to gpsd. */ + (void)gps_close(gpsdata); + if (arg != NULL) + (void)free(arg); + + return 0; +#endif +} + |