[Git][NTPsec/ntpsec][master] 2 commits: Add gps-log to log gpsd tdop and nSats. --local-gps to plot it.

Gary E. Miller gitlab at mg.gitlab.com
Sat Sep 24 04:38:00 UTC 2016


Gary E. Miller pushed to branch master at NTPsec / ntpsec


Commits:
b4371828 by Gary E. Miller at 2016-09-23T19:52:35-07:00
Add gps-log to log gpsd tdop and nSats.  --local-gps to plot it.

Not quite done, but working for me. gps-log logs the gpsd data for
tdop and nSats to a file.  If the gpsd file exists then ntpviz
plots the data.

- - - - -
2bd0a3eb by Gary E. Miller at 2016-09-23T21:37:15-07:00
tdop is a bit more stable than I expected.

- - - - -


5 changed files:

- contrib/README
- + contrib/gps-log
- docs/includes/ntpviz-body.txt
- ntpstats/ntpviz
- pylib/statfiles.py


Changes:

=====================================
contrib/README
=====================================
--- a/contrib/README
+++ b/contrib/README
@@ -6,6 +6,9 @@ cpu-temp-log is a tool to use the output of 'sensors -u' and write the
 motherboard temperatures to stdout.  Useful to create a log that can be used
 by 'ntpviz --local-temps'
 
+gps-log is a tool to log gpsd data and write the data to stdout.  Useful
+to create a log that can be used by 'ntpviz --local-gps'
+
 pi-temp-log for the Raspberry Pi.  It is a tool to read a magic /sys file
 to get the CPU temperature and write the temperatures to stdout.  Useful
 to create a log that can be used by 'ntpviz --local-temps'


=====================================
contrib/gps-log
=====================================
--- /dev/null
+++ b/contrib/gps-log
@@ -0,0 +1,59 @@
+#!/usr/bin/env python
+# coding: utf-8
+
+import os
+from gps import *
+import time
+from datetime import datetime
+import threading
+
+gpsd = None #seting the global variable
+
+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
+
+  def run(self):
+    global gpsd
+    while gpsp.running:
+      gpsd.next() # loop and grab each set of gpsd info
+
+if __name__ == '__main__':
+  gpsp = GpsPoller() # create the thread
+  try:
+    gpsp.start() # start it up
+    last_time = 0
+    print("# Time       Device     tdop     nSat")
+    while True:
+      #It may take a second or two to get good data
+      #print gpsd.fix.latitude,', ',gpsd.fix.longitude,'  Time: ',gpsd.utc
+
+      try:
+        if 'nan' != gpsd.fix.time and not isnan(gpsd.fix.time):
+           if last_time != gpsd.fix.time:
+               # new fix, log it.
+               print( '%s %s %f %d' % \
+                  (isotime(gpsd.fix.time),
+                   gpsd.device,
+                   gpsd.tdop,
+                   gpsd.satellites_used)
+                  )
+           last_time = gpsd.fix.time
+      except AttributeError as e:
+          print( 'parse error\n') 
+
+      sys.stdout.flush()
+      time.sleep(5) #set to whatever
+
+  except (KeyboardInterrupt, SystemExit): #when you press ctrl+c
+    print "\nKilling Thread..."
+  except Exception as e:       # any error, signal
+    print( e )
+
+  gpsp.running = False
+  gpsp.join() # wait for the thread to finish what it's doing
+  print "Done.\nExiting."


=====================================
docs/includes/ntpviz-body.txt
=====================================
--- a/docs/includes/ntpviz-body.txt
+++ b/docs/includes/ntpviz-body.txt
@@ -8,8 +8,9 @@
 {ntpviz} [-d statsdir] [-g] [-n name] [-p period]
          [-s starttime] [-e endtime]
          [--local-offset | --local-error | --local-jitter | --local-stability]
