2 # -*- coding: utf-8 -*-
4 # Copyright the NTPsec project contributors
6 # SPDX-License-Identifier: BSD-2-Clause
9 usage: ntploggps [-h] [-o] [-l LOGFILE] [-v] [-V]
11 gpsd log file generator
14 -h, --help show this help message and exit
15 -l LOGFILE, --logfile LOGFILE
16 append log data to LOGFILE instead of stdout
17 -o, --once log one line, then exit
18 -w WAIT, --wait WAIT wait WAIT seconds after each log line, default 5
19 -v, --verbose be verbose
20 -V, --version show program's version number and exit
22 See the manual page for details.
25 from __future__
import print_function
29 import logging
.handlers
38 ntploggps: can't find the Python argparse module
39 If your Python version is < 2.7, then manual installation is needed:
40 # pip install argparse
46 except ImportError as e
:
47 sys
.stderr
.write("ntploggps: can't find Python GPSD library.\n")
48 sys
.stderr
.write("%s\n" % e
)
52 class logfile_header_class(logging
.handlers
.TimedRotatingFileHandler
):
53 'A class to modify the file logging handler.'
55 'function to add header to new file on rotation.'
57 super(logfile_header_class
, self
).doRollover()
60 self
.stream
.write('# Time Device TDOP nSat\n')
64 "Create logging object"
65 logFormat
= logging
.Formatter('%(message)s')
66 # Create logger for gpsd
67 Logger
= logging
.getLogger()
68 Logger
.setLevel(logging
.INFO
)
72 file = logfile_header_class(
79 file = logging
.StreamHandler(sys
.stdout
)
81 file.setLevel(logging
.INFO
)
82 # Create the formatter and add it to the handler
83 file.setFormatter(logFormat
)
84 # Add the handler to the logger
85 Logger
.addHandler(file)
89 parser
= argparse
.ArgumentParser(description
="gpsd log file generator",
91 See the manual page for details.
94 parser
.add_argument('-l', '--logfile',
96 help="append log data to LOGFILE instead of stdout",
99 parser
.add_argument('-o', '--once',
102 help="log one line, then exit")
104 parser
.add_argument('-w', '--wait',
107 help="wait WAIT seconds after each log line, default 5",
111 parser
.add_argument('-v', '--verbose',
116 parser
.add_argument('-V', '--version',
118 version
="ntploggps ntpsec-@NTPSEC_VERSION_EXTENDED@")
120 args
= parser
.parse_args()
123 print("ntploggps: arguments:")
129 out
= open(args
.logfile
[0], mode
='a')
130 except io
.UnsupportedOperation
as e
:
131 sys
.stderr
.write("ntploggps: can't open logfile %s\n" % args
.logfile
)
132 sys
.stderr
.write("%s\n" % e
)
136 print("ntploggps: opened log file %s" % args
.logfile
[0])
143 class GpsPoller(threading
.Thread
):
144 running
= False # True when thread is running. Quit when set False
147 threading
.Thread
.__init
__(self
)
149 self
.satellites_used
= None
151 # start the streaming of gps data
153 self
.gpsd
= gps
.gps(mode
=gps
.WATCH_ENABLE
)
154 except BaseException
as e
:
155 sys
.stderr
.write("ntploggps: Can't connect to gpsd, %s\n"
156 " Is gpsd running?\n" % e
)
162 if self
.gpsd
.read() == -1:
165 if not hasattr(self
.gpsd
, "data"):
167 if self
.gpsd
.data
.get("class", None) != "SKY":
169 satellite_list
= self
.gpsd
.data
.get(
172 count_used_satellites
= None
173 if satellite_list
is not None:
174 count_used_satellites
= sum(
175 map(lambda x
: x
.used
, satellite_list
)
177 time_dilution
= self
.gpsd
.data
.get("tdop", None)
178 device_path
= self
.gpsd
.data
.get("device", None)
179 if count_used_satellites
is None:
180 count_used_satellites
= self
.gpsd
.data
.get(
184 count_used_satellites
,
188 self
.satellites_used
= count_used_satellites
189 self
.tdop
= time_dilution
190 self
.device
= device_path
194 "Return the gpsd time fix"
195 t
= self
.gpsd
.fix
.time
196 if isinstance(t
, int):
198 if isinstance(t
, float):
199 if not gps
.isfinite(t
):
202 return gps
.isotime(t
)
205 if __name__
== '__main__':
206 # this is the main thread
208 print("ntploggps: creating poll thread")
210 gpsp
= GpsPoller() # create the thread
212 # Create the logger instance
213 Logger
= logging_setup()
216 Logger
.info("# Time Device TDOP nSat")
218 gpsp
.start() # start it up
221 # It may take a second or two to get good data
224 current_time
= gpsp
.time
227 satellites_used
= gpsp
.satellites_used
229 if current_time
is not None and \
230 device
is not None and \
231 satellites_used
is not None and \
233 if last_time
!= current_time
:
234 s
= '%i %s %f %d' % (current_time
, device
, tdop
,
237 last_time
= current_time
242 except AttributeError as e
:
243 print('parse error\n')
245 # wait a bit before next log
246 time
.sleep(args
.wait
[0])
248 except (KeyboardInterrupt, SystemExit): # when you press ctrl+c
249 args
.once
= True # stop the retry loop
251 print("\nKilling Thread...")
253 # print a blank line to make bash happy
255 except Exception as e
: # any error, signal
258 # tell the thread to die
261 # wait for the thread to finish what it's doing
265 print("ntploggps: Done -- Exiting.")