Package: ntpdshm
Overviewpython-ntpdshmprovides a Python interface tontpd’sshared memorydriver 28. A single
classNtpdShmexposes the fields of the shared memory structure as attributes that can be read and written.
In addition there are properties to set the clock and receive timestamps from float values. There is also a convenienceupdate()function for setting the time related fields in a single step.python-ntpdshmis implemented usingSwig.python-ntpdshmworks with the following Python versions.Python 2.6Python 2.7Python 3.3Python 3.4Python 3.5PyPy (but not PyPy3!)Exampleimportntpdshmntpd_shm=ntpdshm.NtpdShm(unit=0)The members of the C struct can be accessed by their original names. These havenotbeen converted into PEP-8 compliant names.printntpd_shm.modeprintntpd_shm.clockTimeStampSecprintntpd_shm.clockTimeStampUSecprintntpd_shm.clockTimeStampNSec# only ntpd 4.2.7p303 or later, probably random value otherwiseprintntpd_shm.receiveTimeStampSecprintntpd_shm.receiveTimeStampUSecprintntpd_shm.receiveTimeStampNSec# only ntpd 4.2.7p303 or later, probably random value otherwiseprintntpd_shm.leapprintntpd_shm.precisionprintntpd_shm.validIn addition there are two pseudo properties that combine the second and microsecond attributes into
“float” timestamps. These don’t support nanosecond precision as (as far as I know) it is not possible
to detect whetherntpddoes support nanosecond resolution.printntpd_shm.clockTimeStamp# clockTimeStampSec.clockTimeStampUSecprintntpd_shm.receiveTimeStamp# receiveTimeStampSec.receiveTimeStampUSecThe process to feedntpdan external reference time is shown below.importtimeclock_time=get_clock_time()# `get_clock_time` must be implemented somewhere else and# return a float.recev_time=time.time()ntpd_shm.valid=0# don't use Python booleanntpd_shm.clockTimeStamp=clock_timentpd_shm.receiveTimeStamp=recv_timentpd_shm.precision=-5# 2^-5 = 0.03125 seconds in this casentpd_shm.count+=1ntpd_shm.valid=1As this is somewhat cumbersome, there is a convenience methodupdate()that achieves the same in
a single line. It requires theclock_timeas mandatory argument and accepts several optional
arguments.ntpd_shm.update(clock_time,recv_time=recv_time,precision=-5)# Or simply, if no other fields are to be changed. The receive timestamp is set# automatically.ntpd_shm.update(clock_time)Applications“Off by one second” reference timeA just for fun example of usingpython-ntpdshmis to implement an “off by one second” reference time source forntpd. While this example makes no sense at all for practical purposes it provides a useful template for how it all fits together.First we write the code for the reference clock.importtimeimportntpdshmdefget_clock_time():returntime.time()-1.0# always be exactly one second behind.defmain():ntpd_shm=ntpdshm.NtpdShm(unit=2)ntpd_shm.mode=0# set modentpd_shm.precision=-6# set precision oncentpd_shm.leap=0# how would we know about leap seconds?whileTrue:clock_time=get_clock_time()ntpd_shm.update(clock_time)time.sleep(1.0)if__name__=='__main__':main()Then add the shared memory reference clock tontp.conf:# ntp.conf
...
server 127.127.28.2 noselect     # unit=2, never select this reference
fudge 127.127.28.2 refid PYTH stratum 10Restartntpdand monitor the output ofntpq-pn. The offset should be exactly -1000 msec:$ntpq-pnremote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
...
 127.127.28.2    .PYTH.          10 l    9   16  377    0.000  -1000.0   0.017History0.1.0 (15-Dec-2015)Initial version