Browse Source

New upstream version 3.17

tags/upstream/3.17^0
Bernd Zeimetz 2 years ago
parent
commit
fe63bf31c0
100 changed files with 5540 additions and 2492 deletions
  1. +35
    -0
      .travis.build
  2. +17
    -0
      .travis.yml
  3. +71
    -25
      INSTALL
  4. +13
    -2
      NEWS
  5. +2
    -2
      Qgpsmm.pc.in
  6. +1
    -1
      README
  7. +1009
    -570
      SConstruct
  8. +0
    -6
      TODO
  9. +4
    -4
      bits.c
  10. +3
    -2
      bits.h
  11. +82
    -27
      build.txt
  12. +37
    -19
      cgps.c
  13. +0
    -47
      clock_gettime.c
  14. +1
    -1
      compiler.h
  15. +3
    -0
      contrib/.gitignore
  16. +0
    -6
      contrib/README
  17. +8
    -4
      contrib/SConstruct
  18. +0
    -0
      contrib/ais-samples/ais-nmea-sample.log
  19. +0
    -0
      contrib/ais-samples/ais-nmea-sample.log.chk
  20. +7
    -1
      contrib/ashctl.c
  21. +7
    -2
      contrib/binlog.c
  22. +7
    -2
      contrib/binreplay.c
  23. +1
    -0
      contrib/gps
  24. +69
    -0
      contrib/gpsData.py
  25. +12
    -5
      contrib/motosend.c
  26. +64
    -115
      contrib/ntpshmviz
  27. +26
    -15
      contrib/webgps.py
  28. +0
    -48
      daemon.c
  29. +1
    -0
      dbusexport.c
  30. +43
    -27
      devtools/ais.py
  31. +6
    -2
      devtools/aivdmtable
  32. +43
    -35
      devtools/cycle_analyzer
  33. +36
    -23
      devtools/flocktest
  34. +1
    -0
      devtools/gps
  35. +47
    -40
      devtools/identify_failing_build_options.py
  36. +8
    -0
      devtools/regress-builder
  37. +10
    -6
      devtools/regressdiff
  38. +19
    -5
      devtools/sizes
  39. +5
    -1
      devtools/striplog
  40. +87
    -69
      devtools/tablegen.py
  41. +5
    -2
      devtools/test_json_validity.py
  42. +154
    -0
      devtools/uninstall_cleanup.py
  43. +1
    -1
      doc/explan_libgpsd_core.c.xml
  44. +14
    -2
      driver_ais.c
  45. +4
    -4
      driver_evermore.c
  46. +8
    -2
      driver_garmin.c
  47. +3
    -2
      driver_garmin_txt.c
  48. +8
    -4
      driver_geostar.c
  49. +3
    -3
      driver_italk.c
  50. +5
    -2
      driver_navcom.c
  51. +440
    -39
      driver_nmea0183.c
  52. +15
    -10
      driver_nmea2000.c
  53. +3
    -3
      driver_oncore.c
  54. +1
    -1
      driver_proto.c
  55. +298
    -297
      driver_rtcm2.c
  56. +194
    -24
      driver_rtcm3.c
  57. +9
    -6
      driver_sirf.c
  58. +547
    -0
      driver_skytraq.c
  59. +2
    -2
      driver_superstar2.c
  60. +154
    -15
      driver_tsip.c
  61. +14
    -8
      driver_ubx.c
  62. +13
    -1
      driver_zodiac.c
  63. +207
    -5
      drivers.c
  64. +24
    -15
      gegps
  65. +17
    -1
      geoid.c
  66. +10
    -54
      gps.1
  67. +38
    -8
      gps.h
  68. +14
    -65
      gps.xml
  69. +7
    -3
      gps/__init__.py
  70. +47
    -27
      gps/client.py
  71. +296
    -179
      gps/fake.py
  72. +137
    -178
      gps/gps.py
  73. +219
    -51
      gps/misc.py
  74. +2
    -2
      gps2udp.1
  75. +17
    -8
      gps2udp.c
  76. +1
    -1
      gps2udp.xml
  77. +1
    -0
      gps_json.h
  78. +4
    -2
      gps_maskdump.c
  79. +28
    -18
      gpscap.ini
  80. +75
    -35
      gpscap.py
  81. +48
    -32
      gpscat
  82. +2
    -2
      gpscat.1
  83. +1
    -1
      gpscat.xml
  84. +11
    -6
      gpsclient.c
  85. +2
    -2
      gpsctl.1
  86. +29
    -7
      gpsctl.c
  87. +1
    -1
      gpsctl.xml
  88. +39
    -23
      gpsd.8
  89. +87
    -28
      gpsd.c
  90. +68
    -37
      gpsd.h
  91. +0
    -19
      gpsd.h-head
  92. +9
    -6
      gpsd.php
  93. +9
    -6
      gpsd.php.in
  94. +57
    -29
      gpsd.xml
  95. +78
    -51
      gpsd_config.h
  96. +130
    -20
      gpsd_json.5
  97. +44
    -9
      gpsd_json.c
  98. +81
    -4
      gpsd_json.xml
  99. +18
    -15
      gpsdclient.c
  100. +2
    -2
      gpsdctl.8

+ 35
- 0
.travis.build View File

@@ -0,0 +1,35 @@
#!/bin/bash
set -e
set -x

export PATH=/usr/sbin:/usr/bin:/sbin:/bin

eval "$(dpkg-buildflags --export=sh)"

export DEB_HOST_MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH)

SCONSOPTS="$@ prefix=/usr"
SCONSOPTS="${SCONSOPTS} systemd=yes"
SCONSOPTS="${SCONSOPTS} nostrip=yes"
SCONSOPTS="${SCONSOPTS} dbus_export=yes"
SCONSOPTS="${SCONSOPTS} docdir=/usr/share/doc/gpsd"
SCONSOPTS="${SCONSOPTS} libdir=/usr/lib/${DEB_HOST_MULTIARCH}"
SCONSOPTS="${SCONSOPTS} gpsd_user=gpsd"
SCONSOPTS="${SCONSOPTS} gpsd_group=dialout"
SCONSOPTS="${SCONSOPTS} debug=yes"

export SCONSOPTS

export PYTHONS="$(pyversions -v -r '>= 2.3')"

if [ "$PYTHONS" = "" ]; then
export PYTHONS="2"
fi

for py in $PYTHONS; do
python${py} /usr/bin/scons ${SCONSOPTS}
python${py}-dbg /usr/bin/scons ${SCONSOPTS}
done

/usr/bin/scons build-all www check


+ 17
- 0
.travis.yml View File

@@ -0,0 +1,17 @@
sudo: required
language: generic

# Some versions of clang++ don't work with some C++ headers, due to an
# issue with __float128. Until this is reproducible in a more debuggable
# 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"

services:
- docker

script:
- wget -O- http://build-in-debian.bzed.at/script.sh | sh -

+ 71
- 25
INSTALL View File

@@ -54,7 +54,7 @@ running Fedora Core, Ubuntu, or stock Debian you can skip this step,
as the stock configuration has the right properties.

gpsd requires two things: (1) that GPS devices have group read and
write enabled, and (2) all of them are have the same group ID as a
write enabled, and (2) all of them have the same group ID as a
prototypical device, typically /dev/ttyS0 under Linux or /dev/tty00
under *BSD. It does not actually matter what the owning group is, as
gpsd will look this up on startup. Alternatively, (3), you can set a
@@ -87,24 +87,20 @@ A minimum build of GPSD can run pretty close to the metal; all it
absolutely needs is the C runtime support. The test clients and
various additional features have additional prerequisites:

|==========================================================================
|pthreads library | support for PPS timekeeping on serial GPSes
|DBUS | gpsd will issue DBUS notifications
|ncurses | a test client and the GPS monitor depend on this
|libtinfo5 | shared low-level terminfo library (see below)
|libusb-1.0.x or later | better USB device discovery
|Qt + qmake | libQgpsmm depends on this
|python2.x, x >=6 | required for various clients and utilities
|pgtk-2/cairo bindings | the main test client, xgps, needs this
|==========================================================================
|===============================================================================
|pthreads library | support for PPS timekeeping on serial GPSes
|DBUS | gpsd will issue DBUS notifications
|ncurses | a test client and the GPS monitor depend on this
|libtinfo5 | shared low-level terminfo library (see below)
|libusb-1.0.x or later | better USB device discovery
|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
|===============================================================================

Some ncurses packages contain the terminfo library; some break it out
separately as libtinfo5 or libtinfo.

The Python code in GPSD is actually compatible back to Python 2.4 except that
you need either the json library module from 2.6 or the functionally
equivalent simplejson backport.

