2015年12月8日

地震とか火山噴火情報を閲覧できるWebサイトを作った

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
作るのを思い立ってから半年くらい掛かった... (実質作業時間は短い)

地震火山詳報
http://evi.prioris.jp

地震と火山(桜島に限らない)に関する気象庁XML電文情報と、それに付随する情報を配信するWebサイトです。
これの立ち上げに伴い、桜島詳報を閉じました。
現時点では火山噴火情報は未実装ですが、統合するつもりで地震火山詳報とネーミングしたので、近々実装します。
と言っても、桜島詳報のコードをちょっと改造して合体させるだけなのですが、最近全国的に火山活動が落ち着いているのでモチベーションが...
実装しました!
12月12日より、噴火に関する火山観測報も追加しました。
桜島詳報では桜島の噴火・爆発のみを扱っていましたが、地震火山詳報では桜島以外の火山(阿蘇山など)の情報を配信されます。

発生した地震の詳細ページでは、震源と揺れを観測した地域の震度がGoogle Mapsライクな操作感で閲覧できます。
例 : 震源・震度情報(2015年12月4日 5時40分頃に発生した地震) - 地震火山詳報

震源や震度のアイコンをクリックすると、上記画像のように地名や座標が表示されます。
地図はOpenStreetMapを使っています。
あとレスポンシブ対応なのでスマホでもPCでも良い感じに閲覧可能です。

地震火山詳報は、地震に関する情報をTwitterとPushbulletでも配信しています。
(Pushbulletって何?っていう人は、EngadgetとかLifehackerの記事を読むといいです。)

Twitter : @Prioris_EVI
Pushbullet : #earthquake_jp

上記Pushbulletのチャンネルは、日本全国のすべての地震(震度1〜)をプッシュ通知で教えてくれるので若干鬱陶しいです。
(日本全国でこんな頻度で地震が起きてるんだ〜!っと認識するのには最高ですが)
というわけで、震度3以上の地震があった時だけプッシュ通知してくれるチャンネルもあります。

Pushbullet : #earthquake_int3over

桜島、阿蘇山の噴火・爆発時プッシュ通知はYoにて配信しています。

Yo : SAKURAJIMA (鹿児島県 桜島の噴火・爆発時に配信)
Yo : ASOSAN (熊本県 阿蘇山の噴火・爆発時に配信)

技術的な話


以下の記事の集大成みたいな感じです。

PostgreSQLとPostGISで国土数値情報(行政区域)を扱ってみる (2015/06)
PostGISで気象庁の細分区域&市町村等に対応する重心を求める (2015/06)
OpenLayers 3で気象庁発表の震度をマッピングする (2015/07)
OL3で扱える地図タイルをShapeから生成する (2015/12)

あと、ベースとして以下も。
桜島が噴火したYoの裏側 (2014/08)

上記の記事中にも書いていますが、気象庁XML電文から震度マップ(GeoJSON)を作るのに必要なデータやGeoJSON生成コードはオープンソースとして公開しています。

9SQ/jma-eqarea-centroid (気象庁が用いる地域区分の重心座標テーブル)
9SQ/jma-eqxml2geojson (気象庁XMLから上記テーブルを利用してGeoJSONを生成する)
9SQ/seismic-intensity-map (震度GeoJSONをOpenStreetMapにオーバーレイ表示する)

...以下詳細...

気象庁から送られてくる震源・震度に関する情報のXML電文には、発生時刻や地震の規模を表すマグニチュード、震源地の座標、津波に関するコメント、そして揺れを観測した地域の地域コードと地名、震度が含まれています。
このXML電文から、震源地の座標を地図にプロットするのは非常に簡単ですが、各地の震度を、その地域の中心となる場所にプロットするというのが結構面倒です。
というのも、気象庁は地域コードや地名のテーブルは公開していますが、その中心(厳密に言えば重心)座標は提供していません。
また、気象庁の区域割りはちょっと特殊で、例えば「石狩地方北部」みたいに、ある程度の市区町村をまとめていたりします。
そこで、まずこれらの区域の中心座標を求めよう、ということで...

1. PostgreSQLとPostGISで国土数値情報(行政区域)を扱ってみる (2015/06)
国土交通省から提供されている行政区域(群市区町村みたいな区域割り)のShapefileをPostgreSQLに読み込んで

2. PostGISで気象庁の細分区域&市町村等に対応する重心を求める (2015/06)
PostGISを使って気象庁が提供している区域とすり合わせて、重心を出力し、テーブルを作り

