Story
I knew about Google Latitude from a friend when I bought my HTC mobile. I used it a few times before I updated my ROM to a cooked ROM that has no Google Latitude app installed. The story begins when I noticed by chance that my Google Latitude gadget on iGoogle reflected my location although I had not accessed Google Latitude from my mobile recently. I Googled for geo features of Google Gears and discovered that they are able to give you your location using Wi-Fi towers only. What follows is a discussion about Google Gears geo features and a proposal of how it might work. I developed a tool as a proof-of-concept of how can we use Wi-Fi geo location directly using a simple C# application.
Introduction
The article is divided into two sections. The first section is an investigation and ideas about how Google can get geo location using only local Wi-Fi! The second part is the coding part, in which we make an application that uses Google services to get geo location.
Background
First, try to connect your computer to a wired network - no Wi-Fi - and then try to find your location using Google Latitude. Google will give you "Unknown Location" as it will not be able to locate your location. Switch the very same computer to a Wi-Fi connection and use Google Latitude again. Now the result will be completely different - Google can give you accurate coordinates of your location. That means the location cannot be determined by the IP address only. Using IP, you can know the country, city, and regions in case you know from ISPs how they distribute their IPs geographically.
The second thing I heard about is that BBC has a service that gives you weather information based on your location that it gets from Google Gear. I decided to monitor HTTP traffic using a tool such as Fiddler. I was looking for:
- What data is retrieved from my PC in order to locate my location?
- How does BBC communicate with the Google location service via my PC?
The BBC weather site downloads JavaScript to my PC that locally calls Google Gears, and then Google calculates my location and sends it to the BBC website. The following figure shows this information. As we can see, Google Gears collects all Wi-Fi towers that can be detected from my PC in the following form: { mac_address , signal_strength, SSID}.
This data is sent in JSON format to www.google.com/loc/json and Google replies with my latitude, longitude, and even my own address. The above information that is sent to Google is good enough to roughly locate your position relative to these Wi-Fi towers, but to locate the absolute location, you need to know the absolute location of these Wi-Fi towers!! Again, it is not clear to me how Google knows such information. I made some more investigation and found that in case GSM data is available, this data is also sent together with the Wi-Fi information.
How does Google Gears Geo Location work?
From here, I will try to describe, based on the above info, how Google might use this information to give location information. In the case of GPS, data sent to Google contains:
- GPS data
- GSM towers
- Wi-Fi towers
In the case of a mobile that supports a GPS, it is enough to determine the GSM towers to have accurate info about location. This info is sent to Google as part of the request. But as we can see, this information already contains the geo location, so Google might do the following:
- Calculate you location [latitude and longitude].
- Use Wi-Fi data to calculate your relative position to each Wi-Fi.
- Calculate the absolute position of each Wi-Fi tower based on a and b:
- Mobile absolute location is already known.
- Wi-Fi relative location from the mobile is known.
Now, Google stores the mac_address and the SSID together with the absolute location in a geo database that is kept updated when possible.
In case you open your laptop and connect to Google Latitude, Google can determine your absolute location using the Wi-Fi towers only because it already knows, from other queries from you and different persons, the absolute location of the Wi-Fi towers. As we can see in the following figure, the blue person sends GPS, GSM towers info, and Wi-Fi towers info. Google calculates the Wi-Fi towers info. Now the green person can know his location by querying Google with Wi-Fi towers only.
This is not that easy. We need to think of many challenges such as similar Wi-Fi names, changing mac-addresses, Wi-Fi turning on/off etc.
Let's Make Our Application
The desktop application that I made here is a POC, and is pretty simple. It works in two steps:
- Get Wi-Fi data from PC.
- Send this info to Google and wait for response.
The first part is possible using a useful library to access Wi-Fi information from C#.
Get the Wi-Fi adapter:
Json = @"{ ""host"" : ""Test"",
""radio_type"" : ""unknown"",
""request_address"" : true,
""version"" : ""1.1.0"",
""wifi_towers"" : [ ";
lstWifi.Items.Clear();
WlanClient wLanClient = new NativeWifi.WlanClient();
if (wLanClient.Interfaces.Length == 0)
{
MessageBox.Show("No Wifi Interfaces found.");
return;
}
Wlan.WlanBssEntry[] lstWlanBss = wLanClient.Interfaces[0].GetNetworkBssList();
if (lstWlanBss == null)
{
MessageBox.Show("No networks has been detected.");
return;
}
Enumerate the available Wi-Fi towers and concatenate the JSON string.
System.Text.StringBuilder SB = new StringBuilder();
foreach (var oWlan in lstWlanBss )
{
ListViewItem lstItem = lstWifi.Items.Add(
System.Text.Encoding.UTF8.GetString(oWlan.dot11Ssid.SSID));
lstItem.SubItems.Add(CalculateSignalQuality(oWlan.linkQuality).ToString());
string MAC = ConvertToMAC(oWlan.dot11Bssid);
lstItem.SubItems.Add(MAC);
SB.Append(@"{""mac_address"" :""");
SB.Append(MAC);
SB.Append(@"""");
SB.Append(@", ""signal_strength"" :");
SB.Append(CalculateSignalQuality(oWlan.linkQuality).ToString());
SB.Append(@", ""ssid"" : """);
SB.Append(System.Text.Encoding.UTF8.GetString(oWlan.dot11Ssid.SSID, 0,
(int)oWlan.dot11Ssid.SSIDLength));
SB.Append(@""" },");
}
Json += SB.ToString().Substring(0, SB.Length - 1);
Json += "]}";
textSent.Text = Json;
The second part is to form an HTTP request and parse the response.
HttpWebRequest request =
(HttpWebRequest)HttpWebRequest.Create(@"http://www.google.com/loc/json");
request.ContentType = "application/json; charset=utf-8";
request.Accept = "application/json, text/javascript, */*";
request.Method = "POST";
using (StreamWriter writer = new StreamWriter(request.GetRequestStream()))
{
writer.Write(textSent.Text);
}
WebResponse response = request.GetResponse();
Stream stream = response.GetResponseStream();
string json = "";
using (StreamReader reader = new StreamReader(stream))
{
while (!reader.EndOfStream)
{
json += reader.ReadLine();
}
}
txtResponse.Text = json;
ParseLocation(json);
Points of Interest
If the Wi-Fi section is not working with you if you don't have Wi-Fi, you can still use the application by editing the request text to retrieve different locations.
Disclaimer
The above Google technique is only a guess by me based on simple evidence and logic thinking. This document describes the analytical thinking and how I deduced this technique that could be partially or totally untrue.
Useful Links