-	 [ --all-peer-jitters
+	 [   --all-peer-jitters
 	   | --all-peer-offsets
+	   | --local-gps
 	   | --local-offset-histogram
 	   | --local-offset-multiplot
 	   | --local-temps
@@ -70,6 +71,11 @@ The following plots are available:
 --local-jitter::
    Clock time-jitter plot from the loop statistics (field 5).
 
+--local-gps::
+   Plot GPS Time Dilution of Precision (tdop) and Number of Sats Used
+   (nSats).  This plot is only generated if there is a log file named
+   gpsd in the log file directory.
+
 --local-offset::
    Clock time and clock frequency offsets from the loop statistics
    (fields 3 and 4).


=====================================
ntpstats/ntpviz
=====================================
--- a/ntpstats/ntpviz
+++ b/ntpstats/ntpviz
@@ -10,6 +10,7 @@ Usage: ntpviz [-d statsdir] [-g] [-n name] [-p days]
                 | --peer-offsets=hosts | --all-peer-offsets
                 | --peer-jitters=hosts | --all-peer-jitters
                 | --local-temps
+                | --local-gps
                 | --local-offset-multiplot]
               [-o outdir]
               [-D N]
@@ -190,6 +191,45 @@ plot \\
         plot_template += plot_data
         return plot_template
 
+    def local_gps_gnuplot(self):
+        "Generate GNUPLOT code graphing local gps statistics"
+        sitename = self.sitename
+        gpsmap = self.gpssplit()
+        gpslist = list(gpsmap.keys())
+        gpslist.sort()
+
+        if not len( gpsmap) or not len( gpslist):
+            sys.stderr.write("ntpviz: WARNING: no gps data to graph\n")
+            return ''
+
+        gps_data = ()
+        plot_data = ""
+        for key in gpslist:
+            d = "\n".join(gpsmap[key])
+            plot_data += d + "\ne\n" + d + "\ne\n"
+        # remove trailing "e\n"
+        plot_data = plot_data[:-2]
+
+        plot_template = NTPViz.Common + """\
+set title "%(sitename)s: Local GPS
+set ytics format "%%1.3f tdop" nomirror textcolor rgb '#0060ad'
+set y2tics format "%%2.0f nSat"  nomirror textcolor rgb '#dd181f'
+set style line 1 lc rgb '#0060ad' lt 1 lw 1 pt 7 ps 0   # --- blue
+set style line 2 lc rgb '#dd181f' lt 1 lw 1 pt 5 ps 0   # --- red
+plot \\
+""" % locals()
+
+        for key in gpslist:
+            plot_template += """\
+'-' using 1:3 title '%(key)s tdop' with line, \\
+'-' using 1:4 title '%(key)s nSat' with line axis x1y2, \\
+""" % locals()
+
+        # strip the trailing ", \\n"
+        plot_template = plot_template[:-4] + "\n"
+        plot_template += plot_data
+        return plot_template
+
     def local_error_gnuplot(self):
         "Plot the local clock frequency error."
         if not len( self.loopstats):
@@ -622,6 +662,7 @@ if __name__ == '__main__':
             "all-peer-offsets", "peer-offsets=",
             "all-peer-jitters", "peer-jitters=",
             "local-temps",
+            "local-gps",
             "local-offset-multiplot",
         ])
     except getopt.GetoptError as err:
@@ -633,7 +674,7 @@ if __name__ == '__main__':
     generate = False
     show_local_offset = show_local_error = show_local_jitter = False
     show_local_stability = show_local_offset_histogram = show_temps = False
-    show_local_offset_multiplot = False
+    show_local_offset_multiplot = show_gps = False
     show_peer_offsets = show_peer_jitters = None
     outdir = "ntpgraphs"
     debug_level = 0
@@ -677,6 +718,8 @@ if __name__ == '__main__':
             show_peer_jitters = []
         elif switch == "--local-temps":
             show_temps = True
+        elif switch == "--local-gps":
+            show_gps = True
         elif switch == "--local-offset-multiplot":
             show_local_offset_multiplot = True
     if 0 < debug_level:
