Browse Source

New upstream version 3.18.1

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

+ 4
- 3
.travis.yml View File

@@ -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


.travis.build → .travis/build.sh View File

@@ -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
- 0
.vimrc View File

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

+ 17
- 18
INSTALL View File

@@ -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
- 0
NEWS View File

@@ -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


+ 484
- 320
SConstruct
File diff suppressed because it is too large
View File


+ 35
- 2
TODO View File

@@ -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


+ 1
- 1
Tachometer.c View File

@@ -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>


+ 1
- 1
Tachometer.h View File

@@ -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_


+ 1
- 1
TachometerP.h View File

@@ -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_


+ 0
- 3
ais_json.i View File

@@ -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. */


+ 1
- 1
bits.c View File

@@ -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


+ 1
- 1
bits.h View File

@@ -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_


+ 34
- 17
build.txt View File

@@ -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


+ 208
- 1
cgps.1 View File

@@ -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>

+ 737
- 489
cgps.c
File diff suppressed because it is too large
View File


+ 7
- 0
contrib/README View File

@@ -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


+ 4
- 5
contrib/SConstruct View File

@@ -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
- 0
contrib/clock_test.c View File

@@ -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);
}

+ 1
- 1
contrib/gps View File

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

+ 52
- 45
contrib/gpsData.py View File

@@ -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
- 0
contrib/gpssnmp.c View File

@@ -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;
}

+ 56
- 32
contrib/ntpshmviz View File

@@ -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
- 0
contrib/skyview2svg View File

@@ -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)

+ 51
- 26
contrib/webgps.py View File

@@ -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</td><td>%d</td><td>%d</td><td>%d</td><td>%s</td></tr>\n" % (
s.PRN, s.elevation, s.azimuth, s.ss, s.used and 'Y' or 'N'
))
fh.write("\t\t\t\t\t<tr><td>%d</td><td>%d</td><td>%d</td>"
"<td>%d</td><td>%s</td></tr>\n" %
(s.PRN, s.elevation, s.azimuth, s.ss,
s.used and 'Y' or 'N'))

fh.write("\t\t\t\t</table>\n\t\t\t\t<table border=0>\n")

@@ -131,9 +148,12 @@ class SatTracks(gps):
if self.fix.mode >= MODE_2D:
row('Latitude', deg_to_str(self.fix.latitude, 'SN'))
row('Longitude', deg_to_str(self.fix.longitude, 'WE'))
row('Altitude', self.fix.mode == MODE_3D and "%f m" % self.fix.altitude or 'N/A')
row('Speed', not isnan(self.fix.speed) and "%f m/s" % self.fix.speed or 'N/A')
row('Course', not isnan(self.fix.track) and "%f°" % self.fix.track or 'N/A')
row('Altitude', self.fix.mode == MODE_3D and "%f m" %
self.fix.altitude or 'N/A')
row('Speed', isfinite(self.fix.speed) and "%f m/s" %
self.fix.speed or 'N/A')
row('Course', isfinite(self.fix.track) and "%f°" %
self.fix.track or 'N/A')
else:
row('Latitude', 'N/A')
row('Longitude', 'N/A')
@@ -141,34 +161,35 @@ class SatTracks(gps):
row('Speed', 'N/A')
row('Course', 'N/A')

row('EPX', not isnan(self.fix.epx) and "%f m" % self.fix.epx or 'N/A')
row('EPY', not isnan(self.fix.epy) and "%f m" % self.fix.epy or 'N/A')
row('EPV', not isnan(self.fix.epv) and "%f m" % self.fix.epv or 'N/A')
row('Climb', self.fix.mode == MODE_3D and not isnan(self.fix.climb) and
"%f m/s" % self.fix.climb or 'N/A'
)
row('EPX', isfinite(self.fix.epx) and "%f m" % self.fix.epx or 'N/A')
row('EPY', isfinite(self.fix.epy) and "%f m" % self.fix.epy or 'N/A')
row('EPV', isfinite(self.fix.epv) and "%f m" % self.fix.epv or 'N/A')
row('Climb', self.fix.mode == MODE_3D and isfinite(self.fix.climb) and
"%f m/s" % self.fix.climb or 'N/A')

state = "INIT"
if not (self.valid & ONLINE_SET):
newstate = 0
state = "OFFLINE"
else:
newstate = self.fix.mode
if newstate == MODE_2D:
state = self.status == STATUS_DGPS_FIX and "2D DIFF FIX" or "2D FIX"
state = "2D FIX"
elif newstate == MODE_3D:
state = self.status == STATUS_DGPS_FIX and "3D DIFF FIX" or "3D FIX"
state = "3D FIX"
else:
state = "NO FIX"
if newstate != self.state:
self.statetimer = time.time()
self.state = newstate
row('State', state + " (%d secs)" % (time.time() - self.statetimer))
row('State', "%s (%d secs)" % (state, time.time() - self.statetimer))