== Installing gpsd ==

=== Install your distributions package(s) ===
@@ -191,14 +187,14 @@ to first install the MacPorts package. Follow their install procedure
at: http://www.macports.org/install.php

Then use their port command to install scons, and optionally git if you
want to access the develpment source.
want to access the development source.

--------------------------------------------------------------
# port install scons
# port install git
--------------------------------------------------------------

While runnning gpsd, or scons check, you may run out of shared memory
While running gpsd, or scons check, you may run out of shared memory
segments. If so, you will see this error message:

--------------------------------------------------------------
@@ -224,12 +220,12 @@ If you are using a USB based GPS you will likely need the Prolific
PL2303 driver. You can find it here:
http://www.prolific.com.tw/US/ShowProduct.aspx?p_id=229&pcid=41

== Special Notes for Rasberry Pi Installation ==
== Special Notes for Raspberry Pi Installation ==

gpsd will build, install and run on the Rasberry Pi (RasPi) and Pi 2
gpsd will build, install and run on the Raspberry Pi (RasPi) and Pi 2
using Debian jessie. Other distributions based on
Debian (raspbian, etc) will work fine as well. The gpsd
package in Debian Wheezy is known to be flakey, be sure to update to a
package in Debian Wheezy is known to be flaky, be sure to update to a
new version of gpsd from source.

=== Raspbian ===
@@ -255,7 +251,7 @@ testing PPS inputs.
The rest of the installation is just as for any other source based
install, as noted in the file *build.txt* .

=== Other Debian derivitives (including stock) ===
=== Other Debian derivatives (including stock) ===
==== Jessie ====
--------------------------------------------------------------
# apt-get install scons libncurses5-dev python-dev pps-tools
@@ -278,7 +274,7 @@ If your scons is less than 2.3.0 you will need to get a newer scons
from wheezy-backport. Partial instructions are detailed here:
http://backports.debian.org/Instructions/

Basically you need to add this line to /etc/apt/sources.list:
Basically you need to add this line to /etc/apt/sources.list:

--------------------------------------------------------------
deb http://http.debian.net/debian wheezy-backports main
@@ -335,6 +331,8 @@ 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.

@@ -343,16 +341,64 @@ this GPS you also get a good 1PPS signal. This works as any other GPS
with gpsd, but there are two things to note. The GPS takes over the
serial console: /dev/ttyAMA0. The PPS signal will be on GPIO Pin #4.

Only two specific changes need to be made to make the HAT work. First
Only three specific changes need to be made to make the HAT work. First
in the file /boot/cmdline.txt, remove this part "console=ttyAMA0,115200
kgdboc=ttyAMA0,115200)". That frees the serial port from console use so
the GPS can use it.

Second you need to tell the boot process to load the pps_gpio module
and attach /dev/pps0 to GPIO ping 4. Do that by adding this line
and attach /dev/pps0 to GPIO pin 4. Do that by adding this line
to the bottom of /boot/config.txt: dtoverlay=pps-gpio,gpiopin=4

Reboot and proceed as for any other operating system to use gpsd.
Reboot so those changes take effect.

Run gpsd like this:

--------------------------------------------------------------
~ # 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
be autodetected. and used for PPS if available.

gpsd 3.17 and up only:

--------------------------------------------------------------
~ # gpsd -D 5 -N -n /dev/ttyAMA0
--------------------------------------------------------------

You can verify gpsd is using the PPS by running ntpshmmon:

--------------------------------------------------------------
~ # ntpshmmon
# Name Seen@ Clock Real L Prec
sample NTP0 1461619703.641899335 1461619703.445224418 1461619703.000000000 0 -1
sample NTP2 1461619703.642203397 1461619702.999262204 1461619703.000000000 0 -20
sample NTP0 1461619704.142097363 1461619703.445224418 1461619703.000000000 0 -1
sample NTP2 1461619704.142204134 1461619703.999258157 1461619704.000000000 0 -20
--------------------------------------------------------------

If you do not see NTP2 then you misconfigured the pps_gpio driver.

The serial time is provided to ntpd on NTP0, the PPS time is on NTP2, not
on NTP1 like described earlier. So your ntp.conf will need to be adjusted
from:

--------------------------------------------------------------
# GPS PPS reference (NTP1)
server 127.127.28.1 prefer
fudge 127.127.28.1 refid PPS
--------------------------------------------------------------

To:

--------------------------------------------------------------
# GPS PPS reference (NTP2)
server 127.127.28.2 prefer
fudge 127.127.28.2 refid PPS
--------------------------------------------------------------

Now proceed as for any other operating system to use gpsd.

Warning, the pps_gpio driver in all linux kernels up to the current
3.19 only reports one edge. Be sure to validate that your PPS signal


+ 13
- 2
NEWS View File

@@ -1,5 +1,16 @@
GPSD project news

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
bug that occasionally confused NTP. Support for Spectratime iSync
GRClok and LNRClok oscillators. gpxlogger can reconnect when
the GPS loses the fix. xgps and xgpsspeed moved to python-gi,
getting shut of the deprecated pygtk2 bindings. Default mode for
xgpsspeed is now the more interesting nautical display. gpsmon
includes the hostname with the device display. gpsprof now has
centimeter precision.

3.16: 2016-01-08 (Eric S. Raymond <esr@snark.thyrsus.com>)
Test rebuilds for mid-2015 leapsecond bump. Regression tests will
run even if "python" in Python 3. Build correctly on systems where
@@ -12,7 +23,7 @@
CCFLAGS contains options that are only compatible with the
cros1s-compiler. Fix Savannah bug #45342: SConstruct generates wrong
*.pc files. Fix Savannah bug #46495: gpsd_poll may crash due to
unitialized pointer (probably due to bugg FD_ISSET on hos
unitialized pointer (probably due to buggy FD_ISSET on host
system). Fix Savannah bug #46648: gpsd crashes and buffer overflow
is reported when terminated. Fix Savannah bug #46802: AIVDM to CSV
is broken in some weird cases. Fix Savannah bug #46804: JSON
@@ -20,7 +31,7 @@

3.15: 2015-06-03 (Eric S. Raymond <esr@snark.thyrsus.com>)
Fix a rare crash bug related to devices becoming inaccessible while timed out.
Accept NMEA 4.1 GSV sententences with the trailing signal-ID field.
Accept NMEA 4.1 GSV sentences with the trailing signal-ID field.
Fixed incorrect decode of south latitudes in AIS Type 17 messages.
splint has been retired; this removes almost 2KLOC of annotations.
chrpath is no longer a build dependency. Corrected Beidou/QZNSS display


+ 2
- 2
Qgpsmm.pc.in View File

@@ -1,7 +1,7 @@
prefix=@prefix@
exec_prefix=${prefix}
libdir=${exec_prefix}@libdir@
includedir=${prefix}/include
libdir=@libdir@
includedir=@includedir@
qt_config=lex yacc warn_on uic resources qt release incremental link_prl def_files_disabled exceptions no_mocdepend stl qt_no_framework create_pc create_prl moc thread dll

Name: Qgpsmm


+ 1
- 1
README View File

@@ -109,7 +109,7 @@ application engineer at SiRF. He assisted us with the correction and
tuning of the SiRF binary-protocol driver, shedding a good deal of
light on murky aspects of the chip's behavior.

We are also delighted to acknowlege the assistance of Timo Ylhainen, VP of
We are also delighted to acknowledge the assistance of Timo Ylhainen, VP of
Software Operations at Fastrax. He clarified a number of points about
the iTalk protocol, helping to further development of iTalk support.



+ 1009
- 570
SConstruct
File diff suppressed because it is too large
View File


+ 0
- 6
TODO View File

@@ -51,12 +51,6 @@ uses the serial port for time_pps_init).

*** Client bugs

**** In gpsmon's PPS Offset field

Presently PPS Offset is displayed in direct mode for NMEA, SiRF, and
UBX devices. Others should probably do likewise, notably the
Motorola Oncore and Garmin drivers.

*** Dispatcher/network issues

**** Reading AISHub data via UDP confuses xgps with short writes


+ 4
- 4
bits.c View File

@@ -37,7 +37,7 @@ uint64_t ubits(unsigned char buf[], unsigned int start, unsigned int width, bool
fld >>= (CHAR_BIT - end);
}

fld &= ~(-1LL << width);
fld &= ~(~0ULL << width);

