はじめに
加古川市オープンデータ API は、いわゆる REST API になっていて、追加で OAuth2 を使います。ちょうど facebook API や twitter API などと同じような構成です。利用する際の処理の流れは大きく分けて、OAuth2 の部分と、REST API の部分の二つにわかれます。
OAuth2
OAuth2 は少し難しく見えます(そして実際ややこしいです)が、OAuth2 の処理が終わった後、最終的には「アクセストークン」が発行されます。
なにはともあれ OAuth2 の処理を行うには、決められた手順を踏まないとできません。OAuth2 で使用する様々な文字列は、「利用申請兼通知書」で申請すると得られます。「利用申請兼通知書」ですが、「アカウントの登録」と「アプリの登録」の二つのパートがあります。初回に「アカウント発行」のみ行い、後で「アプリの登録」を行うということもできるはずです。とりあえずデータを閲覧したいというだけであれば、「アカウントの発行」のみで大丈夫です。どうやればいいのか十分わかっている場合は、両方同時に申請してもよいでしょう。
https://opendata-api-kakogawa.jp/odp/contact/
「利用申請兼通知書」のExcelシートの送付ですが、これはウェブのフォームで送付することができます(もちろん書面で送付することもできます)。必要な項目を記入して、加古川市の「スマイルメール」の送付フォームで添付ファイルとして送信してください。スマイルメールの件名は「加古川市オープンデータAPI 利用申請書兼通知書」と記入するとよいでしょう。
https://www.smilemail-kakogawa.jp/form/index.php?section_cd=1006
OAuth2 は様々な用途に汎用的に使えるように整備されてきたため、登場人物がたくさん出てきます。Authorization Code Grant が推奨される方法とされていますが、それが唯一の正解というわけではありません。自分が思い描いている形がどこに着地するかは、一度考えてみるとよいでしょう。
OAuth2 のガイドとしては「データ利活用基盤サービス(FIWARE)アプリケーション開発ガイド 認証認可編」が参考になります(注1)。チュートリアルでは「アクセストークン」が得られた後の処理方法について説明します。
データの取得
curl
でデータを取得してみます。ここでは「アクセストークン」を仮に 16b1f828-cbb2-4bde-a066-946594e01dc5
としています。実際に得られたものに置き換えて試してみてください。
curl -v "https://api.opendata-api-kakogawa.jp/orion/v1.0/queryContext" \
-X POST \
--header "Authorization: Bearer 16b1f828-cbb2-4bde-a066-946594e01dc5" \
--header "Content-type: application/json" \
--data '{"entities":[{"isPattern":"true","id":".*"}]}'
加古川市オープンデータ API で採用されている fiware-orion の NGSI v1 は少し変わった流儀をしていて、問い合わせのクエリで条件を request body で POST 送信します(v2 では GET に改められています)(注2)。
上の例は最小の例です。条件を追加すると絞り込みができます。isPattern
が true の場合は、id
に正規表現を指定します。fiware orion では、この正規表現は POSIX 正規表現で、glibc の拡張正規表現が使えます。つまり .*
で全てにマッチします。
jq
コマンドを通して整形すると結果が見やすくなります。ID だけ並べてみましょう。
$ curl -s https://api.opendata-api-kakogawa.jp/orion/v1.0/queryContext \
-X POST \
--header "Authorization: Bearer 16b1f828-cbb2-4bde-a066-946594e01dc5" \
--header "Content-type: application/json" \
--data '{"entities":[{"isPattern":"true","id":".*"}]}' \
| jq .contextResponses[].contextElement.id
"jp.opendata-api-kakogawa.AEDFacilities.Shikanren.1"
"jp.opendata-api-kakogawa.Transportaion.KakobusHigashikakogawa.1"
"jp.dev-necjfiware.PublicFacilities.Churinjo.1"
"jp.dev-necjfiware.Tourism.KanbeYukari.1"
"jp.dev-necjfiware.ChildcareCenter.1"
"jp.dev-necjfiware.BarrierFreeFacilities.1"
"jp.opendata-api-kakogawa.DisasterManagementFacilities.KinkyuHinanbashoHinanjo.1"
"jp.dev-necjfiware.CareOffices.Fukugou.1"
"jp.opendata-api-kakogawa.CareOffices.Fukugou.1"
"jp.opendata-api-kakogawa.ChildcareCenter.1"
"jp.opendata-api-kakogawa.BarrierFreeFacilities.1"
"jp.opendata-api-kakogawa.PublicFacilities.Churinjo.1"
"jp.opendata-api-kakogawa.Tourism.KanbeYukari.1"
"jp.opendata-api-kakogawa.FloodHazardMap.ShinsuiJisseki.1"
"jp.opendata-api-kakogawa.LandslideHazardMap.KyukeisyaHigaiSoutei.1"
"jp.opendata-api-kakogawa.LandslideAreaHazardMap.Sanpuku.1"
"jp.opendata-api-kakogawa.PondHazardMap.Tameike.1"
"jp.opendata-api-kakogawa.DisasterManagementFacilities.Tsunami.1"
"jp.opendata-api-kakogawa.DisasterManagementFacilities.Hinanjo.1"
"jp.opendata-api-kakogawa.DisasterManagementFacilities.KinkyuHinanbasho.1"
意外と少ないですね。実は一度に取得できる件数はデフォルトで 20 件に絞られています。query string に detail=on
を追加すると全体の件数も分かるようです。
$ curl -s https://api.opendata-api-kakogawa.jp/orion/v1.0/queryContext \
-X POST \
--header "Authorization: Bearer 16b1f828-cbb2-4bde-a066-946594e01dc5" \
--header "Content-type: application/json" \
--data '{"entities":[{"isPattern":"true","id":".*"}]}' \
| jq .errorCode.details
"Count: 1649"
このような処理は一般的に「ページネーション」と呼ばれます。fiware-orion のドキュメントもありますので、適宜ページを繰って読み出してください(注3)。
https://fiware-orion.readthedocs.io/en/master/user/pagination/index.html#pagination-using-ngsiv1
データの中身
NGSI ではデータの形が決まっていて、「あるデータ」は「ID で識別され、「属性を複数持つ」という形です。試しに 1 つだけ取り出してみましょう(説明のため内容を若干編集しています)。
$ curl -s "https://api.opendata-api-kakogawa.jp/orion/v1.0/queryContext?limit=1" \
-X POST \
--header "Authorization: Bearer 16b1f828-cbb2-4bde-a066-946594e01dc5" \
--header "Content-type: application/json" \
--data '{"entities":[{"isPattern":"true","id":".*"}]}'
| jq
{
"contextResponses": [
{
"contextElement": {
"type": "AEDFacilities",
"isPattern": "false",
"id": "jp.opendata-api-kakogawa.AEDFacilities.Shikanren.1",
"attributes": [
{
"name": "住所",
"type": "xsd:string",
"value": "加古川町本町194"
},
{
"name": "名称",
"type": "xsd:string",
"value": "中央消防署"
}
]
},
"statusCode": {
"code": "200",
"reasonPhrase": "OK"
}
}
]
}
上記の例では jp.opendata-api-kakogawa.AEDFacilities.Shikanren.1
が ID で、「住所」と「名称」という属性を持っています。
加古川オープンデータのサイトには複数のデータセットが登録されていますが、これらは同列に混ぜて取り出すことができるようになっています。取得の際に条件を追加して、例えば {"type":"AEDFacilities"}
を追加するときれいに 1 つのデータセットを抜き出せます。
用語 : Broker と context
fiware orion は data broker つまり、データを右から左に伝搬させる通知機能を持っています。一般的に言われる MQTT, AMQP や kafka で登場する broker と同じものです。NGSI では、通知を受け取るには通知を受け取る HTTP エンドポイントを subscribe します。NGSI-10 の notifyContext
を使います。fiware orion はデータ登録先の機能を持ちますし、データの更新をトリガーとして通知を伝搬するブローカーとしても動作します。
これを試すには通知を受け取るサーバが必要になります。GCP の無料インスタンスなどを使って実験するとよいでしょう。次に subscribe と unsubscribe の例を示します。
$ curl "https://api.opendata-api-kakogawa.jp/orion/v1.0/subscribeContext" \
-X POST \
--header "Authorization: Bearer 16b1f828-cbb2-4bde-a066-946594e01dc5" \
--header "Content-type: application/json" \
--data '{"entities":[{"isPattern":"true","id":".*"}],
"reference":"http://example.com/v1/notify"}'
| jq
{
"subscribeResponse": {
"subscriptionId": "5b35ee3b0c736c3c77d0df75",
"duration": "PT24H"
}
}
$ curl "https://api.opendata-api-kakogawa.jp/orion/v1.0/unsubscribeContext" \
-X POST \
--header "Authorization: Bearer 16b1f828-cbb2-4bde-a066-946594e01dc5" \
--header "Content-type: application/json" \
--data '{"subscriptionId":"5b35ee3b0c736c3c77d0df75"}'
| jq
{
"subscriptionId": "5b35ee3b0c736c3c77d0df75",
"statusCode": {
"code": "200",
"reasonPhrase": "OK"
}
}
上記の例では、有効期間を省略しました。デフォルトでは PT24H
の24時間になるようです。期限が切れる前に定期的にアップデートしましょう。この期間が都合が悪い時は、subscribe 時に duration
パラメータを指定しましょう。ISO8601 の表記方法なので、例えば P1M は P
= period, 1M
= 1 month となります(注3)。
fiware orion へのデータ更新は、単なる登録データの更新のように見えます。fiware orion から離れて、もう少し視点を高く持って NGSI の概念をもう少し広く見ると、データの登録をスイッチのオンオフのように考えることもできます。テレビを指し示すデータに "ON" を登録すると、実際のスイッチにも伝わってテレビが "ON" になる、といった具合です。このため NGSI の用語では、このデータのことを単なるデータとは呼ばずに、意識的に「コンテキスト」と呼んでいます。「コンテキストに値をセットする」と言えば、理解がしやすくなります。対比のためにいくつか例を挙げると、「(コンピュータ用語で)レジスタに値をセットする」だったり「(ネットワーク機器用語で)snmpで値をセットする」だったりします。
認証
実は OAuth2 自体は認証の仕組みではありません。一般的に言われている認証は、内部が複数の機能に分割されて Authentication, Authorization, Accounting の 3 つに分割されます。Authentication は「誰であるか」を特定する認証、Authorization は「許可を与える」承認、Accounting は「利用状態の管理」です。OAuth2 自体はこのうちの Authorization の枠組みです。
加古川オープンデータの申請書では AAA のすべてが入っていますが、これをそのままエンドユーザに提供する必要はありません。アプリケーションの用途に応じて、追加で AAA の仕組みを設計して使うとよいでしょう。
環境構築
Windows 10 では次の手順が簡単です
- Windows Store から Ubuntu をインストール
- apt-get update
- apt-get install -y curl jq
注釈
注1
加古川市で公開している開発ガイドはとても役に立ちます。 http://www.city.kakogawa.lg.jp/soshikikarasagasu/kikakubu/jouhouseisakuka/opendata/1528499081092.html
OAuth2 の原典は RFC 6749 を参照してください。https://tools.ietf.org/html/rfc6749
注2
残念ながら十分に記述された仕様は存在しませんが、次のドキュメントが手掛かりになります。
- 「データ利活用基盤サービス(FIWARE)アプリケーション開発ガイド データ収集蓄積編」
- 第6章 Context Consumer 開発者向けガイド
- 7.2.1 NGSI-10 インタフェース
- OMA "NGSI Context Management"
- OMA-TS=NGSI_Context_Management-V1_0-20120529-A
- 5.4.1
- https://fiware-orion.readthedocs.io/en/master/user/walkthrough_apiv1/index.html#query-context-operation
注3
- https://ja.wikipedia.org/wiki/ISO_8601#%E7%B6%99%E7%B6%9A%E6%99%82%E9%96%93
- https://www.iso.org/iso-8601-date-and-time-format.html
- https://www.iso.org/standard/40874.html
追記
6/30 土曜日に申請書送付して、7/4 水曜日にアカウント発行されました。おおよその目安として。添付ファイルをパスワード付き zip ファイルにくるんでメール、パスワードを別途送信、というフローを使っている様子なので、備考欄にメールアドレス以外の連絡手段を書いておくとよいのかも……?