Browse Source

New upstream version 3.18.1

suites/experimental
Christian Ehrhardt 4 years ago
committed by Bernd Zeimetz
parent
commit
b41905b77a
  1. 7
      .travis.yml
  2. 6
      .travis/build.sh
  3. 3
      .vimrc
  4. 35
      INSTALL
  5. 25
      NEWS
  6. 804
      SConstruct
  7. 37
      TODO
  8. 2
      Tachometer.c
  9. 2
      Tachometer.h
  10. 2
      TachometerP.h
  11. 3
      ais_json.i
  12. 2
      bits.c
  13. 2
      bits.h
  14. 51
      build.txt
  15. 209
      cgps.1
  16. 1226
      cgps.c
  17. 7
      contrib/README
  18. 9
      contrib/SConstruct
  19. 110
      contrib/clock_test.c
  20. 2
      contrib/gps
  21. 97
      contrib/gpsData.py
  22. 91
      contrib/gpssnmp.c
  23. 88
      contrib/ntpshmviz
  24. 367
      contrib/skyview2svg
  25. 77
      contrib/webgps.py
  26. 2
      crc24q.c
  27. 2
      crc24q.h
  28. 2
      dbusexport.c
  29. 698
      devtools/ais.py
  30. 2
      devtools/gps
  31. 1
      devtools/identify_failing_build_options.py
  32. 106
      devtools/tablegen.py
  33. 3
      devtools/test_json_validity.py
  34. 9
      devtools/uninstall_cleanup.py
  35. 2
      driver_ais.c
  36. 20
      driver_evermore.c
  37. 2
      driver_garmin.c
  38. 2
      driver_garmin_txt.c
  39. 2
      driver_geostar.c
  40. 998
      driver_greis.c
  41. 6
      driver_greis.h
  42. 24
      driver_greis_checksum.c
  43. 25
      driver_italk.c
  44. 2
      driver_italk.h
  45. 12
      driver_navcom.c
  46. 322
      driver_nmea0183.c
  47. 41
      driver_nmea2000.c
  48. 2
      driver_nmea2000.h
  49. 2
      driver_oncore.c
  50. 16
      driver_proto.c
  51. 2
      driver_rtcm2.c
  52. 3
      driver_rtcm3.c
  53. 43
      driver_sirf.c
  54. 27
      driver_skytraq.c
  55. 2
      driver_superstar2.c
  56. 2
      driver_superstar2.h
  57. 20
      driver_tsip.c
  58. 900
      driver_ubx.c
  59. 121
      driver_ubx.h
  60. 2
      driver_zodiac.c
  61. 25
      drivers.c
  62. 94
      gegps
  63. 2
      gegps.1
  64. 6
      geoid.c
  65. 209
      gps.1
  66. 129
      gps.h
  67. 63
      gps.xml
  68. 9
      gps/__init__.py
  69. 156
      gps/client.py
  70. 39
      gps/fake.py
  71. 138
      gps/gps.py
  72. 7
      gps/misc.py
  73. 16
      gps/watch_options.py
  74. 2
      gps2udp.c
  75. 2
      gps2udp.xml
  76. 13
      gps_json.h
  77. 5
      gps_maskdump.c
  78. 2
      gpscap.ini
  79. 18
      gpscap.py
  80. 49
      gpscat
  81. 2
      gpscat.xml
  82. 2
      gpsclient.c
  83. 9
      gpsctl.c
  84. 2
      gpsctl.xml
  85. 140
      gpsd.c
  86. 53
      gpsd.h
  87. 2
      gpsd.hotplug
  88. 2
      gpsd.rules.in
  89. 2
      gpsd.usermap
  90. 2
      gpsd.xml
  91. 21
      gpsd_config.h
  92. 106
      gpsd_json.5
  93. 196
      gpsd_json.c
  94. 72
      gpsd_json.xml
  95. 4
      gpsdclient.c
  96. 2
      gpsdclient.h
  97. 2
      gpsdctl.c
  98. 2
      gpsdctl.xml
  99. 6
      gpsdecode.c
  100. 2
      gpsdecode.xml

7
.travis.yml

@ -6,9 +6,10 @@ language: generic
# context, we disable the C++ builds in the clang case.
env:
- TRAVIS_DEBIAN_DISTRIBUTION=unstable TRAVIS_DEBIAN_BUILD_COMMAND="/bin/bash .travis.build" TRAVIS_DEBIAN_BUILD_DEPENDENCIES="build-essential debhelper po-debconf python-all-dev python-all-dbg xsltproc docbook-xsl docbook-xml asciidoc libncurses-dev libusb-1.0-0-dev libdbus-1-dev libglib2.0-dev libdbus-glib-1-dev makedev libbluetooth-dev libqt4-dev lsb-release bc dpkg-dev scons chrpath dh-buildinfo pps-tools dh-systemd"
- TRAVIS_DEBIAN_DISTRIBUTION=unstable TRAVIS_DEBIAN_BUILD_COMMAND="/bin/bash .travis.build libgpsmm=no qt=no" TRAVIS_DEBIAN_BUILD_DEPENDENCIES="build-essential debhelper po-debconf python-all-dev python-all-dbg xsltproc docbook-xsl docbook-xml asciidoc libncurses-dev libusb-1.0-0-dev libdbus-1-dev libglib2.0-dev libdbus-glib-1-dev makedev libbluetooth-dev libqt4-dev lsb-release bc dpkg-dev scons chrpath dh-buildinfo pps-tools dh-systemd clang" TRAVIS_DEBIAN_BUILD_ENVIRONMENT="CC=clang CXX=clang++"
- TRAVIS_DEBIAN_DISTRIBUTION=stable TRAVIS_DEBIAN_BUILD_COMMAND="/bin/bash .travis.build" TRAVIS_DEBIAN_BUILD_DEPENDENCIES="build-essential debhelper po-debconf python-all-dev python-all-dbg xsltproc docbook-xsl docbook-xml asciidoc libncurses-dev libusb-1.0-0-dev libdbus-1-dev libglib2.0-dev libdbus-glib-1-dev makedev libbluetooth-dev libqt4-dev lsb-release bc dpkg-dev scons chrpath dh-buildinfo pps-tools dh-systemd"
- TRAVIS_DEBIAN_DISTRIBUTION=unstable TRAVIS_DEBIAN_BUILD_COMMAND="/bin/bash .travis/build.sh" TRAVIS_DEBIAN_BUILD_DEPENDENCIES="build-essential debhelper po-debconf python-all-dev python-all-dbg xsltproc docbook-xsl docbook-xml asciidoc libncurses-dev libusb-1.0-0-dev libdbus-1-dev libglib2.0-dev libdbus-glib-1-dev makedev libbluetooth-dev qtbase5-dev qt5-default lsb-release bc dpkg-dev scons chrpath dh-buildinfo pps-tools dh-systemd python-serial"
- TRAVIS_DEBIAN_DISTRIBUTION=unstable TRAVIS_DEBIAN_BUILD_COMMAND="/bin/bash .travis/build.sh" TRAVIS_DEBIAN_BUILD_DEPENDENCIES="build-essential debhelper po-debconf python-all-dev python-all-dbg xsltproc docbook-xsl docbook-xml asciidoc libncurses-dev libusb-1.0-0-dev libdbus-1-dev libglib2.0-dev libdbus-glib-1-dev makedev libbluetooth-dev libqt4-dev lsb-release bc dpkg-dev scons chrpath dh-buildinfo pps-tools dh-systemd python-serial"
- TRAVIS_DEBIAN_DISTRIBUTION=unstable TRAVIS_DEBIAN_BUILD_COMMAND="/bin/bash .travis/build.sh libgpsmm=no qt=no" TRAVIS_DEBIAN_BUILD_DEPENDENCIES="build-essential debhelper po-debconf python-all-dev python-all-dbg xsltproc docbook-xsl docbook-xml asciidoc libncurses-dev libusb-1.0-0-dev libdbus-1-dev libglib2.0-dev libdbus-glib-1-dev makedev libbluetooth-dev libqt4-dev lsb-release bc dpkg-dev scons chrpath dh-buildinfo pps-tools dh-systemd clang python-serial" TRAVIS_DEBIAN_BUILD_ENVIRONMENT="CC=clang CXX=clang++"
- TRAVIS_DEBIAN_DISTRIBUTION=stable TRAVIS_DEBIAN_BUILD_COMMAND="/bin/bash .travis/build.sh" TRAVIS_DEBIAN_BUILD_DEPENDENCIES="build-essential debhelper po-debconf python-all-dev python-all-dbg xsltproc docbook-xsl docbook-xml asciidoc libncurses-dev libusb-1.0-0-dev libdbus-1-dev libglib2.0-dev libdbus-glib-1-dev makedev libbluetooth-dev libqt4-dev lsb-release bc dpkg-dev scons chrpath dh-buildinfo pps-tools dh-systemd python-serial"
services:
- docker

6
.travis.build → .travis/build.sh