/* was extraction as a little-endian requested? */
if (le)
@@ -63,12 +63,12 @@ int64_t sbits(signed char buf[], unsigned int start, unsigned int width, bool le
uint64_t fld = ubits((unsigned char *)buf, start, width, le);

/* ensure width > 0 as the result of
1LL << (width - 1)
1ULL << (width - 1)
is undefined for width <= 0 */
assert(width > 0);

if (fld & (1LL << (width - 1))) {
fld |= (-1LL << (width - 1));
if (fld & (1ULL << (width - 1))) {
fld |= (~0ULL << (width - 1));
}
return (int64_t)fld;
}


+ 3
- 2
bits.h View File

@@ -35,12 +35,13 @@
extern float getlef32(const char *, int);
extern double getled64(const char *, int);

#define putle16(buf, off, w) do {putbyte(buf, (off)+1, (uint)(w) >> 8); putbyte(buf, (off), (w));} while (0)
#define putle32(buf, off, l) do {putle16(buf, (off)+2, (uint)(l) >> 16); putle16(buf, (off), (l));} while (0)
#define putle16(buf, off, w) do {putbyte(buf, (off)+1, (unsigned int)(w) >> 8); putbyte(buf, (off), (w));} while (0)
#define putle32(buf, off, l) do {putle16(buf, (off)+2, (unsigned int)(l) >> 16); putle16(buf, (off), (l));} while (0)

/* big-endian access */
#define getbes16(buf, off) ((int16_t)(((uint16_t)getub(buf, (off)) << 8) | (uint16_t)getub(buf, (off)+1)))
#define getbeu16(buf, off) ((uint16_t)(((uint16_t)getub(buf, (off)) << 8) | (uint16_t)getub(buf, (off)+1)))
#define getbeu24(buf, off) ((uint32_t)(((uint16_t)getbeu16(buf, (off)) << 8) | getub(buf, (off)+2)))
#define getbes32(buf, off) ((int32_t)(((uint16_t)getbeu16(buf, (off)) << 16) | getbeu16(buf, (off)+2)))
#define getbeu32(buf, off) ((uint32_t)(((uint16_t)getbeu16(buf, (off)) << 16) | getbeu16(buf, (off)+2)))
#define getbes64(buf, off) ((int64_t)(((uint64_t)getbeu32(buf, (off)) << 32) | getbeu32(buf, (off)+4)))


+ 82
- 27
build.txt View File

@@ -9,18 +9,26 @@ Some hints for people building binary packages are in packaging/readme.txt.

== Quick start ==

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,
this line will do:
these lines will do:

tar -xzf gpsd-X.YY.tar.gz
cd gpsd-X.YY
scons && scons check && sudo scons udev-install

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. GPSD's
own Python scripts assume that "#!/usr/bin/env python2" will invoke a
Python 2 interpreter.
it by saying "python2 /usr/bin/scons" or something similar.

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

@@ -50,22 +58,18 @@ is included at the end of this file.
Necessary components for any build:

|============================================================================
|C compiler | gpsd and client library are written in C
|Python 2.x, x >= 6 | some code is generated from python scripts
|scons | for executing the build recipe
|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
|============================================================================

Note: There must be a Python 2 interpreter named 'python' in your path,
or the regression tests will fail. On some systems you might need to
arrange this by putting symlink in a local directory on $PATH.

=== C compiler ===

C99 conformance is required in the compiler. The C code depends on one
C11 feature (supported by GCC, clang, and pretty much any C compiler
that also speaks C++): anonymous unions. We could eliminate these,
but the cost would be source-level interface breakage if we have to
move structure members in and out of unions.
move certain structure members in and out of unions.

Some portions of the code using shared-memory segments are improved by
the C11 stdatomic.h features for lockless concurrency. These are: the
@@ -86,7 +90,8 @@ clang produces a gpsd that passes all regression tests.

=== Python ===

You will need Python 2.5 or later for the build.
You will need Python 2.x at minor version 6 or later or Python 3 at
at minor version 3 or later.

While Python is required to build GPSD from source (the build uses
some code generators in Python), it is not required to run the service
@@ -99,11 +104,11 @@ 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 test client requires the following Python extensions:
The xgps and xgpsspeed test clients require the following Python extensions:

|============================================================================
|gobject | GNOME object introspection library
|pygtk | Python bindings for GTK
|python-gi | Python bindings for gobject-introspection libraries
|python-gi-cairo | Python bindings for Cairo toolkit under GI
|===========================================================================

=== Scons ===
@@ -119,7 +124,7 @@ various additional capabilities and extensions:
|C++ compiler | allows building libgpsmm C++ wrapper for client library
|Qt 4.53+ | allows building libQgpsmm C++ wrapper for client library
|libcap | Capabilities library, allows 1PPS support under Linux
|curses | curses screen-painting library, allows building cgps
|(n)curses | curses screen-painting library, used by cgps and gpsmon
|============================================================================

If you have libusb-1.0.0 or later, the GPSD build will autodetect
@@ -188,7 +193,7 @@ These are listed in rough order of devices covered as of 2013; the
PL23203 by itself accounts for over 70% of deployed USB mice. We
recommend building with pl2303, ftdi_sio, cypress_m8, and cp210x.

We've receive a bug report that suggests the Python test framework
We've received a bug report that suggests the Python test framework
requires legacy PTY support (CONFIG_LEGACY_PTYS) from the Linux
kernel. You should make sure you're in the 'dialout' group in order
to have permission to use these devices.
@@ -246,8 +251,8 @@ To enable hotplugging of USB GPSes under Linux, you may do 'scons
udev-install' to put the appropriate udev rules and wrapper files in
place.

You will need php and php-gd installed to support the PHP web page.
included with the distribution. To install it, copy the file
You will need php and php-gd installed to support the PHP web page
generator included with the distribution. To install it, copy the file
'gpsd.php' to your HTML document directory. Then see the
post-installation instructions in INSTALL for how to configure it.

@@ -330,7 +335,7 @@ client library to be available on all the Qt supported platforms.
Please see http://qt.nokia.com/doc/4.6/supported-platforms.html for a
status of Qt supported platforms as of version 4.6.

minimal=yes: people building for extremely constrained environments
minimal=no: people building for extremely constrained environments
may want to set this. It changes the default for all boolean (feature)
options to false; thus, you get *only* the options you specify on the
command line. Thus, for example, if you want to turn off all features
@@ -342,6 +347,19 @@ scons minimal=yes socket_export=yes nmea0183=yes

will do that.

-----------------------------------------------
scons minimal=yes gpsd=False gpsdclients=False
-----------------------------------------------

generates only libgps.a

-----------------------------------------------
scons minimal=yes shared=True gpsd=False gpsdclients=False
-----------------------------------------------

generates only libgps.so


== Port and toolchain testing ==

'scons check' will run a comprehensive regression-test suite. You
@@ -350,15 +368,34 @@ machine type. GPSD does enough bit-twiddling and floating point that
it is very sensitive to toolchain problems; you'll want to be sure
those aren't going to bite you in production.

So the tests will run fast and be easy to do often, we make the test
So that the tests will run fast and be easy to do often, we make the test
framework shove data through the pty and socket layers *way* faster
than would ever occur in production. If you get regression-test
failures that aren't repeatable and look like the test framework is
sporadically failing to feed the last line or two of test loads, try
using the slow=yes option with scons check. If that fails, try
increasing the delay constants in gps/fake.py. If you have to do this,
increasing the delay value via the WRITE_PAD environment variable
(above the value reported in the test output). If you have to do this,
please report your experience to the GPSD maintainers.

Both the builds and the tests are highly parallelizable via the scons
-j option, which can gain a substantial speedup on a multicore machine.
Because the output from the various jobs is interleaved, it may be more
difficult to understand error results with multiple jobs. In that event,
simply rerun without the -j option for more straightforward output.

If coveraging is enabled (coveraging=yes), then Python programs run
during testing are run via Python coveraging. This prefixes the relevant
commands with the content of the python_coverage option, whose default
value of "coverage run" is appropriate if the standard Python coverage
package is installed and accessible in the command path. It can be
set to a different value if necessary, or set to the empty string to
disable Python coveraging. The latter happens automatically (with a
message) if the tool cannot be found. When running multiple jobs with
"-j", if python_coverage has its default value, "--parallel" is automatically
appended to the command. With a non-default setting, accommodating
parallelism is the user's responsibility.

For instructions on how to live-test the software, see the file INSTALL.

== Reverting to a clean state ==
@@ -371,10 +408,23 @@ stuff is left in place.
If you interrupted a regression test, 'scons testclean' will remove
generated test programs.

You can run 'scons sconsclean' to temove most of the configuration
state that scons keeps. Be aware, however, thatr doing this can
You can run 'scons sconsclean' to remove most of the configuration
state that scons keeps. Be aware, however, that doing this can
confuse scons; you may need to run 'scons --config=force' afterwards
to make your build succeed.
to make your build succeed. At the time of this writing, you can also
remove all the scons state with "rm -rf .scon*", though that could change
in a future release of scons. This method does not "confuse scons".
If you use any of these actions in combination with "scons -c", do the
latter first, as removing scons's state may change its notions of what
needs to be cleaned.

If you're building in a clone of the git repository, you can use
"git clean -dxf" to remove all untracked files. Note, however, that
this will remove any files you have created on your own, in addition
to build products and scons temporaries. You can alternatively use
"git clean -dxn" to see what would be removed without actually removing
anything, or "git clean -dxi" to remove things selectively. Using
"git clean" after "scons -c" usually results in a fairly short list.

== Notes on Android:

@@ -426,7 +476,12 @@ $ git clone [...]
Cloning into gpsd...
[...]
$ cd gpsd
$ cp ../.scons-option-cache .
----

Edit .scons-options-cache (may not exist) and add lines, describing
what your target architecture and build preferences are.

----
$ cat .scons-option-cache
libgpsmm = False
libQgpsmm = False


+ 37
- 19
cgps.c View File

@@ -101,6 +101,7 @@
#include "compiler.h" /* for UNUSED */
#include "gpsdclient.h"
#include "revision.h"
#include "os_compat.h"

static struct gps_data_t gpsdata;
static time_t status_timer; /* Time of last state change. */
@@ -126,7 +127,7 @@ static bool compass_flag = false;
#endif /* TRUENORTH */

/* pseudo-signals indicating reason for termination */
#define CGPS_QUIT 0 /* voluntary yterminastion */
#define CGPS_QUIT 0 /* voluntary termination */
#define GPS_GONE -1 /* GPS device went away */
#define GPS_ERROR -2 /* low-level failure in GPS read */
#define GPS_TIMEOUT -3 /* low-level failure in GPS waiting */
@@ -356,23 +357,23 @@ static void update_compass_panel(struct gps_data_t *gpsdata)
(void)snprintf(scr, sizeof(scr), "n/a");
(void)mvwprintw(datawin, 2, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);

/* Fill in the pitch. */
/* Fill in the climb. */
if (isnan(gpsdata->fix.climb) == 0) {
(void)snprintf(scr, sizeof(scr), "%.1f", gpsdata->fix.climb);
(void)snprintf(scr, sizeof(scr), "%.2f", gpsdata->fix.climb);
} else
(void)snprintf(scr, sizeof(scr), "n/a");
(void)mvwprintw(datawin, 3, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);

/* Fill in the roll. */
/* Fill in the speed. */
if (isnan(gpsdata->fix.speed) == 0)
(void)snprintf(scr, sizeof(scr), "%.1f", gpsdata->fix.speed);
(void)snprintf(scr, sizeof(scr), "%.2f", gpsdata->fix.speed);
else
(void)snprintf(scr, sizeof(scr), "n/a");
(void)mvwprintw(datawin, 4, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);

/* Fill in the speed. */
/* Fill in the altitude. */
if (isnan(gpsdata->fix.altitude) == 0)
(void)snprintf(scr, sizeof(scr), "%.1f", gpsdata->fix.altitude);
(void)snprintf(scr, sizeof(scr), "%.3f", gpsdata->fix.altitude);
else
(void)snprintf(scr, sizeof(scr), "n/a");
(void)mvwprintw(datawin, 5, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);
@@ -392,6 +393,20 @@ static void update_compass_panel(struct gps_data_t *gpsdata)
}
#endif /* TRUENORTH */

