2011年03月04日

PHPでHTTPのマルチパートレスポンスをデコードする

 HTTPでファイルアップロード等をするときは enctype="multipart/form-data" を指定してマルチパートのデータをPOSTするが、その逆バージョンで、HTTPサーバがマルチパートになったデータを返してきた時の処理。ブラウザがあんまり対応していないせいか、PHPのライブラリでデコード処理が用意されていそうでいて、そんなことはないようだ。
 PEARのライブラリに、MIMEのマルチパートメールをデコードするMail_MimeDecodeがあるので、これを流用することにする。

 マルチパートレスポンスと言っても、メールのマルチパートと構造はほぼ一緒で、バウンダリを含むContent-typeがレスポンスヘッダにあるので、ヘッダのContent-typeとレスポンスボディをくっつけて、Mail_mimeDecode::decodeに渡してやればいいわけだ。PEAR の HTTP_Client で取れば、HTTP_Client::currentResponse の返値に ['headers']['content-type'] があるので、これをそのまま使える。

 というわけで、こんな関数を用意して
require_once("Mail/mime.php");
function decode_multipart_httpresp($contenttype, $body)
{
$data['include_bodies'] = true;
$data['input'] = "Content-type: ".$contenttype."\r\n\r\n".$body;

$res = Mail_mimeDecode::decode($data);

$ret = array();
foreach( $res->parts as $i => $obj){
$ret[ $obj->d_parameters['name'] ] = $obj->body;
}
return $ret;
}
HTTP_Clientで取ってきたデータをくべてやる。
require_once("HTTP/Client.php");
$client = new HTTP_Client();
$rcode = $client->get('http://usouso.hogehoge/xxx/');
$resp = $client->currentResponse();
$ret = decode_multipart_httpresp($resp['headers']['content-type'], $resp['body']);
var_dump($ret);
HTTPサーバが返却したマルチパートレスポンスがこんな感じだったとすると
HTTP/1.1 200 OK
Date: Fri, 13 Feb 2011 06:51:44 GMT
Content-Type: multipart/mixed; boundary=HoNgErAbOuNdArY
Connection: close

--HoNgErAbOuNdArY
Content-Disposition: form-data; name="param01"
Content-Type: text/html; charset=utf-8

HTMLデータ....

--HoNgErAbOuNdArY
Content-Disposition: form-data; name="param02"
Content-Type: image/jpeg

JPEGデータ...

--HoNgErAbOuNdArY
Content-Disposition: form-data; name="param03"
Content-Type: application/json; charset=utf-8

{
"JSON":"データ"
}

--HoNgErAbOuNdArY--
デコードしたらこうなる。
Array
(
[param01] => HTMLデータ....


[param02] => JPEGデータ...


[param03] => {
"JSON":"データ"
}
)
ただ、細かいところは、状況に応じて変える必要はある。マルチパートじゃないレスポンスが来たときとか、マルチパートの中身を更にデコードするとか、パート毎のcontenttypeを取るとか。
posted by usoinfo at 10:48 | Comment(0) | 開発 | このブログの読者になる | 更新情報をチェックする

2011年02月24日

逆ジオコーディング Windows版

 逆ジオコーダーを何かに組み込んで使ってみるテストその2、Windows用のアプリケーションにしてみた。(ダウンロードはこちらから)

urgeo_dump1t2.pngurgeo_dump2t2.png
 こんな感じ。GUI版とコマンドライン版があるが、機能は一緒。手元のマシンでの変換速度は、CSVを一括でくべたとき毎秒50〜100件程度。WebベースのAPIよりはずっと速い。まあ、ローカルに全部データを持っているわけだから当たり前だが。

 変換エンジン部はDLL化して、別のアプリケーションから組み込まれて使うことも一応想定した。と言っても、今のところ車載PCで動かす以外の用途は、あまり思いつかないな。
posted by usoinfo at 07:33 | Comment(0) | 開発 | このブログの読者になる | 更新情報をチェックする