@ -17,6 +17,12 @@ SCONSOPTS="${SCONSOPTS} libdir=/usr/lib/${DEB_HOST_MULTIARCH}"
SCONSOPTS="${SCONSOPTS} gpsd_user=gpsd"
SCONSOPTS="${SCONSOPTS} gpsd_group=dialout"
SCONSOPTS="${SCONSOPTS} debug=yes"
### SCONSOPTS="${SCONSOPTS} qt=yes" # The default qt=yes must be overridable
SCONSOPTS="${SCONSOPTS} xgps=no" # Until we figure out the right Gtk3 packages
if dpkg -s qtbase5-dev 1>/dev/null 2>&1; then
SCONSOPTS="${SCONSOPTS} qt_versioned=5"
fi
export SCONSOPTS

3
.vimrc

@ -0,0 +1,3 @@
# gpsd vim settings
# Python 3 does not like tabs in files
:set tabstop=4 shiftwidth=4 expandtab

35
INSTALL

@ -1,6 +1,6 @@
= GPSD Installation Instructions =
:title: GPSD Installation Instructions
:description: Here are the steps for installing GPSD and verifying its performance.
:description: Steps for installing GPSD and verifying its performance.
:keywords: GPSD, GPS, installation
:author: Eric S. Raymond <esr@thyrsus.com>
:robots:index,follow
@ -96,6 +96,7 @@ various additional features have additional prerequisites:
|Qt + qmake | libQgpsmm depends on this
|python2.x(x>=6) or 3.y(y>=2) | required for various clients and utilities
|python-GI bindings | the test clients xgps and xgpsspeed, need this
|pyserial | ubxtool and zerk need this
|===============================================================================
Some ncurses packages contain the terminfo library; some break it out
@ -105,13 +106,13 @@ separately as libtinfo5 or libtinfo.
=== Install your distributions package(s) ===
Up-to-date gpsd packages are generally available for Linux
distributions including Debian and derivatives (including Ubuntu and
Mint), Fedora and derivatives (including CentOS), openSUSE, PCLinuxOS,
Mageia, and Slackware. In the embedded space, CeroWRT carries
GPSD. The GPSD package in the FreeBSD ports tree is also reliably up
to date. Even if your distribution is not on this list, it is quite
likely GPSD has already been packaged for it.
Up-to-date gpsd packages are generally available for Linux distributions
including Debian and derivatives (including Ubuntu and Mint), Fedora and
derivatives (including CentOS), openSUSE, PCLinuxOS, Mageia, Gentoo, and
Slackware. In the embedded space, CeroWRT and Yocto carry GPSD. The
GPSD package in the FreeBSD ports tree is also reliably up to date.
Even if your distribution is not on this list, it is quite likely GPSD
has already been packaged for it.
Whatever distribution you are running, the name of the core GPSD
package containing the service daemon is almost certainly "gpsd".
@ -141,8 +142,8 @@ watcher modes. You should see lines beginning with '{' that are
JSON objects representing reports from your GPS; these are reports
in GPSD protocol.
4. Start the xgps or cgps client. Calling it with no arguments should
do the right thing. You should see a display panel with
4. Start the xgps or cgps client. Calling it with no arguments
should do the right thing. You should see a display panel with
position/velocity-time information, and a satellite display. The
displays won't look very interesting until the GPS acquires satellite
lock.
@ -166,11 +167,11 @@ us information to add a new line to the table. Directions are
included on that page. We can also use updates of the latest version
number known to work with hardware already supported.
3. GPSD includes a PHP script that you can use to generate a PHP
status page for your GPS if you wish. (It may not be in the core
package.) It should be manually copied to your HTTP document directory.
The first time it's invoked, it will generate a file called
'gpsd_config.inc' in that directory containing configuration
3. GPSD includes gpsd.php, a PHP script, that you can use to generate
a PHP status page for your GPS if you wish. (It may not be in the
core package.) It should be manually copied to your HTTP document
directory. The first time it's invoked, it will generate a file
called 'gpsd_config.inc' in that directory containing configuration
information; edit to taste.
4. There are other non-essential scripts that may be useful; these
@ -331,8 +332,6 @@ install, as noted in the file *build.txt* .
=== Other Raspberry Pi tips ===
Note: this does not apply to the RasPi3.
Any USB connected GPS that is known to work with gpsd will work fine on
the RasPi. No special instructions apply.
@ -355,7 +354,7 @@ Reboot so those changes take effect.
Run gpsd like this:
--------------------------------------------------------------
~ # gpsd -D 5 -N -n /dev/ttyAMA0/dev/pps0
~ # gpsd -D 5 -N -n /dev/ttyAMA0 /dev/pps0
--------------------------------------------------------------
If you are on the RasPi with gpsd version 3.17, or above, /dev/pps0 can

25
NEWS

@ -1,5 +1,30 @@
GPSD project news
3.19: not released yet
3.18.1: 2018-10-19 (Gary E. Miller <gem@rellim.com>)
Fix some installation issues.
A few minor updates to ubxtool and driver_ubx.
Add contrib/skyview2svg
3.18: 2018-10-02 (Gary E. Miller <gem@rellim.com>)
Add ECEF support to ievermore, italk,Skytraq, SiRF, U-blox drivers.
Add ECEF support to JSON, cgps and xgps.
Add GREIS (Javad) driver from Virgin Orbit.
Add CLI tools zerk and ubxtool to manage JAVAD and u-blox GPS.
Add gnssid:svid to satellite_t, cgps and xgps. PRN will die.
Add gnssid:svid to JSON, cgps and xgps.
Add stricter version checking (more to todo).
More and better regression tests.
Better Python dependency checking, at build time and runtime.
Fix several buffer issues.
New polar plots, and improved statistice, in gpsprof.
gpsd master/slave mode works, first time ever.
All isnan() changed to !isfinite(), fixing many bugs.
Client-side Python libraries may automatically reconnect
Too many other bug fixes and improvements to mention.
Over 1,000 commits from 46 different commiters.
3.17: 2017-09-07 (Eric S. Raymond <esr@snark.thyrsus.com>)
Repair support for non-NMEA devices requring active probing
(e.g. Garmin USB GPSes). Apply OS X build fixes. Fix a SiRF driver

804
SConstruct

File diff suppressed because it is too large

37
TODO

@ -8,6 +8,13 @@ the "Hacking Guide" on the project website.
The list of bugs exposed by gpsd in other software has moved to
the "Upstream Bugs" page on the project website.
** Installation **
Improve the uninstall target. Remove library syminks.
Make libdir conform to new Gentoo layout: 32bit in lib/ and 64bit in
lib64/. Doing that also makes the uninstall more complex.
** Documentation **
We now have two different calibration procedures in the Time Service
@ -20,14 +27,40 @@ the calibration process less annoying?
** Things to do when we can break compatibility **
In gps_data_t make device subtype longer. 128 chars long sounds good.
In gps_data_t add more string like subtype for HW version, SW version, etc.
In gps_data_t, save PPS precision; this will require creating a pps struct.
Where would PPS precision come from?
In gps_fix_t, maybe change time away from float to timespec?
Convert all the time_t (double) and timeval (usec) to timespec (nsec).
That could be done one small step at a time.
Add MMSI sequence number fields to AIS type 7.
Make the Python JSON client as smart as the C JSON client. Gonna be
a big job. The C client checks all the JSON classes for completeness
and correctness. For example, a missing JSON field will be replaced
with a default value. Also out of bounds values are fixed. The Python
client does no checks. it just mushes a JSON sentance into a big Python
variable. No validity checking, no missing fields fixed, etc. The C
client uses a generic validator function, fed with templates for each
JSON message. Initially harder than a simple procedural parser, Once
running it is very robust and easy to tweak.
Handle mutifrequency GNSS (B1, E1, L1, L2, B3, L3, L5, L2C, E5, E6,
etc.)
Handle raw measurements, like UBX-RXM-RAW. With an uploader for
postprocessing.
add u-blox IMU (UBX-ESF-RAW) and qErr (UBX-TIM-TP) support.
Adding a sample Go client (gpspipe -> pytogo -> Go ?).
Add RTCM3, RINEX, and/or RAW message forwarders.
Move webgps.py out of contrib. It needs a man page and light cleanup.
** Bugs in gpsd and its clients:
*** Tracker bugs

2
Tachometer.c

@ -7,7 +7,7 @@
* Cleaned up and simplified by Eric S. Raymond, December 2004.
*
* This file is Copyright (c) 2010 by the GPSD project
* BSD terms apply: see the file COPYING in the distribution root for details.
* SPDX-License-Identifier: BSD-2-clause
*/
#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>

2
Tachometer.h

@ -1,6 +1,6 @@
/*
* This file is Copyright (c) 2010 by the GPSD project
* BSD terms apply: see the file COPYING in the distribution root for details.
* SPDX-License-Identifier: BSD-2-clause
*/
#ifndef _GPSD_TACHOMETER_H_
#define _GPSD_TACHOMETER_H_