fh.write("""\t\t\t\t</table>
\t\t\t</td>
\t\t\t<td>
\t\t\t\t<canvas id=satview width=425 height=425>
\t\t\t\t\t<p>Your browser needs HTML5 &lt;canvas> support to display the satellite view correctly.</p>
\t\t\t\t\t<p>Your browser needs HTML5 &lt;canvas> support to display
the satellite view correctly.</p>
\t\t\t\t</canvas>
\t\t\t\t<script type='text/javascript'>draw_satview();</script>
\t\t\t</td>
@@ -227,14 +248,14 @@ function draw_satview() {
// tracks
ctx.lineWidth = 0.6;
ctx.strokeStyle = 'red';
""");
""")

# Draw the tracks
for t in self.sattrack.values():
if t.posn:
fh.write(" ctx.globalAlpha = %s; ctx.beginPath(); %sctx.stroke();\n" % (
t.stale == 0 and '0.66' or '1', t.track()
))
fh.write(" ctx.globalAlpha = %s; ctx.beginPath(); "
"%sctx.stroke();\n" %
(t.stale == 0 and '0.66' or '1', t.track()))

fh.write("""
// satellites
@@ -261,7 +282,9 @@ function draw_satview() {
fh.write("ctx.rect(%d, %d, 16, 16); " % (x - 8, y - 8))
else:
fh.write("ctx.arc(%d, %d, 8, 0, circle, 0); " % (x, y))
fh.write("ctx.fill(); ctx.stroke(); ctx.strokeText('%s', %d, %d);\n" % (s.PRN, x - 6 + offset, y + 4))
fh.write("ctx.fill(); ctx.stroke(); "
"ctx.strokeText('%s', %d, %d);\n" %
(s.PRN, x - 6 + offset, y + 4))

fh.write("""
ctx.restore();
@@ -328,6 +351,7 @@ function draw_satview() {
):
break


def main():
argv = sys.argv[1:]

@@ -365,5 +389,6 @@ def main():
pickle.dump(sat.sattrack, p)
p.close()


if __name__ == '__main__':
main()

+ 1
- 1
crc24q.c View File

@@ -24,7 +24,7 @@
* requires this.
*
* This file is Copyright (c) 2008,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 <stdbool.h>
#include <stdio.h>


+ 1
- 1
crc24q.h View File

@@ -1,7 +1,7 @@
/* Interface for CRC-24Q cyclic redundancy chercksum 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
*/
#ifndef _CRC24Q_H_
#define _CRC24Q_H_


+ 1
- 1
dbusexport.c View File

@@ -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
*/
#include "gpsd.h"
#if defined(DBUS_EXPORT_ENABLE)


+ 389
- 309
devtools/ais.py
File diff suppressed because it is too large
View File


+ 1
- 1
devtools/gps View File

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

+ 1
- 0
devtools/identify_failing_build_options.py View File

@@ -135,6 +135,7 @@ def main(starting_number_of_options=0):

return failed_configurations


if __name__ == '__main__':
failed = main(0)
for row in failed:


+ 62
- 44
devtools/tablegen.py View File

@@ -63,7 +63,9 @@
# Preserve this property!
from __future__ import absolute_import, print_function, division

import sys, getopt
import getopt
import sys


def correct_table(wfp):
# Writes the corrected table.
@@ -74,6 +76,7 @@ def correct_table(wfp):
else:
print(t.rstrip(), file=wfp)


def make_driver_code(wfp):
# Writes calls to bit-extraction macros.
# Requires UBITS, SBITS, UCHARS to act as they do in the AIVDM driver.
@@ -99,8 +102,8 @@ def make_driver_code(wfp):
if not record:
continue
if ftype == 'x':
print("\t/* skip %s bit%s */" % (width, ["", "s"][width>'1']),
file=wfp)
print("\t/* skip %s bit%s */" % (width,
["", "s"][width > '1']), file=wfp)
continue
if ftype[0] == 'a':
arrayname = name
@@ -110,39 +113,44 @@ def make_driver_code(wfp):
if explicit:
lengthfield = last
print(indent + "for (i = 0; i < %s; i++) {" % lengthfield,
file=wfp)
file=wfp)
else:
lengthfield = "n" + arrayname
print(indent + "for (i = 0; ARRAY_BASE + (ELEMENT_SIZE*i) < bitlen; i++) {", file=wfp)
print(indent + "for (i = 0; ARRAY_BASE + "
"(ELEMENT_SIZE*i) < bitlen; i++) {", file=wfp)
indent += step
print(indent + "int a = ARRAY_BASE + (ELEMENT_SIZE*i);",
file=wfp)
file=wfp)
continue
offset = offsets[i].split('-')[0]
if arrayname:
target = "%s.%s[i].%s" % (structnme, arrayname, name)
offset = "a + " + offset
offset = "a + " + offset
else:
target = "%s.%s" % (structname, name)
if ftype[0].lower() in ('u', 'i', 'e'):
print(indent + "%s\t= %sBITS(%s, %s);" % \
(target, {'u':'U', 'e':'U', 'i':'S'}[ftype[0].lower()], offset, width), file=wfp)
print(indent + "%s\t= %sBITS(%s, %s);" %
(target,
{'u': 'U', 'e': 'U', 'i': 'S'}[ftype[0].lower()],
offset, width), file=wfp)
elif ftype == 't':
print(indent + "UCHARS(%s, %s);" % (offset, target), file=wfp)
elif ftype == 'b':
print(indent + "%s\t= (bool)UBITS(%s, 1);" % (target, offset),
file=wfp)
else:
print(indent + "/* %s bits of type %s */" % (width,ftype),
file=wfp)
print(indent + "/* %s bits of type %s */" %
(width, ftype), file=wfp)
last = name
if arrayname:
indent = base
print(indent + "}", file=wfp)
if not explicit:
print(indent + "%s.%s = ind;" % (structname, lengthfield), file=wfp)
print("#undef ARRAY_BASE", file=wfp)
print("#undef ELEMENT_SIZE", file=wfp)
print(indent + "%s.%s = ind;" %
(structname, lengthfield), file=wfp)
print("#undef ARRAY_BASE", file=wfp)
print("#undef ELEMENT_SIZE", file=wfp)


def make_structure(wfp):
# Write a structure definition correponding to the table.
@@ -152,8 +160,10 @@ def make_structure(wfp):
step = 4
inwards = step
arrayname = None

def tabify(n):
return ('\t' * (n // 8)) + (" " * (n % 8))
return ('\t' * (n // 8)) + (" " * (n % 8))

print(tabify(baseindent) + "struct {", file=wfp)
for (i, t) in enumerate(table):
if '|' in t:
@@ -177,14 +187,14 @@ def make_structure(wfp):
ftype = ftype[1:]
else:
lengthfield = "n%s" % arrayname
print(tabify(baseindent + inwards)
+ "signed int %s;" % lengthfield, file=wfp)
print(tabify(baseindent + inwards) +
"signed int %s;" % lengthfield, file=wfp)
if arrayname.endswith("s"):
typename = arrayname[:-1]
else:
typename = arrayname
print(tabify(baseindent + inwards) + "struct %s_t {" % typename,
file=wfp)
print(tabify(baseindent + inwards) + "struct %s_t {" %
typename, file=wfp)
inwards += step
arraydim = ftype[1:]
continue
@@ -208,9 +218,10 @@ def make_structure(wfp):
if "->" in structname:
typename = structname.split("->")[1]
if "." in typename:
structname = structname.split(".")[1]
structname = structname.split(".")[1]
print(tabify(baseindent) + "} %s;" % typename, file=wfp)


def make_json_dumper(wfp):
# Write the skeleton of a JSON dump corresponding to the table.
# Also, if there are subtables, some initializers
@@ -223,13 +234,16 @@ def make_json_dumper(wfp):
value = value[:-10]
wfp.write(' "%s",\n' % value)
wfp.write(" };\n")
wfp.write('#define DISPLAY_%s(n) (((n) < (unsigned int)NITEMS(%s_vocabulary)) ? %s_vocabulary[n] : "INVALID %s")\n' % (name.upper(), name, name, name.upper()))
wfp.write('#define DISPLAY_%s(n) (((n) < '
'(unsigned int)NITEMS(%s_vocabulary)) ? '
'%s_vocabulary[n] : "INVALID %s")\n' %
(name.upper(), name, name, name.upper()))
wfp.write("\n")
record = after is None
# Elements of each tuple type except 'a':
# 1. variable name,
# 2. unscaled printf format
# 3. wrapper for unscaled variable reference
# 3. wrapper for unscaled variable reference
# 4. scaled printf format
# 5. wrapper for scaled variable reference
# Elements of 'a' tuple:
@@ -306,30 +320,33 @@ def make_json_dumper(wfp):
sys.exit(1)
last = name
startspan = 0

def scaled(i):
return tuples[i][3] is not None

def tslice(e, i):
return [x[i] for x in tuples[startspan:e+1]]

base = " " * 8
step = " " * 4
inarray = None
header = "(void)snprintf(buf + strlen(buf), buflen - strlen(buf),"
for (i, (var, uf, uv, sf, sv)) in enumerate(tuples):
if uf == None:
if uf is not None:
print(base + "for (i = 0; i < %s.%s; i++) {" % (structname, sv),
file=wfp)
inarray = var
base = " " * 12
startspan = i+1
continue
continue
# At end of tuples, or if scaled flag changes, or if next op is array,
# flush out dump code for a span of fields.
if i+1 == len(tuples):
endit = '}",'
elif tuples[i+1][1] == None:
elif tuples[i+1][1] is not None:
endit = r',\"%s\":[",' % tuples[i+1][0]
elif scaled(i) != scaled(i+1):
endit = ',",'
elif scaled(i) != scaled(i + 1):
endit = ',",'
else:
endit = None
if endit: