Last active
August 21, 2023 08:31
-
-
Save Lauszus/5785023 to your computer and use it in GitHub Desktop.
Python script used to decode GPS data and then generate a html page.Remember to replace the API key with your API key: https://developers.google.com/maps/documentation/javascript/tutorial#api_key.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import serial | |
import time | |
import os | |
import sys | |
from string import Template | |
if os.geteuid() != 0: # Source: https://gist.github.com/davejamesmiller/1965559 | |
os.execvp("sudo", ["sudo"] + sys.argv) | |
ser = serial.Serial('/dev/ttyUSB0',9600,timeout=1) # Open Serial port | |
counter = 0 # Used to generate a html page every 10s | |
in_file = open("maps_template.html", "rt") # Read html template | |
template = in_file.read() | |
in_file.close() | |
def generateHtml(latlng): | |
global template | |
output = Template(template).substitute(lat=latlng[0], lng=latlng[1]) | |
#print(output) | |
out_file = open("html/index.html", "wt") | |
out_file.write(output) | |
out_file.close() | |
def readString(): | |
while 1: | |
while ser.read().decode("utf-8") != '$': # Wait for the begging of the string | |
pass # Do nothing | |
line = ser.readline().decode("utf-8") # Read the entire string | |
return line | |
def getTime(string,format,returnFormat): | |
return time.strftime(returnFormat, time.strptime(string, format)) # Convert date and time to a nice printable format | |
def getLatLng(latString,lngString): | |
lat = latString[:2].lstrip('0') + "." + "%.7s" % str(float(latString[2:])*1.0/60.0).lstrip("0.") | |
lng = lngString[:3].lstrip('0') + "." + "%.7s" % str(float(lngString[3:])*1.0/60.0).lstrip("0.") | |
return lat,lng | |
def printRMC(lines): | |
global counter | |
print("========================================RMC========================================") | |
#print(lines, '\n') | |
print("Fix taken at:", getTime(lines[1]+lines[9], "%H%M%S.%f%d%m%y", "%a %b %d %H:%M:%S %Y"), "UTC") | |
print("Status (A=OK,V=KO):", lines[2]) | |
latlng = getLatLng(lines[3],lines[5]) | |
print("Lat,Long: ", latlng[0], lines[4], ", ", latlng[1], lines[6], sep='') | |
print("Speed (knots):", lines[7]) | |
print("Track angle (deg):", lines[8]) | |
print("Magnetic variation: ", lines[10], end='') | |
if len(lines) == 13: # The returned string will be either 12 or 13 - it will return 13 if NMEA standard used is above 2.3 | |
print(lines[11]) | |
print("Mode (A=Autonomous, D=Differential, E=Estimated, N=Data not valid):", lines[12].partition("*")[0]) | |
else: | |
print(lines[11].partition("*")[0]) | |
counter += 1 | |
if counter == 10: # Generate HTML every 10s | |
counter = 0 | |
generateHtml(latlng) | |
def printGGA(lines): | |
print("========================================GGA========================================") | |
#print(lines, '\n') | |
print("Fix taken at:", getTime(lines[1], "%H%M%S.%f", "%H:%M:%S"), "UTC") | |
latlng = getLatLng(lines[2],lines[4]) | |
print("Lat,Long: ", latlng[0], lines[3], ", ", latlng[1], lines[5], sep='') | |
print("Fix quality (0 = invalid, 1 = fix, 2..8):", lines[6]) | |
print("Satellites:", lines[7].lstrip("0")) | |
print("Horizontal dilution:", lines[8]) | |
print("Altitude: ", lines[9], lines[10],sep="") | |
print("Height of geoid: ", lines[11],lines[12],sep="") | |
print("Time in seconds since last DGPS update:", lines[13]) | |
print("DGPS station ID number:", lines[14].partition("*")[0]) | |
def printGSA(lines): | |
print("========================================GSA========================================") | |
#print(lines, '\n') | |
print("Selection of 2D or 3D fix (A=Auto,M=Manual):", lines[1]) | |
print("3D fix (1=No fix,2=2D fix, 3=3D fix):", lines[2]) | |
print("PRNs of satellites used for fix:", end='') | |
for i in range(0, 12): | |
prn = lines[3+i].lstrip("0") | |
if prn: | |
print(" ", prn, end='') | |
print("\nPDOP", lines[15]) | |
print("HDOP", lines[16]) | |
print("VDOP", lines[17].partition("*")[0]) | |
def printGSV(lines): | |
if lines[2] == '1': # First sentence | |
print("========================================GSV========================================") | |
else: | |
print("===================================================================================") | |
#print(lines, '\n') | |
print("Number of sentences:", lines[1]) | |
print("Sentence:", lines[2]) | |
print("Satellites in view:", lines[3].lstrip("0")) | |
for i in range(0, int(len(lines)/4)-1): | |
print("Satellite PRN:", lines[4+i*4].lstrip("0")) | |
print("Elevation (deg):", lines[5+i*4].lstrip("0")) | |
print("Azimuth (deg):", lines[6+i*4].lstrip("0")) | |
print("SNR (higher is better):", lines[7+i*4].partition("*")[0]) | |
def printGLL(lines): | |
print("========================================GLL========================================") | |
#print(lines, '\n') | |
latlng = getLatLng(lines[1],lines[3]) | |
print("Lat,Long: ", latlng[0], lines[2], ", ", latlng[1], lines[4], sep='') | |
print("Fix taken at:", getTime(lines[5], "%H%M%S.%f", "%H:%M:%S"), "UTC") | |
print("Status (A=OK,V=KO):", lines[6]) | |
if lines[7].partition("*")[0]: # Extra field since NMEA standard 2.3 | |
print("Mode (A=Autonomous, D=Differential, E=Estimated, N=Data not valid):", lines[7].partition("*")[0]) | |
def printVTG(lines): | |
print("========================================VTG========================================") | |
#print(lines, '\n') | |
print("True Track made good (deg):", lines[1], lines[2]) | |
print("Magnetic track made good (deg):", lines[3], lines[4]) | |
print("Ground speed (knots):", lines[5], lines[6]) | |
print("Ground speed (km/h):", lines[7], lines[8].partition("*")[0]) | |
if lines[9].partition("*")[0]: # Extra field since NMEA standard 2.3 | |
print("Mode (A=Autonomous, D=Differential, E=Estimated, N=Data not valid):", lines[9].partition("*")[0]) | |
def checksum(line): | |
checkString = line.partition("*") | |
checksum = 0 | |
for c in checkString[0]: | |
checksum ^= ord(c) | |
try: # Just to make sure | |
inputChecksum = int(checkString[2].rstrip(), 16); | |
except: | |
print("Error in string") | |
return False | |
if checksum == inputChecksum: | |
return True | |
else: | |
print("=====================================================================================") | |
print("===================================Checksum error!===================================") | |
print("=====================================================================================") | |
print(hex(checksum), "!=", hex(inputChecksum)) | |
return False | |
if __name__ == '__main__': | |
while 1: | |
line = readString() | |
lines = line.split(",") | |
if checksum(line): | |
if lines[0][2:] == "RMC": | |
printRMC(lines) | |
pass | |
elif lines[0][2:] == "GGA": | |
printGGA(lines) | |
pass | |
elif lines[0][2:] == "GSA": | |
#printGSA(lines) | |
pass | |
elif lines[0][2:] == "GSV": | |
#printGSV(lines) | |
pass | |
elif lines[0][2:] == "GLL": | |
printGLL(lines) | |
pass | |
elif lines[0][2:] == "VTG": | |
printVTG(lines) | |
pass | |
else: | |
print("\n\nUnknown type:", lines[0], "\n\n") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" /> | |
<style type="text/css"> | |
html { height: 100% } | |
body { height: 100%; margin: 0; padding: 0 } | |
#map-canvas { height: 100% } | |
</style> | |
<script type="text/javascript" | |
src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&sensor=false"> | |
</script> | |
<script type="text/javascript"> | |
function initialize() { | |
var myLatlng = new google.maps.LatLng($lat,$lng); | |
var mapOptions = { | |
center: myLatlng, | |
zoom: 18, | |
mapTypeId: google.maps.MapTypeId.HYBRID | |
}; | |
var map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions); | |
var marker = new google.maps.Marker({ | |
position: myLatlng, | |
map: map, | |
title: '$lat,$lng' | |
}); | |
} | |
google.maps.event.addDomListener(window, 'load', initialize); | |
</script> | |
</head> | |
<body> | |
<div id="map-canvas"/> | |
</body> | |
</html> |
getLatLng() appears to mishandle decimal seconds with leading 0, ex:
lngString="10301.22856"
print(lngString[:3].lstrip('0') + "." + "%.7s" % str(float(lngString[3:])*1.0/60.0).lstrip("0."))
103.20476
actual answer is 103.020476
(The lstrip("0.") is matching twice.)
Affects lat and lng
http://www.hiddenvision.co.uk/ez/?dec_lat=30.03105&dec_lon=-103.020476
So I went this direction:
def getLatLng(latString,lngString):
DD = int(float(latString)/100)
SS = float(latString) - DD * 100
lat = round(DD+SS/60,5)
DD = int(float(lngString)/100)
SS = float(lngString) - DD * 100
lng = round(DD+SS/60,5)
return lat,lng
sorry for not being a pro but I keep getting command not found when hitting run.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
We are trying to run the code and get the following error
lat = latString[:2].lstrip('0') + "." + "%.7s" % str(float(latString[2:])*1.0/60.0).lstrip("0.")
ValueError: could not convert string to float:
Could you help? Thank you