Create a Console Application or Web Service that Gives Precise Geocoordinates of Client Machine
New here? Learn about Bountify and follow @bountify to get notified of new bounties! x

Skyhook or otherwise, I would like to have the geolocation of the host machine generated by a (Windows, Linux, or Android) program. A console application is fine, but I myself cannot work with Skyhook because it gives errors I have failed to resolve. I am explicitly not asking for something utilizing JavaScript because I could do that in two seconds and all that does is report client-side information (obviously). I would like the format to be latitude, longitude — simple. I will be using this in a website.

Is your host computer connected to the Internet via Wi-Fi?
alixaxel almost 7 years ago
@terrasoftlabs is the host the one you want the latitude and longitude for? or do you want to get the longitude/latitude oh the client connecting to the website?
alex almost 7 years ago
The host machine, wherever the code is stored. The host will have WiFi.
gabrielnahmias almost 7 years ago
awarded to alixaxel

Crowdsource coding tasks.

2 Solutions


First of all, what do you mean by client machine? Because both the bounty title and the answer @alex provided seem to suggest you want the coordinates of the machine calling the method, while your bounty emphatizes that you want the coordinates of the host machine that is actually running the method. I'm going to assume that you mean the latter (host = host, not client), if it's not let me know.

Getting Skyhook SDK to work was a bit cryptic but it's easy once you figure it out.

First, you have to register for the SDK here http://www.skyhookwireless.com/location-technology/sdk.php, for this purpose I already registered myself with the user bountify and the realm bountify also. Along with the SDK, there's a pre-compiled binary named wpsapitest and the dinamic libraries it needs (wpsapi.dll for Windows and libwpsapi.so for *nix).

Calling the executable like this wpsapitest --user bountify --realm bountify produces something similar to:

user registered

83.***.***.***: 41.*****3, -8.*****4

41.*****6, -8.*****8    +/-14m  6+0+0  499ms
, 13

The first coordinates are derived from the host current IP and the second pair of coordinates are derived from Wi-Fi / GSM networks (if available), hence more precise. I've coded a little PHP snippet that calls the right executable depending on your host OS, matches all the valid latitude / longitude pairs and returns the last one, here it is:

<?php

function getLocation($user, $realm)
{
    $path = rtrim(str_replace('\\', '/', __DIR__), '/');
    $command = sprintf('%s/bin/wpsapitest -u %s -r %s', $path, $user, $realm);

    if (strncasecmp('WIN', PHP_OS, 3) === 0)
    {
        $command = str_replace('/wpsapitest', '/wpsapitest.exe', $command);
    }

    if (preg_match_all('~(-?\d{1,2}[.]\d+, -?\d{1,3}[.]\d+)~', shell_exec($command), $coordinates, PREG_SET_ORDER) > 0)
    {
        $result = array_pop($coordinates); // 1st coordinate is gathered from IP, 2nd from Wi-Fi - lets get the best one
    }

    return (is_array($result) === true) ? current($result) : false;
}

$user = 'bountify';
$realm = 'bountify';

echo getLocation($user, $realm);

The above produces something similar to 41.*****6, -8.*****8 (asterisks to protect my privacy of course).

I'm not sure if you're familiar or not with PHP, but to call the script from the command line all you need to do is:

php /path/to/skyhook/skyhook.php

Of course, PHP itself needs to be in your path environment variable, on Debian/Ubuntu this is as simple as doing sudo apt-get -y install php5-cli, on Windows you have to download the pre-compiled binaries from the PHP website and place it in a $PATH folder. On *nix, you also need to make sure to give the execute permission to the binary by doing sudo chmod +x /path/to/skyhook/bin/wpsapitest.

I've zipped the whole thing for you here: http://www.filedropper.com/skyhook_1.

