diff options
author | Eric S. Raymond <esr@thyrsus.com> | 2005-06-29 20:38:44 +0000 |
---|---|---|
committer | Eric S. Raymond <esr@thyrsus.com> | 2005-06-29 20:38:44 +0000 |
commit | 7034fb6917d6afc9851dc79518fa1ce83a767e67 (patch) | |
tree | a4b8e41bbc8edd029c93b45210d9e71154fb3eac | |
parent | cba6b916920d78ef3e002061f1229d6c4debecac (diff) | |
download | gpsd-7034fb6917d6afc9851dc79518fa1ce83a767e67.tar.gz |
Experimental code to hunt for a DGPSIP server.
-rw-r--r-- | dgpsip.c | 47 | ||||
-rw-r--r-- | gps.h | 2 | ||||
-rw-r--r-- | gpsd.c | 33 | ||||
-rw-r--r-- | gpsd.h | 2 | ||||
-rw-r--r-- | gpsd.spec.in | 5 | ||||
-rw-r--r-- | gpsd.xml | 24 | ||||
-rw-r--r-- | gpsutils.c | 4 |
7 files changed, 96 insertions, 21 deletions
@@ -31,7 +31,8 @@ int dgpsip_open(struct gps_context_t *context, const char *dgpsserver) (void)gethostname(hn, sizeof(hn)); (void)snprintf(buf,sizeof(buf), "HELO %s gpsd %s\r\nR\r\n",hn,VERSION); (void)write(context->dsock, buf, strlen(buf)); - } + } else + gpsd_report(1, "Can't connect to DGPS server, netlib error %d\n", context->dsock); opts = fcntl(context->dsock, F_GETFL); if (opts >= 0) @@ -89,3 +90,47 @@ void dgpsip_report(struct gps_device_t *session) } } +/* maximum distance from DGPS server for it to be useful (meters) */ +#define DGPS_THRESHOLD 1600000 + +void dgpsip_autoconnect(struct gps_context_t *context, + double lat, double lon, + const char *serverlist) +/* tell the library to talk to the nearest DGPSIP server */ +{ + char buf[BUFSIZ]; + struct dgps_server_t { + double lat, lon; + char server[255]; + double dist; + } keep, hold; + FILE *sfp = fopen(serverlist, "r"); + + if (sfp == NULL) { + gpsd_report(1, "no DGPS server list found.\n"); + context->dsock = -2; /* don't try this again */ + return; + } + + keep.dist = DGPS_THRESHOLD; + keep.server[0] = '\0'; + while (fgets(buf, (int)sizeof(buf), sfp)) { + char *cp = strchr(buf, '#'); + if (cp) + *cp = '\0'; + if (sscanf(buf,"%lf %lf %256s",&hold.lat, &hold.lon, hold.server)==3) { + hold.dist = earth_distance(lat, lon, hold.lat, hold.lon); + if (hold.dist < keep.dist) + memcpy(&keep, &hold, sizeof(struct dgps_server_t)); + } + } + (void)fclose(sfp); + + if (keep.server[0] == '\0') { + gpsd_report(1, "no DGPS server within %d m\n", DGPS_THRESHOLD); + context->dsock = -2; /* don't try this again */ + return; + } + + (void)dgpsip_open(context, keep.server); +} @@ -195,7 +195,7 @@ extern double timestamp(void); extern double iso8601_to_unix(char *); extern /*@observer@*/char *unix_to_iso8601(double t, /*@ out @*/char[], int len); extern double gpstime_to_unix(int, double); -/* extern double earth_distance(double, double, double, double); */ +extern double earth_distance(double, double, double, double); extern double wgs84_separation(double lat, double lon); extern int gpsd_units(void); @@ -48,6 +48,10 @@ #define QLEN 5 +/* Where to find the list of DGPS correction servers, if there is one */ +#define DGPS_SERVER_LIST "/usr/share/gpsd/dgpsip-servers" + + /* * The name of a tty device from which to pick up whatever the local * owning group for tty devices is. Used when we drop privileges. @@ -60,7 +64,7 @@ static bool in_background = false; static jmp_buf restartbuf; /*@ -initallelements -nullassign -nullderef @*/ static struct gps_context_t context = {0, - false, 0, 0, 0, {'\0'}, 0, + false, 0, -1, 0, {'\0'}, 0, LEAP_SECONDS, CENTURY_BASE, #ifdef NTPSHM_ENABLE {0}, @@ -138,13 +142,13 @@ void gpsd_report(int errlevel, const char *fmt, ... ) static void usage(void) { - (void)printf("usage: gpsd [options] \n\ + (void)printf("usage: gpsd [-d dgpsip-server] [-D n] [-F sockfile] [-P pidfile] [-S port] [-h] device...\n\ Options include: \n\ - -f string = set GPS device name \n\ - -S integer (default %s) = set port for daemon \n\ -d host[:port] = set DGPS server \n\ + -F sockfile = specift control socket location\n\ -P pidfile = set file to record process ID \n\ -D integer (default 0) = set debug level \n\ + -S integer (default %s) = set port for daemon \n\ -h = help message \n", DEFAULT_GPSD_PORT); } @@ -1037,10 +1041,8 @@ int main(int argc, char *argv[]) if (dgpsserver) { int dsock = dgpsip_open(&context, dgpsserver); - if (dsock >= 0) { + if (dsock >= 0) FD_SET(dsock, &all_fds); - } else - gpsd_report(1, "Can't connect to DGPS server, netlib error %d\n", dsock); } #ifdef NTPSHM_ENABLE @@ -1192,9 +1194,8 @@ int main(int argc, char *argv[]) } /* be ready for DGPSIP reports */ - if (FD_ISSET(context.dsock, &rfds)) { + if (context.dsock >= 0 && FD_ISSET(context.dsock, &rfds)) dgpsip_poll(&context); - } /* read any commands that came in over control sockets */ for (cfd = 0; cfd < FD_SETSIZE; cfd++) @@ -1212,7 +1213,6 @@ int main(int argc, char *argv[]) /* poll all active devices */ for (channel = channels; channel < channels + MAXDEVICES; channel++) { - if (!allocated_channel(channel)) continue; @@ -1270,6 +1270,19 @@ int main(int argc, char *argv[]) #endif } + /* may be time to hunt up a DGPSIP server */ + if (context.fixcnt > 0 && context.dsock == -1) { + for (channel=channels; channel < channels+MAXDEVICES; channel++) { + if (channel->gpsdata.fix.mode < MODE_NO_FIX) { + dgpsip_autoconnect(&context, + channel->gpsdata.fix.latitude, + channel->gpsdata.fix.longitude, + DGPS_SERVER_LIST); + break; + } + } + } + /* accept and execute commands for all clients */ for (cfd = 0; cfd < FD_SETSIZE; cfd++) { if (subscribers[cfd].active && FD_ISSET(cfd, &rfds)) { @@ -177,6 +177,8 @@ extern int dgpsip_open(struct gps_context_t *, const char *); extern void dgpsip_poll(struct gps_context_t *); extern void dgpsip_relay(struct gps_device_t *); extern void dgpsip_report(struct gps_device_t *); +extern void dgpsip_autoconnect(struct gps_context_t *, + double, double, const char *); extern int gpsd_open(struct gps_device_t *); extern bool gpsd_next_hunt_setting(struct gps_device_t *); diff --git a/gpsd.spec.in b/gpsd.spec.in index e5434d18..ed494109 100644 --- a/gpsd.spec.in +++ b/gpsd.spec.in @@ -72,6 +72,7 @@ cp xgpsspeed.ad "$RPM_BUILD_ROOT"%{_libdir}/X11/app-defaults/xgpsspeed mkdir -p "$RPM_BUILD_ROOT"%{_sysconfdir}/hotplug/usb cp gpsd.hotplug gpsd.usermap "$RPM_BUILD_ROOT"%{_sysconfdir}/hotplug/usb/ # additional gpsd-devel files +mkdir -p "$RPM_BUILD_ROOT"%{_datadir}/gpsd PYVERSION=`python -c "import sys; print sys.version[:3]"` mkdir -p "$RPM_BUILD_ROOT"%{_libdir}/python${PYVERSION}/site-packages cp gps.py gpsfake.py "$RPM_BUILD_ROOT"%{_libdir}/python${PYVERSION}/site-packages @@ -99,6 +100,7 @@ cp gps.py gpsfake.py "$RPM_BUILD_ROOT"%{_libdir}/python${PYVERSION}/site-package %{_mandir}/man1/sirfmon.1* %{_sysconfdir}/hotplug/usb/gpsd.hotplug %{_sysconfdir}/hotplug/usb/gpsd.usermap +%{_datadir}/gpsd/dgps-servers %{_libdir}/python*/site-packages/gps.py* %files -n gpsd-devel @@ -134,7 +136,8 @@ cp gps.py gpsfake.py "$RPM_BUILD_ROOT"%{_libdir}/python${PYVERSION}/site-package and (3) a subtle error in the channel-assignment logic that only showed up with multiple sessions active. In fact, the daemon code no longer uses dynamic-memory allocation at all. Also, the code - no longer relies on FIONREAD working. + no longer relies on FIONREAD working. The daemon now hunts for a + DGPSIP server within 1600000m if the user didn't specify one. * Wed Jun 22 2005 Eric S. Raymond <esr@snark.thyrsus.com> - 2.26 - Time DOP and total DOP are now passed on from GPSes that report @@ -21,7 +21,7 @@ <arg choice='opt'>-f <replaceable>GPS-devicename</replaceable></arg> <arg choice='opt'>-F <replaceable>control-socket</replaceable></arg> <arg choice='opt'>-S <replaceable>listener-port</replaceable></arg> - <arg choice='opt'>-d <replaceable>DGPS-server</replaceable></arg> + <arg choice='opt'>-d <replaceable>DGPSIP-server</replaceable></arg> <arg choice='opt'>-n </arg> <arg choice='opt'>-N </arg> <arg choice='opt'>-h </arg> @@ -56,10 +56,12 @@ protocol used by the USB version of the Garmin 18 and other Garmin USB GPSes. <application>gpsd</application> effectively hides the differences among these.</para> -<para>Optionally, <application>gpsd</application> may get -differential-GPS corrections from a ground station running a RTCM-S104 -server; this will improve user error by roughly a factor of four. -See <xref linkend='accuracy'/> for discussion.</para> +<para><application>gpsd</application> can use differential-GPS +corrections from a ground station running a DGPSIP server that reports +RTCM-S104 data; this will improve user error by roughly a factor of +four. If no server is specified, <application>gpsd</application> will +hunt for one. See <xref linkend='accuracy'/> and <xref +linkend='files'/> for discussion.</para> <para>The program accepts the following options:</para> <variablelist remap='TP'> @@ -781,6 +783,18 @@ device if no GPS device was specified on the command line does not exist.</para> </listitem> </varlistentry> +<varlistentry> +<term><filename>/usr/share/gpsd/dgpsip-servers</filename></term> +<listitem> +<para>A text file listing DGPSIP servers worldwide. If no DGPSIP +server is specified at startup (via the -d option) +<application>gpsd</application> will look here to find the +nearest one. Each line has three space-separated fields: +latitude (decimal degrees), longitude (decimal degrees) and +a server name (optionally followed by a colon and a port number). +Text following # on a line is ignored. Blank lines are ignored.</para> +</listitem> +</varlistentry> </variablelist> </refsect1> @@ -165,7 +165,6 @@ double gpstime_to_unix(int week, double tow) #define Deg2Rad(n) ((n) * DEG_2_RAD) -#ifdef __UNUSED__ static double CalcRad(double lat) /* earth's radius of curvature in meters at specified latitude.*/ { @@ -206,13 +205,12 @@ double earth_distance(double lat1, double lon1, double lat2, double lon2) // a very small amount due to rounding errors in the preceding // calculations (this is prone to happen when the argument points // are very close together). Thus we constrain it here. - if (abs(a) > 1) + if (fabs(a) > 1) a = 1; else if (a < -1) a = -1; return CalcRad((lat1+lat2) / 2) * acos(a); } -#endif /* __UNUSED__ */ /***************************************************************************** |