Subversion Repositories GPS

[/] [gpstime/] [gpstime.py] - Rev 2

Compare with Previous | Blame | View Log

# Script to set the Series 60 phone's time from the GPS time, received
#  from a GPS Bluetooth receiver.  Because Python for Series 60 doesn't
#  allow access to the current time zone setting, and because the value
#  returned by the gmtime() function is off by one hour if DST is set,
#  we have to do some groovy stick handling to convert the GMT/UTC value
#  returned by the GPS to the proper local time.  I welcome suggestions
#  for better ways of doing this.
#
# GPL
#
# Significant assistance and much of the code taken from "S60 Python NMEA Location Viewer" by
# Nick Burch - http://gagravarr.org/code/show_nmea_location.py
#
# Peter Rukavina - Version 0.02 - July 14, 2006
 
import appuifw
import socket
import e32
import time
 
# Bluetooth address to connect to
# Change this to your GPS's bluetooth address!
#   On a Mac OS X machine you can see this under System Preferences | Bluetooth | Devices
#   but you'll have to translate the dashes on the Mac to colons for this script.
gps_addr='00:0B:0D:16:D1:BD'
 
# We want icons etc
appuifw.app.screen='normal'
 
# Define title etc
appuifw.app.title=u"GPS Time"
 
# 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")
 
# This is set to 0 to request a quit
going = 1
 
#############################################################################
 
# 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 = csum ^ ord(c)
	hex_csum = "%02x" % csum
	return hex_csum.upper()
 
# Turn an NMEA timestamp, along with today's date, into an Epoch time number
def format_time(gpstime):
	import time
	hh = int(gpstime[0:2])
	mm = int(gpstime[2:4])
	ss = int(gpstime[4:6])
	now = time.gmtime()
	yyyy = int(now[0])
	MM = int(now[1])
	dd = int(now[2])
	timetuple = (yyyy,MM,dd,hh,mm,ss,0,0,0)
	return timetuple
 
#############################################################################
 
def readline(sock):
	"""Read one single line from the socket"""
	line = ""
	while 1:
		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 = 0
	appuifw.app.exit_key_handler = None
 
#############################################################################
 
# Get the location from a GGA sentence
def get_gga_location(data):
	d = data.split(',')
	ret = {}
	ret['type'] = 'GGA'
	ret['lat'] = "%s%s" % (d[1],d[2])
	ret['long'] = "%s%s" % (d[3],d[4])
	ret['time'] = format_time(d[0])
	return ret
 
# Get the location from a GLL sentence
def get_gll_location(data):
	d = data.split(',')
	ret = {}
	ret['type'] = 'GLL'
	ret['lat'] = "%s%s" % (d[0],d[1])
	ret['long'] = "%s%s" % (d[2],d[3])
	ret['time'] = format_time(d[4])
	return ret
 
# Get the location from a RMC sentence
def get_rmc_location(data):
	d = data.split(',')
	ret = {}
	ret['type'] = 'RMC'
	ret['lat'] = "%s%s" % (d[2],d[3])
	ret['long'] = "%s%s" % (d[4],d[5])
	ret['time'] = format_time(d[0])
	return ret
 
# Calculate the difference between local time and GMT
def calculate_time_diff(utctime):
	import time
	ltime = time.localtime()
	gtime = time.gmtime()
	# Same day both local and GMT
	if (gtime[2] == ltime[2]):
		timediff = ltime[3] - gtime[3]
	# GMT is a day ahead
	elif (gtime[2] > ltime[2]):
		timediff = ltime[3] - (gtime[3] + 12)
	# GMT is a day behind
	else:
		timediff = (ltime[3] + 12) - gtime[3]
 
	utchour = utctime[3]
	gmhour = gtime[3]
 
	# If the value returned by gmtime() is greater than the UTC hour, we know we're in DST and
	# that we thus need to add an hour to the setting of the local time.
	if (gmhour > utchour):
		dst = 1
	else:
		dst = 0
 
	lhour = utchour + timediff
 
	if (dst == 1):
		lhour = lhour + 1
 
	timetuple = (utctime[0],utctime[1],utctime[2],lhour,utctime[4],utctime[5],0,0,0)
	return time.mktime(timetuple)
 
#############################################################################
 
# Loop while active
appuifw.app.exit_key_handler = exit_key_pressed
while going == 1:
	rawdata = readline(sock)
	if not rawdata: break
	data = rawdata.strip()
 
	# Ensure it starts with $GP
	if not data[0:3] == '$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 not 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)
	if sentence_id == 'GLL':
		location = get_gll_location(sentence_data)
	if sentence_id == 'RMC':
		location = get_rmc_location(sentence_data)
 
	# If we got a location, print it
	if not location == {}:
		# Check the location is valid
		if location['lat'] == '0000.0000N' and location['long'] == '0000.0000E':
			print "Invalid GPS location found"
		else:
			newtime = calculate_time_diff(location['time'])
			e32.set_home_time(newtime)
			appuifw.note(u"Set time to %s" % time.asctime(), 'info')
			going = 0
		print ""
 
	# For debugging
	#print data
 
# All done
sock.close()
 
appuifw.app.set_exit()
 

Compare with Previous | Blame | View Log