uTrackMe おもしろいです.かなり DIY なアプリなのですが,GPSログを任意のサーバにPOSTで投げつけられます.ドキュメントもちゃんと読んでませんが,アプリを起動してからのトラックログをまとめて任意の秒間隔*1でサーバに通知できるようです.(最大で何点分のトラックを投げられるかは調べてない).
ともあれ,必要なのは最新の情報だろ!ってことで,受信用の ruby サーバCGIスクリプトを書いてみました!!
#!/usr/bin/ruby print "Content-type: text/html\n\n" require "cgi" cgi = CGI.new if cgi["label"] != "" then i = 0 while i < 86400 if cgi["time[#{i}]"] == "" n = i break end i += 1 end t = Time.at(cgi["time[#{n-1}]"].to_i) str = cgi["label"] + ', ' + t.strftime("%Y/%m/%d-%H:%M:%S").to_s + ", " + cgi\ ["time[#{n-1}]"] + ', ' + cgi["lat[#{n-1}]"] + ', ' + cgi["lon[#{n-1}]"] + ', \ ' + cgi["alt[#{n-1}]"] File.open("./data/" + t.strftime("%Y%m%d").to_s, 'a'){|f| f.write str + "\n" } else str = 'Null' end print <<EOM [SUCC] #{str} EOM
現状,最新のポイントをサーバに送って,サーバではCGIの動いている直下の data フォルダにログを書き出すだけです.つまり,WiFiや3G接続できないときはそのときのGPS情報がサーバに届かずロストします.
しかしながら,このアプリではアプリを起動してからの過去のログもキッチリサーバに送っているので,これらの情報をスクリプト側で再度拾ってやることで,ロストしていたトラックまで補完できますね! いや,これはすごい! 早くこのスクリプトを完成させよう.
アップデートしたよー
#!/usr/bin/ruby print "Content-type: text/html\n\n" require "cgi" require "csv" cgi = CGI.new if cgi["label"] != "" then i = 0 while i < 86400 if cgi["time[#{i}]"] == "" n = i break end i += 1 end t = cgi["time[#{n-1}]"].to_i time = Time.at(t) str = cgi["label"] + ',' + time.strftime("%Y/%m/%d-%H:%M:%S").to_s + "," + cgi["time[#{n-1}]"] + ',' + cgi["lat[#{n-1}]"] + ',' + cgi["lon[#{n-1}]"] + ',' + cgi["alt[#{n-1}]"] if File.exist?("./data/" + Time.at(t).strftime("%Y%m%d").to_s) == true fn = "./data/" + Time.at(t).strftime("%Y%m%d").to_s else if File.exist?("./data/" + Time.at(t-1).strftime("%Y%m%d").to_s) == true fn = "./data/" + Time.at(t-1).strftime("%Y%m%d").to_s end fn = nil end if fn != nil f = open(fn, "r") f.seek(-str.size-1, IO::SEEK_END) last = f.gets last_t = CSV.parse(last)[0][2] f.close i = 0 forgotten_num = 0 last_put_time = 0 while i < 86400 && cgi["time[#{i}]"].to_i < t if cgi["time[#{i}]"].to_i > last_t.to_i + cgi["delta"].to_i forgotten_str = cgi["label"] + ',' + Time.at(cgi["time[#{i}]"].to_i).strftime("%Y/%m/%d-%H:%M:%S").to_s + "," + cgi["time[#{i}]"] + ',' + cgi["lat[#{i}]"] + ',' + cgi["lon[#{i}]"] + ',' + cgi["alt[#{i}]"] if cgi["time[#{i}]"].to_i - last_put_time > cgi["delta"].to_i File.open("./data/" + Time.at(cgi["time[#{i}]"].to_i).strftime("%Y%m%d").to_s, "a"){|f| f.write forgotten_str + "\n" } last_put_time = cgi["time[#{i}]"].to_i forgotten_num += 1 end end i += 1 end end File.open("./data/" + time.strftime("%Y%m%d").to_s, "a"){|f| f.write str + "\n" } else str = 'Null' end if forgotten_num == 0 print "[Succ] " + str else print forgotten_num.to_s + " point(s) not completed just have been up-loaded!" File.open("./data/error", "a"){|f| f.write Time.now.to_s + " " + forgotten_num.to_s + " point(s) not completed just have been up-loaded!" + "\n" } end
というわけで,準リアルタイムアップロード中に WiFi や 3G がちょん切れても,再接続時に未アップロードのポイントをまとめてアップするバージョンに対応しました.
ただし,日付越えをまだ試験しておらんので,注意.
設置方法は簡単.ruby-CGI の動く Linux PC (たぶんどのプラットフォームでもOK)で,CGIとして動くようにこのプログラムを配置し,配置したディレクトリ直下に chmod 777 な data ディレクトリを設ける.設置した cgi へ向けて uTrackMe を設定すれば完了.
data/以下に,その日の日付のテキストファイルが生成され,下記のようなファイルが生成されます.1カラム目の文字列は, uTrackMe で設定した文字列が入ります.
iPodTouch3G,2010/05/24-02:47:06,1274636826,35.XXXXXX,139.XXXXXX,29 iPodTouch3G,2010/05/24-02:47:12,1274636832,35.XXXXXX,139.XXXXXX,27 iPodTouch3G,2010/05/24-02:47:16,1274636836,35.XXXXXX,139.XXXXXX,27 iPodTouch3G,2010/05/24-02:47:22,1274636842,35.XXXXXX,139.XXXXXX,28 iPodTouch3G,2010/05/24-02:47:26,1274636846,35.XXXXXX,139.XXXXXX,30
フォーマットは,
端末識別文字列, 日時, UNIX時刻,緯度,経度,高度
です.
さて,あとはこれを Google Maps に投影するだけなんだけどね….
なお,本プログラムですが,ヘタクソでも目をつぶってください.はじめて ruby さわりましたのです.
- 未実装&バグ
- 複数台対応.現状端末名1つにしか対応してない.
たまに,uploadミスしてないのに,数十個〜数百個のポイントがアップロードされてないと判断して,二重にアップロードしちゃう.なんでだろう.標準出力の桁数が変化したときにf.seekが上手く動いてないのが原因ですね.明日直しておきます.
*1:ミニマム5秒ですが