WebSubの仕組みで気象庁防災情報をリアルタイムに受け取ろう

WebSubの仕組みで気象庁防災情報をリアルタイムに受け取ろう:


��はじめに

地震や台風のような災害情報をリアルタイムに取得する方法はないかと、「気象庁 情報取得」で検索してみたところ、気象庁が公開している「気象庁防災情報」を見つけました。

今回は、この「気象庁防災情報XMLデータ」を受け取るAPIを作って、リアルタイムに更新情報を受け取ってみます。


��気象庁防災情報XML

気象庁が2013年からをXMLで公開している各種災害情報。

提供も、更新情報を自分で取りに行くPULL型だけではなく、更新情報を知らせてくれるPUSH型でも提供しています。

��参考:気象庁防災情報XMLフォーマット 情報提供ページ

今回はこのPUSH型を使って、情報を受け取ります。
仕組みとしてWebSubという、オープンな標準プロトコルを利用して、更新情報を知らせてくれます。


pubsub.png



��WebSub

旧・PubSubHubbub。

データ変更を知らせる事を目的とした、出版者-購読者型(PubSub)の標準プロトコル。

主に、ニュースやブログのフィードの更新を知らせる時に使われている。

��参考:https://ja.wikipedia.org/wiki/WebSub

以下の3者で構成される。

  • 出版者(Publisher)

    • 情報を発信するプログラム。

      • 発信の際に、Hubに知らせる。
    • 今回は「気象庁防災情報」を提供するサービスが担当する。
  • 購読者(Subscriber)

    • 情報を購読するプログラム。
    • 今回は、自分で作る。
  • Hub

    • 出版者が情報を更新した事を、購読者に知らせる。
    • 今回は、Googleが用意しているHubサービスが担当する。


xml_push_image.png


出版者(Publisher)は「情報の更新」等のタイミングで、Hubに対してリクエストを送る。

リクエストを受けたHubは、事前に申請があった購読者(Subscriber)に対して、「更新情報」等を送る。


��作業手順

作業は、大きくは以下の3つの作業を行う。

  1. 購読者(Subscriber)の準備
  2. 気象庁に購読申請の登録
  3. 気象庁からの更新通知確認


��購読者(Subscriber)の準備


��購読者(Subscriber)とは

WebSubの仕組みで言う購読者(Subscriber)とは具体的に何かというと、Hubからのリクエストを受け取れる、REST API(以下、購読者API)です。

Hubは以下の2種類のリクエストを送ってくるので、この2種類のリクエストを受けられれば、購読者(Subscriber)です。

購読確認リクエスト

WebSubの仕組みでは、まずHubに購読申請リクエストを送ります。この購読申請リクエストの中に、購読者APIのURLもセットします。

すると、Hubから指定した購読者APIに対して、GETメソッドのリクエストが送られてきます。

リクエストのクエリストリングには、以下のパラメータがセットされています。

  • hub.verify_token

    • Hubに購読申請する時に指定した、文字列がセットされて送られて来ます。
    • 購読者APIにはHub以外からもリクエストが送れてしまうので、この値を確認する事で、成りすましを防ぎます。
  • hub.challenge

    • Hubが生成するランダムな文字列。
    • この値をそのままレスポンスボディにセットして、Hubにレスポンスとして返す事で、購読開始の意思表示とします。
  • hub.topic

    • Hubに購読申請する時に指定した、購読したいフィードのURL。
  • hub.mode

    • Hubからの購読開始の確認時は"subscribe"という文字列がセットされて送られて来ます。
    • ちなみに、購読終了の確認時は、"unsubscribe"という文字列がセットされます。
  • hub.lease_seconds

    • 購読意思確認リクエストは定期的に送られてくるもので、次回のリクエストまでの時間。
このHubからのリクエストに対してhub.challengeの値をレスポンスボディにセットして返すと、購読開始となります。

更新通知リクエスト

WebSubの仕組みでは、出版者(Publisher)からHubに更新通知リクエストがあれば、Hubは全ての購読者(Subscriber)に、更新通知をPOSTメソッドのリクエストで送ります。


��実装

Subscriberの準備方法については、気象庁で用意しているドキュメントに詳しく書かれています。

��参考:情報提供に係る仕様とSubscriberの構築について

APIサーバーに要件は無いけど、24時間365日の稼働を求められているので、今回はAWSのAPI Gateway+Lambdaで構築します。

今回作るプログラムの全体は以下の通りです。



websub.png


API GatewayでREST APIの作成

API Gatewayで、以下のようなエンドポイントを作ります。

パスは何でもいいので、わかりやすい名前で。 
 
■ 購読確認リクエスト受け取り用API 
[GET] /websub/subscribe 
  以下のクエリストリングを受け取ってLambdaに渡す。 
  ?hub.verify_token=○○&hub.challenge=○○&hub.topi=○○&hub.mode=○○&hub.lease_seconds=○○ 
 
■ 更新通知リクエスト受け取り用API 
[POST] /websub/subscribe 
  リクエストボディをそのままLambdaに渡す。 
Lambdaで内部処理の作成

今回は、node.jsで内部処理を書きます。

const verifyToken = 'himitsunoango'; 
 
/* API Gatewayに返す値の雛形 */ 
const callbackData = { 
        "statusCode": 200, 
        "headers": { 
          "Content-Type" : "application/json; charset=utf-8", 
          "Access-Control-Allow-Origin" : "*" 
        }, 
        "body": "", 
        "isBase64Encoded": false 
      }; 
 
/** 
 * メイン処理 
 * @param event : API Gatewayから渡される値 
 * @param context : Lambdaの各種情報 
 * @param callback : API Gatewayに値を返す時に使う 
 *  
 */ 