@@ -773,6 +816,17 @@ if __name__ == '__main__':
                 sys.stdout.write(plot)
             raise SystemExit(0)
 
+        if show_gps:
+            if not len( stats.gpsd):
+                sys.stderr.write("ntpviz: ERROR: missing gps data\n")
+                raise SystemExit(1)
+            plot = stats.local_gps_gnuplot()
+            if generate:
+                gnuplot(plot)
+            else:
+                sys.stdout.write(plot)
+            raise SystemExit(0)
+
     if show_local_offset_multiplot:
         plot = local_offset_multiplot(statlist)
         if generate:
@@ -835,6 +889,10 @@ frequency.  In other words, how fast it the local clock changes freqency.
 This is field 6 in the loopstats log file.</p>
 <p>Lower is better.  An ideal clock would be a horizontal line at 0ppm.</p>
 """,
+        "local-gps": """\
+<p>Local GPS.  These will be site specific.  It depends on running
+a local gpsd daemon, and logging the data using gps-log.py.</p>
+""",
         "local-jitter": """\
 <p>This shows the jitter of the local clock offset.  In other words,
 how fast the local clock offset is changing.  This is field 5 in the
@@ -1037,6 +1095,7 @@ ntpviz</a>, part of the <a href="https://www.ntpsec.org/">NTPsec project</a>
             ("local-stability", stats.local_offset_stability_gnuplot()),
             ("local-offset-histogram", stats.local_offset_histogram_gnuplot()),
             ("local-temps", stats.local_temps_gnuplot()),
+            ("local-gps", stats.local_gps_gnuplot()),
             ("peer-offsets", stats.peer_offsets_gnuplot()),
         ]
 


=====================================
pylib/statfiles.py
=====================================
--- a/pylib/statfiles.py
+++ b/pylib/statfiles.py
@@ -63,7 +63,7 @@ class NTPStats:
             raise SystemExit(1)
 
         for stem in ("clockstats", "peerstats", "loopstats", "rawstats", \
-                 "temps"):
+                 "temps", "gpsd"):
             lines = []
             try:
                 for logpart in glob.glob(os.path.join(statsdir, stem) + "*"):
@@ -80,14 +80,21 @@ class NTPStats:
                 pass
 
             lines1 = []
-            if stem == "temps":
-                # temps is already in UNIX time
+            if stem == "temps" or stem == "gpsd":
+                # temps and gpsd are already in UNIX time
                 for line in lines:
                     line = line.strip(' \0\r\n\t')
                     if line is not None:
+                        if 0 == len(line):
+                            continue;
                         split = line.split(None, 2)
-                        if int(split[0]) >= starttime and \
-                           int(split[0]) <= endtime:
+                        try:
+                            t = int(float(split[0]))
+                        except:
+                            # ignore comment lines, lines with no time
+                            continue
+
+                        if starttime <= t <= endtime:
                             lines1.append( line)
             else:
                 # Morph first field into Unix time with fractional seconds
@@ -153,6 +160,16 @@ class NTPStats:
             self.peermap[ip].append(line)
         return self.peermap
 
+    def gpssplit(self):
+        "Return a dictionary mapping gps sources to entry subsets."
+        gpsmap = {}
+        for line in self.gpsd:
+            source = line.split()[1]
+            if source not in gpsmap:
+                gpsmap[source] = []
+            gpsmap[source].append(line)
+        return gpsmap
+
     def tempssplit(self):
         "Return a dictionary mapping temperature sources to entry subsets."
         tempsmap = {}



View it on GitLab: https://gitlab.com/NTPsec/ntpsec/compare/d776b0fad5809476e271386d8ddbfdeee4da852e...2bd0a3eb9d49f3ba33ef2a47ef6817d27c96150c
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.ntpsec.org/pipermail/vc/attachments/20160924/0a7b25dc/attachment.html>


More information about the vc mailing list