Jedna z novinek, které nabízejí současné prohlížeče (od verzí: IE 9, FF 3.5, Chrome 5.0, Safari 5.0, Opera 10.60) je Geolocation API. Prohlížeč umí zjistit, kde se fyzicky nacházíte a tuto informaci (po vašem předchozím souhlasu) stránce pomocí JavaScriptu sdělit. Podíváme se, jak tuto funkci můžete využít a nabídnu vám hotovou komponentu pro ASP.NET Web Forms, která to zajišťuje.
Co je Geolocation API a jak funguje?
Geolocation API je technologie (definovaná specifikací W3C), která umožňuje v kompatibilních prohlížečích z JavaScriptu zjistit, kde se právě fyzicky nachází zařízení, které stránku prohlíží. Webové aplikace mohou tuto informaci využít celou řadou způsobů, typicky například "najdi nejbližší pobočku" atd. Ještě větší využití nabízí geolokace v mobilních zařízeních.
Standard definuje jenom rozhraní (API), kterým si aplikace může vyžádat informaci o poloze. Nijak neřeší, jakým způsobem má zařízení tyto informace získat. Nabízí se samozřejmě použití GPS, ale to není vždy možné nebo účelné. GPS přijímač je většinou jenom v mobilních telefonech, běžné počítače a notebooky jím obvykle nedisponují. Také nefunguje uvnitř budov a jeho použití může být energeticky dost náročné.
Skutečnou implementaci v mobilních zařízeních jsem nezkoumal, ale v případě desktopových zařízení lokalizace probíhá na základě IP adresy a dostupných WiFi sítí. V případě požadavku na lokalizaci browser sesbírá údaje o okolních WiFi sítích, tedy jejich názvy, MAC adresy AP a sílu signálu. Tyto údaje pošle lokalizační službě, která je porovná se svou databází WiFi AP se známým umístěním a na základě toho vypočítá pravděpodobnou polohu, kterou pošle zpět. Při výpočtu používá také IP adresu, z níž požadavek přišel. Pokud zařízení nemá WiFi a nebo je vypnutá, jedná se o jediný zdroj, z něhož může být poloha odvozena.
Microsoft Internet Explorer
MSIE 9.0 pošle na adresu https://inference.location.live.net/inferenceservice/v21/Pox/GetLocationUsingFingerprint následující požadavek (formátováno, zkráceno a mírně cenzurováno):
<GetLocationUsingFingerprint xmlns="http://inference.location.live.com"> <RequestHeader> <Timestamp>2011-06-29T19:32:17.0000094Z</Timestamp> <ApplicationId>e1e71f6b-2149-45f3-a298-a20682ab5017</ApplicationId> <TrackingId>00000000-0000-0000-0000-000000000000</TrackingId> <DeviceProfile ClientGuid="00000000-0000-0000-0000-000000000000" Platform="Windows7" ExtendedDeviceInfo="" DeviceType="PC" LFVersion="9.0.8112.16430" OSVersion="7601.17592.amd64fre.win7sp1_gdr.110408-1631" /> <Authorization /> </RequestHeader> <BeaconFingerprint> <Detections> <Wifi7 BssId="1c:af:f7:xx:xx:xx" rssi="-29" /> <Wifi7 BssId="1c:bd:b9:xx:xx:xx" rssi="-34" /> </Detections> </BeaconFingerprint> </GetLocationUsingFingerprint>
Jako odpověď dostane zpět XML dokument s informacemi o poloze:
<GetLocationUsingFingerprintResponse xmlns="http://inference.location.live.com"> <GetLocationUsingFingerprintResult> <ResponseStatus>Success</ResponseStatus> <LocationResult> <ResolverStatus Status="Success" Source="Internal"/> <ResolvedPosition Latitude="52.16274" Longitude="21.04295" Altitude="0"/> <RadialUncertainty>500</RadialUncertainty> <TileResult/> <TrackingId>00000000-0000-0000-0000-000000000000</TrackingId> </LocationResult> <ExtendedV21Result CrowdSourcingLevel="Medium" ServerUtcTime="2011-06-29T19:32:18.3846551Z"/> </GetLocationUsingFingerprintResult> </GetLocationUsingFingerprintResponse>
Lokalizační služba Microsoftu v mém případě moc nefunguje a vytrvale mne umisťuje kamsi do centra Varšavy. Zde se projevuje jedna ze zásadních nevýhod crowdsourcingového určování polohy: předpokládá, že MAC adresy WiFi AP budou unikátní (zkušenost praví, že MAC adresy čehokoliv nejsou zase až tak unikátní, jak by měly být) a že budou neměnné. Některé z AP v mém okolí má zjevně dvojče v Polsku.
Ostatní prohlížeče používají geolokační službu od Google. Například Chrome se táže adresy https://www.google.com/loc/json a posílá jí v JSON serializaci následující data (též zkráceno, formátováno a mírně cenzurováno):
{ "access_token": "x:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "host": "localhost", "radio_type": "unknown", "request_address": false, "version": "1.1.0", "wifi_towers": [ { "age": 0, "mac_address": "00-0e-2e-xx-xx-xx", "signal_strength": -59, "ssid": "corp.altairis.cz" }, { "age": 0, "mac_address": "1c-af-f7-xx-xx-xx", "signal_strength": -29, "ssid": "brno.public.altairis.cz" }, { "age": 0, "mac_address": "1c-bd-b9-xx-xx-xx", "signal_strength": -38, "ssid": "corp.altairis.cz" }, ] }
Zpět obdrží opět JSON serializovanou informaci:
{ "location": { "latitude": 49.123456, "longitude": 16.123456, "accuracy": 144.0 } }
Je vidět, že Google má (zřejmě i zásluhou StreetView wardrivingu) lepší databáze, pozici určil s mnohem větší reálnou přesností. Obecně i Microsoftu to docela funguje, jenom u mne doma ne.
Pokud je WiFi vypnutá, přesnost se výrazně sníží. Google mne v takovém případě hodí do centra Brna (předpokládám, že dokáže zjistit, že jsem v Brně a nic víc). Podle Microsoftu jsem pořád ve Varšavě, ale předpokládám, že se to nějak cacheuje, protože v Praze to fungovalo docela dobře.
Soukromí
Stránka samozřejmě nemůže získat informace o poloze jenom tak, bez souhlasu uživatele. Pokud se stránka pokusí použít geolokaci, prohlížeč vás na to upozorní a vyžádá si váš souhlas. Všechny prohlížeče tak činí neintruzivním způsobem, ukážou někde nějakou "bublinu", nevyhodí klasický obtěžující dialog. Takhle to vypadá v IE 9:
Z hlediska webového uživatele tedy valné nebezpečí nehrozí. Otázky však vyvolávají samotné WPS (WiFi Positioning Systems), tedy shora popsaná metoda shromažďování dat o pozici WiFi AP. Dobrý úvod do problematiky najdete například na webu Kima Camerona.
Implementace v JavaScriptu
Využití Geolocation API v JavaScriptu je poměrně dobře popsáno v samotném standardu, včetně ukázkového kódu. Dokonce i JavaScriptoví začátečníci, jako jsem já, by si s ním měli umět poradit. O vše se stará objekt navigator.geolocation (pokud je null, tak prohlížeč geolokaci nepodporuje). Ten má metodu getCurrentPosition, která volá dva callbacky, jeden pro úspěch a jeden pro případ selhání.
Lze také určit parametry zjištění pozice:
- enableHighAccuracy říká, že prohlížeč má použít nejpřesnější možnou metodu určení, a to i za cenu delšího zjišťování polohy a nebo vyšší spotřeby energie. Základní myšlenka je taková, že např. mobilní zařízení může běžně používat určení polohy podle GSM sítě nebo WiFi, což je méně náročné, ale aplikace si může vyžádat zapnutí GPS modulu ve chvíli, kdy potřebuje přesnou polohu, například pro navigaci. Není mi známo, nakolik je tato idea v praxi implementována. Výchozí hodnota je false.
- maximumAge povoluje prohlížeči použít nacacheovanou hodnotu známou z minula, pokud je novější než daný počet milisekund. Pokud je hodnota nepřítomna nebo nastavena na 0, nesmí prohlážeč cacheovanou hodnotu použít. Podle mých testů v praxi všechny desktopové prohlížeče tuto hodnotu ignorují a cacheují si, jak je jim libo.
- timeout říká, do kolika milisekund musí být získána odpověď. Nestihne-li se to, zahlásí volání chybu. Pokud je hodnota nepřítomna nebo nastavena na Infinity, timeout neexistuje. V tomto čase není zahrnuto čekání na odpověď uživatele, zda s geolokací souhlasí. Vaše implementace by tedy měla počítat s tím, že se nedočká vůbec žádného callbacku, pokud bude uživatel výzvu prostě ignorovat.
V případě úspěšného získání pozice se zavolá callback, který obdrží informace o poloze a případně též směru a rychlosti pohybu (testované desktopové prohlížeče toto vcelku logicky nepodporují). Také dostanete timestamp, čas k němuž byly údaje zjištěny.
V případě chyby je zavolán jiný callback, který obdrží kód chyby, k němuž došlo (1 = uživatel nesouhlasil, 2 = pozice není dostupná, 3 = timeout).
Kromě toho ještě existuje způsob pro získání pravidelných informací o změnách polohy, ale tím se v tomto článku zabývat nebudeme.
Implementace v ASP.NET
Co když potřebujeme získané údaje nějak dostat na serverovou stranu, co ASP.NET? To už Geolocation API neřeší, tomu jde čistě o klientské rozhraní. Záleží samozřejmě na předpokládané aplikaci, někdy bude třeba používat AJAXové callbacky a podobně. Často ale můžete chtít zpracovávat data v rámci odeslaného formuláře stránky samé.
Napsal jsem komponentu, která si na straně klienta zjistí veškeré dostupné údaje pomocí JS Geolocation API a serializuje je do skrytého pole formuláře. Při následném postbacku pak data proparsuje a dává k dispozici pomocí svých vlastností. Zpřístupňuje tedy Geolocation API i těm programátorům, kteří se JavaScriptem nehodlají zabývat.
Komponenta je vyzkoušená v nejnovějších verzích IE, Chrome, Firefoxu a Opery, fungovat by měla i v ostatních prohlížečích (mobilních) a ve starších prohlížečích, které geolokaci nepodporují, se chová mravně.
Stáhněte si zdrojové kódy a ukázkovou aplikaci. Tato komponenta bude součástí další verze Altairis Web UI Toolkitu, ale v současné verzi 2.1.7 dosud není.