exports.handler = (event, context, callback) => { 
 
  console.log(JSON.stringify(event)); 
 
  let reqMethod = event.httpMethod; 
  let reqResource = event.resource 
 
  if (reqMethod === "GET" && reqResource === "/websub/subscribe") { 
    console.log("■ ■ ■ 購読確認処理の実行 ■ ■ ■"); 
    subscribe(event, callback); 
  }  
  else if(reqMethod === "POST" && reqResource === "/websub/subscribe") { 
    console.log("■ ■ ■ 受け取り情報の確認処理の実行 ■ ■ ■"); 
    console.log(event.body); 
 
 
    callbackData.body = "success"; 
    callback(null, callbackData); 
  } 
 
  context.done(); 
 
}; 
 
/* 購読確認処理 */ 
function subscribe(event, callback) { 
 
  /* 指定したトークンである事を確認(なりすましではない) */ 
  if (event.queryStringParameters['hub.verify_token'] !== verifyToken) { 
      callback(null, 'query string error (verify_token : ' + event.querystring['hub.verify_token'] + ')'); 
      context.done(); 
  } 
  /* API Gatewayへの戻り値(注意:bodyは文字列型で返す) */ 
  callbackData.body = event.queryStringParameters['hub.challenge']; 
  callback(null, callbackData); 
 
  return; 
} 
処理自体は大した事は書いていません。

[GET] /websub/subscribeにリクエストが来たら、購読の意思表示として、レスポンスボディにクエリストリングのhub.challengeの値をそのままセットして返しています。

[POST] /websub/subscribeにリクエストが来たら、リクエストのボディの内容(コンテンツの更新情報)を、とりあえずログに出力しています。


��動作確認

気象庁のドキュメントには必ず動作確認を行うように書かれているので、確認を行います。

手順については、気象庁のドキュメントに詳しく書かれていますが、参考までに流れを紹介します。

��参考:XML電文公開(PUSH型)に係る仕様とSubscriberの構築について

Google PubSubHubbub Hubで提供されている、debug機能で動作確認を行います。


debug0.png


購読者(Subscriber)をHubに登録

購読者(Subscriber)をdebugする機能は以下のような画面です。



debug01.png


必要なのは赤枠の部分です。以下のように値をセットして、[Do it!]ボタンを押下します。

  • Callback URL

    • 今回用意した、「購読確認リクエスト受け取り用API」のURLをセットします。
  • Topic URL

    • テストで購読するfeedのURL。何でもいいので、itmedeiaニュースのフィードを使います。
    • https://rss.itmedia.co.jp/rss/2.0/news_special.xml
  • Mode

    • 購読開始が上手く行くか確認したいので、Subscribeをセットします。
  • Verify token

    • 成りすましを防ぐための暗号。今回はLambdaのソースにhimitsunoangoと書いたので、その通りセットします。
[Do it!]ボタンを押下しても、画面上は特に何もありませんが、Hubは「購読確認リクエスト受け取り用API」に、購読開始の確認のリクエストを送っています。

Cloud WatchでAPI Gatewayのログを見ると、リクエストが送られている事を確認できます。



log1.png


購読者(Subscriber)に更新通知を送信

Hubに、用意した購読者(Subscriber)の購読申請が上手く行ったら、出版者(Punblisher)として、Hubに更新通知リクエストを送ります。

以下が、Publishのテスト画面です。


debug02.png


赤枠の「Topic URL」に値をセットして、[Do it!]ボタンを押下します。

  • Topic URL

    • 購読申請時にセットしたfeedのURLをセットする。
    • https://rss.itmedia.co.jp/rss/2.0/news_special.xml
[Do it!]ボタンを押下すると、出版者(Punblisher)がHubに、フィードの更新を通知するリクエストを送った時と、同じ振る舞いをします。

それを受けてHubは、購読者(Subscriber)に更新通知を送ります。

画面上では特に何も無いですが、 Cloud WatchでAPI Gatewayのログを見ると、「更新通知リクエスト受け取り用API」に、Hubからリクエストが送られている事を確認できます。

購読者(Subscriber)のエラーチェック

更新通知リクエストを受け取れたら、購読者(Subscriber)にエラーが無いかチェックします。



debug03.png


赤枠の部分を以下のように値をセットして、[Get Info]ボタンを押下します。

  • Callback URL

    • 今回用意した、「購読確認リクエスト受け取り用API」のURLをセットします。
  • Topic URL

    • 購読申請時にセットしたfeedのURLをセットする。
    • https://rss.itmedia.co.jp/rss/2.0/news_special.xml
診断結果が表示されるので、特に赤枠の項目でエラーが発生していない事を確認する。


check.png


テスト購読終了の申請を行う

テストはこれでOKです。

最後に、テストで購読申請したので、購読終了の申請を行います。



debug04.png


購読終了の申請は、Modeの値を"Unsubscribe"に変更して、[Do it!]ボタンを押下します。


��気象庁に購読申請の登録

ユーザー登録の申請は、以下でダウンロードできるtxtファイルに必要事項を記入して、メールに添付して送るだけです。

��参考:ユーザー登録について

登録まで2周間程度かかるような事が書かれていますが、今回は申請した翌営業日には登録が完了していました。


��気象庁からの更新通知確認

登録が完了しているので、「購読確認リクエスト受け取り用API」にリクエストが来ていないか、Cloud Watchで確認します。


log2.png


ログを見ると、無事に情報が受け取れているようです。

今回は、気象庁からの更新通知を受け取っておしまいですが、このデータを利用して、Slackに投げたり、PUSH通知として飛ばしたり、色々と活用できそうです。


参考

コメント