#!/usr/bin/env python class NoGPSError (Exception): pass def get_lat_lon(): # GPSd Python bindings import gps # Create GPS object session = gps.gps() # Set GPS object as an iterator over reports from GPSd session.stream(gps.WATCH_ENABLE|gps.WATCH_NEWSTYLE) # Loop until we get a report with lat and lon. The limit of 5 loops should be more than enough -- my gps never takes more than three when it has a lock i = 0 while (1): try: session.next() lat, lon = session.data['lat'], session.data['lon'] break except: if (i > 5): raise NoGPSError i += 1 return lat, lon def get_geo_string(lat, lon): # Modules for REST/XML request from GeoNames import urllib from xml.etree import ElementTree as ET # Request the name of the nearest geographical feature placename = ET.parse( urllib.urlopen("http://api.geonames.org/findNearby?lat=" + str(lat) + "&lng=" + str(lon) + "&featureClass=T&username=sethjust") ) subdiv = ET.parse( urllib.urlopen("http://api.geonames.org/countrySubdivision?lat=" + str(lat) + "&lng=" + str(lon) + "&username=sethjust") ) # Format and return place, region, country try: country = subdiv.getiterator("countryName")[0].text except: try: country = placename.getiterator("countryName")[0].text except: country = '' try: region = subdiv.getiterator("adminName1")[0].text except: region = '' try: name = placename.getiterator("name")[0].text except: name = '' if country: if region: if name: result = "%s, %s, %s" % (name, region, country) else: result = "%s, %s" % (region, country) else: if name: result = "%s, %s" % (name, country) else: result = country else: result = "unknown" return result # Main program if (__name__ == "__main__"): # Parse command line options from optparse import OptionParser parser = OptionParser("Usage: %prog [options] NAME FILENAME\nNote: NAME should be enclosed in quotes, unless it contains no spaces.") parser.add_option("--no-gps", action="store_true", dest="nogps", default=False, help="don't attempt to get coordinates from GPS") parser.add_option("-a", "--amail", action="store_true", dest="amail", default=False, help="generate files for Apple's Mail.app (.webarchive)") parser.add_option("--lat", action="store", type="float", dest="lat", help="default latitude, if GPS is unavailable") parser.add_option("--lon", action="store", type="float", dest="lon", help="default longitude, if GPS is unavailable") options, args = parser.parse_args() try: assert(len(args) == 2) except AssertionError: print "You must provide NAME FILENAME\n" parser.print_help() exit() try: assert(((options.lat!=None) & (options.lon!=None)) | ((options.lat==None) & (options.lon==None))) except AssertionError: print "You must provide both lat and lon arguments\n" parser.print_help() exit() # Modules for creating signature file import tempfile, os try: if (options.nogps): raise NoGPSError lat, lon = get_lat_lon() print "Got %f, %f from gps" % (lat, lon) except NoGPSError: if (not options.nogps): print "Failed to get coordinates from GPS" try: assert((options.lat!=None) & (options.lon!=None)) except AssertionError: print "No default coordinates provided; exiting" exit() lat, lon = options.lat, options.lon print "Using %f, %f as coordinates" % (lat, lon) geostring = get_geo_string(lat, lon) lac, loc = 'N', 'E' if lat < 0: lat *= -1 lac = 'S' if lon < 0: lon *= -1 loc = 'W' file = tempfile.NamedTemporaryFile() file.write("\n

") file.write(args[0]) file.write("

\n

") file.write("Current meatspace coordinates, hot from the GPS receiver card in my laptop:") file.write("

\n

") file.write("%.3f %s latitude, %.3f %s longitude" % (lat, lac, lon, loc)) file.write("

\n

") file.write("Nearest geographical feature: " + geostring) file.write("

\n") file.write("\n") file.flush() if (options.amail): os.system("textutil -convert webarchive -output " + args[1] + " " + file.name) else: os.system("cp " + file.name + " " + args[1])