Lokasyon Bazlı Servisler Yaratmak

April 10, 2010

Son 2 yıl içerisinde Mikro-blogları ve bu konuda geliştirilen web uygulamalarının adını çokça duyduk. Bu yıl ise, özellikle lokasyon bazlı uygulama örneklerini görmeye başladık. Foursquare, Loopt, Google Latitude, Gowalla, Rummble ve bu işe yeni girişen Twitter, Facebook aklıma gelen ilk örnekleri. (Ben bu yazıyı hazırlarken; Yahoo, FourSquare’ı satın almayı düşünüyor fakat 100 Milyon$ edip etmeyeceğine karar vermeye çalışıyordu)

Lokasyon bazlı servisler gizlilik konusunuda beraberinde getirdi. Hatta bu konuda Google’ın CEO’su Eric Schmidt’in ‘Gizlenmek istemeniz, gizlenmesi gereken işlerle meşgul olduğunuz anlamına gelir’ demecine en güzel cevabı, “Lütfen beni soyun” anlamına gelen ve foursquare’daki bulunduğunuz konuma göre hırsızlara davetiye çıkaran, PleaseRobMe.com isimli bir sitenin verdiğini düşünüyorum. Halen gizlilik politikaları lokasyon bazlı servislere karşı önyargıları olan insanları tatmin ettiği söylenemez.

Gizlilik konusu daha çok tartışılacak bir konu gibi görünüyor. Bunun en son örneği ise Fazlamesai.net sitesindeki “Kim? Ne zaman? Kiminle? Nerede?” başlıklı yazısı.

Bu tartışmalar süre dursun, lokasyon bazlı servisler artık hayatımıza girdi ve çıkacak gibide durmuyor. Peki bu işin teknik altyapısında neler var, gelin bunları inceleyelim ve bu blogun amacına uygun bir davranış sergileyelim.

Lokasyon Bazlı Servisler (LBS) Nedir? Bir kişinin lokasyon bilgisini almanın birkaç yöntemi vardır. Bunlar;

Yukarıdaki yöntemlerin hepsiyle konum bilgisini (longitude ve latitude) elde etmek mümkün. Bunlardan GPS ve GSM ilgili olan yöntemler, makineden makineye ve operatorden operatore değişiklik gösterebileceği için bu yazının kapsamı dışındadır. GSM ve GPS üzerinden lokasyon çekmek özellikle lokasyonun güvenilirliği gerektiği durumlarda daha etkili olmaktadır. Tabii GSM ve GPS gibi sistemleri simule etmekte mümkün ama şimdilik, küçük bir kesimin yapabileceği bir iş.

Neler Yapılabilir?

Nasıl Yapılabilir?

IP’den lokasyon bulmak için, web üzerinde bu hizmeti alabileceğiniz çok fazla firma var. İlk aklıma gelenleri; IP2Location, MaxMind, GeoPostcodes.

Bunların içinden ücretsiz bir sürümü bulunan MaxMind firmasının GeoLite isimli ürünü ile ilk demomuzu gerçekleştireceğiz.

Gereksinimler

Öncelikle ücretsiz şehir verisini indirelim.

# Ornekte kullanilan GeoLiteCity.dat dosyasının kurulumu
su -
mkdir -p /opt/maxmind
cd /opt/maxmind
wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
gunzip GeoLiteCity.dat.gz
chmod a+r -R /opt/maxmind

# PHP Modülünün kurulumu.
wget http://geolite.maxmind.com/download/geoip/api/php/geoipregionvars.php
wget http://geolite.maxmind.com/download/geoip/api/php/geoipcity.inc

# Eger Apache ayarlarınızda open_base_dir ayari aktif ise
# PHP kodunuzun bulundugu dizine koyun ve örnekteki yolu degistirin.

Şimdi IP’den latitude ve longitude degerlerini bulan kodun demosunu yazalım.

include("geoipcity.inc");
include("geoipregionvars.php");

$gi = geoip_open("/opt/maxmind/GeoLiteCity.dat", GEOIP_STANDARD);
$record = geoip_record_by_addr($gi, $_SERVER["REMOTE_ADDR"]);
geoip_close($gi);

echo "

bulundugunuz sehir


"; echo "
".print_r($record, true)."
";

Bu demonun çalışan haline şuradan erişebilirsiniz.