3. OpenLayers 3で気象庁発表の震度をマッピングする (2015/07)
作成した重心テーブルと気象庁XML電文からOpenLayersなどの地図システムで扱えるGeoJSON形式のデータを生成する

という流れで、震度を地図上のその地域の上に表示させることが出来ました。
ちなみに、表示される位置が中心ではなく重心なのは、地域の形が収まるバウンディングボックスから中心を求めてしまうと、突起やへこみ、極端に長細い岬が出ているような地形ではそれらに引っ張られて視覚的(感覚的?実際的?)な中心から外れてしまうからです。
重心をSQLを叩いてパッと計算(全国分計算するのには数分掛かりましたが)することができるのは、PostGIS最強としか言えません。

この生成した重心座標のテーブルは、上にもリンク張っていますが、GitHubに置いているので、これから気象庁による区域割りの地図上に何か情報を表示させるようなことをしたい方は使ってみてください。

裏側の話


昨年作った桜島の噴火情報配信サイト「桜島詳報」と若干設計が異なります。
以下は、桜島詳報とプッシュ通知システムの構成。


さらに詳しいスライド版はこちら

桜島詳報ではSubscriber自身に色々と他の処理もさせていました。
そして、詳細ページにアクセスする度にXML本体をパースしてサーバ側でページを組み立ていました。

今回のシステムでは、SubscriberはXMLの保存と、電文の種類別に行う動作を振り分けるBridgeに概要を渡すところまでさせています。
それと、概要とUUIDを一緒にMySQLへ入れていた処理を廃止して、XMLをJSONに変換してMongoDBに入れるようにしています。
(桜島詳報のシステムを合体させるために、元のXMLも一緒に保存しています)


今回のシステムでは電文が届く度にjsonが生成され、詳細ページにアクセスすると生成されたjsonを取得してクライアントサイドでページを組み立てていく仕組みです。

届いた電文が震源・震度情報の場合の処理は以下のとおり。


将来的にAPIとか公開するかもなぁーということで、複数のサーバに分けています。
(現時点では性能に余裕があるので1つのVPSの中に上記4つが詰まっている)
地震火山詳報は上記のEVIの部分になります。
今回新たにEDSという地震に関する情報を保存&提供するサーバと、AZMAPという日本の地図タイルを持っているサーバを作りました。

地震火山詳報の震源・震度情報一覧から任意の1ページを開くと、info.json(発生日時や最大震度、マグニチュードなどが入っている)、smallScalePoints.json(広域ポイント)、largeScalePoints.json(詳細ポイント)の3つがEDSからダウンロードされて、JavaScript(jQuery, OpenLayers3)で処理されます。

地震火山詳報のページ内では提供していませんが、情報を各種SNSに流す時に付属させるデータとして、震度マップをWebKitに描画させてキャプチャした画像も生成しています。
こんな画像がTwitterに震源・震度情報の概要と共に投稿されます。


似たような震源・各地の震度画像出力エンジンを作っている会社もありますが、こちらは普通のHTML/CSS/JSで記述されたWebページから画像を生成しているので、簡単に出力する画像のデザインが可能というわけです。

この画像地図は詳細ページの地図と違って、OpenStreetMapの地図タイルを使用していません。
国土交通省の国土数値情報(行政区分)Shapefileから地図タイルを生成して、使用しています。(この地図タイルを持っているのがAZMAPサーバ)

関連する話


これも公開していないのですが、気象庁XML電文が届く度にheadlineをJSONに変換して流しているWebSocketサーバも作って使っています。
これは、グローバルIPを持つサーバが無いと受け取れない気象庁XML電文を、どこでも受信できるように...という考えで立てているのですが、キャパシティがそんなに無いので(今のところ)自分用です。
これをRaspberry Piで受けとって64x16ドットのフルカラーLEDマトリクスに表示させたりしている話は、また改めて記事にしようと思います。

感想と告知


  • 自分の想像(妄想)を形にするものづくりは楽しい。生きている、生きていける理由。
  • Web系欲が満たされたので、またしばらく組み込み系に戻ります。
  • 3か月くらい前から、はぐれエンジニアになって実家療養中です。

0 件のコメント:

コメントを投稿

記事へのコメントはいつも確認している訳ではないので、お返事が遅れる場合があります。
ご質問やご意見は twitter@9SQ へお送り頂けると早くお返事できると思います。