2007年10月7日日曜日

つくもノヲ”X="1≠ 221


携帯電話でGPSということで、perlによるCGIプログラミングが
再燃したことは前のニッキで書いた。

cgiにアクセスすることで、取得したGPS情報をログへ書き込む
ところまでは無事に動いた。しかし・・・・

最終目的は一定の時間が経過したら、たとえば1分ごとにGPS
情報をログへ書き込むということが
そのためには自動更新のタグを追加しないといけない。

我がauの携帯電話「neon」は、WAP2.0という種別のブラウザを
搭載している。HDML種別のブラウザとは異なり、一部動作しない
タグがあるようなのだ。

その一つがontimerタグだ。次のようなコードを書いてみた
(表示の都合上、一部改行)


<wml:card ontimer="device:gpsone?url=http://s1.muryo
-de.etowns.net/~ya570202/location_auto.cgi&ver=1&datum=0
&unit=0&acry=0&number=0">

<wml:timer value="600" />

<p align="center">
自動計測中(1分ごと)
</p>

</wml:card>



どこかのサイトで紹介されていた技で、このコードをcgiに書く。
最初にGPS取得中の画面が表示されただけであとは動作せず。
ログファイルにも最初のGPS情報以外書き込まれず・・・orz

次に試したのが、よくアクセスカウンターで使われる技として
cgiから画像を出力させるというのがある。
imgタグにcgiのURLを指定すると、指定されたcgiが画像を
読み込んで表示する。レンタルサーバーの設定なのか、どうにも
動作せず。画像すらHTMLに表示してくれない・・・orz

そしてformタグを使って、情報を送信しようとしたが、
最後のパラメータ(sec_interval)はcgiで受け取れず・・orz
同じように最初にGPS取得中の画面が出た後はうんともすんとも・・・

<form action="device:gpsone" method="GET">

<input type="hidden" name="url" value="http://s1.muryo
-de.etowns.net/~ya570202/location_auto.cgi">
<input type="hidden" name="ver" value="1">
<input type="hidden" name="datum" value="0">
<input type="hidden" name="unit" value="0">
<input type="hidden" name="acry" value="0">
<input type="hidden" name="number" value="0">
<input type="text" name="sec_interval" size="40">
<input type="submit">

</form>



auの携帯電話はGPSとしてgpsoneを使用しているため、URLの前に
「device:gpsone」と指定する必要がある。そしてGET形式でないと
動作しない。formタグによってGET形式で送信された上記のnameとvalueは、
cgiが参照することができる環境変数QUERY_STRINGに格納される。

cgiではこの環境変数からそれぞれのnameとvalueを参照することができるが、
なぜか最後のsec_intervalのvalueは受け取れないのだ。
受け取れないので、cgiのsleep関数の引数としても使えない・・・orz

ブラウザはjavascriptなどのスクリプトにも対応していないから
このあわせ技も×。

あとは有望なタグを片っ端から試してみた。

まずembedタグは×。
imgタグとcgiの組み合わせの組み合わせならもしかしてと期待しただけに
少しがっかり・・・・orz

metaタグにrefreshを指定する例の「〇秒後にジャンプします」技も×。

ここまでやり尽くして、自動更新は不可能なのか?
いろいろと探っていくうちにとうとう次のコードにたどり着いた。

#!/usr/local/bin/perl --

print "Content-type: text/html\n\n";

#ブラウザ情報取得

my $agent = $ENV{'HTTP_USER_AGENT'};
my $addr = $ENV{'REMOTE_ADDR'};
my $addr2 = $ENV{'HTTP_X_FORWARDED_FOR'};

#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 "GPS情報を正常に取得しました<br>\n";

#ログファイルへの書き込み

open(FP ,"<location.txt") || die "not opened!!<br>\n";
close(FP);

if(open(FP ,">>location.txt"))
{
flock(FP, 2);

print FP "--------------------<br>\n";
print FP "$agent<br>\n";
print FP "REMOTE_ADDR:$addr<br>\n";
print FP "HTTP_X_FORWARDED_FOR:$addr2<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);
}

print "ログファイルへの記録完了しました<br>\n";


sleep 50;

print<<EOM;

<wml>
<onevent type="onenterforward">
<go 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>
</onevent>
</wml>

EOM




GPS情報をログファイルに書き込む後の赤字部分を見て欲しい。
50秒中断した後、再度同じcgiを呼び出すタグを出力させている。
cgiを呼び出すためにoneventタグとgoタグを使用するのだ。

oneventタグのtypeでonenterforwardを指定すると、
goタグを実行する。つまりgoタグのhref=にcgiのURLを指定すると
何もボタン操作などしなくても勝手にそのURLへ飛んでくれる・・・
ということを実験して突き詰めた次第。

初めはhtmlにこの赤字コードを仕込んで実験していたが、
cgiでも出来るのではとやってみたら、案の定うまく動いたので
ならばsleep関数を使えば、好きな時間で更新できると思いついたのに
それほど時間はかからなかった。

ちなみに上のコードではsleepを50にすると、丁度1分で自動的にGPSの
ログを書き込んでくれる。sleepを除いて実験してみたら、GPS情報を
取得してログに書き込むまで、最低10秒かかったためだ。
電波受信の状況が悪ければ、もっと時間がかかるだろう。
なので、10秒未満のGPS取得はできない。

レンタルサーバでの実験なので、設定による処理時間制限のために
sleepを50以上にすると502エラーになる。
自前のサーバならともかく、レンタルサーバで確かめてみたい場合は
この点を注意しておく。

1 件のコメント:

ya さんのコメント...

oneventタグとgoタグのあわせ技って、
よく考えたら危険タグ(笑)