En yakın şeyi bulmak ile anlatılmak istenen bilinen bir lokasyonun etrafında bulunan (diyelim ki 1 kmlik) bir alan içerisindeki nesneleri bulmaktan söz edilmektedir. Örneğin bir ilan sitesi için bu kiralık veya satılık evler, araçlar ve çeşitli taşınır ve taşınmazlar olabilir. Ya da, "Ne/Nerede" servisi için, çilingir, taksi durağı ve eczanenin bulunduğu yerler de bulunabilir. Bu konuda eğer web üzerinde araştırma yapmayı düşünüyorsanız, arama motorlarına "radius search" yazmanız yeterli olacaktır. Karşınızda, lokasyon üzerine, özellikle posta kodu (zipcode) hizmeti sunan siteler çıkacaktır. Tahmin ettiğiniz üzere anahtar kelime, posta kodu bilgisi. Daha doğrusu mahalle seviyesine indirgenmiş longitude ve latitude değerlerine sahip olmak. Bu sayede, yarıçap hesabı (radius) yaparak, örneğin 1km'lik bir alana ait mahallelere erişemek mümkün. İşte işin büyüsü burada. Yelp ve FourSquare bu şekilde size mekan bilgilerini verir.

Bu hesaplamanın nasıl yapıldığını araştırırken, CodeGuru sitesinde Coğrafik Bölge Hesaplamaları başlıklı bir makaleye rastladım. Kodlar C++ diliyle yazılmıştı. Bu işin mantığıyla ilgilenen olay odaklı programcılar için güzel bir makale. Ama yok hani PHP ile yazılmış kodları merak eden ürün odaklı programcı kardeşlerim için ise, Steven Brendtro tarafından PHP diline port edilen GeoCalc sınıfını ve şuradaki makalesini tavsiye ederim.

Peki yarıçap hesabı yapmak için gerekli PHP kütüphanemizde var artık. Aşağıda anlatacağım örnek için, posta kodu veritabanı tablonuz olduğu varsayılmıştır. Yani şimdi bulmamız gereken, posta kodları seviyesinde latitude ve longitude değerleri. Bu konuda ücretli olmasına rağmen şiddetle tavsiye edebileceğim site GeoPostcodes. Gerçekten çok iyi bir içeriğe sahip. Diğer bir alternatif için ise, arama motorundan bulduğum ve hiç deneme fırsatı bulamadığım ZipCodes isimli site. Son olarak posta kodları ile ilgili ücretsiz siteler bulmanız mümkün ama bunların çoğu Amerika için geçerli :(

Peki şimdi gelin GeoCalc ile 1 km’lik bir alan nasıl bulduğumuzu inceleyelim.

include_once("GeoCalc.class.php");
$oGC = new GeoCalc();

// IP'den lokasyon bulma yoluyla bulduğumuz değerler.
$dLongitude = -94.44590241;
$dLatitude = 38.7996;

// Ne kadarlık bir alanda sorgulama yapılacak?!
$dRadius = 1.00;  // in kilometers

// Yarıçap Hesabı.
$dAddLat = $oGC->getLatPerKm() * $dRadius;
$dAddLon = $oGC->getLonPerKmAtLat($dLatitude) * $dRadius;

// Sınırların belirlenmesi.
$dNorthBounds = $dLatitude + $dAddLat;
$dSouthBounds = $dLatitude - $dAddLat;
$dWestBounds = $dLongitude - $dAddLon;
$dEastBounds = $dLongitude + $dAddLon;

print "Merkezi Longitude: $dLongitude\n";
print "Merkezi Latitude: $dLatitude\n";
print "Yarıçap: $dRadius kilometre\n";

print "Kuzey Sınırı: $dNorthBounds\n";
print "Güney Sınırı: $dSouthBounds\n";
print "Doğu Sınırı: $dEastBounds\n";
print "Batı Sınırı: $dWestBounds\n";

// Örnek sql sorgusu ile hangi bölgeleri kapsadığı bulunur.
$strQuery = "SELECT * FROM PostalCodes " .
              "WHERE Latitude > $dSouthBounds " .
              "AND Latitude < $dNorthBounds " .
              "AND Longitude > $dWestBounds " .
              "AND Longitude < $dEastBounds";

Bulunan bu bölge kodlarına bağlı kayıtların çekilmesi ve sayfada listelenmesiyle işlem tamamlanmış olur.

Son olarak, HTML5 ile birlikte gelen lokasyon öğrenme yönteminden söz ederek yazımı sonlandırmak istiyorum. Bu yöntemin, IP'den lokasyon bulmaktan farkı web tarayıcınızdan izin ister ama bunun karşılığında tarayıcının makinede varsa GPS'ten ya da çeşitli servislerden öğreneceği kaliteli bir latitude ve longitude değeri sunar.

if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(function(position) {
        result = "latitude:"+position.coords.latitude+"-";
        result += "longitude:"+position.coords.longitude;
        alert(result);
    });
} else {
    alert("Uzgunum, tarayicinizin cografik konum destegi henuz yok! HTML5 destegi olan bir tarayici kullanin.");
}