つくもノヲ”X="1≠ 211
一時の勢いで分厚い参考書を買って当初は意気揚々と励むのだが、
どうやら私の性格上、熱しやすく冷めやすいようだ。
ある事柄に長続きしないのだ。しばらくして飽きてしまう。
C言語につづいて、CGIサーバーの運用によく使われるperlも
そのひとつだ。しかし、もう使わないと思った参考書を使うことに
なる場合もあるからわからないものだ。
perlに再燃したきっかけは、GPSだ。
カーナビゲーション、略してカーナビや近年の携帯電話には必ずと
いってよいほど搭載されているナビ機能。
現在位置情報を取得するために使われるのが衛星から受け取る
GPS情報だ。
日々の歩いてきた記録として、Googlemapsのマイマップにシコシコと
線を引いているが、webを見ていると取得したgpsログをこのmapsに
マーキングするという面白い情報があったのだ。
取得したGPSログをそのままmapsにマーキングするにはまた別の技術が
必要になってくるようなので、今回はgpsログを取得してログファイルに
書き込んでいくところまでを実現したいと思い立ったのだ。
といっても、GPS受信端末ではない。
それなら別にperlを引っ張り出す必要はない。
携帯電話だ。それも近年搭載がデフォルトになっているGPS搭載の
携帯電話である。
なお手元にあるのがauの「neon」なので、それを前提として話を
進めていくことにしよう。
auの公式サイト(あまり役に立たないけれど)も書いてあるように
受け取ったgps情報を取得し、この情報を表示、あるいはログに
書き込む等のプログラムを作成する必要がある。
作成に使われる言語はいろいろあるが、perl、phpが主なところ。
phpの場合は、プログラムのソースコードを拡張子phpで保存し、
自分で立てたwebサーバか、レンタルサーバに配置する。
もちろん、どちらのサーバに配置する場合もphpがインストールされ
動作していることが前提だ。
無料で実現するには、レンタルサーバを使用することになる。
phpによるソースはwebで探すと見つかるので、なぜかあまり情報が
ない、perlで作成することにした。
このperl、phpなどで作成されたサーバで動作するプログラムを
CGIと呼ぶ。ソースコードをphpなり、perlが読み込みながら
ログファイルに書き込んだり、ブラウザに結果を
返すといった動作をする。これをインタープリター型という。
横道にそれてしまった。話を戻そう。
とりあえず、perlによるCGIを実行するために、
perlが動作するレンタルサーバを探すことになる。
ちょっと探したら、よさそうなレンタルサーバが見つかった。
おまけにphpも動作するようだ。(この辺は自分で探してみて欲しい)
今回、このサーバに配置するファイルは3つ。
取得したgpsを表示してログファイルに書き込むCGIと
CGIのリンクを張ったhtml、そして書き込み用のテキストファイル。
CGIのソースはこんな感じ。#!/usr/local/bin/perl --
#ブラウザ情報取得
print "Content-type:text/plain\n\nGPS情報<br>";
print "--------------------<br>";
print "$ENV{'HTTP_USER_AGENT'}<br>";
print "--------------------<br>";
my $bro =$ENV{'HTTP_USER_AGENT'};
#GPS情報取得
my $str = $ENV{'QUERY_STRING'};
$str =~ s/&/<br>/g;
my @k = split(/<br>/, $str);
for(my $j=0; $j<=$#k; $j=$j+1)
{
my @k1 = split(/=/, $k[$j]);
$k[$j] = $k1[1];
}
#緯度・経度・時刻情報の整形
my @ido = split(/\./, $k[3]);
$ido[0] =~ s/%2b//g;
$k[3] = $ido[0]+$ido[1]/60+$ido[2]/3600+$ido[3]/360000;
my @keido = split(/\./, $k[4]);
$keido[0] =~ s/%2b//g;
$k[4] = $keido[0]+$keido[1]/60+$keido[2]/3600+$keido[3]/360000;
my $year = substr($k[6], 0, 4);
my $month = substr($k[6], 4, 2);
my $day = substr($k[6], 6, 2);
my $hour = substr($k[6], 8, 2);
my $min = substr($k[6], 10, 2);
my $sec = substr($k[6], 12, 2);
print "緯度・経度degree変換<br>\n";
print "$year年$month月$day日$hour時$min分$sec秒
緯度(degree変換):$k[3] 経度(degree変換):$k[4]
<br>\n";
#ログファイルへの書き込み
open(FP ,"
if(open(FP ,">>location.txt"))
{
flock(FP, 2);
print FP "--------------------<br>\n";
print FP "$bro<br>\n";
print FP "--------------------<br>\n";
print FP "取得日時 経度(degree変換) 緯度(degree変換)
<br>\n";
print FP "$year年$month月$day日$hour時$min分$sec秒
$k[4],$k[3]<br>\n";
flock(FP, 8);
close(FP);
}
携帯電話からアクセスすると、GPS情報取得中の画面が表示された後に
ブラウザ情報とGPS情報が表示され、ログファイルに書き込まれる。
さて、配置してすぐに思うとおりに動いてくれたかと言われれば
想定していたが、いろんな落とし穴にはまり、かえってこの苦しみが
楽しい(?)わけで。ソース作成後の注意点として以下何点か挙げておく。
参考になれば。
・perlのパス
#!/usr/local/bin/perl --
まず、意外に見落としやすいだろう。
上のソースを実際に動かすperlのパスを指定するが、
レンタルサーバの設定によっては、パスが少し違っていたり
最後のハイフン「--」を付ける必要があったりするので
動作環境の確認は必須だ。
私が使用しているレンタルサーバでは最後のハイフンを
付けることになっている。
・行最後の「;」、全角文字混入
perlのパスやdo~whileなど条件分岐を除いては、
各行の最後は必ず、「;」を記載する必要がある。
意外に多いミス。C言語のようにデバッカを使わない場合、
つまり人間デバック(笑)なら、行最後の全角スパースとか
なかなか見つからずに悩むことになるのだ・・・・
・「"」と「'」
printはよく使う関数だ。
上のソースでは結果を出力する場合とログファイルに書き込む際に
使われている。
変数に代入された結果を表示するために
例えば、ブラウザ情報が代入されたハッシュ$ENV{'HTTP_USER_AGENT'}
のキーの結果を表示するのに
print "$ENV{'HTTP_USER_AGENT'}<br>";
とするところを間違って「'」で囲ってしまうとか。
print '$ENV{'HTTP_USER_AGENT'}<br>';
・パーミッション(実行権限)
特にunixでサーバを設定した、触ったことがある人なら
ピンと来るはず。「rwxrw-rw-」で表示されるやつだ。
CGIはowner(作成者)だけでなく、他の人も実行できるように
しないといけない。だから、設定として「rwxr-xr-x」(755)
になっていないとこのCGIにアクセスしてもエラーになる。
また、ログファイルは誰でも書き込めないといけないので、
「rwxrw-rw-」(766)と設定しておく。
レンタルサーバではこうした権限変更が許可されていることが
前提だ。
次にCGIのリンクを張ったhtmlのソース。
<html>
<head>
<meta http-equiv="content-type" content="text/html;
charset=Shift_JIS">
<title>gps for perl</title>
</head>
<body>
<p>
au携帯専用/GPS情報取得(手動版)<br>
<a href="device:gpsone?url=http://s1.muryo-de.etowns.net
/~ya570202/location.cgi&ver=1&datum=0&unit=0&acry=0&number=0"
>GO!</a>
<br>
au携帯専用/GPS情報取得(自動版)<br>
<a href="device:gpsone?url=http://s1.muryo-de.etowns.net
/~ya570202/location_auto.cgi&ver=1&datum=0&unit=0&acry=0&number=0"
>GO!</a>
</p>
</body>
</html>
・CGIのURL間違い
http://s1.muryo-de.etowns.net/~ya570202/location.cgi
CGIのソースを置いたURLだ。
私のレンタルサーバの例だが、URLが間違っていても実行エラーと
なるので、html例のようにリンクを張る場合は注意が必要だ。
さて、ここから技術的な話を。
近年の携帯電話のブラウザには大きく2種類あるようだ。
HDMLとWAP2.0だ。
HDMLで書かれたページはHDML機ならそのまま動作する。
ただ、その後継(?)に位置されるWAP2.0、私が今回動作確認に使った
auの「neon」も含めて、動作しない部分が出てくる。
文字の表示だけならまだしも、ページ、HDMLでは「カード」と
呼ぶが、次のカード、つまりリンクから次のページへ飛ぶタグや
電話番号をかけるタグ(勝手に発信するわけでなく、番号が
入力された状態で発信確認がある)などが、そのままでは
動作しない。
auの公式ページが言うところの「XHTML」で記述する必要がある。
そのため、HDMLではできるらしいページの自動更新が使えない。
よって、一定の時間が来る毎にGPS情報を取得してログに書き込む
という実装ができない。
他のサイトで、そんなソースがあったので試しに実行してみたが
GPSログは取得するものの、その後はうんともすんとも・・・orz
まだどこかにアイディアというか、抜け道がないか模索中だったり
そうでなかったり。
・CGIのURLについて
device:gpsone?url=http://s1.muryo-de.etowns.net
/~ya570202/location.cgi&ver=1&datum=0&unit=0&acry=0&number=0
「device:location」とすると、GPSを使わずに近くの基地局から
位置情報を取得するらしく、あまり正確ではないようだ。
そこで、GPSを使うために「device:gpsone」と指定する。
URLの後ろに続く「&」で始まる文字列はperlの参考書にも書いて
あるようにサーバへ引数を渡す手法だ。
引き渡す形式がGETとPOSTと2種類あり、GETの場合は上のように
引数を続けて書いて、サーバへアクセスする。
(今回のCGIではPOSTでは動作しない模様)
GETにより得られる情報は、先述のCGIソース中にある
my $str = $ENV{'QUERY_STRING'};
のように、環境変数のQUERY_STRINGキーに格納される。
この情報から時刻・経度・緯度だけを取り出して、
整形したものをログファイルへ書き込む。
・ログファイルの表示
--------------------
KDDI-TS35 UP.Browser/6.2.0.10.2.1 (GUI) MMP/2.0
--------------------
取得日時 経度(degree変換) 緯度(degree変換)
2007年09月20日13時41分38秒 139.444641666667,35.5442027777778
--------------------
KDDI-TS35 UP.Browser/6.2.0.10.2.1 (GUI) MMP/2.0
--------------------
取得日時 経度(degree変換) 緯度(degree変換)
2007年09月20日13時47分23秒 139.444188888889,35.5414388888889
--------------------
KDDI-TS35 UP.Browser/6.2.0.10.2.1 (GUI) MMP/2.0
--------------------
取得日時 経度(degree変換) 緯度(degree変換)
2007年09月20日14時16分49秒 139.421166666667,35.5602222222222
携帯電話から取得したGPS情報はこのようにログファイルへ
書き込まれていく。実は経度、緯度にも表示形式に種類があって・・・
という話は別のページなり、ブログなりに載っていることなので
ここでは割愛させて頂こう。
百聞は一見に如かず。手元にGPS機能搭載の最近の携帯電話
(できるならauがいいかもしれない)から次のURLへアクセスしてみよう。
http://s1.muryo-de.etowns.net/~ya570202/gps.html
ログファイルは次のURLから。
http://s1.muryo-de.etowns.net/~ya570202/location.txt
「au携帯専用/GPS情報取得(自動版)」とあるけれど、
自動更新の小技が見つからないので、今のところ手動で・・・orz
1 件のコメント:
http://s1.muryo-de.etowns.net
ここ数日で、アカウントを削除されたらしい
ログファイルも404エラーが・・・orz
やっぱり高負荷なcgiと判断されたか・・・
コメントを投稿