2011年02月20日

TinycoreでUSB接続のGPSを使う

 ND-100というUSB接続のGPSレシーバーを買ったのである。多分これの1世代前のやつなんじゃないかと思う。
 今車載しているのは、Holux M-241cというGPSレシーバーで、Tinycoreで全くちゃんと動いていて問題もないのだが、車内の設置場所はダッシュボード上で今後夏に向かうことを思うと壊れてもいい安い奴に付け替えようと考えたのである。
 後者はPCがなくても単体で電池でレシーバーとして使えるが、前者はPCに繋がなきゃならない分、安い。
 こんなの。IMG_6472s.jpg

これを、Tinycoreで使う手順。

1. usb-serial のドライバを入れる。
PL2303は、パッケージが提供されているのでラクチン。Appsからusb-serial-2.6.33.3-tinycore.tczを選んで入れるか、tce-load -wi usb-serial-2.6.33.3-tinycore.tcz する。32bit版と64bit版があるので、64bitの人はそっちを入れる。

2. USBにGPSレシーバを繋ぐ。
繋いだら、モジュールがロードされるはずである。lsmod して、
tc@tinycore:~$ lsmod
Module Size Used by Not tainted
pl2303 10020 0
usbserial 18876 1 pl2303
...
usbserial と pl2303 がロードされているか確認。