/* sort the skyviews
* Used = Y first, then used = N
* then sort by PRN
*/
static int sat_cmp(const void *p1, const void *p2)
{

if ( ((struct satellite_t*)p2)->used - ((struct satellite_t*)p1)->used ) {
return ((struct satellite_t*)p2)->used - ((struct satellite_t*)p1)->used;
}
return ((struct satellite_t*)p1)->PRN - ((struct satellite_t*)p2)->PRN;
}


static void update_gps_panel(struct gps_data_t *gpsdata)
/* This gets called once for each new GPS sentence. */
{
@@ -404,6 +419,8 @@ static void update_gps_panel(struct gps_data_t *gpsdata)
* fix. */
if (gpsdata->satellites_visible != 0) {
int i;
qsort( gpsdata->skyview, gpsdata->satellites_visible,
sizeof( struct satellite_t), sat_cmp);
if (display_sats >= MAX_POSSIBLE_SATS) {
for (i = 0; i < MAX_POSSIBLE_SATS; i++) {
if (i < gpsdata->satellites_visible) {
@@ -479,7 +496,7 @@ static void update_gps_panel(struct gps_data_t *gpsdata)

/* Fill in the altitude. */
if (gpsdata->fix.mode >= MODE_3D && isnan(gpsdata->fix.altitude) == 0)
(void)snprintf(scr, sizeof(scr), "%.1f %s",
(void)snprintf(scr, sizeof(scr), "%.3f %s",
gpsdata->fix.altitude * altfactor, altunits);
else
(void)snprintf(scr, sizeof(scr), "n/a");
@@ -487,7 +504,7 @@ static void update_gps_panel(struct gps_data_t *gpsdata)

/* Fill in the speed. */
if (gpsdata->fix.mode >= MODE_2D && isnan(gpsdata->fix.track) == 0)
(void)snprintf(scr, sizeof(scr), "%.1f %s",
(void)snprintf(scr, sizeof(scr), "%.2f %s",
gpsdata->fix.speed * speedfactor, speedunits);
else
(void)snprintf(scr, sizeof(scr), "n/a");
@@ -511,7 +528,7 @@ static void update_gps_panel(struct gps_data_t *gpsdata)

/* Fill in the rate of climb. */
if (gpsdata->fix.mode >= MODE_3D && isnan(gpsdata->fix.climb) == 0)
(void)snprintf(scr, sizeof(scr), "%.1f %s/min",
(void)snprintf(scr, sizeof(scr), "%.2f %s/min",
gpsdata->fix.climb * altfactor * 60, altunits);
else
(void)snprintf(scr, sizeof(scr), "n/a");
@@ -524,16 +541,17 @@ static void update_gps_panel(struct gps_data_t *gpsdata)
(void)snprintf(scr, sizeof(scr), "OFFLINE");
} else {
newstate = gpsdata->fix.mode;
/*
* DGPS
*/
switch (gpsdata->fix.mode) {
case MODE_2D:
(void)snprintf(scr, sizeof(scr), "2D FIX (%d secs)",
(void)snprintf(scr, sizeof(scr), "2D %sFIX (%d secs)",
(gpsdata->status ==
STATUS_DGPS_FIX) ? "DIFF " : "",
(int)(time(NULL) - status_timer));
break;
case MODE_3D:
(void)snprintf(scr, sizeof(scr), "3D FIX (%d secs)",
(void)snprintf(scr, sizeof(scr), "3D %sFIX (%d secs)",
(gpsdata->status ==
STATUS_DGPS_FIX) ? "DIFF " : "",
(int)(time(NULL) - status_timer));
break;
default:
@@ -642,9 +660,9 @@ static void usage(char *prog)
" -V Show version, then exit\n"
" -s Be silent (don't print raw gpsd data)\n"
" -l {d|m|s} Select lat/lon format\n"
" d = DD.dddddd\n"
" m = DD MM.mmmm'\n"
" s = DD MM' SS.sss\"\n"
" d = DD.ddddddd\n"
" m = DD MM.mmmmmm'\n"
" s = DD MM' SS.sssss\"\n"
" -m Display heading as the estimated magnetic heading\n"
" Valid only for USA (Lower 48 + AK) and Western Europe.\n",
prog);
@@ -791,7 +809,7 @@ int main(int argc, char *argv[])
wait_clicks = 0;
errno = 0;
if (gps_read(&gpsdata) == -1) {
fprintf(stderr, "cgps: socket error 4\n");
(void)fprintf(stderr, "cgps: socket error 4\n");
die(errno == 0 ? GPS_GONE : GPS_ERROR);
} else {
/* Here's where updates go now that things are established. */


+ 0
- 47
clock_gettime.c View File

@@ -1,47 +0,0 @@
/*
* Simulate ANSI/POSIX conformance on platforms that don't have it
*
* This file is Copyright (c) 2010 by the GPSD project
* BSD terms apply: see the file COPYING in the distribution root for details.
*/
#include <time.h>
#include <sys/time.h>

#include "compiler.h"

#ifdef __MACH__
#include <mach/clock.h>
#include <mach/mach.h>
#endif

#ifndef HAVE_CLOCK_GETTIME
int clock_gettime(clockid_t clk_id UNUSED, struct timespec *ts)
{
#ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time
clock_serv_t cclock;
mach_timespec_t mts;
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
clock_get_time(cclock, &mts);
mach_port_deallocate(mach_task_self(), cclock);
ts->tv_sec = mts.tv_sec;
ts->tv_nsec = mts.tv_nsec;
#else
struct timeval tv;
if (gettimeofday(&tv, NULL) < 0)
return -1;
ts->tv_sec = tv.tv_sec;
ts->tv_nsec = tv.tv_usec * 1000;
/* paranoid programming */
if (1000000 <= (tv)->tv_usec) {
(tv)->tv_usec -= 1000000;
(tv)->tv_sec++;
} else if (0 > (tv)->tv_usec) {
(tv)->tv_usec += 1000000;
(tv)->tv_sec--;
}
#endif /* __MACH__ */
return 0;
}
#endif /* HAVE_CLOCK_GETTIME */

/* end */

+ 1
- 1
compiler.h View File

@@ -90,7 +90,7 @@ static inline void memory_barrier(void)
/* we are C++ */
#if __cplusplus >= 201103L
/* C++11 and later has atomics, earlier do not */
atomic_thread_fence(memory_order_seq_cst);
std::atomic_thread_fence(std::memory_order_seq_cst);
#endif
#elif defined HAVE_STDATOMIC_H
/* we are C and atomics are in C98 and newer */


+ 3
- 0
contrib/.gitignore View File

@@ -3,3 +3,6 @@ binlog
binreplay
lla2ecef
motosend
gpsd-*.html
gpsd-*.js
tracks.p

+ 0
- 6
contrib/README View File

@@ -37,12 +37,6 @@ ntpoffset generate an estimate of your GPS's offset from a peerstats
file. For instructions on how to use this script, see the GPSD Time
Service HOWTO in this distrubution, in the www/ subdirectory.

ppscheck watches a specified serial device for changes in handshake lines
CD, RI, and CTS by running ioctl(...., TIOCMIWAIT, ...) in a loop. When it
sees a state change it emits a timestamped line of output dumping the state
of the handshake signals. It's useful for checking whether a device is
emitting 1PPS. There is troubleshooting advice in the header comment.
skyview.php is used to generate pictures of your skyview, and may be
used to help determine if a given antenna placement is appropriate for
some purpose. This tool take a count of samples to collect from GPSD, and


+ 8
- 4
contrib/SConstruct View File

@@ -3,11 +3,15 @@
# won't get used on a daily basis, but someone might find them useful for
# tinkering with their gear.

ashctl = Program("ashctl", ["ashctl.c", "../strl.c"])
# Note that ../gpsd_config.h is required and is built separately


strl = StaticObject("strl", "../strl.c")

ashctl = Program("ashctl", ["ashctl.c", strl])
binlog = Program("binlog", "binlog.c")
binreplay = Program("binreplay", "binreplay.c", parse_flags=['-lutil'])
lla2ecef = Program("lla2ecef", "lla2ecef.c", parse_flags=['-lm'])
motosend = Program("motosend", ["motosend.c", "../strl.c"])
ppscheck = Program("ppscheck", "ppscheck.c")
motosend = Program("motosend", ["motosend.c", strl])

Default(ashctl, binlog, binreplay, lla2ecef, motosend, ppscheck)
Default(ashctl, binlog, binreplay, lla2ecef, motosend)

test/daemon/ais-nmea-sample.log → contrib/ais-samples/ais-nmea-sample.log View File


test/daemon/ais-nmea-sample.log.chk → contrib/ais-samples/ais-nmea-sample.log.chk View File


+ 7
- 1
contrib/ashctl.c View File

@@ -10,6 +10,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h> /* For nanosleep() */
#include <termios.h>
#include <unistd.h>

@@ -157,6 +158,7 @@ static int nmea_send(int fd, const char *fmt, ... )
size_t status;
char buf[BUFSIZ];
va_list ap;
struct timespec delay;

va_start(ap, fmt) ;
(void)vsnprintf(buf, sizeof(buf)-5, fmt, ap);
@@ -167,7 +169,11 @@ static int nmea_send(int fd, const char *fmt, ... )
tcflush(fd, TCIOFLUSH);
status = (size_t)write(fd, buf, strlen(buf));
tcdrain(fd);
usleep(100000);
/* wait 100,000 uSec */
delay.tv_sec = 0;
delay.tv_nsec = 100000000L;
nanosleep(&delay, NULL);

if (status == strlen(buf)) {
return (int)status;
} else {


+ 7
- 2
contrib/binlog.c View File

@@ -11,6 +11,7 @@
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <time.h> /* For nanosleep() */
#include <unistd.h>

void spinner(int );
@@ -19,6 +20,7 @@ int main(int argc, char **argv) {
int speed, n, ifd, ofd;
struct termios term;
char buf[BUFSIZ];
struct timespec delay;

if (argc != 4){
fprintf(stderr, "usage: binlog <speed> <port> <logfile>\n");
@@ -61,8 +63,11 @@ int main(int argc, char **argv) {
int l = read(ifd, buf, BUFSIZ);
if (l > 0)
assert(write(ofd, buf, l) > 0);
usleep(1000);
bzero(buf, BUFSIZ);
/* wait 1,000 uSec */
delay.tv_sec = 0;
delay.tv_nsec = 1000000L;
nanosleep(&delay, NULL);
memset(buf, 0, BUFSIZ);
spinner( n++ );
}
/* NOTREACHED */


+ 7
- 2
contrib/binreplay.c View File

@@ -13,10 +13,11 @@
#include <termios.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <time.h> /* For nanosleep() */
#ifndef __GLIBC__
#include <util.h>
#else
#include <stdlib.h>
#include <pty.h>
#endif

@@ -31,6 +32,7 @@ int main( int argc, char **argv){
char *buf, tn[32];
int ifd, ofd, sfd;
int dflag = 0, c, sleeptime, len, speed = 0;
struct timespec delay;

while((c = getopt(argc, argv, "d:r:s:")) != -1) {
switch(c){
@@ -117,7 +119,10 @@ int main( int argc, char **argv){
tcflush(sfd, TCIFLUSH);
}
spinner( len );
usleep(sleeptime);
/* wait sleeptime Sec */
delay.tv_sec = (time_t)(sleeptime / 1000000000L);
delay.tv_nsec = sleeptime % 1000000000L;
nanosleep(&delay, NULL);
}

munmap(buf, sb.st_size);


+ 1
- 0
contrib/gps View File

@@ -0,0 +1 @@
gpsd-3.17/../gps

+ 69
- 0
contrib/gpsData.py View File

@@ -0,0 +1,69 @@
#! /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

# 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 os
from gps import *
from time import *
import time
import threading

gpsd = None #seting the global variable

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

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)

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
print("Done.\nExiting.")

+ 12
- 5
contrib/motosend.c View File

@@ -11,6 +11,7 @@
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <time.h> /* For nanosleep() and time() */
#include <unistd.h>
#include <limits.h>

@@ -30,7 +31,8 @@ int main(int argc, char **argv) {
int speed, l, fd, n;
struct termios term;
char buf[BSIZ];
time_t s, t;
time_t t;
struct timespec delay;

if (argc != 5){
fprintf(stderr, "usage: motosend <speed> <port> msgtype moto-body-hex\n");
@@ -82,8 +84,13 @@ int main(int argc, char **argv) {
tcflush(fd, TCIOFLUSH);
t = 0; n = 0;
while (1){
usleep(1000);
bzero(buf, BSIZ);
time_t s;
/* wait 1,000 uSec */
delay.tv_sec = 0;
delay.tv_nsec = 1000000L;
nanosleep(&delay, NULL);

memset(buf, 0, BSIZ);
if ((l = read(fd, buf, BSIZ)) == -1)
if (!(EINTR == errno || EAGAIN == errno))
err(1, "read");
@@ -121,7 +128,7 @@ static int moto_send(int fd, char *type, char *body ) {
if ((buf = malloc(l+7)) == NULL)
return -1;

bzero(buf, l+7);
memset(buf, 0, l+7);
buf[0] = '@'; buf[1] = '@';
buf[2] = type[0]; buf[3] = type[1];

@@ -174,7 +181,7 @@ int gpsd_hexpack(char *src, char *dst, int len)
if ((l < 1) || (l > len))
return -1;

bzero(dst, len);
memset(dst, 0, len);
for (i = 0; i < l; i++) {
int k;
if ((k = hex2bin(src+i*2)) != -1)


+ 64
- 115
contrib/ntpshmviz View File

@@ -2,111 +2,54 @@
#
# ntpshmviz - graph the drift of NTP servers
# Written by Keane Wolter <daemoneye2@gmail.com>
#
# pystripchart can be found at
# https://sourceforge.net/projects/jstripchart
#
# To do:
#
# 1. Try using an impulse rather than line plot - this is bursty noise, not
# really a contour.
# 1. Add exit button so the user does not need to do <Ctrl>-w
#

import gtk, stripchart, sys
import sys
# 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])
sys.exit(1)

class ntpOffset:
def __init__(self, stream):
# Initialize the class

# create the GUI for the application
self.create_GUI()

# get the data
self.read_data(stream)

self.create_StripTableau()
self.display_StripTableau()

# enter the GTK main loop
gtk.main()

def create_GUI(self):
# Creates the gui for the class

# create a standard top-level GTK window
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.set_title("NTP Offset")
self.window.connect("destroy", gtk.mainquit)
self.window.set_default_size(700, 400)
self.window.show()

# create a VBox to hold all the top-level GUI items
self.vbox = gtk.VBox()
self.vbox.show()
self.window.add(self.vbox)

# create the toolbar
self.create_toolbar()

def create_StripTableau(self):
# create the striptable widget

# gtk.Adjustment(value, lower, upper, step_incr, page_incr, page_size)
hadj = gtk.Adjustment(0, 0, self.lines, 1, 1, self.lines * 0.5)
sel = gtk.Adjustment(0)
self.striptableau = stripchart.StripTableau(hadj, sel)
self.striptableau.metawidth = 80
self.striptableau.gradewidth = 80
self.vbox.pack_end(self.striptableau.widget, gtk.TRUE, gtk.TRUE)

def create_toolbar(self):
# Create toolbar for zoom and quit buttons

self.toolbar = gtk.Toolbar()
self.toolbar.show()

# Zoom buttons
self.toolbar.insert_stock(gtk.STOCK_ZOOM_IN, "Zoom in", None,
lambda b, w: self.striptableau.zoomIn(), self.window, -1)
self.toolbar.insert_stock(gtk.STOCK_ZOOM_OUT, "Zoom out", None,
lambda b, w: self.striptableau.zoomOut(), self.window, -1)
self.toolbar.insert_stock(gtk.STOCK_ZOOM_FIT, "Zoom fit", None,
lambda b, w: self.striptableau.zoomSel(), self.window, -1)

# Quit button
self.toolbar.insert_stock(gtk.STOCK_QUIT, "Quit", None,
lambda b, w: gtk.mainquit(), self.window, -1)

# Put the toolbar into a HandleBox
self.handlebox = gtk.HandleBox()
self.handlebox.show()
self.handlebox.add(self.toolbar)

# Pack the toolbar into the main window
self.vbox.pack_start(self.handlebox, gtk.FALSE)

def display_StripTableau(self):
# display the graph of each ntp_unit

for ntp_unit in self.ntp_data:
# gtk.Adjustment(value, lower, upper, step_incr, page_incr,
# page_size)
spread = self.ntp_upper[ntp_unit] - self.ntp_lower[ntp_unit]
# prevent divide by zero
if spread == 0:
spread = 1
vadj_ntp = gtk.Adjustment(
self.ntp_lower[ntp_unit], # initial value
self.ntp_lower[ntp_unit] - 0.001, # lower extreme
self.ntp_upper[ntp_unit] + 0.001, # upper extreme
1 / spread, # step_incr
spread, # page_incr
spread) # page size
ntp_item = self.striptableau.addChannel(self.ntp_data[ntp_unit],
vadj_ntp)
ntp_item.name = ntp_unit
# display the data
self.display()

def display(self):
# 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>")

PLT.figure()
subplot_value = 211
for ntp_item in self.ntp_data:
# create the subplot for the data
PLT.subplot(subplot_value)
# setup and create the vlines graph
t = numpy.arange(0, self.line_counts[ntp_item], 1)
PLT.vlines(t, 0, self.ntp_data[ntp_item], color='r')
# add labels
PLT.title("NTP drift for " + ntp_item)
PLT.xlabel('sample')
PLT.ylabel('drift')
# 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
PLT.tight_layout()
PLT.show()

def read_data(self, stream):
# Reads data from a ntp log file. Layout is:
@@ -119,21 +62,22 @@ class ntpOffset:
# - Leep-second notification status
# - Source precision (log(2) of source jitter)

self.ntp_data = {} # data sets for each ntp unit
record = [] # A single record in the file or data stream
line_counts = {} # Count of total lines for each ntp unit
self.lines = 0 # width of graph
self.ntp_upper = {} # Upper limit of the data set
self.ntp_lower = {} # Lower limit of the data set
offset = 0 # offset value to add to the array
self.ntp_vadj = {} # vertical adjustment for each 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:
if line[:1] != '#':
line = line.lstrip()
record = line.split(' ')
offset = numpy.float128(record[3]) - numpy.float128(record[4])
try:
offset = numpy.float128(record[3]) - numpy.float128(record[4])
except:
print ("Invalid data: ", sys.exc_info()[0], ". Data was: ", line)
continue

# If the NTP unit is in the dictionary
# append the offset to the list
@@ -141,24 +85,29 @@ class ntpOffset:
# and add the offset.
if record[1] not in self.ntp_data:
self.ntp_data[record[1]] = []
line_counts[record[1]] = 0
self.ntp_upper[record[1]] = round(offset, 9)
self.ntp_lower[record[1]] = round(offset, 9)
self.line_counts[record[1]] = 0

self.ntp_data[record[1]].append(offset)
line_counts[record[1]] += 1

# Update the bounds of the NTP unit if needed
if offset > self.ntp_upper[record[1]]:
self.ntp_upper[record[1]] = round(offset, 9)
if offset < self.ntp_lower[record[1]]:
self.ntp_lower[record[1]] = round(offset, 9)

# Update the max record count if needed
if line_counts[record[1]] > self.lines:
self.lines = line_counts[record[1]]
self.line_counts[record[1]] += 1
stream.close()

if __name__ == "__main__":
if (len(sys.argv) == 2):
if (sys.argv[1] == "-V" or sys.argv[1] == "--version"):
print ("Version 2.0")
sys.exit()

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/")
sys.exit()

ntpOffset(sys.stdin)
sys.exit()

+ 26
- 15
contrib/webgps.py View File

@@ -36,12 +36,11 @@ If this file is present on start of webgps.py, it is loaded. This allows to
restart webgps.py without losing accumulated satellite tracks.
"""

from __future__ import absolute_import, print_function, division

import time, math, sys, os, pickle
try:
from gps import *
except ImportError:
sys.path.append('..')
from gps import *

from gps import *

TRACKMAX = 1024
STALECOUNT = 10
@@ -52,7 +51,8 @@ def polartocart(el, az):
radius = DIAMETER * (1 - el / 90.0) # * math.cos(Deg2Rad(float(el)))
theta = Deg2Rad(float(az - 90))
return (
-int(radius * math.cos(theta) + 0.5), # switch sides for a skyview!
# Changed this back to normal orientation - fw
int(radius * math.cos(theta) + 0.5),
int(radius * math.sin(theta) + 0.5)
)

@@ -83,7 +83,7 @@ class SatTracks(gps):
'''gpsd client writing HTML5 and <canvas> output.'''

def __init__(self):
gps.__init__(self)
super(SatTracks, self).__init__()
self.sattrack = {} # maps PRNs to Tracks
self.state = None
self.statetimer = time.time()
@@ -112,7 +112,7 @@ class SatTracks(gps):
""" % jsfile)

sats = self.satellites[:]
sats.sort(lambda a, b: a.PRN - b.PRN)
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'
@@ -203,8 +203,8 @@ function draw_satview() {

ctx.beginPath();
ctx.strokeText('N', -4, -202);
ctx.strokeText('E', -210, 4);
ctx.strokeText('W', 202, 4);
ctx.strokeText('W', -210, 4);
ctx.strokeText('E', 202, 4);
ctx.strokeText('S', -4, 210);

ctx.strokeStyle = 'grey';
@@ -244,7 +244,10 @@ function draw_satview() {

# Draw the satellites
for s in self.satellites:
x, y = polartocart(s.elevation, s.azimuth)
el, az = s.elevation, s.azimuth
if el == 0 and az == 0:
continue # Skip satellites with unknown position
x, y = polartocart(el, az)
fill = not s.used and 'lightgrey' or \
s.ss < 30 and 'red' or \
s.ss < 35 and 'yellow' or \
@@ -271,10 +274,13 @@ function draw_satview() {
t.stale -= 1

def delete_stale(self):
stales = []
for prn in self.sattrack.keys():
if self.sattrack[prn].stale == 0:
del self.sattrack[prn]
stales.append(prn)
self.needsupdate = 1
for prn in stales:
del self.sattrack[prn]

def insert_sat(self, prn, x, y):
try:
@@ -342,15 +348,20 @@ def main():
# restore the tracks
pfile = 'tracks.p'
if os.path.isfile(pfile):
p = open(pfile)
sat.sattrack = pickle.load(p)
p = open(pfile, 'rb')
try:
sat.sattrack = pickle.load(p)
except ValueError:
print("Ignoring incompatible tracks file.", file=sys.stderr)
p.close()

try:
sat.run(prefix, period)
except KeyboardInterrupt:
# save the tracks
p = open(pfile, 'w')
p = open(pfile, 'wb')
# No protocol is backward-compatible from Python 3 to Python 2,
# so we just use the default and punt at load time if needed.
pickle.dump(sat.sattrack, p)
p.close()



+ 0
- 48
daemon.c View File

@@ -1,48 +0,0 @@
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#include "gpsd_config.h"
#ifndef HAVE_DAEMON
#if defined (HAVE_PATH_H)
#include <paths.h>
#else
#if !defined (_PATH_DEVNULL)
#define _PATH_DEVNULL "/dev/null"
#endif
#endif

int daemon(int nochdir, int noclose)
/* compatible with the daemon(3) found on Linuxes and BSDs */
{
int fd;

switch (fork()) {
case -1:
return -1;
case 0: /* child side */
break;
default: /* parent side */
exit(EXIT_SUCCESS);
}

if (setsid() == -1)
return -1;
if ((nochdir==0) && (chdir("/") == -1))
return -1;
if ((noclose==0) && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
(void)dup2(fd, STDIN_FILENO);
(void)dup2(fd, STDOUT_FILENO);
(void)dup2(fd, STDERR_FILENO);
if (fd > 2)
(void)close(fd);
}
/* coverity[leaked_handle] Intentional handle duplication */
return 0;
}

#endif /* HAVE_DAEMON */

// end

+ 1
- 0
dbusexport.c View File

@@ -20,6 +20,7 @@ int initialize_dbus_connection(void)
dbus_error_init(&error);
connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
if (connection == NULL) {
dbus_error_free(&error);
/* report error */
return 1;
}


+ 43
- 27
devtools/ais.py View File

@@ -5,6 +5,21 @@
# This file is Copyright (c) 2010 by the GPSD project
# BSD terms apply: see the file COPYING in the distribution root for details.
#
# This code runs compatibly under Python 2 and 3.x for x >= 2.
# Preserve this property!
from __future__ import absolute_import, print_function, division

try:
BaseException.with_traceback

def reraise_with_traceback(exc_type, exc_value, exc_traceback):
raise exc_type(exc_value).with_traceback(exc_traceback)

except AttributeError:

def reraise_with_traceback(exc_type, exc_value, exc_traceback):
raise exc_type, exc_value, exc_traceback

# This decoder works by defining a declarative pseudolanguage in which
# to describe the process of extracting packed bitfields from an AIS
# message, a set of tables which contain instructions in the pseudolanguage,
@@ -25,7 +40,7 @@

# Here are the pseudoinstructions in the pseudolanguage.

class bitfield:
class bitfield(object):
"Object defining the interpretation of an AIS bitfield."
# The only un-obvious detail is the use of the oob (out-of-band)
# member. This isn't used in data extraction, but rather to cut
@@ -43,13 +58,13 @@ class bitfield:
self.formatter = formatter # Custom reporting hook.
self.conditional = conditional # Evaluation guard for this field

class spare:
class spare(object):
"Describes spare bits,, not to be interpreted."
def __init__(self, width, conditional=None):
self.width = width
self.conditional = conditional # Evaluation guard for this field

class dispatch:
class dispatch(object):
"Describes how to dispatch to a message type variant on a subfield value."
def __init__(self, fieldname, subtypes, compute=lambda x: x, conditional=None):
self.fieldname = fieldname # Value of view to dispatch on
@@ -826,7 +841,7 @@ type24b = (
validator=lambda n: n >= 0 and n <= 99,
formatter=ship_type_legends),
bitfield("vendorid", 42, 'string', None, "Vendor ID"),
dispatch("mmsi", {0:type24b1, 1:type24b2}, lambda m: 1 if `m`[:2]=='98' else 0),
dispatch("mmsi", {0:type24b1, 1:type24b2}, lambda m: 1 if repr(m)[:2]=='98' else 0),
)

type24 = (
@@ -929,7 +944,7 @@ from array import array

BITS_PER_BYTE = 8

class BitVector:
class BitVector(object):
"Fast bit-vector class based on Python built-in array type."
def __init__(self, data=None, length=None):
self.bits = array('B')
@@ -943,7 +958,7 @@ class BitVector:
def extend_to(self, length):
"Extend vector to given bitlength."
if length > self.bitlen:
self.bits.extend([0]*((length - self.bitlen +7 )/8))
self.bits.extend([0] * ((length - self.bitlen + 7 ) // 8))
self.bitlen = length
def from_sixbit(self, data, pad=0):
"Initialize bit vector from AIVDM-style six-bit armoring."
@@ -954,13 +969,14 @@ class BitVector:
ch -= 8
for i in (5, 4, 3, 2, 1, 0):
if (ch >> i) & 0x01:
self.bits[self.bitlen/8] |= (1 << (7 - self.bitlen % 8))
self.bits[self.bitlen // 8] |= (1 << (7 - self.bitlen % 8))
self.bitlen += 1
self.bitlen -= pad
def ubits(self, start, width):
"Extract a (zero-origin) bitfield from the buffer as an unsigned int."
fld = 0
for i in range(start/BITS_PER_BYTE, (start + width + BITS_PER_BYTE - 1) / BITS_PER_BYTE):
for i in range(start // BITS_PER_BYTE,
(start + width + BITS_PER_BYTE - 1) // BITS_PER_BYTE):
fld <<= BITS_PER_BYTE
fld |= self.bits[i]
end = (start + width) % BITS_PER_BYTE
@@ -978,7 +994,7 @@ class BitVector:
return self.bitlen
def __repr__(self):
"Used for dumping binary data."
return str(self.bitlen) + ":" + "".join(map(lambda d: "%02x" % d, self.bits[:(self.bitlen + 7)/8]))
return str(self.bitlen) + ":" + "".join(["%02x" % d for d in self.bits[:(self.bitlen + 7) // 8]])

import sys, exceptions, re

@@ -1014,7 +1030,7 @@ def aivdm_unpack(lc, data, offset, values, instructions):
# The try/catch error here is in case we run off the end
# of a variable-length string field, as in messages 12 and 14
try:
for i in range(inst.width/6):
for i in range(inst.width // 6):
newchar = "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^- !\"#$%&'()*+,-./0123456789:;<=>?"[data.ubits(offset + 6*i, 6)]
if newchar == '@':
break
@@ -1025,7 +1041,7 @@ def aivdm_unpack(lc, data, offset, values, instructions):
value = value.replace("@", " ").rstrip()
elif inst.type == 'raw':
# Note: Doesn't rely on the length.
value = BitVector(data.bits[offset/8:], len(data)-offset)
value = BitVector(data.bits[offset // 8:], len(data)-offset)
values[inst.name] = value
if inst.validator and not inst.validator(value):
raise AISUnpackingException(lc, inst.name, value)
@@ -1086,7 +1102,7 @@ def packet_scanner(source):
raise AISUnpackingException(lc, "checksum", crc)
if csum != crc:
if skiperr:
sys.stderr.write("%d: bad checksum %s, expecting %s: %s\n" % (lc, `crc`, csum, line.strip()))
sys.stderr.write("%d: bad checksum %s, expecting %s: %s\n" % (lc, repr(crc), csum, line.strip()))
well_formed = False
else:
raise AISUnpackingException(lc, "checksum", crc)
@@ -1126,8 +1142,8 @@ def parse_ais_messages(source, scaled=False, skiperr=False, verbose=0):
# Collect some field groups into ISO8601 format
for (offset, template, label, legend, formatter) in field_groups:
segment = cooked[offset:offset+len(template)]
if map(lambda x: x[0], segment) == template:
group = formatter(*map(lambda x: x[1], segment))
if [x[0] for x in segment] == template:
group = formatter(*[x[1] for x in segment])
group = (label, group, 'string', legend, None)
cooked = cooked[:offset]+[group]+cooked[offset+len(template):]
# Apply the postprocessor stage
@@ -1168,9 +1184,9 @@ def parse_ais_messages(source, scaled=False, skiperr=False, verbose=0):
raise KeyboardInterrupt
except GeneratorExit:
raise GeneratorExit
except AISUnpackingException, e:
except AISUnpackingException as e:
if skiperr:
sys.stderr.write("%s: %s\n" % (`e`, raw.strip().split()))
sys.stderr.write("%s: %s\n" % (repr(e), raw.strip().split()))
continue
else:
raise
@@ -1180,7 +1196,7 @@ def parse_ais_messages(source, scaled=False, skiperr=False, verbose=0):
if skiperr:
continue
else:
raise exc_type, exc_value, exc_traceback
reraise_with_traceback(exc_type, exc_value, exc_traceback)

# The rest is just sequencing and report generation.

@@ -1189,9 +1205,9 @@ if __name__ == "__main__":

try:
(options, arguments) = getopt.getopt(sys.argv[1:], "cdhjmqst:vx")
except getopt.GetoptError, msg:
print "ais.py: " + str(msg)
raise SystemExit, 1
except getopt.GetoptError as msg:
print("ais.py: " + str(msg))
raise SystemExit(1)

dsv = False
dump = False
@@ -1220,7 +1236,7 @@ if __name__ == "__main__":
elif switch == '-s': # Report AIS in scaled form
scaled = True
elif switch == '-t': # Filter for a comma-separated list of types
types = map(int, val.split(","))
types = list(map(int, val.split(",")))
elif switch == '-v': # Dump raw packet before JSON or DSV.
verbose += 1
elif switch == '-x': # Skip decoding errors
@@ -1242,9 +1258,9 @@ if __name__ == "__main__":
return '"' + str(x) + '"'
else:
return str(x)
print "{" + ",".join(map(lambda x: '"' + x[0].name + '":' + quotify(x[1]), parsed)) + "}"
print("{" + ",".join(['"' + x[0].name + '":' + quotify(x[1]) for x in parsed]) + "}")
elif dsv:
print "|".join(map(lambda x: str(x[1]), parsed))
print("|".join([str(x[1]) for x in parsed]))
elif histogram:
key = "%02d" % msgtype
frequencies[key] = frequencies.get(key, 0) + 1
@@ -1260,14 +1276,14 @@ if __name__ == "__main__":
frequencies[key] = frequencies.get(key, 0) + 1
elif dump:
for (inst, value) in parsed:
print "%-25s: %s" % (inst.legend, value)
print "%%"
print("%-25s: %s" % (inst.legend, value))
print("%%")
sys.stdout.flush()
if histogram:
keys = frequencies.keys()
keys = list(frequencies.keys())
keys.sort()
for msgtype in keys:
print "%-33s\t%d" % (msgtype, frequencies[msgtype])
print("%-33s\t%d" % (msgtype, frequencies[msgtype]))
except KeyboardInterrupt:
pass
# End

+ 6
- 2
devtools/aivdmtable View File

@@ -4,6 +4,10 @@
#
# This file is Copyright (c) 2010 by the GPSD project
# BSD terms apply: see the file COPYING in the distribution root for details.
#
# This code runs compatibly under Python 2 and 3.x for x >= 2.
# Preserve this property!
from __future__ import absolute_import, print_function, division

sixbits = (
"000000", "000001", "000010", "000011", "000100",
@@ -24,10 +28,10 @@ sixbits = (
def asciiarmor():
print("`--------`-------`---------`-------")
print(" Char ASCII Decimal Bits")
for ch in range(ord('0'), ord('W')+1) + range(ord('`'), ord('w')+1):
for ch in list(range(ord('0'), ord('W')+1)) + list(range(ord('`'), ord('w')+1)):
n = ch - 48
if n >= 40: n -= 8
print '"%s" %3d %3d %s' % (chr(ch), ch, n, sixbits[n])
print('"%s" %3d %3d %s' % (chr(ch), ch, n, sixbits[n]))
print("---------------------------------------")

if __name__ == "__main__":


+ 43
- 35
devtools/cycle_analyzer View File

@@ -52,20 +52,26 @@ device will confuse the NMEA cycle detector, leading to more reports per cycle
than the ideal.

"""
# 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 sys, os, getopt, json

from gps.misc import polystr, isotime

verbose = 0
suppress_regular = False
parse_json = False

class analyze_error:
class analyze_error(BaseException):
def __init__(self, filename, msg):
self.filename = filename
self.msg = msg
def __repr__(self):
return '%s: %s' % (self.filename, self.msg)

class event:
class event(object):
def __init__(self, tag, time=0):
self.tag = tag
self.time = time
@@ -77,7 +83,7 @@ class event:
__repr__ = __str__

def tags(lst):
return map(lambda x: x.tag, lst)
return [x.tag for x in lst]

def extract_from_nmea(filename, lineno, line):
"Extend sequence of tag/timestamp tuples from an NMEA sentence"
@@ -86,7 +92,7 @@ def extract_from_nmea(filename, lineno, line):
"GLL": 5,
"GGA": 1,
"GBS": 1,
"PASHR": 4,
"PASHR": {"POS": 4},
}
fields = line.split(",")
tag = fields[0]
@@ -94,8 +100,11 @@ def extract_from_nmea(filename, lineno, line):
tag = tag[3:]
elif tag[0] == "$":
tag = tag[1:]
if tag in hhmmss:
timestamp = fields[hhmmss[tag]]
field = hhmmss.get(tag)
if isinstance(field, dict):
field = field.get(fields[1])
if field:
timestamp = fields[field]
return [event(tag, timestamp)]
else:
return []
@@ -106,12 +115,12 @@ def extract_from_json(filename, lineno, line):
return []
try:
sentence = json.loads(line)
if u"time" not in sentence:
if "time" not in sentence:
return []
return [event(sentence[u"tag"].encode("iso-8859-1"), "%.2f" % sentence[u"time"])]
except ValueError, e:
print line.rstrip()
print e
return [event(polystr(sentence["class"]), "%.2f" % isotime(sentence["time"]))]
except ValueError as e:
print(line.rstrip(), file=sys.stderr)
print(repr(e), file=sys.stderr)
return []

def extract_timestamped_sentences(fp, json_parse=parse_json):
@@ -119,7 +128,7 @@ def extract_timestamped_sentences(fp, json_parse=parse_json):
sequence = []
lineno = 0
while True:
line = fp.readline()
line = polystr(fp.readline())
if not line:
break
lineno += 1
@@ -140,9 +149,9 @@ def analyze(sequence, name):
if not sequence:
return
if "sequence" in stages:
print "Raw tag/timestamp sequence"
print("Raw tag/timestamp sequence")
for e in sequence:
print e
print(e)
# Then, do cycle detection
events = []
out_of_order = False
@@ -161,9 +170,9 @@ def analyze(sequence, name):
if out_of_order and verbose:
sys.stderr.write("%s: has some timestamps out of order.\n" % name)
if "events" in stages:
print "Event list:"
print("Event list:")
for e in events:
print e
print(e)
# Now group events into bursts
bursts = []
current = []
@@ -174,9 +183,9 @@ def analyze(sequence, name):
else:
current.append(e)
if "bursts" in stages:
print "Burst list:"
print("Burst list:")
for burst in bursts:
print burst
print(burst)
# We need 4 cycles because the first and last might be incomplete.
if tags(events).count("<") < 4:
sys.stderr.write("%s: has fewer than 4 cycles.\n" % name)
@@ -196,7 +205,7 @@ def analyze(sequence, name):
if "trim" in stages:
"After trimming:"
for burst in bursts:
print burst
print(burst)
# Now the actual clique analysis
unequal = False
for i in range(len(bursts)-1):
@@ -208,7 +217,7 @@ def analyze(sequence, name):
# Should know now if cycle is regular
if regular:
if not suppress_regular:
print "%s: has a regular cycle %s." % (name, " ".join(tags(bursts[0])))
print("%s: has a regular cycle %s." % (name, " ".join(tags(bursts[0]))))
else:
# If it was not the case that all cycles matched, then we need
# a minimum of 6 cycles because the first and last might be
@@ -218,16 +227,16 @@ def analyze(sequence, name):
sys.stderr.write("%s: variable-cycle log has has fewer than 6 cycles.\n" % name)
return
if verbose > 0:
print "%s: has a split or variable cycle." % name
print("%s: has a split or variable cycle." % name)
cycle_enders = []
for burst in bursts:
if burst[-1].tag not in cycle_enders:
cycle_enders.append(burst[-1].tag)
if len(cycle_enders) == 1:
if not suppress_regular:
print "%s: has a fixed end-of-cycle sentence %s." % (name, cycle_enders[0])
print("%s: has a fixed end-of-cycle sentence %s." % (name, cycle_enders[0]))
else:
print