Archived:NMEA (GPS) Location Viewer
(New page: Category:S60Category:PythonCategory:Code Examples Good starter code for working with GPS data: Connects to a bluetooth GPS receiver and parses the NMEA sentence, printing the...) |
hamishwillee
(Talk | contribs) m (Hamishwillee - Bot update - Add ArticleMetaData) |
||
| (4 intermediate revisions by 3 users not shown) | |||
| Line 1: | Line 1: | ||
| − | [[ | + | {{ArticleMetaData <!-- v1.2 --> |
| − | + | |sourcecode= <!-- Link to example source code e.g. [[Media:The Code Example ZIP.zip]] --> | |
| + | |installfile= <!-- Link to installation file (e.g. [[Media:The Installation File.sis]]) --> | ||
| + | |devices= <!-- Devices tested against - e.g. ''devices=Nokia 6131 NFC, Nokia C7-00'') --> | ||
| + | |sdk= <!-- SDK(s) built and tested against (e.g. [http://linktosdkdownload/ Qt SDK 1.1.4]) --> | ||
| + | |platform= <!-- Compatible platforms - e.g. Symbian^1 and later, Qt 4.6 and later --> | ||
| + | |devicecompatability= <!-- Compatible devices e.g.: All* (must have internal GPS) --> | ||
| + | |dependencies= <!-- Any other/external dependencies e.g.: Google Maps Api v1.0 --> | ||
| + | |signing= <!-- Signing requirements - empty or one of: Self-Signed, DevCert, Manufacturer --> | ||
| + | |capabilities= <!-- Capabilities required by the article/code example (e.g. Location, NetworkServices. --> | ||
| + | |keywords= <!-- APIs, classes and methods (e.g. QSystemScreenSaver, QList, CBase --> | ||
| + | |language= <!-- Language category code for non-English topics - e.g. Lang-Chinese --> | ||
| + | |translated-by= <!-- [[User:XXXX]] --> | ||
| + | |translated-from-title= <!-- Title only --> | ||
| + | |translated-from-id= <!-- Id of translated revision --> | ||
| + | |review-by= <!-- After re-review: [[User:username]] --> | ||
| + | |review-timestamp= <!-- After re-review: YYYYMMDD --> | ||
| + | |update-by= <!-- After significant update: [[User:username]]--> | ||
| + | |update-timestamp= <!-- After significant update: YYYYMMDD --> | ||
| + | |creationdate= 20070329 | ||
| + | |author= [[User:Cjmartin]] | ||
| + | }} | ||
| + | [[Category:Location]][[Category:PySymbian]] | ||
Good starter code for working with GPS data: | Good starter code for working with GPS data: | ||
| Line 52: | Line 73: | ||
gga_log_fh = open(gga_log_file,'a'); | gga_log_fh = open(gga_log_file,'a'); | ||
| − | # This is set to | + | # This is set to False to request a quit |
| − | going = | + | going = True |
############################################################################# | ############################################################################# | ||
| Line 62: | Line 83: | ||
csum = 0 | csum = 0 | ||
for c in data: | for c in data: | ||
| − | csum = | + | csum ^= ord(c) |
| − | hex_csum = "% | + | hex_csum = "%02X" % csum |
| − | return hex_csum | + | return hex_csum |
# Format a NMEA timestamp into something friendly | # Format a NMEA timestamp into something friendly | ||
| Line 80: | Line 101: | ||
yy = date[4:6] | yy = date[4:6] | ||
yyyy = int(yy) + 2000 | yyyy = int(yy) + 2000 | ||
| − | return "%s %s %d" % (dd, months[ | + | return "%s %s %d" % (dd, months[int(mm)-1], yyyy) |
############################################################################# | ############################################################################# | ||
| Line 87: | Line 108: | ||
"""Read one single line from the socket""" | """Read one single line from the socket""" | ||
line = "" | line = "" | ||
| − | while | + | while True: |
char = sock.recv(1) | char = sock.recv(1) | ||
if not char: break | if not char: break | ||
| Line 97: | Line 118: | ||
"""Function called when the user requests exit""" | """Function called when the user requests exit""" | ||
# TODO Figure out why going in the main thread isn't updated | # TODO Figure out why going in the main thread isn't updated | ||
| − | going = | + | going = False |
appuifw.app.exit_key_handler = None | appuifw.app.exit_key_handler = None | ||
| Line 105: | Line 126: | ||
def get_gga_location(data): | def get_gga_location(data): | ||
d = data.split(',') | d = data.split(',') | ||
| − | + | return { | |
| − | + | 'type': 'GGA', | |
| − | + | 'lat': "%s%s" % (d[1],d[2]), | |
| − | + | 'long': "%s%s" % (d[3],d[4]), | |
| − | + | 'time': format_time(d[0]) | |
| − | + | } | |
# Get the location from a GLL sentence | # Get the location from a GLL sentence | ||
def get_gll_location(data): | def get_gll_location(data): | ||
d = data.split(',') | d = data.split(',') | ||
| − | + | return { | |
| − | + | 'type': 'GLL', | |
| − | + | 'lat': "%s%s" % (d[0],d[1]), | |
| − | + | 'long': "%s%s" % (d[2],d[3]), | |
| − | + | 'time': format_time(d[4]) | |
| − | + | } | |
# Get the location from a RMC sentence | # Get the location from a RMC sentence | ||
def get_rmc_location(data): | def get_rmc_location(data): | ||
d = data.split(',') | d = data.split(',') | ||
| − | + | return { | |
| − | + | 'type': 'RMC', | |
| − | + | 'lat': "%s%s" % (d[2],d[3]), | |
| − | + | 'long': "%s%s" % (d[4],d[5]), | |
| − | + | 'time': format_time(d[0]) | |
| − | + | } | |
############################################################################# | ############################################################################# | ||
| Line 136: | Line 157: | ||
# Loop while active | # Loop while active | ||
appuifw.app.exit_key_handler = exit_key_pressed | appuifw.app.exit_key_handler = exit_key_pressed | ||
| − | while going | + | while going: |
rawdata = readline(sock) | rawdata = readline(sock) | ||
if not rawdata: break | if not rawdata: break | ||
| Line 142: | Line 163: | ||
# Ensure it starts with $GP | # Ensure it starts with $GP | ||
| − | if not data | + | if not data.startswith('$GP'): |
continue | continue | ||
| Line 150: | Line 171: | ||
if data[-3] == '*': | if data[-3] == '*': | ||
exp_checksum = generate_checksum(data[1:-3]) | exp_checksum = generate_checksum(data[1:-3]) | ||
| − | if | + | if exp_checksum != data[-2:]: |
print "Invalid checksum %s, expecting %s" % (data[-2:], exp_checksum) | print "Invalid checksum %s, expecting %s" % (data[-2:], exp_checksum) | ||
continue | continue | ||
| Line 171: | Line 192: | ||
# Log GGA packets periodically | # Log GGA packets periodically | ||
| − | + | gga_log_count += 1 | |
if gga_log_count == gga_log_interval: | if gga_log_count == gga_log_interval: | ||
gga_log_count = 0 | gga_log_count = 0 | ||
gga_log_fh.write(rawdata) | gga_log_fh.write(rawdata) | ||
| − | + | elif sentence_id == 'GLL': | |
location = get_gll_location(sentence_data) | location = get_gll_location(sentence_data) | ||
| − | + | elif sentence_id == 'RMC': | |
location = get_rmc_location(sentence_data) | location = get_rmc_location(sentence_data) | ||
# If we got a location, print it | # If we got a location, print it | ||
| − | if | + | if location != {}: |
# Check the location is valid | # Check the location is valid | ||
if location['lat'] == '0000.0000N' and location['long'] == '0000.0000E': | if location['lat'] == '0000.0000N' and location['long'] == '0000.0000E': | ||
| Line 208: | Line 229: | ||
</code> | </code> | ||
| + | |||
| + | [[Category:Symbian]][[Category:Code Snippet]] | ||
Revision as of 07:03, 27 July 2012
Article Metadata
Good starter code for working with GPS data:
Connects to a bluetooth GPS receiver and parses the NMEA sentence, printing the location to the screen.
From Nick's Code - check there for any updates.
# Basic script to grab the current location from an NMEA bluetooth GPS,
# and log it to the screen
# Also optionally logs periodic location data to a file, so you can see
# where you were
#
# GPL
#
# Nick Burch - v0.01 (15/01/2006)
import appuifw
import socket
# Bluetooth address to connect to
# Change this to your GPS's bluetooth address!
gps_addr='00:15:4B:01:14:EE'
# How many GGA sentences between logging
# Set to 0 to prevent logging
gga_log_interval = 10
gga_log_count = 0
# File to log GGA sentences into
gga_log_file = 'e:\\nmea_gga_log.txt'
# We want icons etc
appuifw.app.screen='normal'
# Define title etc
appuifw.app.title=u"NMEA Location Disp"
# Alert them to the GPS we're going to connect to
appuifw.note(u"Will connect to GPS %s" % gps_addr, 'info')
# Connect to the bluetooth GPS using the serial service
sock=socket.socket(socket.AF_BT, socket.SOCK_STREAM)
target=(gps_addr,1)
sock.connect(target)
appuifw.note(u"Connected to the GPS")
# Open the GGA log file, in append mode
gga_log_fh = open(gga_log_file,'a');
# This is set to False to request a quit
going = True
#############################################################################
# Generate the checksum for some data
# (Checksum is all the data XOR'd, then turned into hex)
def generate_checksum(data):
csum = 0
for c in data:
csum ^= ord(c)
hex_csum = "%02X" % csum
return hex_csum
# Format a NMEA timestamp into something friendly
def format_time(time):
hh = time[0:2]
mm = time[2:4]
ss = time[4:]
return "%s:%s:%s UTC" % (hh,mm,ss)
# Format a NMEA date into something friendly
def format_date(date):
months = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec')
dd = date[0:2]
mm = date[2:4]
yy = date[4:6]
yyyy = int(yy) + 2000
return "%s %s %d" % (dd, months[int(mm)-1], yyyy)
#############################################################################
def readline(sock):
"""Read one single line from the socket"""
line = ""
while True:
char = sock.recv(1)
if not char: break
line += char
if char == "\n": break
return line
def exit_key_pressed():
"""Function called when the user requests exit"""
# TODO Figure out why going in the main thread isn't updated
going = False
appuifw.app.exit_key_handler = None
#############################################################################
# Get the location from a GGA sentence
def get_gga_location(data):
d = data.split(',')
return {
'type': 'GGA',
'lat': "%s%s" % (d[1],d[2]),
'long': "%s%s" % (d[3],d[4]),
'time': format_time(d[0])
}
# Get the location from a GLL sentence
def get_gll_location(data):
d = data.split(',')
return {
'type': 'GLL',
'lat': "%s%s" % (d[0],d[1]),
'long': "%s%s" % (d[2],d[3]),
'time': format_time(d[4])
}
# Get the location from a RMC sentence
def get_rmc_location(data):
d = data.split(',')
return {
'type': 'RMC',
'lat': "%s%s" % (d[2],d[3]),
'long': "%s%s" % (d[4],d[5]),
'time': format_time(d[0])
}
#############################################################################
# Loop while active
appuifw.app.exit_key_handler = exit_key_pressed
while going:
rawdata = readline(sock)
if not rawdata: break
data = rawdata.strip()
# Ensure it starts with $GP
if not data.startswith('$GP'):
continue
# If it has a checksum, ensure that's correct
# (Checksum follows *, and is XOR of everything from
# the $ to the *, exclusive)
if data[-3] == '*':
exp_checksum = generate_checksum(data[1:-3])
if exp_checksum != data[-2:]:
print "Invalid checksum %s, expecting %s" % (data[-2:], exp_checksum)
continue
# Strip the checksum
data = data[:-3]
# Grab the parts of the sentence
talker = data[1:3]
sentence_id = data[3:6]
sentence_data = data[7:]
# The NMEA sentences we're interested in are:
# GGA - Global Positioning System Fix Data
# GLL - Geographic Position
# RMC - GPS Transit Data
location = {}
if sentence_id == 'GGA':
location = get_gga_location(sentence_data)
# Log GGA packets periodically
gga_log_count += 1
if gga_log_count == gga_log_interval:
gga_log_count = 0
gga_log_fh.write(rawdata)
elif sentence_id == 'GLL':
location = get_gll_location(sentence_data)
elif sentence_id == 'RMC':
location = get_rmc_location(sentence_data)
# If we got a location, print it
if location != {}:
# Check the location is valid
if location['lat'] == '0000.0000N' and location['long'] == '0000.0000E':
print "Invalid GPS location found"
else:
print "Source of location is %s" % location['type']
print "Lat is %s" % location['lat']
print "Long is %s" % location['long']
print "Time is %s" % location['time']
print ""
# Future:
# Grab satellites in view from GSV
# Grab satellites in use from GSA
# Grab speed and direction from VTG
# For debugging
#print data
# All done
sock.close()
gga_log_fh.close()
print "All done"
appuifw.app.set_exit()