3. gpsd を動かす。
gpsdもパッケージから入る。gpsd.tczを入れればOK。
入れたら、gpsd とGPSレシーバを繋ぐ。GPSレシーバは、多分(他のUSBシリアルの機器を繋いでなければ)/dev/ttyUSB0に見えているはずである。
tc@tinycore:~$ ls /dev/ttyUSB0
/dev/ttyUSB0
ここに、シリアルの速度をsttyでセットして、gpsdを上げる。
tc@tinycore:~$ stty 38400 < /dev/ttyUSB0
tc@tinycore:~$ gpsd -b /dev/ttyUSB0
tc@tinycore:~$ ps a|grep gpsd
2856 tc gpsd -b /dev/ttyUSB0
ND-100やM-241cは38400bpsだが、ここはそれぞれのGPSレシーバの速度に合わせて適切な値にセット。gpsdが走っているのを確認したら、GPSからのダンプデータを読んでみる。ncで2947番を覗く。
tc@tinycore:~$ echo "?WATCH={\"nmea\":true};" | nc localhost 2947
{"class":"VERSION","release":"2.96~dev","rev":"2011-01-21T22:13:04","proto_majo
r":3,"proto_minor":3}
{"class":"DEVICES","devices":[{"class":"DEVICE","path":"/dev/ttyUSB0","activate
d":1298097752.25,"flags":1,"driver":"Generic NMEA","native":0,"bps":38400,"pari
ty":"N","stopbits":1,"cycle":1.00}]}
{"class":"WATCH","enable":true,"json":false,"nmea":true,"raw":0,"scaled":false,
"timing":false}
$GPRMC,064232.000,A,****.****,N,*****.****,E,0.0,158.6,190211,,,A*61
$GPGGA,064232.000,****.****,N,*****.****,E,1,09,1.0,80.0,M,12.8,M,,0000*68
$GPVTG,158.6,T,,M,0.0,N,0.0,K,A*07
$GPGLL,****.****,N,*****.****,E,064232.00,A,A*66
$GPGSA,A,3,05,08,09,15,18,21,26,27,28,,,,1.9,1.0,1.6*3D
こんな感じでNMEA0813センテンスが流れてくれば、動作している。他のLinuxでも、大体似たような手順で使えるようになるはずである。
タグ:Tinycore Linux GPS
posted by usoinfo at 11:35 | Comment(0) | 開発 | このブログの読者になる | 更新情報をチェックする

2011年02月19日

TinycoreでXvesaが使えない時にXorgにする

我が家にいる、10年選手のDynabook SS/S5は、いろいろなLinuxを入れては、開発用マシンとして静かな余生を送っている。
そのSS/S5に、Tinycoreを入れようとしたところ、Xvesaが立ち上がらないのでCD-ROMからブートしても画面が出ない。Ubuntu10.04はちゃんとXが使えているので、使えないはずはない。
というわけで、TinycoreでXが上がらないときの対策。使用したのはTinycore3.5。

1. まずCD-ROMのブートで "tinycore text superuser" でテキストモードで上げる。上がってプロンプトが来たら、usbinstall でTinycoreをインストールする。

2. インストールした先からTinycoreをブートするが、まず "tyinycore text" でテキストモードで上げる。プロンプトが来たら、tce-load -wi Xorg-7.5.tcz でXorgをインストールする。startx でXが上がれば、Xorg動作OK。

3. /etc/X11/xorg.conf を作る。cp /etc/X11/xorg.conf.vesa /etc/X11/xorg.conf でOK。
ついでに、キーマップを日本語に変えるときは、xorg.conf に以下の行を追加。
Section "InputDevice"
Identifier "Keyboard0"
Driver "kbd"
Option "XkbLayout" "jp" # この行追加
Option "XkbModel" "jp106" # この行追加
EndSection


4. vi で /opt/.filetool.lst を開き、etc/X11/xorg.conf と1行追加。(編集するのは.xfiletool.lstではない)

5. リブートすれば、Xが使えるようになっている。はず。この辺が参考になる。


ついでに、usbinstallは、ディスクのパーティションテーブルを全部ぶっ飛ばして全体をパーティションしてからインストールしようとするので、既に他のOSが入っていると具合が悪い。そんなときは、usbinstall のスクリプトをちょっと書き換える。

まずあらかじめfdiskでインストール先のパーティションを切っておく。
TinycoreをCD-ROMから上げたら、rootになって、/usr/bin/usbinstallusbhdd_setup(FATに入れる時) またはusbext_setup(extに入れる時) を書き換える。
  dd if=/dev/zero of=/dev/$DEVICE bs=1k count=1 >/dev/null 2>&1 &
この行がパーティションテーブルをぶっ飛ばしているのでコメントアウト。
  fdisk /dev/$DEVICE << EOF >/dev/null 2>&1
n
p
1


a
1
t
6
w
EOF
ここがfdiskをしているので、ここもコメントアウト。
  dd if=/usr/local/share/syslinux/mbr.bin of=/dev/$DEVICE
ここがMBRを書き換えてるので、既に入ってる他のブートローダーを使うときは、ここもコメントアウト。

そして
TARGET="$DEVICE"1
この 1 を、インストールしたいパーティション番号に変える。全部できたら、usbinstall を普通に実行すればOK。

ちなみに、ディスクはぶっ飛ばしてもいいけどパーティションサイズだけは指定値にしたい、と言うときは、fdisk しているところの<< EOF から EOFまでの間の、空白の2行のうち下の空行を、サイズを +(サイズ)M と変える。
  fdisk /dev/$DEVICE << EOF >/dev/null 2>&1
n
p
1

+1024M
a
1
t
6
w
EOF
こんな感じにすると、1Gのパーティションが切れる。

まあ、スクリプトを読んでみれば、別段難しいことはしていないのだが、Tinycoreはこういうカンタンなところが扱いやすくていい。
タグ:Linux Tinycore
posted by usoinfo at 13:49 | Comment(0) | 開発 | このブログの読者になる | 更新情報をチェックする

2011年02月18日

CentOSのBASEリポジトリをローカルにミラーする

何台もあるとupdateにかかる時間も結構あるので、ローカルにリポジトリを作っておいてもいいかなと思って。
#!/bin/sh

SOURCE=ftp.riken.jp/centos/5 # リポジトリの取得元
INSTALLDIR=/mnt/centos/5 # ローカルの配置先
TARGETS="addons centosplus contrib extras isos os updates"
# 取得するツリー。必要なものだけあればいい。
# アップデートだけなら "os/x86_64 updates/x86_64" とかで足りる。

for DIR in ${TARGETS}
do
mkdir -p ${INSTALLDIR}/${DIR}
rsync -rptv --delete rsync://${SOURCE}/${DIR}/ ${INSTALLDIR}/${DIR}/
done
あとはapacheでリポジトリのディレクトリが見えるようにして、/etc/yum.repos.d/CentOS-Base.repo でbaseurlを向けてやれば完了。
タグ:Linux CentOS
posted by usoinfo at 07:50 | Comment(0) | 開発 | このブログの読者になる | 更新情報をチェックする

2011年02月14日

Google App Engine で Hello World! を公開する(約15分)

無料で使えるなら、使ってみようじゃないか、と思って、ちょっと触ってみた。Hello World!まで到達するのに15分の手順。

1. (なければGoogleのアカウントを作って)Google App Engine にログイン。
http://code.google.com/intl/ja/appengine/

2. AppEngineのアカウントというかアプリケーションというかドメイン名というか、を登録。
'App Engine アカウントを登録します。' から進むか、https://appengine.google.com/ へ行く。
Application Identifier は必須項目で、作ったアプリケーションにアクセスする http://xxxxx.appspot.com/ の xxxxx になるので、適切なものを決める。

3. 開発環境を整備する

Pythonをダウンロードしてインストール。Pythonは2.x系でないといけないらしい(Googleの説明には2.5.2と書いてある)。今回は2.7.1があったのでそれにした。http://www.python.org/download/ から。
更に、GAE SDK for Python をダウンロードしてインストール。http://code.google.com/intl/ja/appengine/downloads.html から。

Google App Engine Launcher を実行すると、Pythonの実行ファイルへのパスがないよと言われたりするので、メニューの Edit -> Preferences で設定。
Python Path には、インストールしたpython.exeを指定。
App Engine SDK には、GAE SDKのルートを指定。
Editor には好きなものを。

4. アプリケーションを作る
File -> Create New Application で新しいアプリケーションを作成。
Application name は、2. で登録した xxxxx を指定する。その他は人それぞれに適当に。

Createすると、指定したフォルダに main.py, app.yaml, index.yaml ができる。
とりあえず main.py がHello Worldしてる本体。ちらっと見ると、Hello World!を出力しそうな感じのコードが書いてある。

Google App Engine Launcher で作ったアプリを選んでRun。ブラウザから、http://localhost:8080/ (ポートは人それぞれ) にアクセスして、Hello World! が出てくればOK。

5. アプリケーションのアップロード
Google App Engine Launcher で作ったアプリを選んでDeploy。Googleアカウントのメールアドレスとパスワードを入れると、アップロードされる。
できたら、http://xxxxx.appspot.com/にアクセス。Hello World!が出てくればOK。

後は、やりたいことを main.py 他にコーディングするだけだ。


これだけでは何なので、GAEで外部のwebページを取ってくるサンプルコード。GAEのurlfetch を使う。
from google.appengine.ext import webapp
from google.appengine.ext.webapp import util
from google.appengine.api import urlfetch

class MainHandler(webapp.RequestHandler):
def get(self):
url = '取ってくるURL'
html = '取ってきたデータがここに'
try:
result = urlfetch.fetch(url)
html = result.content
except urlfetch.InvalidURLError:
html = 'InvalidURLError'
except urlfetch.DownloadError:
html = 'DownloadError'
except urlfetch.ResponseTooLargeError:
html = 'ResponseTooLargeError'
except urlfetch.Error:
html = 'Error'
self.response.out.write(html)

def main():
application = webapp.WSGIApplication([
('/', MainHandler),
],debug=True)
util.run_wsgi_app(application)

if __name__ == '__main__':
main()
Pythonはじめて触った。謎い。
タグ:Python GAE
posted by usoinfo at 11:26 | Comment(0) | 開発 | このブログの読者になる | 更新情報をチェックする

2011年02月13日

逆ジオコーディング Twitter BOT

 逆ジオコーダーを何かに組み込んで使ってみるテスト、ということで、緯度経度をつぶやくと住所に変換するTwitterBOTを作ってみた。ただまあ正直、何に使うのかは作った本人もよくわからない

 使い方。@usogeo2addr に緯度経度を半角数字でつぶやく。例えばこう。
@usogeo2addr 34.39.11.68 133.55.22.44
5〜20分くらい待つと、BOTが住所に変換した結果をreplyしてくる。(詳しくは説明書きを)

 BOTの処理本体はland.toのサーバに置いてあって、www.mywebcron.comを使って定期的に呼び出しているのだが、安定度が今ひとつ。land.to は時々、ファイルがあるのに404を返すことがあったり、mywebcronは混雑のためか、設定値より大きく遅れてcronが動くことがあったり。なので、あまりリアルタイム性はない。でもまあ、無料のサービスでできるんだから、不平を言うようなものでもなく、むしろありがたいくらいのものだ。

 本当は、Twitter のツイートに含まれる位置情報を取って、何でも受け取ったツイートからその住所を返せればいいんだけど、どうやらまだ位置情報追加機能は米国のみのサービスらしく、どうも位置情報を入れたstatus updateをくべても、位置は取れないようである。ちょっと残念。使えるようにならんかなあ。
posted by usoinfo at 16:48 | Comment(0) | 開発 | このブログの読者になる | 更新情報をチェックする

2011年02月09日

Windows・VC++でZlibを使う(VisualStudio2008)

圧縮展開と言えばZlibがお手軽。Linuxではlibzがほぼ標準で入ってるから何も考えず使えるが、Windowsでは自分でzlibをコンパイルしないといけない。いやまあ、勿論、コンパイル済のDLLを使ってもいいんだけど、zlib.netに置いてあるのはまだ1.2.3だとか、アプリのexeに埋め込みたいとか、そういうことを考えると、自前でコンパイルしておきたいのであった。
というわけで、Windowsでzlibを使うための手順。コンパイルした環境は Visual Studio 2008。

まずはhttp://www.zlib.net/からzlibのソースを持ってくる。今日の段階で最新版は1.2.5。取ってきたら解凍する。"ほにゃらら\zlib-1.2.5" というフォルダができる。

ReadMeとかを読み散らかしてもWindows用のコンパイル手順がねえなあ、と思ったら、win32\Makefile.msc の中にVC++用の例があった。ただ、このままだと微妙に、普通のMFCアプリから使いにくいので、ちょっと変更する。

要点は、コンパイラオプションに、"/MD" じゃなくて、使いたいものに合わせる。普通のMFCアプリケーションは、リリースビルドで /MT、デバッグビルドで /MTd なので、このままだとリンカで_mallocとかが重複宣言と言われるから。
さらに、デバッグビルドは "/Zi" じゃなくて "/Z7" にして PDBも作る。無視してもいいけど、デバッグビルドでリンカが、"PDBがない" と警告するから。

zlib-1.2.5\win32\Makefile.msc をエディタで開き、14行目あたりに、追加のオプションの変数を足して、
# optional build flags
LOC =
OC =
OL =
27行目、30行目あたりの、コンパイラオプションとリンカオプションをちょっと変える。
CFLAGS  = -nologo -W3 -O2 -Oy- -Fd"zlib" $(LOC) $(OC)
LDFLAGS = -nologo -debug -incremental:no -opt:ref $(OL)
そしたら、コンパイル。コマンドプロンプトを開き、
> cd ****\zlib-1.2.5

VC++の環境変数を読み込む。
これはインストールした環境によって場所が違うと思うので適当に読み替えて実行。
> "C:\Program Files\Microsoft Visual Studio 9.0\VC\bin\vcvars32.bat"

そして、リリース用なら
> nmake -f win32\Makefile.msc LOC="-DASMV -DASMINF" OBJA="inffas32.obj match686.obj" \
OC="/MT"

デバッグ用なら
> nmake -f win32\Makefile.msc LOC="-DASMV -DASMINF" OBJA="inffas32.obj match686.obj" \
OC="/MTd /Z7" OL="/PDB:zlib.pdb"


コンパイルに成功すれば、zlib1.dll,zdll.lib,zlib.lib (デバッグビルドならzlib.pdbも) ができる。
後は、DLLを使うなら zlib1.dll と zdll.lib を使うか zlib1.dll とGetProcAddressを使うなり、staticに組み込むなら zlib.lib をリンカの入力オプションに追加すればよい。

圧縮するときは
	UINT	ss,ds,clen;	// データサイズ
BYTE* ps,pd; // データバッファ
// ss に入力データサイズ、ps に入力データ をセット
// ds に出力バッファサイズ、ds に出力バッファ をセット

z_stream z;
z.zalloc = Z_NULL;
z.zfree = Z_NULL;
z.opaque = Z_NULL;
deflateInit(&z, Z_DEFAULT_COMPRESSION)

z.avail_in = ss; // 元データのサイズ
z.avail_out = ds; // 圧縮データ格納先サイズ
z.next_in = ps; // 元データのポインタ
z.next_out = pd; // 圧縮データの格納先
deflate(&z, Z_FINISH);

clen = ss - z.avail_out; // 圧縮済のデータのサイズ
deflateEnd(&z);

展開するときは
	UINT	cs,ss,len;	// データサイズ
BYTE* pc,ps; // データバッファ
// cs に圧縮データサイズ、pc に圧縮データ をセット
// ss に出力バッファサイズ、ps に出力バッファ をセット

z_stream z;
z.zalloc = Z_NULL;
z.zfree = Z_NULL;
z.opaque = Z_NULL;
inflateInit(&z);

z.avail_in = cs;
z.avail_out = ss;
z.next_in = pc;
z.next_out = ps;
inflate(&z, Z_NO_FLUSH);

len = ss - z.avail_out; // 展開済データのサイズ
inflateEnd(&z);

こんな感じで。エラー処理は省略。
posted by usoinfo at 19:25 | Comment(0) | 開発 | このブログの読者になる | 更新情報をチェックする

2011年01月31日

postfixで "unable to look up public/pickup: Permission denied"

メール配送にはpostfixを使っているのだが、
usoinfo@usohost:/home/usoinfo% ls -al /usr/sbin/sendmail
lrwxrwxrwx 1 root root 21 6月 9 2010 /usr/sbin/sendmail -> /etc/alternatives/mta
usoinfo@usohost:/home/usoinfo% ls -al /etc/alternatives/mta
lrwxrwxrwx 1 root root 26 6月 10 2010 /etc/alternatives/mta -> /usr/sbin/sendmail.postfix
usoinfo@usohost:/home/usoinfo% ls -al /usr/sbin/sendmail.postfix
-rwxr-xr-x 1 root root 190164 8月 15 2008 /usr/sbin/sendmail.postfix
rootでないユーザー、例えばapacheとかで、cat hoge.txt | /usr/sbin/sendmail uso@aho.aho とかしてメールを送ろうとすると、
Jan 31 08:00:37 usohost postfix/postdrop[32433]: warning: unable to look up public/pickup: Permission denied
とWarningが出る。メールは出ていったものの、何かいけない気がする。どうすりゃいいんだろう。

わからん。わからんので、postfix check。
[root@usohost ~]# postfix check
postfix/postfix-script: warning: not owned by group postdrop: /usr/sbin/postqueue
postfix/postfix-script: warning: not owned by group postdrop: /usr/sbin/postdrop
[root@usohost ~]# chgrp postdrop /usr/sbin/postqueue
[root@usohost ~]# chgrp postdrop /usr/sbin/postdrop
ownerがpostdropじゃない、と怒られた。設定してもう一度。
[root@usohost ~]# postfix check
postfix/postfix-script: warning: not set-gid or not owner+group+world executable: /usr/sbin/postqueue
postfix/postfix-script: warning: not set-gid or not owner+group+world executable: /usr/sbin/postdrop
[root@usohost ~]# chmod 2755 /usr/sbin/postqueue
[root@usohost ~]# chmod 2755 /usr/sbin/postdrop
今度はSGIDビットが立ってないと怒られた。設定してもう一度。
[root@usohost ~]# postfix check
[root@usohost ~]#
許されたようだ。Warningは出なくなったので、とりあえずこれでよしとしよう。

忘れがちなSUID/SGIDのまとめ。
chmodのアタマに4でSUID。ファイルのオーナーの権限で実行。
chmodのアタマに2でSGID。ファイルのグループの権限で実行。
ファイルのオーナーとグループをちゃんと確認してからビットを立てるようにしよう。
タグ:Linux postfix
posted by usoinfo at 08:25 | Comment(0) | 開発 | このブログの読者になる | 更新情報をチェックする

2011年01月23日

逆ジオコーディング 緯度経度から住所へ変換する

 緯度経度から住所に変換する機能を作ってみたのである

 うちの車に積んであるカーナビは、WindowsCEにSDを挿して動く安価なポータブルナビ(これではないが、こんな感じの。というかこのユピテルYPL433siはゼノサーガのKOSMOSの声でナビってくれるらしい。すげえ欲しい。)で、地図もなにも全データひっくるめて2Gしか持っていない。でも、走っている現在位置の大まかな地名(××県○○市、くらい)は表示してくれる。無論、単なる安ナビなので、ネットワークには繋がっていない。スタンドアローンである。この表示は、勿論、緯度経度の情報から現在の住所を探索しているわけだ。

 緯度経度からその住所を引く、これを逆ジオコーディング(Reverse Geocoding)と呼ぶらしい。緯度経度を住所に変換したいだけであれば、そんなに難しいことはなく、巷にあるいわゆる地図サービスを使えばいいわけである。例えば、Yahoo!地図やマピオンで緯度経度で地図を表示させれば、HTMLのどこかに「××県○○市△△町周辺」等という文字列が出てくるし、あるいはもっとちゃんとするならGoogle Mapの逆ジオコーディングAPIもある。それで、車載したGPSから取った緯度経度を、サーバに投げて地図サービスを引いて住所に、等ということをしていたのである。

 が、不満がなくはないのである。
 外部のサービスはネットワークが繋がってないと使えないので、通信できないところでは使用できない。電波の届かないところを走るときだってあるので、若干不便である。ではローカルデバイスの中だけでなんとかしようと思うと、この変換データというのが大きくて、軽々に導入できそうにない。国交省の位置参照情報データは、CSVで1Gもある。保持しておくのも大変だし、探索も大変である。
 そんなわけで、外部のサーバを使わない、組み込み可能な逆ジオコーディング機能を作ったらどんな塩梅になるかと思って作ってみたのである。
 これである。緯度経度住所コンバータ

 軽量にしようといろいろ試行錯誤した結果、街区符号以下は諦めることとして、丁目番地・大字レベルまでのデータで、圧縮かけて大体25Mくらいのデータサイズになった。というか、かなり頑張ったんだけど、これ以上データサイズを減らす方法を思いつかなかった。内訳は、参照ポイントデータに21M、都道府県市区町村名に0.2M、丁目番地に3.8Mである。参照ポイント数は、元の約1200万から1/4くらいに減らしている。まあ、レンタルサーバの容量が100Mなので、25Mはまあまあ安心できるサイズではあろうか。探索時間は入力と状態によるだろうが、最大10秒くらい。これも、短縮しようとすると参照ポイントデータに細工が必要で容量が増えたりするので悩ましいところ。実用性とのバランスが難しい。

 例えば、北緯35.42.29.83東経140.52.10.36は、「千葉県銚子市犬吠埼」。探索3秒。うーむ、あとどこに改良の余地があるだろう。。。
posted by usoinfo at 11:54 | Comment(0) | 開発 | このブログの読者になる | 更新情報をチェックする