2
TachometerP.h

@ -1,6 +1,6 @@
/*
* This file is Copyright (c) 2010 by the GPSD project
* BSD terms apply: see the file COPYING in the distribution root for details.
* SPDX-License-Identifier: BSD-2-clause
*/
#ifndef _GPSD_TACHOMETERP_H_
#define _GPSD_TACHOMETERP_H_

3
ais_json.i

@ -3,8 +3,6 @@
*/
#define NITEMS(x) (int)(sizeof(x)/sizeof(x[0]))
/*@ -fullinitblock */
const struct json_attr_t json_ais1[] = {
AIS_HEADER
@ -1212,7 +1210,6 @@
};
/*@ +fullinitblock */
/* Generated code ends. */

2
bits.c

@ -1,7 +1,7 @@
/* bits.c - bitfield extraction code
*
* This file is Copyright (c)2010 by the GPSD project
* BSD terms apply: see the file COPYING in the distribution root for details.
* SPDX-License-Identifier: BSD-2-clause
*
* Bitfield extraction functions. In each, start is a bit index - not
* a byte index - and width is a bit width. The width is bounded above by

2
bits.h

@ -9,7 +9,7 @@
* Both 32- and 64-bit systems with gcc are OK with this set.
*
* This file is Copyright (c)2010 by the GPSD project
* BSD terms apply: see the file COPYING in the distribution root for details.
* SPDX-License-Identifier: BSD-2-clause
*/
#ifndef _GPSD_BITS_H_
#define _GPSD_BITS_H_

51
build.txt

@ -13,7 +13,7 @@ You can download the lastest gpsd tarball from:
http://download.savannah.gnu.org/releases/gpsd/
Under Linux, assuming you have all your build prerequisites in place,
these lines will do:
these lines will do, and need to be run as root:
tar -xzf gpsd-X.YY.tar.gz
cd gpsd-X.YY
@ -22,13 +22,22 @@ these lines will do:
If you get any errors, you need to read the detailed instructions that follow.
If 'scons' fails, it is possible that your target system has moved to
Python 3 as its default 'python' interpreter, but you can work around
it by saying "python2 /usr/bin/scons" or something similar.
Python 3 and removed the program 'python'. Python.org says that if
you have an installed Python, there should be a program in your path
called 'python'. This is specified in PEP 394. This rule is not always
followed. You can work around this by linking python3 to python like
this
Occasionally, builds may fail in completely bizarre ways due to a corrupted
scons database. This seems to relate to ^Cing the build at an inopportune
moment. If you suspect that, see "Reverting to a clean state" below and
then try again.
ln -s /usr/bin/python3 /usr/bin/python
Both 'scons' and 'gpsd' work fine on either Python 2 or Python 3. Which
python you have installed should be transparent to the user, if python
is installed correctly.
Occasionally, builds may fail in completely bizarre ways due to a
corrupted scons database. This seems to relate to ^Cing the build at
an inopportune moment. If you suspect that, see "Reverting to a clean
state" below and then try again.
== Supported platforms ==
@ -41,9 +50,9 @@ installed:
* FreeBSD, NetBSD, OpenBSD
* Android, using the official Google toolchain from the NDK
We consider failure to build and function on any of these platforms
a serious bug; if you encounter it, please complain on the
development list.
We consider failure to build and function on any of these platforms a
serious bug; if you encounter it, please complain on the development
list <gpsd-dev@nongnu.org>.
Port difficulty to any system conforming to POSIX-2001.1 should be minimal.
@ -60,7 +69,7 @@ Necessary components for any build:
|============================================================================
|C compiler | gpsd and client library are written in C
|scons | for executing the build recipe
|Python 2.x(x>=6) | for scons and some helper scripts
|Python2.x(x>=6) or 3.y(y>=2) | for scons and some helper scripts
|============================================================================
=== C compiler ===
@ -104,13 +113,21 @@ extensions. Usually these are called "python" and "python-dev". You
will know you are missing the latter if your compilation fails
because of a missing Python.h.
The xgps and xgpsspeed test clients require the following Python extensions:
The xgps and xgpsspeed clients will only be installed if these Python
extensions are installed:
|============================================================================
|python-gi | Python bindings for gobject-introspection libraries
|python-gi-cairo | Python bindings for Cairo toolkit under GI
|===========================================================================
The ubxtool and zerk clients will only be installed if this Python
extensions is installed:
|============================================================================
|pyserial | Python Serial Port extension
|===========================================================================
=== Scons ===
You will need scons version 2.3.0 (from 2013-03-02) or later to build the code.
@ -204,11 +221,11 @@ To build gpsd for your host platform from source, simply call 'scons'
in a working-directory copy. (Cross-build is described in a later
section.)
To clean the built files, call 'scons -c' . To clean scons' cache,
call 'scons sconsclean'. Doing both should return your working directory
to a near pristine state as far as building is concerned. Some user
created files may remain, and source code changes will not have been
reverted..
To clean the built files, call 'scons -c' . To clean scons' cache, call
'scons sconsclean'. Run 'rm -f .sconsign.dblite' to clear the scons
database. Doing all three should return your working directory to a
near pristine state as far as building is concerned. Some user created
files may remain, and source code changes will not have been reverted..
You can specify the installation prefix, as for an autotools build, by
running "scons prefix=<installation_root>". The default value is

209
cgps.1

