Created
September 17, 2013 19:56
-
-
Save Anton-2/6599694 to your computer and use it in GitHub Desktop.
Hack used in pythonista to read the device geolocation info.
This version adds some error handling, and the ability to control the geo location service options ( see http://diveintohtml5.info/geolocation.html )
The fake http protocol is very crude, it may be a better opttion to use python's BaseHTTPServer.
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
import socket | |
import webbrowser | |
import datetime | |
import json | |
from collections import namedtuple | |
class GeoLocationError(Exception): | |
def __init__(self, code, message): | |
self.code = code | |
self.message = message | |
def __str__(self): | |
return 'code={}, msg={}'.format(self.code, self.message) | |
LocationInfo = namedtuple('LocationInfo', 'longitude latitude accuracy altitude altitudeAccuracy heading speed timestamp') | |
html = """ | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<script> | |
function returnToPythonista() { | |
window.open('pythonista://', '_self', ''); | |
window.setTimeout(function () { | |
window.close(); | |
},0); | |
} | |
var xhr = new XMLHttpRequest(); | |
xhr.addEventListener("loadend", function () { | |
window.setTimeout(returnToPythonista,0); | |
}, false); | |
xhr.open('POST', '/', true); | |
function sendPosition(position) { | |
xhr.send(JSON.stringify([false, position])); | |
} | |
function handleError(positionError) { | |
xhr.send(JSON.stringify([true, positionError])); | |
} | |
options = %s; | |
navigator.geolocation.getCurrentPosition(sendPosition, handleError, options); | |
</script> | |
</head> | |
<body> | |
<h1>Wait...</h1> | |
</body> | |
</html> | |
""" | |
def get_location(port=3050, enableHighAccuracy=False, timeout=5000, maximumAge=0): | |
s = socket.socket() | |
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) | |
s.bind( ('127.0.0.1', port) ) | |
s.listen(1) | |
def send(data): | |
s2, addrinfo = s.accept() | |
resp = s2.recv(2048) | |
body_len = None | |
for line in resp.splitlines(): | |
if line.startswith('Content-Length'): | |
body_len = int(line.split(':')[1]) | |
if body_len is not None: | |
body_start = resp.index('\r\n\r\n')+4 | |
buf = resp[body_start:] | |
resp = buf + s2.recv(body_len-len(buf)) | |
else: | |
resp = '' | |
s2.send("\r\n".join(("HTTP/1.0 200 OK", "Content-Type: text/html", "Content-Length: {}".format(len(data)), "", data))) | |
s2.close() | |
return resp | |
webbrowser.open('safari-http://localhost:{}/'.format(port)) | |
# Send html page on first connection | |
options = dict(enableHighAccuracy=enableHighAccuracy, timeout=timeout, maximumAge=maximumAge) | |
send(html % json.dumps(options)) | |
# Send empty page, we are only interested in POST data | |
data = send("") | |
s.close() | |
error, info = json.loads(data) | |
if error: | |
raise GeoLocationError(**info) | |
timestamp = datetime.datetime.fromtimestamp(info['timestamp']/1000.0) | |
return LocationInfo(timestamp=timestamp, **info['coords']) | |
if __name__ == '__main__': | |
try: | |
loc = get_location(enableHighAccuracy=False) | |
print 'loc: ', loc | |
except GeoLocationError as error: | |
print 'failed: ', error.message |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment