Tuesday, August 3, 2010

bash oneliner, get GPS location + street address

Hey there folks,

It's been quite some time since I last blogged, just been busy with $reallife. Today I'll show you how to an answer the eternal question of "Where am I" from the comfort of your bash shell

The following code only works if:
- You run it in a root shell (Ubuntu users do: "sudo -i" then paste it)
- You are connected via Wifi to some access point
- Your wireless adapter is called wlan0 (otherwise replace it with the correct name)
- You're using a Linux system or something similar (i.e. Windows won't really work here)

et voila


/bin/echo '{"version": "1.1.0","host": "maps.google.com","request_address": true,"address_language": "en_GB", "wifi_towers": [{"mac_address": "' $( iwlist wlan0 scan | grep Address | head -1 | awk '{print $5}' | sed -e 's/ //g' ) '","signal_strength": 8,"age": 0}]}' | sed -e 's/" /"/' -e 's/ "/"/g' > /tmp/post.$$ && curl -X POST -d @/tmp/post.$$ http://www.google.com/loc/json | sed -e 's/{/\n/g' -e 's/,/\n/g'


I didn't really spend much time cleaning it up, since I'm busy, so that's like the first thing that worked. If any of you guys can skip writing to the file, let me know and I'll update it

PS: If the returned information is wrong, or some kind of "unknown" .. Consider yourself lucky, very lucky! That means Google does not (yet?) know where your wifi AP is. For the rest of us .. tin-foil all the way

10 comments:

Abdelrahman said...
This comment has been removed by the author.
Anonymous said...

/bin/echo '{"version": "1.1.0","host": "maps.google.com","request_address": true,"address_language": "en_GB", "wifi_towers": [{"mac_address": "' $( iwlist wlan0 scan | grep Address | head -1 | awk '{print $5}' | sed -e 's/ //g' ) '","signal_strength": 8,"age": 0}]}' | sed -e 's/" /"/' -e 's/ "/"/g' | curl -X POST -d @/dev/fd/0 http://www.google.com/loc/json | sed -e 's/{/\n/g' -e 's/,/\n/g'

Kamal said...

Very well linville .. nice trick with /dev/fd0. Actually curl does support reading from stdin with "-d -", but for some reason that results in json parsing error

Anonymous said...

@linville

Thanks! That worked.. and now I'm worried :-/

kabel said...

OSX version: replace the $(iwlist ... sed -e 's/ //g') with

$( /System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -s | grep -o "\([0-9a-f]\{2\}:\)\{5\}[0-9a-f]\{2\}" | head -1 )

Can also use that in a for loop to pull all in the area and iterate over them. May post a better version later.

Kamal said...

@kabel Thank you for the OSX variant. Community is great :)

आदित्य प्रताप वन्देमातरम said...

Thanks for the great tip! It is really useful.

John said...

This fills in more info

echo -n "{\"version\": \"1.1.0\",\"host\": \"maps.google.com\",\"request_address\": true,\"address_language\": \"en_GB\", \"wifi_towers\": [`iwlist scan 2> /dev/null | tr -d '\n' | sed -e 's/Cell [0-9]* - Address: \([0-9A-Z:]*\)[^C]*Channel:\([0-9]*\)[^S]*Signal level=\([0-9-]*\) dBm[^E]*E[^E]*ESSID:"\([^"]*\)"/\{"mac_address": "\1","signal_strength": \3,"age": 0,"channel": \2,"ssid": "\4"}/g' -e 's/[^{]*{/{/' -e 's/}[^{]*{/},{/g' -e 's/\}[^}]*$/\}/' `]}" | curl -s -X POST -d @/dev/fd/0 http://www.google.com/loc/json

Unknown said...

to skip writing file you could use wget instead of curl:

wget -q --post-data="`/bin/echo '{"version": "1.1.0","host": "maps.google.com","request_address": true,"address_language": "en_GB", "wifi_towers": [{"mac_address": "' $( iwlist wlan0 scan | grep Address | head -1 | awk '{print $5}' | sed -e 's/ //g' ) '","signal_strength": 8,"age": 0}]}' | sed -e 's/" /"/' -e 's/ "/"/g'`" -O - http://www.google.com/loc/json | sed -e 's/{/\n/g' -e 's/,/\n/g'

Unknown said...

And append this to Rob's to generate a Google Maps URL to pass to your favorite browser...

|perl -e 'my $la;my $lo;use strict;while(<>){if(m{"longitude":(.*)}){$lo=$1}elsif(m{"latitude":(.*)}){$la=$1}};print "http://maps.google.com/maps?q=$la,$lo\n"'

There's probably a shorter way to pull the long/lat into x,y format.