@ -1 +1,208 @@
.so gps.1
'\" t
.\" Title: gps
.\" Author: [see the "AUTHORS" section]
.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
.\" Date: 9 Aug 2004
.\" Manual: GPSD Documentation
.\" Source: The GPSD Project
.\" Language: English
.\"
.TH "GPS" "1" "9 Aug 2004" "The GPSD Project" "GPSD Documentation"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.\" http://bugs.debian.org/507673
.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
.nh
.\" disable justification (adjust text to left margin only)
.ad l
.\" -----------------------------------------------------------------
.\" * MAIN CONTENT STARTS HERE *
.\" -----------------------------------------------------------------
.SH "NAME"
cgps, gegps, gps, lcdgps, xgps, xgpsspeed \- test clients for gpsd
.SH "SYNOPSIS"
.HP \w'\fBcgps\fR\ 'u
\fBcgps\fR [\-D\ \fIdebug\-level\fR] [\-h] [\-l\ [[d]\ |\ [m]\ |\ [s]]] [\-m] [\-s] [\-u\ [[i]\ |\ [n]\ |\ [m]]] [\-V] [\fIserver\fR [\fI:port\fR [\fI:device\fR]]]
.HP \w'\fBgegps\fR\ 'u
\fBgegps\fR [\-d\ \fIdirectory\fR] [\-h] [\-i] [\-V]
.HP \w'\fBlcdgps\fR\ 'u
\fBlcdgps\fR [\-h] [\-j] [\-l\ [[d]\ |\ [m]\ |\ [s]]] [\-s] [\-u\ [[i]\ |\ [n]\ |\ [m]]] [\-V] [\fIserver\fR [\fI:port\fR [\fI:device\fR]]]
.HP \w'\fBxgps\fR\ 'u
\fBxgps\fR [\-?] [\-D\ \fIdebug\-level\fR] [\-h] [\-l\ [[d]\ |\ [m]\ |\ [s]]] [\-u\ [[i]\ |\ [n]\ |\ [m]]] [\-V] [\fIserver\fR [\fI:port\fR [\fI:device\fR]]]
.HP \w'\fBxgpsspeed\fR\ 'u
\fBxgpsspeed\fR [\-\-debug\ \fIdebug\-level\fR] [\-\-device\ \fIdevice\fR] [\-h] [\-\-host\ \fIhost\fR] [\-\-landspeed] [\-\-maxspeed\ \fImaxspeed\fR] [\-\-nautical] [\-\-port\ \fIport\fR] [\-\-speedunits\ {[mph]\ |\ [kph]\ |\ [knots]}] [\-V] [\fIserver\fR [\fI:port\fR [\fI:device\fR]]]
.SH "DESCRIPTION"
.PP
These are the demonstration clients shipped with
gpsd\&. They have some common options:
.PP
The
\fB\-h\fR
option causes each client to emit a summary of its options and then exit\&.
.PP
The
\fB\-V\fR
option causes each client to dump the package version and exit\&.
.PP
The
\fB\-l\fR
option, when present, sets the format of latitude and longitude reports\&. The value \*(Aqd\*(Aq produces decimal degrees and is the default\&. The value \*(Aqm\*(Aq produces degrees and decimal minutes\&. The value \*(Aqs\*(Aq produces degrees, minutes, and decimal seconds\&.
.PP
xgps,
cgps, and
lcdgps
look at variables in the environment to figure out what units they should default to using for display \(em imperial, nautical, or metric\&. Here are the variables and values they check:
.sp
.if n \{\
.RS 4
.\}
.nf
GPSD_UNITS one of:
imperial = miles/feet
nautical = knots/feet
metric = km/meters
LC_MEASUREMENT
en_US = miles/feet
C = miles/feet
POSIX = miles/feet
[other] = km/meters
LANG
en_US = miles/feet
C = miles/feet
POSIX = miles/feet
[other] = km/meters
.fi
.if n \{\
.RE
.\}
.PP
These preferences may be overridden by the
\fB\-u\fR
option\&.
.PP
Where present, the
\fB\-u\fR
option can be used to set the system units for display; follow the keyword with \*(Aqi\*(Aq for \*(Aqimperial\*(Aq for American units (feet in altitude and error estimates, miles per hour in speeds), \*(Aqn\*(Aq for \*(Aqnautical\*(Aq (feet in altitude and error estimates, knots in speed) or \*(Aqm\*(Aq for \*(Aqmetric\*(Aq (meters in altitude and error estimates, kilometers per hour in speeds)\&.
.PP
The
\fB\-D\fR
option, when present, sets a debug level; it is primarily for use by GPSD developers\&. It enables various progress messages to standard error\&.
.PP
By default, clients collect data from all compatible devices on localhost, using the default GPSD port 2947\&. An optional argument to any client may specify a server to get data from\&. A colon\-separated suffix is taken as a port number\&. If there is a second colon\-separated suffix, that is taken as a specific device name to be watched\&. However, if the server specification contains square brackets, the part inside them is taken as an IPv6 address and port/device suffixes are only parsed after the trailing bracket\&. Possible cases look like this:
.PP
localhost:/dev/ttyS1
.RS 4
Look at the default port of localhost, trying both IPv4 and IPv6 and watching output from serial device 1\&.
.RE
.PP
example\&.com:2317
.RS 4
Look at port 2317 on example\&.com, trying both IPv4 and IPv6\&.
.RE
.PP
71\&.162\&.241\&.5:2317:/dev/ttyS3
.RS 4
Look at port 2317 at the specified IPv4 address, collecting data from attached serial device 3\&.
.RE
.PP
[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:2317:/dev/ttyS5
.RS 4
Look at port 2317 at the specified IPv6 address, collecting data from attached serial device 5\&.
.RE
.PP
Not all clients shipped with GPSD are documented here\&. See also the separate manual pages for
\fBgpspipe\fR(1)
and
\fBgpsmon\fR(1)
and
\fBgpxlogger\fR(1)
\&.
.SS "xgps"
.PP
xgps
is a simple test client for
gpsd
with an X interface\&. It displays current GPS position/time/velocity information and (for GPSes that support the feature) the locations of accessible satellites\&.
.PP
In the sky view, satellites are color\-coded to indicate quality of signal; consult the data display to the left for exact figures in dB\&. Square icons indicate WAAS/EGNOS satellites, circles indicate ordinary GPS satellites\&. Filled icons were used in the last fix, outline icons were not\&.
.SS "xgpsspeed"
.PP
xgpsspeed
is a speedometer that uses position information from the GPS\&. It accepts an \-h option and optional argument as for
gps, or a \-V option to dump the package version and exit\&.
.PP
The default display mode is a speed and track presentation modeled after a marine navigation display; for backward compatibility the \-\-nautical option forces this mode\&. The \-\-landspeed option produces a simple speedometer\&.
.PP
The \-speedunits option can be used to set the speed units for display; follow the keyword with knots for nautical miles per hour, kph for kilometres per hour, or mph for miles per hour\&. The default is miles per hour\&.
.PP
In the nautical mode only, \-\-maxspeed sets the maximum on the speedometer\&.
.SS "cgps"
.PP
cgps
is a client resembling
xgps, but without the pictorial satellite display and able to run on a serial terminal or terminal emulator\&.
.PP
The
\fB\-s\fR
option prevents
cgps
from displaying the data coming from the daemon\&. This display can also be toggled with the s command\&.
.PP
The
\fB\-m\fR
option will display your magnetic heading (as opposed to your true heading)\&. This is a calculated value, not a measured value, and is subject to a potential error of up to two degrees in the areas for which the calculation is valid (currently Western Europe, Alaska, and Lower 48 in the USA)\&. The formulas used are those found in the Aviation Formulary v1\&.43\&.
.PP
cgps
terminates when you send it a SIGHUP or SIGINT; given default terminal settings this will happen when you type Ctrl\-C at it\&. It will also terminate on \*(Aqq\*(Aq
.SS "lcdgps"
.PP
A client that passes
gpsd
data to
lcdproc, turning your car computer into a very expensive and nearly feature\-free GPS receiver\&. Currently assumes a 4x40 LCD and writes data formatted to fit that size screen\&. Also displays 4\- or 6\-character Maidenhead grid square output\&.
.SS "gegps"
.PP
This program collects fixes from
gpsd
and feeds them to a running instance of Google Earth for live location tracking\&.
.PP
The
\fB\-d\fR
argument is the location of the Google Earth installation directory\&. If not specified, it defaults to the current directory\&.
.PP
If you have the free (non\-subscription) version, start by running with the
\fB\-i\fR
option to drop a clue in the Google Earth installation directory, as \*(AqOpen_in_Google_Earth_RT_GPS\&.kml\*(Aq, then open that file in Places (File > Open\&.\&.\&.)\&. Run
gpsd
in the normal way after that\&.
.SH "SEE ALSO"
.PP
\fBgpsd\fR(8),
\fBlibgps\fR(3),
\fBlibgpsmm\fR(3),
\fBgpsfake\fR(1),
\fBgpsctl\fR(1),
\fBgpscat\fR(1),
\fBgpsprof\fR(1)\&.
\fBgpspipe\fR(1)\&.
\fBgpsmon\fR(1)\&.
\fBgpxlogger\fR(1)\&.
.SH "AUTHORS"
.PP
Remco Treffcorn, Derrick Brashear, Russ Nelson & Eric S\&. Raymond, Jeff Francis (cgps), Chen Wei
<weichen302@aol\&.com>
(gegps & xgpsspeed), Robin Wittler
<real@the\-real\&.org>
(xgpsspeed)\&.
.PP
This manual page by Eric S\&. Raymond
<esr@thyrsus\&.com>

1226
cgps.c

File diff suppressed because it is too large

7
contrib/README

@ -2,6 +2,13 @@ The following tools are not production-ready. They are included only as
conveniences, examples or rudimetary starting points for other development
efforts.
skyview2svg reads the skyview from gpspipe, and creates an svg image
of the skyview.
gpssnmp a tool to return some SNMP values from the running local gpsd.
clock_test is used to test the latency of the system call clock_getttime().
binlog and binreplay are probably only useful for people developing
drivers for new protocols, when gpsfake does not yet know what to do
with a log file. These utilities are not particularly clever - they

9
contrib/SConstruct

@ -6,12 +6,11 @@
# Note that ../gpsd_config.h is required and is built separately
strl = StaticObject("strl", "../strl.c")
ashctl = Program("ashctl", ["ashctl.c", strl])
ashctl = Program("ashctl", "ashctl.c")
binlog = Program("binlog", "binlog.c")
binreplay = Program("binreplay", "binreplay.c", parse_flags=['-lutil'])
clock_test = Program("clock_test", "clock_test.c", parse_flags=['-lm'])
lla2ecef = Program("lla2ecef", "lla2ecef.c", parse_flags=['-lm'])
motosend = Program("motosend", ["motosend.c", strl])
motosend = Program("motosend", "motosend.c")
Default(ashctl, binlog, binreplay, lla2ecef, motosend)
Default(ashctl, binlog, binreplay, clock_test, lla2ecef, motosend)

110
contrib/clock_test.c

@ -0,0 +1,110 @@
/*
* clock_test. A simple program to test the latency of the clock_gettime() call
*
* Compile: gcc clock_test.c -lm -o clock_test
*
*/
#include <getopt.h> /* for getopt() */
#include <limits.h> /* for LONG_MAX */
#include <math.h> /* for pow(), sqrt() */
#include <stdio.h> /* for printf() */
#include <stdlib.h> /* for qsort() */
#include <time.h> /* for time_t */
#define NUM_TESTS 101 /* default samples, make it odd for a clean median */
#define DELAY 10000000 /* default delay between samples in ns, 10 ms is good */
int compare_long( const void *ap, const void *bp)
{
long a = *((long *)ap);
long b = *((long *)bp);
if ( a < b ) return -1;
if ( a > b ) return 1;
return 0;
}
int main(int argc, char **argv)
{
int i;
int opt; /* for getopts() */
int verbose = 0;
int samples = NUM_TESTS;
long delay = DELAY;
long *diffs = NULL;
long min = LONG_MAX, max = 0, sum = 0, mean = 0, median = 0;
double stddev = 0.0;
while ((opt = getopt(argc, argv, "d:hvn:")) != -1) {
switch (opt) {
case 'd':
delay = atol(optarg);
break;
case 'n':
samples = atoi(optarg);
/* make odd, for a good median */
if ( (samples & 1) == 0) {
samples += 1;
}
break;
case 'v':
verbose = 1;
break;
case 'h':
/* fall through */
default: /* '?' */
fprintf(stderr, "Usage: %s [-h] [-d nsec] [-n samples] [-v]\n\n", argv[0]);
fprintf(stderr, "-d nsec : nano seconde paus between samples\n");
fprintf(stderr, "-h : help\n");
fprintf(stderr, "-n samples : Number of samples, default %d\n", NUM_TESTS);
fprintf(stderr, "-v : verbose\n");
exit(EXIT_FAILURE);
}
}
diffs = alloca( sizeof(long) * (samples + 2)); /* add 2 for off by one errors */
/* collect test data */
for ( i = 0 ; i < samples; i++ ) {
struct timespec now, now1, sleep, sleep1;
(void)clock_gettime(CLOCK_REALTIME, &now);
(void)clock_gettime(CLOCK_REALTIME, &now1);
diffs[i] = now1.tv_nsec - now.tv_nsec;
if ( now1.tv_sec != now.tv_sec ) {
/* clock roll over, fix it */
diffs[i] += 1000000000; /* add one second */
}
/* instead of hammering, sleep between tests, let the cache get cold */
sleep.tv_sec = 0;
sleep.tv_nsec = delay; /* sleep delay */
/* sleep1 unused, should not be returning early */
nanosleep(&sleep, &sleep1);
}
/* analyze test data */
/* print diffs, calculate min and max */
for ( i = 0 ; i < samples; i++ ) {
if ( verbose > 0 ) {
printf("diff %ld\n", diffs[i]);
}
sum += diffs[i];
if ( diffs[i] < min ) min = diffs[i];
if ( diffs[i] > max ) max = diffs[i];
}
mean = sum / (samples - 1);
qsort( diffs, samples, sizeof(long), compare_long);
median = diffs[(samples / 2) + 1];
for ( i = 0 ; i < samples; i++ ) {
stddev += pow(diffs[i] - mean, 2);
}
stddev = sqrt(stddev/samples);
printf("samples %d, delay %ld ns\n", samples, delay);
printf("min %ld ns, max %ld ns, mean %ld ns, median %ld ns, StdDev %ld ns\n",
min, max, mean, median, (long)stddev);
}

2
contrib/gps

@ -1 +1 @@
gpsd-3.17/../gps
gpsd-3.18.1/../gps

97
contrib/gpsData.py

@ -1,7 +1,7 @@
#! /usr/bin/python
# Written by Dan Mandle http://dan.mandle.me September 2012
# http://www.danmandle.com/blog/getting-gpsd-to-work-with-python/
# License: GPL 2.0
# License: GPL 2.0
# This code runs compatibly under Python 2 and 3.x for x >= 2.
# Preserve this property!
@ -13,57 +13,64 @@ from time import *
import time
import threading
gpsd = None #seting the global variable
gpsd = None # setting the global variable
os.system('clear') # clear the terminal (optional)
os.system('clear') #clear the terminal (optional)
class GpsPoller(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
global gpsd #bring it in scope
gpsd = gps(mode=WATCH_ENABLE) #starting the stream of info
self.current_value = None
self.running = True #setting the thread running to true
def __init__(self):
threading.Thread.__init__(self)
global gpsd # bring it in scope
gpsd = gps(mode=WATCH_ENABLE) # starting the stream of info
self.current_value = None
self.running = True # setting the thread running to true
def run(self):
global gpsd
while gpsp.running:
# this will continue to loop and grab EACH set of
# gpsd info to clear the buffer
next(gpsd)
def run(self):
global gpsd
while gpsp.running:
next(gpsd) #this will continue to loop and grab EACH set of gpsd info to clear the buffer
if __name__ == '__main__':
gpsp = GpsPoller() # create the thread
try:
gpsp.start() # start it up
while True:
#It may take a second or two to get good data
#print gpsd.fix.latitude,', ',gpsd.fix.longitude,' Time: ',gpsd.utc
gpsp = GpsPoller() # create the thread
try:
gpsp.start() # start it up
while True:
# It may take a second or two to get good data
# print(gpsd.fix.latitude,', ',gpsd.fix.longitude,'
# Time: ',gpsd.utc
os.system('clear')
os.system('clear')
print()
print(' GPS reading')
print('----------------------------------------')
print('latitude ', gpsd.fix.latitude)
print('longitude ', gpsd.fix.longitude)
print('time utc ', gpsd.utc, ' + ', gpsd.fix.time)
print('altitude (m)', gpsd.fix.altitude)
print('eps ', gpsd.fix.eps)
print('epx ', gpsd.fix.epx)
print('epv ', gpsd.fix.epv)
print('ept ', gpsd.fix.ept)
print('speed (m/s) ', gpsd.fix.speed)
print('climb ', gpsd.fix.climb)
print('track ', gpsd.fix.track)
print('mode ', gpsd.fix.mode)
print()
print("%s satellites in view:" % len(gpsd.satellites))
for sat in gpsd.satellites:
print(" %r" % sat)
print()
print(' GPS reading')
print('----------------------------------------')
print('latitude ' , gpsd.fix.latitude)
print('longitude ' , gpsd.fix.longitude)
print('time utc ' , gpsd.utc,' + ', gpsd.fix.time)
print('altitude (m)' , gpsd.fix.altitude)
print('eps ' , gpsd.fix.eps)
print('epx ' , gpsd.fix.epx)
print('epv ' , gpsd.fix.epv)
print('ept ' , gpsd.fix.ept)
print('speed (m/s) ' , gpsd.fix.speed)
print('climb ' , gpsd.fix.climb)
print('track ' , gpsd.fix.track)
print('mode ' , gpsd.fix.mode)
print()
print("%s satellites in view:" % len(gpsd.satellites))
for sat in gpsd.satellites:
print(" %r" % sat)
time.sleep(5) # set to whatever
time.sleep(5) #set to whatever
except (KeyboardInterrupt, SystemExit):
# when you press ctrl+c
print("\nKilling Thread...")
gpsp.running = False
gpsp.join() # wait for the thread to finish what it's doing
except (KeyboardInterrupt, SystemExit): #when you press ctrl+c
print("\nKilling Thread...")
gpsp.running = False
gpsp.join() # wait for the thread to finish what it's doing
print("Done.\nExiting.")
print("Done.\nExiting.")

91
contrib/gpssnmp.c

@ -0,0 +1,91 @@
/* gpssnmp - poll local gpsd for SNMP variables
*
* Copyright (c) 2016 David Taylor <gpsd@david.taylor.name>
*
* Copyright (c)2018 by the GPSD project
* SPDX-License-Identifier: BSD-2-clause
*
* To build this:
* gcc -o gpssnmp gpssnmp.c -lgps
*
*/
#include <gps.h>
#include <stdio.h>
#include <string.h>
static void usage() {
printf("\n"
"Usage:\n"
"\n"
"to get OID_VISIBLE\n"
" $ gpssnmp -g .1.3.6.1.2.1.25.1.31\n"
" .1.3.6.1.2.1.25.1.31\n"
" gauge\n"
" 13\n"
"\n"
"to get OID_USED\n"
" $ gpssnmp -g .1.3.6.1.2.1.25.1.32\n"
" .1.3.6.1.2.1.25.1.32\n"
" gauge\n"
" 4\n"
"\n"
"to get OID_SNR_AVG\n"
" $ gpssnmp -g .1.3.6.1.2.1.25.1.33\n"
" .1.3.6.1.2.1.25.1.33\n"
" gauge\n"
" 22.250000\n"
"\n");
}
int main (int argc, char **argv) {
struct gps_data_t gpsdata;
#define OID_VISIBLE ".1.3.6.1.2.1.25.1.31"
#define OID_USED ".1.3.6.1.2.1.25.1.32"
#define OID_SNR_AVG ".1.3.6.1.2.1.25.1.33"
if ((argc > 2) && (strcmp ("-g", argv[1]) == 0)) {
int i;
double snr_total=0;
double snr_avg = 0.0;
int status, used, visible;
status = gps_open (GPSD_SHARED_MEMORY, DEFAULT_GPSD_PORT, &gpsdata);
status = gps_read (&gpsdata);
used = gpsdata.satellites_used;
visible = gpsdata.satellites_visible;
for(i=0; i<=used; i++) {
if (gpsdata.skyview[i].used > 0 && gpsdata.skyview[i].ss > 1) {
// printf ("i: %d, P:%d, ss: %f\n", i, gpsdata.skyview[i].PRN,
// gpsdata.skyview[i].ss);
snr_total+=gpsdata.skyview[i].ss;
}
}
gps_close (&gpsdata);
if (used > 0) {
snr_avg = snr_total / used;
}
if (strcmp (OID_VISIBLE, argv[2]) == 0) {
printf (OID_VISIBLE);
printf ("\n");
printf ("gauge\n");
printf ("%d\n", visible);
}
if (strcmp (OID_USED, argv[2]) == 0) {
printf (OID_USED);
printf ("\n");
printf ("gauge\n");
printf ("%d\n", used);
}
if (strcmp (OID_SNR_AVG, argv[2]) == 0) {
printf (OID_SNR_AVG);
printf ("\n");
printf ("gauge\n");
printf ("%lf\n", snr_avg);
}
} else {
usage();
}
return 0;
}

88
contrib/ntpshmviz

@ -1,25 +1,37 @@
#!/usr/bin/env python
#
# ntpshmviz - graph the drift of NTP servers
# Written by Keane Wolter <daemoneye2@gmail.com>
'''
ntpshmviz - graph the drift of NTP servers
Written by Keane Wolter <daemoneye2@gmail.com>
'''
#
# To do:
#
# 1. Add exit button so the user does not need to do <Ctrl>-w
# 2. Allow for a continuous stream of data to be graphed
#
from __future__ import absolute_import, print_function, division
import sys
# need numpy for float128, normal python floats are too small to hold a timespec
# need numpy for float128, normal python floats are too small to
# hold a timespec
import numpy
try:
import matplotlib.pyplot as PLT
from matplotlib.figure import Figure
except:
print("Please make sure matplotlib is installed properly:", sys.exc_info()[0])
except ImportError:
print("Please make sure matplotlib is installed properly:",
sys.exc_info()[0])
sys.exit(1)
class ntpOffset:
gps_version = '3.18.1'
class ntpOffset(object):
"The master Class"
def __init__(self, stream):
"Initialize class ntpOffset"
# get the data
self.read_data(stream)
@ -27,10 +39,11 @@ class ntpOffset:
self.display()
def display(self):
# display the graphs
"display the graphs"
# Alert the user that closing the graphs can be done with "Ctrl-w"
print ("Please note that the graph can be closed with the key combination of <Ctrl-w>")
print ("Please note that the graph can be closed with the "
"key combination of <Ctrl-w>")
PLT.figure()
subplot_value = 211
@ -47,12 +60,16 @@ class ntpOffset:
# increment the subplot by 1.
# this allows for each data group to have it's own graph
subplot_value += 1
# make sure there is no graph or data overlapping each other and display the graph
# make sure there is no graph or data overlapping each other and
# display the graph
PLT.tight_layout()
PLT.show()
def read_data(self, stream):
# Reads data from a ntp log file. Layout is:
"Read data from a ntp log file."
# Layout is:
#
# - The keyword "sample"
# - The NTP unit from which it was collected.
@ -62,11 +79,11 @@ class ntpOffset:
# - Leep-second notification status
# - Source precision (log(2) of source jitter)
self.ntp_data = {} # data sets for each ntp unit
self.line_counts = {} # Count of total lines for each ntp unit
record = [] # A single record in the file or data stream
offset = 0 # offset value to add to the array
self.lines = 0 # width of graph
self.ntp_data = {} # data sets for each ntp unit
self.line_counts = {} # Count of total lines for each ntp unit
record = [] # A single record in the file or data stream
offset = 0 # offset value to add to the array
self.lines = 0 # width of graph
for line in stream:
if len(line.split(' ')) > 6:
@ -74,9 +91,11 @@ class ntpOffset:
line = line.lstrip()
record = line.split(' ')
try:
offset = numpy.float128(record[3]) - numpy.float128(record[4])
offset = (numpy.float128(record[3]) -
numpy.float128(record[4]))
except:
print ("Invalid data: ", sys.exc_info()[0], ". Data was: ", line)
print ("Invalid data: ", sys.exc_info()[0],
". Data was: ", line)
continue
# If the NTP unit is in the dictionary
@ -84,29 +103,34 @@ class ntpOffset:
# Otherwise, create a new list in the dictionary
# and add the offset.
if record[1] not in self.ntp_data:
self.ntp_data[record[1]] = []
self.ntp_data[record[1]] = []
self.line_counts[record[1]] = 0
self.ntp_data[record[1]].append(offset)
self.line_counts[record[1]] += 1
stream.close()
if __name__ == "__main__":
if (len(sys.argv) == 2):
if len(sys.argv) >= 2:
if (sys.argv[1] == "-V" or sys.argv[1] == "--version"):
print ("Version 2.0")
sys.exit()
sys.stderr.write("ntpshmviz: Version %s\n" % gps_version)
sys.exit(0)
if (sys.argv[1] == "-h" or sys.argv[1] == "--help"):
print ("Usage: <input stream> | ntpshmviz")
print ("Example: cat SAMPLES | ntpshmviz")
print ("")
print ("Options:")
print ("\t-h: help message")
print ("\t-V: version information")
print ("")
print ("Report ntpshmviz bugs to Keane Wolter, daemoneye2@gmail.com")
print ("gpsd homepage: www.catb.org/gpsd/")
print("""
Usage: <input stream> | ntpshmviz [-h|--help] [-V|--version]
Example: ntpshmmon -n 100 | ntpshmviz
Options:
\t-h: help message
\t-V: version information
Report ntpshmviz bugs to Keane Wolter, daemoneye2@gmail.com
or gpsd-users@nongnu.org
gpsd homepage: www.catb.org/gpsd/
""")
sys.exit()
ntpOffset(sys.stdin)

367
contrib/skyview2svg

@ -0,0 +1,367 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
skyview2svg -- Create an SVG image of GPS satellites sky view.
Read from file or stdin the JSON data produced by gpsd,
example usage:
gpspipe -w | skyview2svg > skyview.svg
For GPSD JSON format see: http://www.catb.org/gpsd/gpsd_json.html
"""
# SPDX-License-Identifier: BSD-2-clause
# This code runs compatibly under Python 2 and 3.x for x >= 2.
# Preserve this property!
from __future__ import absolute_import, print_function, division
import datetime
import json
import math
import sys
__author__ = "Niccolo Rigacci"
__copyright__ = "Copyright 2018 Niccolo Rigacci <niccolo@rigacci.org>"
__license__ = "BSD-2-clause"
__email__ = "niccolo@rigacci.org"
__version__ = "3.18.1"
# ------------------------------------------------------------------------
# ------------------------------------------------------------------------
def polar2cart(azimuth, elevation, r_max):
"""Convert polar coordinates in cartesian ones."""
radius = r_max * (1 - elevation / 90.0)
theta = math.radians(float(azimuth - 90))
return (
int(radius * math.cos(theta) + 0.5),
int(radius * math.sin(theta) + 0.5)
)
# ------------------------------------------------------------------------
# ------------------------------------------------------------------------
def cutoff_err(err, err_min, err_max):
"""Cut-off Estimated Error between min and max."""
if err is None or err >= err_max:
return err_max, '&gt;'
if err <= err_min:
return err_min, '&lt;'
else:
return err, ''
# ------------------------------------------------------------------------
# Read JSON data from file or stdin, search a {'class': 'SKY'} line.
# ------------------------------------------------------------------------
EXIT_CODE = 0
SKY = None
TPV = None
try:
if len(sys.argv) > 1:
with open(sys.argv[1]) as f:
while True:
SENTENCE = json.loads(f.readline())
if 'class' in SENTENCE and SENTENCE['class'] == 'SKY':
SKY = SENTENCE
if 'class' in SENTENCE and SENTENCE['class'] == 'TPV':
TPV = SENTENCE
if SKY is not None and TPV is not None:
break
else:
while True:
SENTENCE = json.loads(sys.stdin.readline())
if 'class' in SENTENCE and SENTENCE['class'] == 'SKY':
SKY = SENTENCE
if 'class' in SENTENCE and SENTENCE['class'] == 'TPV':
TPV = SENTENCE
if SKY is not None and TPV is not None:
sys.stdin.close()
break
except (IOError, ValueError):
# Assume empty data and write msg to stderr.
EXIT_CODE = 100
sys.stderr.write("Error reading JSON data from file or stdin."
" Creating an empty or partial skyview image.\n")
if SKY is None:
SKY = {}
if TPV is None:
TPV = {}
# ------------------------------------------------------------------------
# Colors for the SVG styles.
# ------------------------------------------------------------------------
# Background and label colors.
BACKGROUND_COLOR = '#323232'
LBL_FONT_COLOR = 'white'
FONT_FAMILY = 'Verdana,Arial,Helvetica,sans-serif'
# Compass dial.
COMPASS_STROKE_COLOR = '#9d9d9d'
DIAL_POINT_COLOR = COMPASS_STROKE_COLOR
# Satellites constellation.
SAT_USED_FILL_COLOR = '#00ff00'
SAT_UNUSED_FILL_COLOR = '#d0d0d0'
SAT_USED_STROKE_COLOR = '#0b400b'
SAT_UNUSED_STROKE_COLOR = '#101010'
SAT_USED_TEXT_COLOR = '#000000'
SAT_UNUSED_TEXT_COLOR = '#000000'
# Sat signal/noise ratio box and bars.
BARS_AREA_FILL_COLOR = '#646464'
BARS_AREA_STROKE_COLOR = COMPASS_STROKE_COLOR
BAR_USED_FILL_COLOR = '#00ff00'
BAR_UNUSED_FILL_COLOR = '#ffffff'
BAR_USED_STROKE_COLOR = '#324832'
BAR_UNUSED_STROKE_COLOR = BACKGROUND_COLOR
# ------------------------------------------------------------------------
# Size and position of elements.
# ------------------------------------------------------------------------
IMG_WIDTH = 528
IMG_HEIGHT = 800
STROKE_WIDTH = int(IMG_WIDTH * 0.007)
# Scale graph bars to accomodate at least MIN_SAT values.
MIN_SAT = 12
NUM_SAT = MIN_SAT
# Auto-scale: reasonable values for Signal/Noise Ratio and Error.
SNR_MAX = 30.0 # Do not autoscale below this value.
# Auto-scale horizontal and vertical error, in meters.
ERR_MIN = 5.0
ERR_MAX = 75.0
# Create an empty list, if satellites list is missing.
if 'satellites' not in SKY.keys():
SKY['satellites'] = []
if len(SKY['satellites']) < MIN_SAT:
NUM_SAT = MIN_SAT
else:
NUM_SAT = len(SKY['satellites'])
# Make a sortable array and autoscale SNR.
SATELLITES = {}
for sat in SKY['satellites']:
SATELLITES[sat['PRN']] = sat
if float(sat['ss']) > SNR_MAX:
SNR_MAX = float(sat['ss'])
# Compass dial and satellites placeholders.
CIRCLE_X = int(IMG_WIDTH * 0.50)
CIRCLE_Y = int(IMG_WIDTH * 0.49)
CIRCLE_R = int(IMG_HEIGHT * 0.22)
SAT_WIDTH = int(CIRCLE_R * 0.24)
SAT_HEIGHT = int(CIRCLE_R * 0.14)
# GPS position.
POS_LBL_X = int(IMG_WIDTH * 0.50)
POS_LBL_Y = int(IMG_HEIGHT * 0.62)
# Sat signal/noise ratio box and bars.
BARS_BOX_WIDTH = int(IMG_WIDTH * 0.82)
BARS_BOX_HEIGHT = int(IMG_HEIGHT * 0.14)
BARS_BOX_X = int((IMG_WIDTH - BARS_BOX_WIDTH) * 0.5)
BARS_BOX_Y = int(IMG_HEIGHT * 0.78)
BAR_HEIGHT_MAX = int(BARS_BOX_HEIGHT * 0.72)
BAR_SPACE = int((BARS_BOX_WIDTH - STROKE_WIDTH) / NUM_SAT)
BAR_WIDTH = int(BAR_SPACE * 0.70)
BAR_RADIUS = int(BAR_WIDTH * 0.20)
# Error box and bars.
ERR_BOX_X = int(IMG_WIDTH * 0.65)
ERR_BOX_Y = int(IMG_HEIGHT * 0.94)
ERR_BOX_WIDTH = int((BARS_BOX_X + BARS_BOX_WIDTH) - ERR_BOX_X)
ERR_BOX_HEIGHT = BAR_SPACE * 2
ERR_BAR_HEIGHT_MAX = int(ERR_BOX_WIDTH - STROKE_WIDTH*2)
# Timestamp
TIMESTAMP_X = int(IMG_WIDTH * 0.50)
TIMESTAMP_Y = int(IMG_HEIGHT * 0.98)
# Text labels.
LBL_FONT_SIZE = int(IMG_WIDTH * 0.036)
LBL_COMPASS_POINTS_SIZE = int(CIRCLE_R * 0.12)
LBL_SAT_SIZE = int(SAT_HEIGHT * 0.75)
LBL_SAT_BAR_SIZE = int(BAR_WIDTH * 0.90)
# Get timestamp from GPS or system.
if 'time' in SKY:
UTC = datetime.datetime.strptime(SKY['time'], '%Y-%m-%dT%H:%M:%S.%fZ')
elif 'time' in TPV:
UTC = datetime.datetime.strptime(TPV['time'], '%Y-%m-%dT%H:%M:%S.%fZ')
else:
UTC = datetime.datetime.utcnow()
TIME_STR = UTC.strftime('%Y-%m-%d %H:%M:%S UTC')
# ------------------------------------------------------------------------
# Output the SGV image.
# ------------------------------------------------------------------------
print('''<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg
xmlns="http://www.w3.org/2000/svg"
width="%d"
height="%d">''' % (IMG_WIDTH, IMG_HEIGHT))
# NOTICE: librsvg v.2.40 has a bug with "chain" multiple class selectors:
# it does not handle a selector like text.label.title and a
# tag class="label title".
print('<style type="text/css">')
# Labels.
print(' text '
'{ font-family: Verdana,Arial,Helvetica,sans-serif; font-weight: bold;}')
print(' text.label { fill: %s; font-size: %dpx; }' %
(LBL_FONT_COLOR, LBL_FONT_SIZE))
print(' text.label-title { font-size: %dpx; text-anchor: middle; }' %
(int(LBL_FONT_SIZE * 1.4),))
print(' text.label-prn { font-size: %dpx; text-anchor: end; }' %
(LBL_SAT_BAR_SIZE,))
print(' text.label-center { text-anchor: middle; }')
print(' text.label-snr { text-anchor: start; }')
print(' text.label-err { text-anchor: end; }')
# Compass dial.
print(' circle.compass '
'{ stroke: %s; stroke-width: %d; fill-opacity: 0; }' %
(COMPASS_STROKE_COLOR, STROKE_WIDTH,))
print(' line.compass { stroke: %s; stroke-width: %d; }' %
(COMPASS_STROKE_COLOR, STROKE_WIDTH))
print(' text.compass '
'{ fill: %s; font-size: %dpx; text-anchor: middle; }' %
(DIAL_POINT_COLOR, LBL_COMPASS_POINTS_SIZE))
# Satellites constellation.
print(' rect.sats { stroke-width: %d; fill-opacity: 1.0; }' %
(STROKE_WIDTH,))
print(' rect.sats-used { stroke: %s; fill: %s; }' %
(SAT_USED_STROKE_COLOR, SAT_USED_FILL_COLOR))
print(' rect.sats-unused { stroke: %s; fill: %s; }' %
(SAT_UNUSED_STROKE_COLOR, SAT_UNUSED_FILL_COLOR))
print(' text.sats { font-size: %dpx; text-anchor: middle; }' %
(LBL_SAT_SIZE,))
print(' text.sats-used { fill: %s; }' % (SAT_USED_TEXT_COLOR,))
print(' text.sats-unused { fill: %s; }' % (SAT_UNUSED_TEXT_COLOR,))
# Box containing bars graph.
print(' rect.box { fill: %s; stroke: %s; stroke-width: %d; }' %
(BARS_AREA_FILL_COLOR, BARS_AREA_STROKE_COLOR, STROKE_WIDTH))
# Graph bars.
print(' rect.bars { stroke-width: %d; opacity: 1.0; }' %
(STROKE_WIDTH,))
print(' rect.bars-used { stroke: %s; fill: %s; }' %
(BAR_USED_STROKE_COLOR, BAR_USED_FILL_COLOR))
print(' rect.bars-unused { stroke: %s; fill: %s; }' %
(BAR_UNUSED_STROKE_COLOR, BAR_UNUSED_FILL_COLOR))
print('</style>')
# Background and title.
print('<rect width="100%%" height="100%%" fill="%s" />' %
(BACKGROUND_COLOR,))
print('<text class="label label-title" x="%d" y="%d">'
'Sky View of GPS Satellites</text>' %
(int(IMG_WIDTH * 0.5), int(LBL_FONT_SIZE * 1.5)))
# Sky circle with cardinal points.
print('<circle class="compass" cx="%d" cy="%d" r="%d" />' %
(CIRCLE_X, CIRCLE_Y, CIRCLE_R))
print('<circle class="compass" cx="%d" cy="%d" r="%d" />' %
(CIRCLE_X, CIRCLE_Y, int(CIRCLE_R / 2)))
print('<line class="compass" x1="%d" y1="%d" x2="%d" y2="%d" />' %
(CIRCLE_X, CIRCLE_Y - CIRCLE_R, CIRCLE_X, CIRCLE_Y + CIRCLE_R))
print('<line class="compass" x1="%d" y1="%d" x2="%d" y2="%d" />' %
(CIRCLE_X - CIRCLE_R, CIRCLE_Y, CIRCLE_X + CIRCLE_R, CIRCLE_Y))
print('<text x="%d" y="%d" class="compass">%s</text>' %
(CIRCLE_X, CIRCLE_Y - CIRCLE_R - LBL_COMPASS_POINTS_SIZE, 'N'))
print('<text x="%d" y="%d" class="compass">%s</text>' %
(CIRCLE_X, CIRCLE_Y + CIRCLE_R + LBL_COMPASS_POINTS_SIZE, 'S'))
print('<text x="%d" y="%d" class="compass">%s</text>' %
(CIRCLE_X - CIRCLE_R - LBL_COMPASS_POINTS_SIZE,
CIRCLE_Y + int(LBL_COMPASS_POINTS_SIZE*0.4), 'W'))
print('<text x="%d" y="%d" class="compass">%s</text>' %
(CIRCLE_X + CIRCLE_R + LBL_COMPASS_POINTS_SIZE,
CIRCLE_Y + int(LBL_COMPASS_POINTS_SIZE*0.4), 'E'))
# Lat/lon.
POS_LAT = "%.5f" % (float(TPV['lat']),) if 'lat' in TPV else 'Unknown'
POS_LON = "%.5f" % (float(TPV['lon']),) if 'lon' in TPV else 'Unknown'
print('<text class="label label-center" x="%d" y="%d">Lat/Lon: %s %s</text>' %
(POS_LBL_X, POS_LBL_Y, POS_LAT, POS_LON))
# Satellites signal/noise ratio box.
print('<rect class="box" x="%d" y="%d" rx="%d" ry="%d" '
'width="%d" height="%d" />' %
(BARS_BOX_X, BARS_BOX_Y - BARS_BOX_HEIGHT, BAR_RADIUS,
BAR_RADIUS, BARS_BOX_WIDTH, BARS_BOX_HEIGHT))
SS_LBL_X = int(BARS_BOX_X + STROKE_WIDTH * 1.5)
SS_LBL_Y = int(BARS_BOX_Y - BARS_BOX_HEIGHT + LBL_FONT_SIZE +
STROKE_WIDTH * 1.5)
print('<text class="label label-snr" x="%d" y="%d">'
'Satellites Signal/Noise Ratio</text>' % (SS_LBL_X, SS_LBL_Y))
# Box for horizontal and vertical estimated error.
if 'epx' in TPV and 'epy' in TPV:
EPX = float(TPV['epx'])
EPY = float(TPV['epy'])
EPH = math.sqrt(EPX**2 + EPY**2)
elif 'eph' in TPV:
EPH = float(TPV['eph'])
else:
EPH = ERR_MAX
EPV = float(TPV['epv']) if 'epv' in TPV else ERR_MAX
ERR_H, SIGN_H = cutoff_err(EPH, ERR_MIN, ERR_MAX)
ERR_V, SIGN_V = cutoff_err(EPV, ERR_MIN, ERR_MAX)
ERR_LBL_X = int(ERR_BOX_X - STROKE_WIDTH * 2.0)
ERR_LBL_Y_OFFSET = STROKE_WIDTH + BAR_WIDTH * 0.6
print('<rect class="box" x="%d" y="%d" rx="%d" ry="%d" '
'width="%d" height="%d" />' %
(ERR_BOX_X, ERR_BOX_Y - ERR_BOX_HEIGHT, BAR_RADIUS,
BAR_RADIUS, ERR_BOX_WIDTH, ERR_BOX_HEIGHT))
# Horizontal error.
POS_X = ERR_BOX_X + STROKE_WIDTH
POS_Y = ERR_BOX_Y - ERR_BOX_HEIGHT + int((BAR_SPACE - BAR_WIDTH) * 0.5)
ERR_H_BAR_HEIGHT = int(ERR_H / ERR_MAX * ERR_BAR_HEIGHT_MAX)
print('<text class="label label-err" x="%d" y="%d">'
'Horizontal error %s%.1f m</text>' %
(ERR_LBL_X, ERR_LBL_Y_OFFSET + POS_Y, SIGN_H, ERR_H))
print('<rect class="bars bars-used" x="%d" y="%d" rx="%d" '
' ry="%d" width="%d" height="%d" />' %
(POS_X, POS_Y, BAR_RADIUS, BAR_RADIUS, ERR_H_BAR_HEIGHT, BAR_WIDTH))
# Vertical error.
POS_Y = POS_Y + BAR_SPACE
ERR_V_BAR_HEIGHT = int(ERR_V / ERR_MAX * ERR_BAR_HEIGHT_MAX)
print('<text class="label label-err" x="%d" y="%d">'
'Vertical error %s%.1f m</text>' %
(ERR_LBL_X, ERR_LBL_Y_OFFSET + POS_Y, SIGN_V, ERR_V))
print('<rect class="bars bars-used" x="%d" y="%d" rx="%d" '
' ry="%d" width="%d" height="%d" />' %
(POS_X, POS_Y, BAR_RADIUS, BAR_RADIUS, ERR_V_BAR_HEIGHT, BAR_WIDTH))
# Satellites and Signal/Noise bars.
i = 0
for prn in sorted(SATELLITES):
sat = SATELLITES[prn]
BAR_HEIGHT = int(BAR_HEIGHT_MAX * (float(sat['ss']) / SNR_MAX))
(sat_x, sat_y) = polar2cart(float(sat['az']), float(sat['el']), CIRCLE_R)
sat_x = int(CIRCLE_X + sat_x)
sat_y = int(CIRCLE_Y + sat_y)
rect_radius = int(SAT_HEIGHT * 0.25)
sat_rect_x = int(sat_x - (SAT_WIDTH) / 2)
sat_rect_y = int(sat_y - (SAT_HEIGHT) / 2)
sat_class = 'used' if sat['used'] else 'unused'
print('<rect class="sats sats-%s" x="%d" y="%d" width="%d" '
' height="%d" rx="%d" ry="%d" />' %
(sat_class, sat_rect_x, sat_rect_y, SAT_WIDTH, SAT_HEIGHT,
rect_radius, rect_radius))
print('<text class="sats %s" x="%d" y="%d">%s</text>' %
(sat_class, sat_x, sat_y + int(LBL_SAT_SIZE*0.4), sat['PRN']))
pos_x = (int(BARS_BOX_X + (STROKE_WIDTH * 0.5) +
(BAR_SPACE - BAR_WIDTH) * 0.5 + BAR_SPACE * i))
pos_y = int(BARS_BOX_Y - BAR_HEIGHT - (STROKE_WIDTH * 1.5))
print('<rect class="bars bars-%s" x="%d" y="%d" rx="%d" ry="%d" '
'width="%d" height="%d" />' %
(sat_class, pos_x, pos_y, BAR_RADIUS, BAR_RADIUS,
BAR_WIDTH, BAR_HEIGHT))
x = int(pos_x + BAR_WIDTH * 0.5)
y = int(BARS_BOX_Y + (STROKE_WIDTH * 1.5))
print('<text class="label label-prn" x="%d" y="%d" '
'transform="rotate(270, %d, %d)">%s</text>' %
(x, y, x, y, sat['PRN']))
i = i + 1
print('<text class="label label-center" x="%d" y="%d">%s</text>' %
(TIMESTAMP_X, TIMESTAMP_Y, TIME_STR))
print('</svg>')
sys.exit(EXIT_CODE)

77
contrib/webgps.py

@ -3,7 +3,8 @@
"""webgps.py
This is a Python port of webgps.c from http://www.wireless.org.au/~jhecker/gpsd/
This is a Python port of webgps.c
from http://www.wireless.org.au/~jhecker/gpsd/
by Beat Bolli <me+gps@drbeat.li>
It creates a skyview of the currently visible GPS satellites and their tracks
@ -38,17 +39,29 @@ restart webgps.py without losing accumulated satellite tracks.
from __future__ import absolute_import, print_function, division
import time, math, sys, os, pickle
import math
import os
import pickle
import sys
import time
from gps import *
gps_version = '3.18.1'
if gps.__version__ != gps_version:
sys.stderr.write("webgps.py: ERROR: need gps module version %s, got %s\n" %
(gps_version, gps.__version__))
sys.exit(1)
TRACKMAX = 1024
STALECOUNT = 10
DIAMETER = 200
def polartocart(el, az):
radius = DIAMETER * (1 - el / 90.0) # * math.cos(Deg2Rad(float(el)))
radius = DIAMETER * (1 - el / 90.0) # * math.cos(Deg2Rad(float(el)))
theta = Deg2Rad(float(az - 90))
return (
# Changed this back to normal orientation - fw
@ -77,7 +90,9 @@ class Track:
def track(self):
'''Return the track as canvas drawing operations.'''
return 'M(%d,%d); ' % self.posn[0] + ''.join(['L(%d,%d); ' % p for p in self.posn[1:]])
return('M(%d,%d); ' % self.posn[0] + ''.join(['L(%d,%d); ' %
p for p in self.posn[1:]]))
class SatTracks(gps):
'''gpsd client writing HTML5 and <canvas> output.'''
@ -108,15 +123,17 @@ class SatTracks(gps):
\t\t<tr>
\t\t\t<td>
\t\t\t\t<table border=0 class=num>
\t\t\t\t\t<tr><th>PRN:</th><th>Elev:</th><th>Azim:</th><th>SNR:</th><th>Used:</th></tr>
\t\t\t\t\t<tr><th>PRN:</th><th>Elev:</th><th>Azim:</th><th>SNR:</th>
<th>Used:</th></tr>
""" % jsfile)
sats = self.satellites[:]
sats.sort(key=lambda x: x.PRN)
for s in sats:
fh.write("\t\t\t\t\t<tr><td>%d&l