Skip to content

Instantly share code, notes, and snippets.

Last active Apr 19, 2022
What would you like to do?
Python script used to decode GPS data and then generate a html page.Remember to replace the API key with your API key:
#!/usr/bin/env python
import serial
import time
import os
import sys
from string import Template
if os.geteuid() != 0: # Source:
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 =
def generateHtml(latlng):
global template
output = Template(template).substitute(lat=latlng[0], lng=latlng[1])
out_file = open("html/index.html", "wt")
def readString():
while 1:
while"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(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("Mode (A=Autonomous, D=Differential, E=Estimated, N=Data not valid):", lines[12].partition("*")[0])
counter += 1
if counter == 10: # Generate HTML every 10s
counter = 0
def printGGA(lines):
#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(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(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(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(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);
print("Error in string")
return False
if checksum == inputChecksum:
return True
print("===================================Checksum error!===================================")
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":
elif lines[0][2:] == "GGA":
elif lines[0][2:] == "GSA":
elif lines[0][2:] == "GSV":
elif lines[0][2:] == "GLL":
elif lines[0][2:] == "VTG":
print("\n\nUnknown type:", lines[0], "\n\n")
<!DOCTYPE html>
<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% }
<script type="text/javascript"
<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);
<div id="map-canvas"/>
Copy link

tppaz commented Nov 27, 2015

Good day Mr Lauszus! What specific program did you use to run this code?


Copy link

Lauszus commented Jan 18, 2016

@tppaz sorry for the late reply. It is simply a Python script. Please see:

Copy link

petely commented Mar 24, 2018

I downloaded the .ZIP, unpacked it. Changed the serial port to the one my GPS board is connected to and ran it.
Here's what happened:
corv-root: chmod 0755
corv-root: ./
File "./", line 22
output = Template(template).substitute(lat=latlng[0], lng=latlng[1])
IndentationError: unexpected indent

System: LMDE linux

Copy link

trickidicki commented Jul 6, 2019

IndentationError: unexpected indent

The code has mixed tabs and spaces. Line 22 starts with a tab. Do a search-and-replace for the tab character and replace it with the right number of spaces (often 4).

Copy link

Lauszus commented Aug 1, 2019

@trickidicki thanks. It should be fixed now.

Copy link

reddwarfff commented Oct 29, 2019

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

Copy link

rgrokett commented Jul 16, 2021

getLatLng() appears to mishandle decimal seconds with leading 0, ex:
print(lngString[:3].lstrip('0') + "." + "%.7s" % str(float(lngString[3:])*1.0/60.0).lstrip("0."))
actual answer is 103.020476
(The lstrip("0.") is matching twice.)
Affects lat and lng

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

Copy link

Jbono84 commented Apr 19, 2022

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