Содержание статьи
Тысячи лет назад о такой штуке, как GPS, никто не мог даже мечтать. Но моряки
и путешественники отлично справлялись с навигацией, используя компас и карты,
солнце и звезды. Сейчас – век цифровой, но тоже есть немало способов определить
месторасположение без всяких там систем глобального позиционирования.
Спору нет, GPS - классная штука, но что делать, если приемника под рукой нет?
Далеко не у каждого есть встроенный чип в мобиле. Да и владелец автомобиля
совсем не обязательно успел обзавестись устройством навигации. Так как же быть?
Если не брать в расчет редкие и экзотические варианты, то основных способа три:
- Определить IP и с помощью специальной базы данных определить город, в
котором находишься, и нередко - долготу и широту. - Определить расположение по находящимся рядом базовым станциям GSM/UMTS.
Это возможно при наличии базы данных с идентификаторами вышек и их
координатами. - Использовать для вычисления широты и долготы информацию о находящихся
рядом точках доступа Wi-Fi, передав запрос с их характеристиками на
специальный сервер.
Итак, начнем с самого простого.
IP нам в помощь
Когда мне нужно проверить свой внешний IP, чтобы убедиться, например, что я
включил VPN или прокси, я всегда использую сервис
ip2location.com.
Приятно, что помимо самого IP-адреса выводится информация о провайдере, его
месторасположении (город, страна, штат), а зачастую… еще и координаты. Само
собой, в базе не будут указаны широта и долгота для самого обычного клиента
интернет-услуг. Как правило, данные указываются для провайдера, реже - для
крупных компаний, имеющих большие диапазоны статических IP. Получается, что,
подключившись к сети (например, через любой открытый hotspot или просто
воспользовавшись компьютером), можно с большой долей вероятности определить
примерное место, где ты находишься. Конечно, способ примитивный - и более того,
самый неточный из всех представленных в этой статье. С другой стороны, это
реальный шанс определить месторасположение, всего лишь открыв страничку в
интернете. А если сварганить специальный трекер, установить его на КПК и
отслеживать IP-шники, которые он получает при коннекте к открытым WiFi-сетям, то
реально вычислить передвижения девайса.
Использовать сервис в чистом виде, а именно – переходя браузером по ссылке
ip2location.com, скучно
и беспонтово. Месторасположение на карте не увидеть, лог не сохранить, а сама
страница слишком тяжелая для мобильного инета - короче, это не наш путь. От
сервиса нам нужно только одно - база соответствий разных IP-адресов их
расположению, которую ip2location предлагает приобрести за довольно разумные
деньги. Само собой, подобные базы быстро расплываются по варезным порталам и
торрентам, причем в двух вариантах: .cvs (текстовом) и .bin (бинарном). С такой
базой несложно заточить любое приложение под себя. Правда, IP-адрес в базе
хранится в специальном цифровом виде без точек и разделения на октеты, но
следующая PHP-функция поможет привести обычный IP-шник к нужному виду:
function Dot2LongIP ($IPaddr)
{
if ($IPaddr == "") {
return 0;
} else {
$ips = split ("\.", "$IPaddr");
return ($ips[3] + $ips[2] * 256 + $ips[1] * 256 * 256 + $ips[0] * 256 * 256 *
256);
}
}
Имея такой ключ для адреса, ничего не стоит найти соответствующие ему
координаты в текстовой базе. Если же в распоряжении будет база в BIN-формате, то
задача еще проще. Для Perl, C, Python, PHP, Ruby, C#, VB.NET, Java, Visual Basic
сервисом подготовлены готовые модули (http://www.ip2location.com/developers.aspx),
которые легко использовать в своем проекте. В случае с PHP достаточно закинуть
на сайт модуль IP2Location.inc.php и создать несложный скриптик:
<?php
include("IP2Location.inc.php");
$ip = IP2Location_open("samples/IP-COUNTRY-SAMPLE.BIN", IP2LOCATION_STANDARD);
$record = IP2Location_get_all($ip, "_IP-АДРЕС_");
echo "$record->country_long : " . $record->country_long;
echo "$record->city : " . $record->city;
echo "$record->isp : " . $record->isp;
echo "$record->latitude : " . $record->latitude;
echo "$record->longitude : " . $record->longitude;
IP2Location_close($ip);
?>
Можно просто вывести на экран, залогировать или отобразить на карте с помощью
Google Maps, передав широту и долготу в качестве параметра:
http://maps.google.com/maps?f=l&hl=en&q='+query+'&near='+str(lat)+','+str(lng)+'&ie=UTF8&z=12&om=1
Используем мобильные вышки!
Старая байка о том, что спецслужбы могут найти человека по сигналу от его
мобильника - один из тех случаях, когда на самом деле все так и есть. Да чего
там спецслужбы, если на это способна даже совершенно бесплатная программа Google
Maps (www.google.com/gmm).
По сути, это удобная оболочка для доступа к одноименному веб-сервису,
позволяющему смотреть фотографии местности со спутника, рельеф и – во многих
случаях – карты с возможностью проложить маршруты. Думаю, рассмотреть крышу
своего дома через maps.google.com пробовали все. Работать с таким сайтом через
браузер на мобильном телефоне (даже если это сверхскоростная Opera Mini) крайне
сложно, поэтому в Google, подсуетившись, сделали удобную оболочку для просмотра
карт. Оформили ее в виде приложения для самых разных платформ – от обычных
мобильных, поддерживающих Java, до смартфонов и коммуникаторов на Windows Mobile
и Symbian S60 3rd Edition, престижных BlackBerry, а теперь еще и Android, к
которой мы пока не привыкли, но очень скоро будем воспринимать как одну из
основных платформ для телефона. В том же iPhone Google Maps встроена по
умолчанию. Так вот, помимо удобного просмотра этих самых карт и спутниковых
снимков, у утилиты есть одна замечательная кнопка «Мое месторасположение». Один
клик - и на карте отмечается нахождение телефона. Да, для владельцев трубок с
GPS это сущая ерунда: нашли чем удивить! Но надо видеть лица тех пользователей,
которые видят на экране свое месторасположение, хотя никаких навигационных
приблуд у них не было и в помине! Впрочем, это только так кажется.
Телефонная трубка всегда находится в зоне действия, по меньшей мере, одной
базовой станции сотовой сети. Ну, или не находится - но в этом случае от нее
толку не более чем от кирпичика. Любая из базовых станций имеет некоторый набор
параметров, которые получает телефон - благодаря этому каждую БС можно
распознать. Один из таких параметров – CellID (сокращенно CID) - уникальный
номер для каждой соты, выданный оператором. Зная его, ты можешь распознать
базовую станцию, а зная расположение базовой станции, можешь, понять где
находишься. Точность варьируется от нескольких сотен метров и до нескольких
километров, но это неплохая отправная точка, чтобы разобраться с координатами.
Получается, имея в наличии табличку, где в соответствии с каждой базовой
станцией будет сопоставлены ее координаты, можно примерно вычислить положение
абонента. А раз Google Maps может так лихо определять месторасположение
человека, то у него такая база данных есть. Но откуда? Расположение базовых
станцией различных операторов – пускай и не секретная, но вряд ли открытая
информация. Даже учитывая масштабность проектов Гугла, с трудом можно поверить,
что тот договорился со всеми операторами сотовой связи - определение
местоположения работает в любом месте (забегая вперед, скажу, что правильнее
говорить «может работать в любом месте»). Ответ скрывается в лицензионном
соглашении во время установки программы, на который мы, конечно же, забили и
сразу нажали «Я согласен» :). А ведь там черным по белому написано, что,
принимая соглашение, мы разрешаем программе анонимно передавать на сервер
информацию о текущем расположении и информации о сотовых вышках поблизости. Да!
Базу данных с примерными координатами базовых станций составляют для Google сами
пользователи Google Maps, имеющие на борту своих телефонов и коммуникаторов
встроенный приемник GPS. И что самое классное: даже при полном отказе от
использования как официальных, так и неофициальных (собранных энтузиастами с
помощью специальных сканнеров - подробнее читай во врезке) баз с расположением
станций, функция для определения месторасположения работает на «ура». Проверь
сам.
GSM-навигация своими руками
Возможность посмотреть в программе свое расположение - само по себе здорово,
но разве ж можно отказаться от соблазна использовать базы Google'а в корыстных
целях? Как тебе, например, идея создать собственный трекер, который определял бы
текущее расположение БС и передавал его на наш сервер? Эдакий жучок средствами
самого телефона, который работает везде и всегда!
Компания не разглашает протокол взаимодействия Google Maps, не публикуя API,
однако его легко вскрыли, просто проснифав трафик и реверснув часть кода. Помимо
http-запросов на загрузку карт, отчетливо видно, что программа отправляет
запросы по адресу
http://www.google.com/glm/mmap, причем именно тогда, когда пользователь
желает получить текущее месторасположение. Вот и попался наш скриптик – в
качестве параметров ему передаются технические значения базовой станции: MCC,
MNC, LAC и CellID.
MCC - код страны (для России - 250)
MNC - код сети (МТС - 01, Мегафон - 02, Билайн - 99 и т.п.)
LAC - код локальной зоны (другими словами, совокупности базовых станций,
обслуживаемых одним контроллером)
CellID (CID) - идентификатор, состоит из номеров базовой станции и сектора
Зная, куда посылать данные, осталось эти значения получить! Наиболее простой
способ - прямо в программе Google Maps перейти в «Справку», там щелкнуть «Общие
сведения», и в самом конце этой странички будет строка с параметрами в формате
myl:MCC:MNC:LAC:CellID. Куда больший простор для деятельности предоставляют
специальные программы netmonitor'ы: с их помощью можно логировать параметры при
переключении от одной станции к другой, извлекать параметры «соседей»
(находящихся в поле зрения других БС), да и просто получать куда более подробную
информацию. Для каждой платформы есть свои реализации нетмониторов с различными
возможностями - ты можешь выбрать программу под себя.
Теперь, когда все необходимые параметры получены, можно обратиться на сервер
и попробовать получить ответ. Приведу для этого несложный скрипт на Python'е,
который написал наш соотечественник Skvo и опубликовал на форуме
forum.netmonitor.ru:
net, cid, lac = 25002, 9164, 4000
import urllib
a = '000E00000000000000000000000000001B0000000000000000000000030000'
b = hex(cid)[2:].zfill(8) + hex(lac)[2:].zfill(8)
c = hex(divmod(net,100)[1])[2:].zfill(8) + hex(divmod(net,100)[0])[2:].zfill(8)
string = (a + b + c + 'FFFFFFFF00000000').decode('hex')
try:
data = urllib.urlopen('http://www.google.com/glm/mmap',string)
r = data.read().encode('hex')
if len(r) > 14:
print float(int(r[14:22],16))/1000000, float(int(r[22:30],16))/1000000
else:
print 'no data in google'
except:
print 'connect error'
Для запуска, естественно, потребуется интерпретатор Python'а (обязательно 2-й
ветки, потому как на 3-й не запустится), который можно скачать с сайта
http://python.org/download/releases. В первой строке скрипта, как несложно
догадаться, необходимо подставить NET (MCC и MNC, написанные слитно), CID, LAC.
В результате скрипт сформирует запрос на сервер http://www.google.com/glm/mmap и
отправит его. Если базовая станция с этими параметрами есть в базе, то на экран
выведутся координаты, например, «59.200274 39.836925». В противном случае скрипт
выдаст ошибку: «no data in google». Любителям программировать не составит труда
добавить пару строчек, например, по указанным NET и LAC перебрать все варианты
CID (от 1 до 65536), и, посмотрев, какие сектора имеются у Гугла, узнать их
примерные координаты. Если тебе неохота морочить голову скриптами, на наш диск
мы выложили GUI-программу, написанную на C# (исходники прилагаются). В этом
случае ты автоматически получишь еще и ссылку, отображающую координаты на сайте
Google Maps. Ссылки на реализации на других языках смотри в боковом выносе.
Интересно, что на сервер передаются всего лишь три параметра, причем
ключевыми являются только значения LAC и CellID. А MCC/MNC необходимы на тот
случай, если в базе есть несколько пар с одинаковыми LAC, CellID. При этом
телефон может получать намного больше информации о текущей станции – взять хотя
бы мощность сигнала, однако эти параметры в расчетах не используются. Получается
крайне простой алгоритм. Один сектор - одна координата, независимо от того,
находится ли пользователь в 100 метрах от базовой станции или в километре от
нее, координата будет одинаковая!
Отдельно хочу сказать, что замечательный проект «Яндекс.Карты», который я
особенно люблю за возможность отображения точек, имеет точно такой же
функционал. И ровно так же, как и Google, предоставляет своей программе данные о
точке по запросу с указанием Cell ID, LAC, NET параметров:
http://mobile.maps.yandex.net/cellid_location/?&cellid=%d&operatorid=%d&countrycode=%d&lac=%d
Единственное отличие в том, что ответ сервис «Яндекса» возвращает в
XML-формате, который легко и удобно парсится для извлечения любых параметров.
О базовых станциях сотовых сетей
В статье я упоминал о неофициальных базах данных с расположением вышек
различных сотовых сетей. В интернете существует немало проектов, где
энтузиасты делятся собранной нетмониторами информацией. Из иностранных это –
celldb.org/aboutapi.php,
www.opencellid.org/api,
gsmloc.org/code,
cellid.telin.nl. Каждый
из них имеет простой API для получения координат с помощью обычного
HTTP-запроса, при этом в качестве параметров указываются традиционные MCC,
MNC, Cell ID и LAC.Отдельно хочу упомянуть наш русский проект Netmonitor.ru, в котором собрана
инфа о большом количества БС Мегафона, МТС, Билайна, ТЕЛЕ2 и даже Skylink. К
тому же, на сайте располагается еще и крупнейший форум для исследователей
сотовых сетей.
Как заставить работать навигационные программы
Какой бы замечательной ни была программа Google Maps, использовать ее в
качестве навигационного инструмента, мягко говоря, затруднительно. Было бы
здорово, пускай и примерные, но все-таки координаты скормить нормальной
программе навигации, с хорошими картами, подробной адресацией и проработанными
алгоритмами прокладки маршрута. Некоторые программы, например, «Навител» и
«Автоспутник» имеют еще один плюс: они умеют подгружать информацию о пробках и
учитывать ее при составлении маршрута. Чисто теоретически, ничего не стоит
написать подобное приложение самому. Алгоритм прост:
- Получаем текущие координаты при каждой смене базовой станции;
- Отправляя запрос на спутник, получаем примерные координаты;
- Эмулируем в системе последовательный порт и в простом формате NMEA,
который используют GPS-навигаторы, транслируем туда текущие координаты.
Именно этот принцип лежит в программе VirtualGPS (www.kamlex.com),
предназначенной для устройств на платформе Windows Mobile 2003, WM 5, WM 6, WM
6.1. Бесплатная lite версия программы определяет текущее расположение по вышкам
сотовой связи и эмулирует GPS. После запуска прога создает в системе новый порт,
который нужно указать в настройках любимой навигационной программы - и та,
ничего не подозревая, будет считать, что подключена к настоящему GPS-приемнику.
На что способен Wi-Fi
Будучи раздосадован тем, что большинство WiFi-точке в городе либо закрыты,
либо платные, подумай о том, что и им можно найти применение. Полагаю, не надо
говорить для чего :). Принцип точно такой же: определив все точки доступа
поблизости, отправляем информацию о MAC-адресах (добавляя при желании
идентификатор сети SSID) на специальный сервис. Тот проверяет их координаты и
выдает тебе твое примерное расположение. Такая технология давно функционирует в
Штатах, где покрытие Wi-Fi зашкаливает настолько, что скрыться от него уже,
похоже, негде. WPS (Wi-Fi Positioning System) предоставляет компания SKYHOOK
Wireless (www.skyhookwireless.com),
разработавшая клиентские приложения для разных платформ и собрав первоначальную
базу с точками доступа. Быстро появились и альтернативные приложения, которые,
используя API-сервиса, получают координаты пользователя. Среди них -
замечательный плагин для Firefox'а Geode (http://labs.mozilla.com/geode_welcome),
который подставляет информацию о текущем местоположении на любом веб-сайте (во
время создания нового поста в блог, например).
Увы, в России хоть как-то заставить работать SKYHOOK мне так и не удалось.
Зато наши соотечественники вплотную взялись за реализацию подобной идеи,
воплотив в жизнь сервис Wi2Geo (www.wi2geo.ru),
который мне почему-то очень хочется назвать Wi2Go :). Ребята уже сейчас
предоставляют приложения для Windows Mobile, Symbian, Windows и Mac OS X, а для
навигации используют базу IP-адресов, информацию о ячейках GSM и, собственно,
точках доступа Wi-Fi. Базы никому не запрещено использовать в своих целях,
воспользовавшись открытым API (http://labs.wi2geo.ru/basicapi.php).
Огорчает только, что проект будет развиваться только в тех городах, где большое
покрытие Wi-Fi. А таковым пока можно назвать только Москву.
А как же трекинг?
Выше мы говорили о трекинге пользователя - системе, позволяющей в реальном
времени отследить положение пользователя на карте. Неплохо, если бы подобную
штуку установили на свои телефоны все друзья. Тогда ничего бы не стоило узнать,
кто где, и при необходимости - договориться о встрече. Ребята из Google
реализовали это в функции Google Latitude, с недавнего времени доступной опять
же пользователям мобильных Google Maps. К сожалению, через браузер просмотреть
расположение друзей можно только в Штатах, но ведь ничего не мешает использовать
американский прокси?
Есть и другой вариант. На сайте
http://forum.xda-developers.com/showthread.php?t=340667 совершенно бесплатно
можно скачать специальную программу для трекинга, клиентская часть которой
устанавливается на коммуникатор на базе WM, а серверная - на любой веб-сервер.
Далее положение объекта можно просмотреть через программу Google Earth. Реально
работающее решение для бизнеса, которое с учетом открытых исходников несложно
доработать под себя!
WWW
Параметры Google Maps:
http://mapki.com/wiki/Google_Map_Parameters
Делаем GPS-адаптер для мобильного телефона своими руками:
http://tinkerlog.com/2007/07/13/interfacing-an-avr-controller-to-a-gps-mobile-phone
Мануал по получению координат по данным сотовой точки через Yahoo:
http://developer.yahoo.com/yrb/zonetag/locatecell.html
Реализация работы с базой данных Google Maps
На PHP:
http://www.witracks.com.br/gmaps.txt
j2me:
http://www.mapnav.spb.ru/site/e107_plugins/forum/forum_viewtopic.php?9736
android:
http://www.anddev.org/poor_mans_gps_-_celltowerid_-_location_area_code_-lookup-t257.html
C#:
http://www.sebbi.de/archives/2008/04/25/google-maps-mylocation-in-c-sharp
На Python для S60:
http://blog.jebu.net/2008/07/google-cell-tower-mapping-with-python-on-s60
На C#:
http://maps.alphadex.de/datafiles/fct0e1b11782832f02.cs
На Java для Android OS:
http://davanum.wordpress.com/2007/12/01/android-much-better-geo-location-from-just-cellidlac
На Delphi:
http://forum.netmonitor.ru/about4470-0-asc-60.html