I could easily set this up with Cron to continually execute?
gabrielnahmias almost 7 years ago
@terrasoftlabs If you are familiar with cron, 00 * * * * /usr/local/bin/php /path/to/geoscript/geoscript.php command in the cron tab in Linux should work for you. It would run the script every single hour.
alex almost 7 years ago
Why would you need to run it out of cron, though? I mean, a server's geolocation almost never changes - is your server floating in international waters or something? :)
tml almost 7 years ago
@terrasoftlabs: You could, but I am also curious why you would need that. To add the new cronjob (under Debian/Ubuntu) all you need to do is ( sudo crontab -l; echo "@hourly php /path/to/skyhook/skyhook.php" ) | sudo crontab -. You can read more at https://help.ubuntu.com/community/CronHowto. On Windows, I suggest you use something like pyCron (http://www.kalab.com/freeware/pycron/pycron.htm), it's really good.
alixaxel almost 7 years ago

This is a PHP script. For this script, the geolocation/coordinates comes from hostip.info which uses the client's IP. The script uses PHP cURL which I based off code from this site. A demo of the script is available here.

<?php
    // Grab data from HostIP
    $url = "http://api.hostip.info/get_json.php?ip=".$_SERVER['SERVER_ADDR']."&position=true";
    // Initializing curl
    $ch = curl_init($url);

    // Configuring curl options
    $options = array(
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => array('Content-type: application/json')
    );

    // Setting curl options
    curl_setopt_array($ch, $options);

    // Getting results
    $result =  curl_exec($ch);

    // Printing out data
    $output = json_decode($result);
    $coord = ("(".$output->{"lat"}.", ".$output->{"lng"}.")");
    print($coord);
?>
Function

If you wanted a function for to accomplish this, here is one. The function returns the latitude and longitude of the client (based off their IP) as an array. The first value in the array is the latitude and the second is the longitude.

<?php
    function coord_from_ip() {
    $ch = curl_init("http://api.hostip.info/get_json.php?ip=".$_SERVER['SERVER_ADDR']."&position=true");
    curl_setopt_array($ch, array(CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => array('Content-type: application/json')));
    $output = json_decode(curl_exec($ch));
    return array($output->{"lat"}, $output->{"lng"});
}
?>

Notes

The JavaScript Geolocation is still probably the best bet because it is the most acurrate. The problem with processing geolocation server-sided is that there is limited data that can be accessed by the server.

More

Just for whoever ends up coming across this bounty and is looking for some simple geolocation code, the below script uses data from geoiptool.com.

Raw Code

<?php
    // Grab data from HostIP
    $url = "http://geoiptool.com/data.php";

    // Initializing curl
    $ch = curl_init($url);

    // Configuring curl options
    $options = array(CURLOPT_RETURNTRANSFER => true);

    // Setting curl options
    curl_setopt_array($ch, $options);

    // Getting results
    $result =  curl_exec($ch);

    // Printing out data
    $output = new SimpleXMLElement($result);
    $coord = ("(".$output->marker[0]["lat"].", ".$output->marker[0]["lng"].")");
    print($coord);
?>

Function

<?php
    function coord_from_ip() {
        $ch = curl_init("http://geoiptool.com/data.php");
        curl_setopt_array($ch, array(CURLOPT_RETURNTRANSFER => true));
        $output = new SimpleXMLElement(curl_exec($ch));
        return array($output->marker[0]["lat"], $output->marker[0]["lng"]);
    }
?>
Hey @alex, shouldn't it be SERVER_ADDR instead? Also, file_get_contents() would probably suffice for this.
alixaxel almost 7 years ago
@alixaxel depends... I'm not sure if he wants the server geolocation or the client location. And yes, file_get_contents() should work, but I prefer cURL when calling resources from other servers.
alex almost 7 years ago
This is incredibly off-base because it shows my IP as being in CA in the US which probably means it's determining through the ISP server locations.
gabrielnahmias almost 7 years ago
@terrasoftlabs, Like I said, it's coming from hostip.info. The information may not be correct as it is determining your info from your IP (which comes from your ISP). I will try to look for a more accurate solution.
alex almost 7 years ago
No worries; this is nifty but not fit for my purposes. Thanks.
gabrielnahmias almost 7 years ago
View Timeline