I was thinking of building own low stratum NTP server for home. Stratum 0 NTP services are available out of atomic clocks, satellites or via some radio links.
Any GPS module can easily get datetime (UTC) from satellite transmissions along with latitude, longitude (for geo positioning), speed, altitude etc.
To build the project, I bought NEO N8N GPS module for about 1400 INR and a USB UART (CP2102 chip based) for another 150 INR.
GPS modules do receive byte strings, which are essentially NMEA 183 standard sentences. Parsing these sentences can yield you variety of information, such as latitude, longitude, date, time (in UTC), altitude, speed, number visible satellites and so on.
I wrote a small python code to get this data and in future, I will use time data to build a NTP for home. Which I can publish in my DHCP server for DHCP clients (mobiles, laptops etc at home).
In the code you have to mention usb port where UART module is inserted. To find port, use dmesg command as following.
manish@finch:~ $ dmesg
....
....
[311156.396726] usb 1-1.3: new full-speed USB device number 3 using xhci_hcd
[311156.584201] usb 1-1.3: New USB device found, idVendor=10c4, idProduct=ea60, bcdDevice= 1.00
[311156.584223] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[311156.584242] usb 1-1.3: Product: CP2102 USB to UART Bridge Controller
[311156.584259] usb 1-1.3: Manufacturer: Silicon Labs
[311156.584275] usb 1-1.3: SerialNumber: 0001
[311156.953112] usbcore: registered new interface driver usbserial_generic
[311156.954512] usbserial: USB Serial support registered for generic
[311156.984981] usbcore: registered new interface driver cp210x
[311156.985055] usbserial: USB Serial support registered for cp210x
[311156.985182] cp210x 1-1.3:1.0: cp210x converter detected
[311156.991117] usb 1-1.3: cp210x converter now attached to ttyUSB0
....
....
#!/usr/bin/python3
import serial
import datetime
def dec2deg(value):
dec = value/100.00
deg = int(dec)
min = (dec - int(dec))/0.6
position = deg + min
position = "%.7f" %(position)
return position
mapscale = 18
while True:
port="/dev/ttyUSB0"
ser=serial.Serial(port, baudrate=9600, timeout=0.5)
gpsdata=ser.readline()
try:
#print(gpsdata)
gpsdata = gpsdata.decode("utf8")
try:
#print(gpsdata)
gpsdata = gpsdata.split(',')
#print(gpsdata)
if "GNRMC" in gpsdata[0]:
hrs, min, sec = gpsdata[1][0:2], gpsdata[1][2:4], gpsdata[1][4:6]
day, month, year = gpsdata[9][0:2], gpsdata[9][2:4], gpsdata[9][4:6]
datetimeutc = "{}:{}:{} {}/{}/{}".format(hrs, min, sec, day, month, year)
datetimeutc = datetime.datetime.strptime(datetimeutc, '%H:%M:%S %d/%m/%y')
speed = round(float(gpsdata[7])*1.852,2)
message = "Datetime={} ,speed={} kmph".format(datetimeutc, speed)
print(message)
if "GNGGA" in gpsdata[0]:
#print(gpsdata)
lat = dec2deg(float(gpsdata[2]))
lon = dec2deg(float(gpsdata[4]))
alt = gpsdata[9]
satcount = gpsdata[7]
message = "Altitude={}, Satellites={}\n".format(alt, satcount)
gearth = "https://earth.google.com/web/search/@{},{},{}\n".format(lat,lon,alt)
mapsapp = "geo:{},{}\n".format(lat, lon)
map = "https://www.openstreetmap.org/#map={}/{}/{}\n\n".format(mapscale, lat, lon)
print(message, gearth, mapsapp, map)
except:
print("unable to process", gpsdata)
except:
print("unable to decode", gpsdata)
Sample output:
Datetime=2022-02-06 12:25:00 ,speed=1.28 kmph
Altitude=241.6, Satellites=06
https://earth.google.com/web/search/@29.9646572,76.8888248,241.6
geo:29.9646572,76.8888248
https://www.openstreetmap.org/#map=18/29.9646572/76.8888248
Datetime=2022-02-06 12:25:01 ,speed=1.0 kmph
Altitude=242.0, Satellites=06
https://earth.google.com/web/search/@29.9646555,76.8888285,242.0
geo:29.9646555,76.8888285
https://www.openstreetmap.org/#map=18/29.9646555/76.8888285
Datetime=2022-02-06 12:25:02 ,speed=0.09 kmph
Altitude=241.9, Satellites=06
https://earth.google.com/web/search/@29.9646563,76.8888293,241.9
geo:29.9646563,76.8888293
https://www.openstreetmap.org/#map=18/29.9646563/76.8888293
Datetime=2022-02-06 12:25:03 ,speed=0.16 kmph
Altitude=242.0, Satellites=06
https://earth.google.com/web/search/@29.9646567,76.8888295,242.0
geo:29.9646567,76.8888295
https://www.openstreetmap.org/#map=18/29.9646567/76.8888295