Skip to content

Instantly share code, notes, and snippets.

@cwells
Created May 19, 2019 20:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cwells/0b7e824bbc7b714688238223fc8d8c1f to your computer and use it in GitHub Desktop.
Save cwells/0b7e824bbc7b714688238223fc8d8c1f to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
SKYHOOK_SDK_KEY = '<your skyhook sdk key>'
SKYHOOK_URL = 'https://global.skyhookwireless.com/wps2/location'
UUID = '<generate using uuidgen>'
import time
import webbrowser
import gi
gi.require_version('NM', '1.0')
from gi.repository import NM, GLib, Gio
from skyhook import Skyhook
main_loop = GLib.MainLoop()
def callback_scan_complete(client, result):
get_location(get_access_points(wireless_device))
main_loop.quit()
def scan_access_points(device):
device.request_scan_async(Gio.Cancellable(), callback_scan_complete)
def get_access_points(device):
def ssid_to_utf8(ap):
ssid = ap.get_ssid()
if not ssid: return ""
return NM.utils_ssid_to_utf8(ap.get_ssid().get_data())
return [
( ap.get_bssid().replace(':', ''), str(ap.get_strength()), ssid_to_utf8(ap) )
for ap in device.get_access_points()
]
def get_location(access_points):
skyhook = Skyhook(SKYHOOK_SDK_KEY, SKYHOOK_URL)
location = skyhook.get_location(UUID, access_points)
if location:
webbrowser.open_new_tab(f"https://maps.google.com/maps?q={location['latitude']},{location['longitude']}")
else:
print("Unable to determine location.")
client = NM.Client.new(None)
connections = [
c.get_uuid()
for c in client.get_connections()
]
wireless_device = [
device
for device in client.get_devices()
if device.get_device_type() == NM.DeviceType.WIFI
and device.get_active_connection().get_uuid()
][0]
scan_access_points(wireless_device)
main_loop.run()
#!/usr/bin/env python3
import requests
from lxml import etree, objectify
class Skyhook:
def __init__(self, skyhook_sdk_key, skyhook_url):
self.skyhook_sdk_key = skyhook_sdk_key
self.skyhook_url = skyhook_url
def __prepare_location_rq_xml(self, device_id, access_points):
if not access_points: return None
root = etree.Element("LocationRQ", xmlns="http://skyhookwireless.com/wps/2005", version="2.21")
root.set("street-address-lookup", "none");
root.set("profiling", "true");
auth_elm = etree.SubElement(root, "authentication", version="2.2")
key_elm = etree.SubElement(auth_elm, "key")
key_elm.set("key", self.skyhook_sdk_key);
key_elm.set("username", device_id);
for ap in access_points:
ap_elm = etree.SubElement(root, "access-point")
mac = etree.SubElement(ap_elm, "mac").text = ap[0]
ssid = etree.SubElement(ap_elm, "ssid").text = ap[2]
signal = etree.SubElement(ap_elm, "signal-strength").text = ap[1]
age = etree.SubElement(ap_elm, "age").text = str(0)
return etree.tostring(root);
def __parse_location_rs_xml(self, loc_rs_xml):
root_rs = objectify.fromstring(loc_rs_xml)
for elm in root_rs.getiterator():
if not hasattr(elm.tag, 'find'):
continue
i = elm.tag.find('}')
if i >= 0:
elm.tag = elm.tag[i + 1:]
objectify.deannotate(root_rs, cleanup_namespaces=True)
coerce = {
'latitude' : float,
'longitude' : float,
'accuracy' : int
}
fix = {}
for elm in root_rs.iter():
fix[elm.tag] = coerce.get(elm.tag, lambda e: e)(elm.text)
if len(fix) < 3:
return None
return fix
def get_location(self, device_id, access_points):
""" Get location of 'device_id' using list of wifi access-points.
device_id: unique id of device
access_points: array of wifi access-points in the following format:
[[mac, rssi, ssid], [mac, rssi, ssid]]
[['001a1ee99745', '-47', 'tp-wpa2'], ['001a1ee99744', '-47', 'tp-wpa']]
returns fix, format: {'latitude': 40.064514, 'longitude': -75.46025, 'accuracy': 136}
"""
if not access_points: return None
try:
ap_data = self.__prepare_location_rq_xml(device_id, access_points)
if not ap_data:
return
response = requests.post(self.skyhook_url, headers={ 'Content-Type': 'text/xml' }, data=ap_data)
return self.__parse_location_rs_xml(response.content)
except Exception as e:
print(e)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment