■「imakoko!」あるいは「いまココ!」とは?
auのGPS携帯電話から連続的に位置を通知、それをログに取り、ログをGoogleMap上に表示するcgiスクリプトです。
まったくの無保証ですので、利用される場合は自己責任でよろしくお願いします。
■設置
○準備
- cgiが使えるサーバを用意する。
- cgiを設置するディレクトリでのGoogleMapsAPIKeyを取得する。(参照→「GoogleMapを使う」)
○設置
- cgiスクリプト中の「各サイトでの個別設定」の部分を設定する。
- cgiスクリプトを設置する。(cgiスクリプト自体の文字コードはutf-8を推奨)
- 設置するディレクトリ、このプログラムのパーミッションを適切に設定する。(ディレクトリはファイル書き込み可能、このプログラムは実行可能に。)
■使い方
○ログを取る方法
- auの携帯電話からMainMenuで、ログファイル名と通知間隔を設定(ログファイル名と通知間隔をフォームに入力し、Executeのボタンを押す。)
- auの携帯電話からStartLogのリンクに飛ぶ。
○ログを読む方法
- MainMenuで、「ReadLog」のリンクに飛び、LogMenuから、読みたいログを選択する。(GoogleMapの動くPC上のみから可能。auの携帯電話では使えない。)
■使い方の注意
- ログ名を分けるのは、排他処理のためではないので、1人の人がログを取っているときに、ログ名と通知間隔の設定が変更されると、先にログを取っている人のログも変更された設定のログに保存されます。
■サンプル
サンプルを置いておきます。
http://hpcgi1.nifty.com/kinseijin/map/imakoko.cgi
排他処理をしていないので、利用がかち合ったら、うまくログがとれないかもしれませんが、そこはサンプルということでご容赦を。
■ソース
#!/usr/local/bin/perl
#
# imakoko.cgi --- auのGPS携帯から位置情報を連続的に取得し、GoogleMapに
# プロット、軌跡を描くcgiスクリプト
#
# 設置方法:
# 1. 設置するディレクトリでのGoogleMapsAPIKeyを取得する。
# 2. このcgiの「各サイトでの個別設定」の部分を設定する。
# 3. このcgiを設置する。(cgiスクリプト自体の文字コードはutf-8を推奨)
# 4. 設置するディレクトリ、このプログラムのパーミッションを適切に設定する。
#
### ここから、各サイトでの個別設定
# シェバング(最初の行)は、OKですか?【確認必須】
# このcgiを設置するディレクトリでのGoogleMapsAPIKey【設定必須】
$GoogleMapsAPIKey = '';
#$GoogleMapsAPIKey = 'ABQIAAAApBUCPi6dZcJJChQ2Jf06RRQKKSeFISyvZfdbrKeuaYSwEyEIfRTQSr4PH4yQ9sjKQb6Rd9BDhSBeYg';
# 日本語のコード(utf-8(非変更)を推奨。それ以外は動作未確認。)
$Charset = 'utf-8';
#$Charset = 'euc';
# 測地系(WGS-84(非変更)を推奨。それ以外は動作未確認。)
( $Datum , $DatumCode ) = ( 'wgs84' , 0 );
#( $Datum , $DatumCode ) = ( 'tky' , 1 );
# 定数の設定(日本語で表示したければコメントを付け替える)
( $DEG , $MIN , $SEC , $DirN , $DirS , $DirE , $DirW , $sALT , $sDAT , $sACC ) =( '/' , '/' , '/' , 'N' , 'S' , 'E' , 'W' , 'Altitude' , 'Datum' , 'Accuracy');
#( $DEG , $MIN , $SEC , $DirN , $DirS , $DirE , $DirW , $sALT , $sDAT , $sACC ) = ( '度' , '分' , '秒' , '北緯' , '南緯' , '東経' , '西経' , '高度' , '測地系' , '測位精度');
# 設置場所関連(非変更を推奨)
$ConfigFile ='./config.txt';
$LogDir = '.';
# URLは自動取得。サーバによってうまくいかない場合は、ここを変更。
$U="http://$ENV{HTTP_HOST}$ENV{SCRIPT_NAME}";
# device:gpsoneを呼び出すURI
$R = "device:gpsone?url=$U&ver=1&datum=$DatumCode&unit=0&acry=0&number=0";
### メインルーチン
# 引数の取得と判断
$_ = $ENV{'QUERY_STRING'};
if ( /^(log.*)/ ) {
# ログファイル名であれば、地図を表示
putGoogleMap( $1 );
# エラーになって戻ってきたら、標準画面を表示
putDefaultMenu();
} elsif ( /lat=/ && /¥&/ ) {
# device:gpsone が吐き出すものであれば
readConfig();
if ( $l ne '' ) { $l = '-' . $l }
if ( -e "log$l" ) {
open( LOG , "+>>$LogDir/log$l" );
seek( LOG , 0 , 2 );
} else {
open( LOG , ">$LogDir/log$l" );
}
print LOG "$_¥n";
close LOG;
putHdml();
} elsif ( /^menu/ ) {
# ログを選ぶメニュー
print "Content-Type: text/html¥n¥n";
print "imakoko.cgi --- LogMenu ";
print "imakoko.cgi --- LogMenu
¥n";
opendir( DIR , "$LogDir" );
@list = sort readdir( DIR );
closedir( DIR );
foreach( @list ) {
if ( /^log/ ) { print qq($_
¥n); }
}
print "¥n";
exit;
} else {
# 引数が無かったら、または不適なものであればメニューを表示
putDefaultMenu( $_ );
}
exit;
### サブルーチン
# putDeafultMenu --- 標準メニューを表示
sub putDefaultMenu {
my( $s ) = @_;
$s .= '&';
if ( $s =‾ /name=([^&]*)&/ ) {
my( $k ) = $1;
if( $k =‾ /[^_0-9a-zA-Z]/ ) {
$wl = "$k is not valid name. Write in [_0-9a-zA-Z]";
readConfig();
} else {
$l = $k;
}
}
if ( $s =‾ /intv=([0-9]*)&/ ) {
$v = $1;
writeConfig();
} else {
readConfig();
}
putHtml();
}
# readConfig --- ログ名、ログ間隔を設定ファイル($ConfigFile)から読み出す
sub readConfig {
if ( -e $ConfigFile ) {
open( IN , $ConfigFile );
my( @r ) = ;
close IN;
foreach( @r ) {
if ( /LogName=([_0-9a-zA-Z]*)/ ) { $l = $1 }
if ( /Interval=([0-9]+)/ ) { $v = $1 }
}
} else {
$l = ''; $v = 600;
}
}
# writeConfig --- ログ名、ログ間隔を設定ファイル($ConfigFile)に保存する
# エラー処理が甘い?
sub writeConfig {
open( OUT , ">$ConfigFile" );
print OUT "LogName=$l¥nInterval=$v¥n";
close OUT;
}
# putHtml --- メニューのHTML部分を表示する
# $U : url identified me , $R : gpsone , $l : LogName , $wl : About LogName
# $v : interval ( * 0.1 sec. )
sub putHtml
{
print "Content-type: text/html¥n¥n";
print <<"END_OF_HTML";
imakoko.cgi
imakoko.cgi --- Main Menu
StartLog
ReadLog
END_OF_HTML
exit;
}
# putHdml --- au携帯電話に渡すHDML部分を表示する
sub putHdml {
my( $s ) = @_;
my $date;
$date = localtime(time);
print "Content-Type: text/x-hdml¥n¥n";
print <<"END_OF_HDML";
imakoko.cgi
$date
Logging Now
Back to MainMenu
END_OF_HDML
exit;
}
# putGoogleMap --- ログをGoogleMap上に表示する
sub putGoogleMap
{
# ログの取得
my( $s ) = @_;
if ( !-e $s ) { return; }
open( FILE , $s );
@logBody = ;
close FILE;
# ログの処理
foreach( @logBody ) {
s/%([A-Fa-f0-9][A-Fa-f0-9])/pack("c", hex($1))/ge;
# 引数を変数名として取得
foreach $key ( lat , lon , alt , 'time' , datum , vert , fm ) {
if ( /$key=([^&]*)/ ) { $$key = $1 } else { $$key = '' }
}
if ( ( $lat eq '' ) || ( $lon eq '' ) ) {
# lat , lon が無ければ無視
next;
} else {
foreach $key ( lat , lon ) {
$_ = $$key;
s/([-+]*[0-9]+)¥.([0-9]+)¥.([0-9.]+)/$1$DEG$2$MIN$3$SEC/;
$$key = $1 + $2 / 60 + $3 / 3600;
$skey = 's' . $key;
$$skey = $_;
}
$slat =‾ s/^¥+/$DirN/;
$slat =‾ s/^¥-/$DirS/;
$slon =‾ s/^¥+/$DirE/;
$slon =‾ s/^¥-/$DirW/;
$time =‾ s|(¥d¥d¥d¥d)(¥d¥d)(¥d¥d)(¥d¥d)(¥d¥d)(¥d*)|$1/$2/$3 $4:$5:$6|;
$fm = ( 'GPS-FIX' , 'Hybrid-FIX' , 'AFLT-FIX' , 'SECTOR-CENTER' )[ $fm ];
$datum = ( 'WGS-84' , 'TKY' )[ $datum ];
$s = "$slat¥n$slon¥n$sALT:$alt m¥n$time¥n$sDAT:$datum¥n$sACC:$fm¥n";
$s =‾ s/¥n/
/g;
$s = qq($s);
push( @L1 , qq|new GPoint( $lon , $lat ),'$s'| );
push( @L2 , qq|new GPoint($lon ,$lat)| );
$clat = $lat; $clon = $lon;
}
}
# GoogleMapの描画
print "Content-type: text/html; charset=$Charset¥n¥n";
## ヘッダ部分と当初部処理
print <<"END_OF_HEAD";
END_OF_FOOT
exit;
}
1;