[PYTHON] Geolocation on Intel Edison

Edison sensor

Since Edison does not have a sensor, it is not possible to pick up information from the outside world without attaching various sensors externally. ・ ・ Can't you pick it up?

** You can get Wifi information! !! ** **

Geolocation

Geolocation is the estimation of the position on the map. GPS is famous. GPS is a technology that estimates the position by the general theory of relativity based on the time information sent from geostationary satellites that are orbiting far around the earth. But this time it doesn't matter. The target this time is information on Wifi access points (APs) scattered around the world. Many APs continue to emit radio waves at one point without being moved too much. Since the radio waves used in Wifi etc. have high frequencies, they are quickly attenuated and do not fly too far. In addition, it is known that the strength of radio waves attenuates with distance. Looking at the nature of this area, some people thought that the position of the received device on the map could be specified by the strength of the Wifi signal. And Google has done that on a global scale. And how, we can also use the API. That is Google Map Geolocation API. If you send the surrounding AP information consolidated in JSON to the API URL, the estimated position information will be returned immediately.

code

Please register as a developer with Google and obtain the API key of Google Map. This is the GAPI_KEY in the code below. It seems that it can be used free of charge within 1000 requests / day and 1 request / second. Of the following code. Where it is ELI_MAC, enter the MAC address of the AP to be excluded from the position estimation. In my case, I put the MAC address of the tethering mobile phone used for Edison's communication.

geo.py


#!/usr/bin/env python
# -*- coding: utf-8 -*-

import commands, datetime, time
import re
import json, requests

GAPI_KEY = "fa1iuEe32hw4iusiWKgrwFEheERfieunGeWW"
ELI_MAC = ["12:34:56:78:9A:BC"]

re_mac = re.compile("\s+Cell \d{2} - Address: (\w{2}:\w{2}:\w{2}:\w{2}:\w{2}:\w{2})")
re_ch = re.compile("\s+Channel:(\d+)")
re_freq = re.compile("\s+Frequency:(\S+) GHz")
re_qual = re.compile("\s+Quality=(\S+)  Signal level=(\S+) dBm")
re_essid = re.compile("\s+ESSID:\"([^\"]+)\"")

class AP:
	def __init__(self, _mac, _channel, _frequency, _quality, _signal, _essid=""):
		self.mac = _mac
		self.channel = _channel
		self.frequency = _frequency
		self.quality = _quality
		self.signal = _signal
		self.essid = _essid
		self.time = datetime.datetime.now()
	def show(self):
		print("%s, %s, %s, %s, %s, %s" % (self.essid, self.mac, self.channel, self.frequency, self.quality, self.signal))
	def getVal(self):
		t = datetime.datetime.now() - self.time
		age = t.seconds * 1000 + t.microseconds / 1000
		return {"macAddress":self.mac, "signalStrength":self.signal, "age":age, "channel":self.channel}

def getAPList():
	aplist = []
	res = commands.getoutput("/sbin/iwlist wlan0 scan")

	essid = ""
	mac = ""
	channel = ""
	frequency = ""
	quality = ""
	signal = ""

	for t in res.splitlines():
		m = re_mac.match(t)
		if m:
			mac = m.group(1)
			continue
		m = re_ch.match(t)
		if m:
			channel = m.group(1)
			continue
		m = re_freq.match(t)
		if m:
			frequency = m.group(1)
			continue
		m = re_qual.match(t)
		if m:
			quality = m.group(1)
			signal = m.group(2)

			if mac not in ELI_MAC:
				aplist.append(AP(mac, channel, frequency, quality, signal, essid))

			continue
		m = re_essid.match(t)
		if m:
			essid = m.group(1)
			continue
	
	return aplist

def getLocationFromWifi(wifilist):
	url = "https://www.googleapis.com/geolocation/v1/geolocate?key=%s" % GAPI_KEY
	headers = {"Content-Type": "application/json"}
	data = json.dumps({"wifiAccessPoints":wifilist})

	r = requests.post(url, data=data, headers=headers)
	geo = r.json()

	return {"Latitude":geo['location']['lat'], "Longitude":geo['location']['lng'], "Accuracy":geo['accuracy']}



if __name__ == '__main__':
	aps = {}

	while True:
		naps = getAPList()

		lapsk = aps.keys()
		napsk = []

		# add new APs to AP list.
		for ap in naps:
			if ap.mac not in lapsk:
				aps[ap.mac] = ap
			# make new AP names list
			napsk.append(ap.mac)

		# search missed APs to delete from AP list
		for ap in lapsk:
			if ap not in napsk:
				aps.pop(ap)

		loc = getLocationFromWifi([d.getVal() for d in aps.values()])

		print("Latitude: %f, Longitude: %f, Accuracy; %f" % (loc['Latitude'], loc['Longitude'], loc['Accuracy']))
		print("https://www.google.co.jp/maps/@%s,%s,21z?hl=ja" % (loc["Latitude"], loc["Longitude"]))

		time.sleep(30)

Execute this code with administrator privileges. When I ran it at home with the intention of testing it, I was a little scared because it was identified at a level that I might even know the room number.

Experiment

The results of position estimation when moving between Akihabara and Ochanomizu on foot are shown below. The red dot is the estimated position. In this experiment, in order to avoid the time limit of the API, only the AP information was acquired, and the position estimation was performed after returning home. Wifi位置推定

The GPS data when walking while collecting Wifi information around the area with Edison is as follows. Again, the accuracy is not so good, so it is for reference only. Wifi位置推定

Consideration

I laugh at the place where the red dot suddenly appears in front of Ochanomizu station, but there are also places where I am surprised to estimate the position. If you filter at a common sense movement speed, or?

Yeah. I chose Akihabara as the experimental site because I thought there would be a large number of sample Wifi APs. Depending on the location, I could see nearly 60 APs, which was more than I expected.

Summary

Recommended Posts

Geolocation on Intel Edison
Startup Intel Edison
Push notification to Intel Edison
Debian Intel Edison and put scikit-learn
Infrared remote control reception with Intel Edison