Code Repo    |     RSS
MD's Technical Sharing



Wednesday, October 21, 2009

Open Cell-ID database

In my previous post, I have shown you how to use Google Maps API to retrieve your approximate location using information from the currently connected network. In particular, the API requires the Mobile Country Code (MCC), Mobile Network Code (MNC), Location Area Code (LAC), and Cell-ID (CID) to return the approximate location. This works well but requires Internet access to use the Google API and there is no direct access to the cell-id database.

Opencellid - open source cell-id database

Luckily there is an alternative for those interested in the full cell-id database, take a look at opencellid (http://www.opencellid.org/). The project aims to build of a complete world-wide database of cell-id and its associated location information. Users can run the opencellid clients on their phone to submit their location information to the server. The average geocode associated with every cell-id submitted will be calculated and made downloadable here. There are also APIs for developers available to write their own client to access the database.

The data is in CSV text format and includes:
  • mcc, mnc, lac, cellid: the cell-id information from the connected mobile network
  • lon, lat: the average geocode of the above cell-id information.
  • nbsamples: number of samples submitted for the given cell-id. The higher the number of samples, the more accurate the geocode information is
After spending some time converting the cell-id raw data downloaded from opencellid website into a SQL Server 2008 database and using some queries to remove apparently invalid entries (invalid MCC, MNC, LAC or CID), the following statistics are observed as at the time of writing this post:

+ Total apparently valid entries: 570296
+ Total entries for Singapore: 3232. [In Singapore, Singtel alone is estimated to have at least 10 000 cells]
+ Total number of MCCs: 182
+ Top 5 MCCs having the most entries: 262 (Germany, 79725 entries), 234 (UK, 47954 entries), 724 (Brazil, 39343 entries), 310 (USA, 33510 entries), 250 (Russia, 28533 entries)
+ Number of MCCs having fewer than 100 entries: 64
+ Number of MCCs having fewer than 1000 entries: 122
+ Number of MCCs having fewer than 5000 entries: 153

Obviously the database seems incomplete and the accuracy also has to be questioned. However, given the open nature of the project, it is hoped that the database will improve with time, in terms of the number entries and the accuracy, and eventually can be as reliable as Google's location API.
Read More »

Thursday, October 1, 2009

Google Maps API on Windows Mobile

Although Google Maps client for Windows Mobile and the Google Maps API have long been available, there have been few samples to use the Google Maps API on a Windows Mobile phone. This is because Google Maps API is available in Javascipt and meant for websites and its terms of service only allow using the API on websites, and not applications.

Getting Google Maps API to work on Windows Mobile

For a .NET application, possible workarounds (despite violating the TOS) including using the Json.NET library to execute JavaScript from the application and parse the response from google. However, this is not feasible for a Windows Mobile application since there is currently no versions of Json.NET available for the .NET Compact Framework, and porting the library is a difficult task.

Luckily somebody has done some reverse-engineering on the Google Maps API and made available the observations here. The ideas is that, all Google Maps API functions post their request to http://maps.google.com/maps, and if the request format is known, we can directly call the API from our application using HttpWebRequest class, without having to resort to Json.NET library.

Retrieving your approximate location

The original web page has long gone, but luckily web.archive.org keeps a copy of it. Among the samples, the most interesting one features the ability to get your (approximate) location (e.g. longitude and latitude. a.k.a geocode) from the cells that your mobile phone is currently connected to. Precisely, the application needs to provide the Mobile Country Code (MCC, 525 for Singapore), Mobile Network Code (MNC, 01 for Singtel), Location Area Code (LAC), and Cell-ID and the API will return the approximate geocode.

On a Windows Mobile device, the MCC and the MNC can be retrieved either using lineGetCurrentOperator from Telephony API (TAPI) or RIL_GetCellTowerInfo from Radio Interface Layer (RIL). The other 2 parameters (LAC, CID) can only be retrieved via RIL. Notice that since implementations of TAPI and RIL are OEM-dependent, on some phones you can use both API, on other phones you can use one but not the other and some phones will prohibit access to both APIs.

Getting the address of a location

I improved the sample code further by adding the ability to display the address resolved from geocode. The approach is straightforward by passing the geocode to the following Google URL and passing the response:

http://maps.google.com/maps?output=json&f=q&hl=en&q=103,2&ie=UTF8&z=15

where 103 and 2 are the latitude and longitude respectively. The output=json parameter tells Google to return the output in simple text format, which can be read by your code; without it you'll get a full Google Maps web page.

Getting nearby locations and their addresses

When you use Google Maps' My Location feature with no GPS, you'll get a message like "Your location within 300 meteres". The accuracy (e.g. 300 meters in this case) is calculated automatically based on the cells you are connected to, the neighbouring cells and perhaps the phone signal strength. There is no documented algorithm to calculate this, and the above API also does not return this parameter.

To cater for this, you can get a list of nearby locations within x km of the geocode returned by Google by using the following code snippet to query all the neighbouring geocodes:

double longLatInterval = 0.02;
double longLatDelta = 0.005;
double maxDistance = 1; //get all locations within the specified distance, in km
for (double curLong = lon - longLatDelta; curLong < lon + longLatInterval; curLong += longLatDelta)
for (double curLat = lat - longLatDelta; curLat < lat + longLatInterval; curLat += longLatDelta)
{
double dist = distance(curLat, curLong, lat, lon, 'K');

if (dist < maxDistance)
{
//found a possible nearby location
}
}

where (lon, lat) is your current geocode. You can get the function to calculate the distance between 2 geocodes from here.

The full sample source code can be downloaded here. It is an Windows Mobile 6 console application written in C# that simply displays the addresses of nearby locations and then quits.
Read More »