AndroidをGPSロガーにする
Python mini Hack-a-thon (http://atnd.org/events/12812) での即興ネタ。
- SL4AでGPSの座標情報が取得できる。
- Py4AにはGoogleスプレッドシートライブラリが用意されている。
- ということで、Googleスプレッドシートに座標情報を保存してみた。以上。
- SL4Aでスクリプトを一定時間起動にセットすれば、ネット接続&バッテリーが持つ限り自分の行動が保存されていく。
- スプレッドシートを公開設定すれば、自分の行動が他人に丸分かり。ストーカーされたい人は大喜び(汗)。
- フォックスハンティング、スコットランドヤードごっことか出来そう?
- Googleマップと組み合わせて地図で座標表示とか?(今回はそこまでやりません)
まずGoogleドキュメントにログインして、1行目に「latitude」「longitude」「timestamp」の3つのラベルをつけたスプレッドシートを作っておきます。
gdoc_config.pyにはGoogleドキュメントのアカウントを記述します。
gpslogger.pyの中のKEY、GIDには、先に作ったスプレッドシートのキーとワークシートIDを埋め込みます。なおワークシートID「od6」というのは「最初に作られたワークシート」の意味です。なんでそうなるかは不明。
(gdoc_config.py)
EMAIL = '...' ## アカウント PASSWORD = '...' ## パスワード
(gpslogger.py)
import android import sys import time import gdata.spreadsheet.service from gdoc_config import EMAIL, PASSWORD KEY = '...' ## スプレッドシートのキー文字列 GID = 'od6' ## スプレッドシートのワークシートID droid = android.Android() droid.startLocating() for i in xrange(30): location = droid.readLocation() geo = None if location and location.result: result = location.result print result for src in (u'gps', u'network'): if result.has_key(src): geo = result[src] break if geo: break time.sleep(1) else: droid.makeToast('timeout') sys.exit(0) gd = gdata.spreadsheet.service.SpreadsheetsService() gd.email = EMAIL gd.password = PASSWORD gd.source = 'gpslogger' gd.ProgrammaticLogin() data = { 'latitude': str(geo['latitude']), 'longitude': str(geo['longitude']), 'timestamp': time.asctime(), } result = gd.InsertRow(data, KEY, GID) if isinstance(result, gdata.spreadsheet.SpreadsheetsList): droid.makeToast('success') else: droid.makeToast('fail') droid.stopLocating()
汚い書き方で読みづらくて申し訳ないです。概要はこんな感じです。
APIは座標情報を辞書型で返しますが、キーは「gps」「network」の2種類あります。前者は内蔵GPSまたはBluetooth接続した外部GPSロガー等から取った場合、後者はおそらくGoogleのAPIを使ったネットワーク情報ベースのようです。
ここではgps→networkの順に参照していますが、「network」の方はときどき間違った座標を返すことがあります(後述を参照)。確実にGPSデータが取れる端末であれば「gps」だけに固定した方がいいかもしれません。
startLocating()を実行してもすぐに座標が取れるようにはならないため、データが取れるまでreadLocation()を30秒間繰り返しています。ネットワーク情報ベースなら(ネットの速度によりますが)5〜20秒くらいで終わりますし、外部GPSロガーを使う場合も、自律的に測量したデータをBluetoothで引くだけなので比較的速く終わります。ただ内蔵GPSで万が一測量していない状態から始めたりすると1分で終わらないと思うので、状況によっては繰り返しの秒数を増やさないといけないと思います。
余談
デモで、リアルタイムでGoogleスプレッドシートに記録されていくのは結構興味深かったと思います。これはもちろんGoogleスプレッドシートがリアルタイムで画面書き換えをやってるからすごいのであって、SL4A + Py4Aがすごいわけではありませんw
余談2
ところでこのデモ中、最初は正しく会場(株式会社gumiさん)の座標が記録されていたのですが、途中から急に座標が変わり、長野県上田市のとあるおそば屋さん(1ヶ月前Python Hack-a-thon冬合宿で立ち寄った)の座標が記録されるようになってしまいました。
どうやらAndroidの座標取得APIは、GPSがあれば座標とIPアドレスとを結びつけてGoogle側に送り、ネットワーク情報ベースの測量ではそれを参照するだけ、という仕組みのようです。私は、おそば屋さんのとき外部GPSロガーを使い、今回のデモのときはネットワーク情報ベースで座標取得を行いました。このため、たまたまキャリアが同じIPアドレスを振ったか何かで、過去の座標を引っ張ってきてしまったようです。
takanory さんのような真っ当な端末(Nexus S)を使えば話は別ですが、私のように携帯回線を持たないAndroid端末で、日によってGPSロガー使ったりネットワークベースで座標取ったりすると、このような楽しい現象が起こるということに注意してください。
(ふつーの人はやらないと思いますが…)
参考
- android-scripting API Reference (http://code.google.com/p/android-scripting/wiki/ApiReference)
- Write to a Google Spreadsheet from a Python script (http://www.mattcutts.com/blog/write-google-spreadsheet-from-python/)