1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

手軽に始めるFIWARE入門。データ連携基盤が簡単に作れます

Last updated at Posted at 2025-03-08

この記事はFIWAREを始めたい人の為の入門となります。手軽に始められるように簡単な例を挙げながら基本的な機能を紹介していきます。

FIWAREについて検索して資料を読んでもピンとこなくて、どこから始めたらいいかわからない人の為に書いています。

はじめに

大まかな説明

FIWAREって何なの?という説明は本当に難しいことです。私は仕事で使うことになったから勉強することになったが、最初はこれがわからないことが多くて困難でした。やっとわかってきた今だからこのように、自分の納得できる説明と始め方を記事に残すことにしました。

簡単に言うと、FIWAREとは「APIを作るプラットフォーム」です。「プラットフォーム」と言ってもピンとこないならもっと簡単に「APIを作る手段」や「APIを作るツール」と言ってもいいです。用はこれを使うことでAPIが作れること。

APIの意味がよくわからない方もいるかと思いますが、ここでの説明は割愛して、前提の知識として進めていきます。FIWAREはAPIを構築する為にあるものだから、まずAPIの意味を理解してからにしましょう。

APIを作る手段は色々ありますが、FIWAREはその一つに過ぎないです。APIも目的や機能によって色んな種類に分けられますが、FIWAREで作れるAPIは「データ連携基盤」というものです。

これも又説明必要な単語ですが、データ連携基盤は簡単にいうとデータを提供する者データを使う者連携(つまりやり取りの仲介)するAPIのことです。

  • データを提供する者はFIWAREのプラットフォームにデータを預かる
  • データを使う者はそのプラットフォームからデータを取得する

ただしデータ連携基盤はただ連携する役目でありデータベース自体ではないので、データを保存するデータベースも別として準備する必要があります。

イメージはこんな感じです。

又、複数のデータ連携基盤を関連付けして管理することもできます。複雑になりますが、こういうイメージです。

普段APIはrails、django、springなどウェブアプリケーションフレームワークによって作られることが多いが、もし作りたいAPIがデータ連携基盤ならFIWAREを使う方が手軽に作れます。その為に特化されたプラットフォームだから。

それにFIWAREによって作られたデータ連携基盤の間の連携はレジストレーションという方法を通じて、やりやすいというメリットがあります。もしどこでもFIWAREを使っていたら標準化されて、色々単純になるでしょう。

だからFIWAREは推奨されて、今でも普及していきます。

FIWARE Orionとは

FIWAREを始める人にとって混乱しやすいのは、FIWAREの概念の曖昧さです。

実はFIWAREとはただの一つのソフトウェアやフレームワークのことではなく、色んなコンポーネントからなされるものです。

  • FIWARE Orion
  • FIWARE Cygnus
  • FIWARE Draco
  • FIWARE QuantumLeap
  • FIWARE Wirecloud
  • などなど

このように色んなコンポーネントがあって、目的によってこれらを組み合わせることで望んだAPIを作れます。

ただし殆どの場合、必ず使われるのはFIWARE Orionです。これはFIWAREの中心のコンポーネントとも言えます。

OrionはOrion Context Brokerとも呼ばれます。Brokerは「仲介人」という意味です。つまりOrionの役目はコンテキスト(データ、情報)のやり取りを仲介することです。

名前の由来は星座のオリオン座でしょうね。CygnusやDracoなど他のコンポーネントの名前も星座の名前が多いです。私は天文学出身なのでよく馴染んでいる名前です。

でも今オリオンというと、丁度放送中のこのアニメ……。
orion_rubik.jpg
……全然関係ない話ですみません。

OrionはFIWAREの基本機能であり、他はFIWAREの拡張機能、と認識してもいいと思います。

以下の説明はFIWARE Orionの説明となります。この記事は入門なので、他のコンポーネントのことはここで一切触れません。FIWAREの理解はまずFIWARE Orionの理解からにしましょう。

勉強の為の資料に関して

FIWARE Orionの勉強の為に、FIWAREコミュニティの公式ドキュメントやチュートリアルがあります。

ただし私はこれを読んでも正直難しすぎて殆ど飲み込めませんでした。その後deepseekに聞いたりqiitaの記事など色んなところから情報を集めたりして整理して漸く理解できたのです。

FIWAREの入門は全然簡単なものではないのです。幸い現在ネットで関連の資料が豊富なので読み漁るのも手です。相性もあるからどの入門がいいかは一概には言えないでしょう。私のこの記事もその資料の一つになれたら嬉しいです。

NGSI v2とは

本題に入る前にもう一つ理解しておいた方がいいのはNGSIのことです。NGSIとはデータを記述する方式の一つであり、JSONの一種です。

そのNGSIは昔からあって、その後改善が行われてNGSI v2になって今広く使われています。そしてこのNGSI v2はFIWAREのデータのやり取りに使われている標準の形式となっています。

NGSI v2についてこの記事はおすすめです。

ただし、すぐちゃんと覚える必要がないと思います。「こういう書き方」だと認識しておけばいいです。

ではここから本番に入ります。

FIWARE Orionのサーバー構築と起動

FIWARE Orionを使い始める方法は色々あります。これも入門しようとする人が戸惑いやすいところの一つですね。ここで私が一番簡単だと思っている方法を採用します。それはdockerを使うという方法です。

ただしdockerの知識がなくても大丈夫です。dockerが難しいということは私も同感。私も今までdockerを使ったことありません。今回ただdockerをインストールして、コマンドを打つだけで終わりなので、本格的なdockerの理解がなくてもいいです。

dockerを使ったことないという人も多いと思いますが、やはりこれを使うと便利です。FIWARE Orionの起動はOSや環境に依存するので、手動で設定するのはかなり面倒です。そこでdockerを使うとたった2行のコマンドですぐ済みます。

まずはdockerのインストールから始めましょう。その後コマンドラインでdockerを打ってエラーが出なければ準備完了です。

そしてコマンドラインでこれを実行したらFIWARE Orionのサーバーが起動するはずです。(ここでインターネットで設定用ファイルを取得することになるので、暫く時間がかかります)

docker run --name mongo600 -d mongo:6.0
docker run -d --name orionza --link mongo600:mongodb -p 1026:1026 telefonicaiot/fiware-orion -dbURI mongodb://mongo600

起動した後、ちゃんと動いているかブラウザでこのURLにアクセスして確認できます。
http://localhost:1026/v2

もしこのようなJSONが現れたら、成功です。

{"entities_url":"/v2/entities","types_url":"/v2/types","subscriptions_url":"/v2/subscriptions","registrations_url":"/v2/registrations"}

若しくは、Pythonのrequestsを使って同様なことをすることもできます。

import requests,json

url = "http://localhost:1026/v2"
res = requests.get(url)
print(res) # 応答コードを表示
# わかりやすいjson形式で表示
print(json.dumps(res.json(),indent=2,ensure_ascii=False))
<Response [200]>
{
  "entities_url": "/v2/entities",
  "types_url": "/v2/types",
  "subscriptions_url": "/v2/subscriptions",
  "registrations_url": "/v2/registrations"
}

ここに表示されたのは、ただこれから使うAPIのルーティングの一部です。

URLにv2がありますが、これはNGSI v2を使っているからです。だからこれからアクセスするAPIのURLは全部http://localhost:1026/v2から始めます。

dockerの起動に使ったコマンドに関しては簡単に説明すると、1行目はmongodbのデータベースサーバーを立てる為です。FIWARE Orion自体はただの仲介するものであり、データベース自体ではないから、データを保存する為にmongodbが使われます。

そして2行目こそ本当にOrionのサーバーを立てるコマンドです。その中でmongo600はmongodbのサーバーにつけられた任意の名前であり、好きに変えればいいです。orionzaという名前もです。

1026はデフォルトのポート番号であり、普段はそのまま使っていいです。今回はローカルでサーバーを作ったからhttp://localhost:1026はFIWARE Orionのサーバーとなります。

こうやって立てられたFIWARE Orionによって、これからデータベースと接続してデータを閲覧取得追加削除修正などできます。こんなイメージです。

使い始める

データを入れる

今のデータベースの中にまだ何のデータも入っていないので、まずはデータを入れることから始めます。データ追加はhttp://localhost:1026/v2/entitiespostメソッドでできます。

ここから先「エンティティentity / entitiesという単語がよく出てきますが、これは簡単に説明できる概念ではないので、見ていって自分で理解するしかないと思いますが、さっくりいうと「エンティティ」とはFIWAREにおいて「取り扱うデータの塊」と認識してもいいでしょう。つまりデータは「エンティティ」という形で扱われます。具体的にどんなものなのか例を読んでいくとわかってくると思います。

このhttp://localhost:1026/v2/entitiesはその名の通りエンティティを扱う為のURLです。postでエンティティを1つ追加することになります。

ただしpostに使うデータNGSI v2形式のJSONです。ここで書きやすいようにPythonでやりますが、cURLなど他の方法でも勿論いいです。実は公式サイトの例などでも主にcURLを使っているのですが、正直わかりづらいです。

Pythonの方がJSONとほぼ同じ書き方ができて、NGSIを扱う時直感的でわかりやすいはずだと思うのでPythonで説明することにします。ここでただリクエストを作る手段としてPythonを使うだけでPythonは必須ではなく、自分の使いしやすい方法を選べばいいです。大事なのは特定のURL適切なデータでリクエストを送ることです。

では、次のコードは「駅」の簡単データを登録する例となります。

import requests

url = "http://localhost:1026/v2/entities"
data_dic = {
    "id": "hakataeki",
    "type": "Eki",
    "namae": {"value": "博多駅"},
    "ido": {"value": 33.590000},
    "keido": {"value": 130.420611}
}
res = requests.post(url,json=data_dic)
print(res)

リクエストの結果として201が返されたら成功です。

<Response [201]>

これでデータが登録されているはずです。

エンティティのデータの構造に関して

今回の例で入れたデータについて簡単な説明をします。このデータの入れ方はNGSI v2の形式です。色んな属性を入れるが、特別なのはidtypeで、他の属性は任意です。

idはそのエンティティを示す重複不可のものであり、typeはそのエンティティが何のエンティティかを説明するものです。

FIWAREでは色んなエンティティを全部扱うが、どんなデータかを区別するのはtypeです。例えば今回は駅のデータを登録したいのでtypeEkiにします。会社のデータを入れたい時はKaishaなどの名前のtypeでもいいです。

idtypeもどんな名前にするかは自由ですが、使える文字は英文字a-z A-Zと数字0-9-_.:のみです。typeは大文字で始めるという習慣もありますが、必須ではありません。

他の属性は特定のtypeのエンティティが持つべき値を入れる為です。例えば今回は駅の「名前」と「緯度」と「軽度」3つ入れました。idtypeと違って、書き方は"属性名": {"value": "属性の値"}という形になって面倒に見えますが、それは属性はただの値だけではなく、データ型やメタデータの情報も入れられるからです。これについて後でもっと詳しく説明します。

データ追加の失敗例

データ登録は色んな原因によって失敗で終わる可能性があります。その時エラーメッセージが返されて原因をわかることができます。

例えばidに使ってはいけない文字が入っている場合です。

import requests

url = "http://localhost:1026/v2/entities"
data_dic = {"id": "東京駅?"}
res = requests.post(url,json=data_dic)
print(res,res.text)
<Response [400]> {"error":"BadRequest","description":"Invalid characters in entity id"}

こうやってデータ追加が成功かどうかわかりますね。

入れたデータを表示してみる

http://localhost:1026/v2/entitiesに普通のgetでアクセスしたら全てのエンティティが表示されます。

今データを入れたから、ブラウザなどでhttp://localhost:1026/v2/entitiesにアクセスしてみたら入れられたデータが表示されるはずです。ここで綺麗で読みやすい形で表示する為にPythonを使います。

import requests,json

url = "http://localhost:1026/v2/entities"
res = requests.get(url)
print(res)
# 取得できたデータ
print(json.dumps(res.json(),indent=2,ensure_ascii=False))
# ヘッダー
print(json.dumps(dict(res.headers),indent=2,ensure_ascii=False))
<Response [200]>
[
  {
    "id": "hakataeki",
    "type": "Eki",
    "ido": {
      "type": "Number",
      "value": 33.59,
      "metadata": {}
    },
    "keido": {
      "type": "Number",
      "value": 130.420611,
      "metadata": {}
    },
    "namae": {
      "type": "Text",
      "value": "博多駅",
      "metadata": {}
    }
  }
]
{
  "Date": "Sat, 8 Mar 2025 10:39:39 GMT",
  "Fiware-Correlator": "8387bc64-ef98-11ef-9ada-0242ac110003",
  "Content-Type": "application/json",
  "Content-Length": "202"
}

出てきたエンティティは最初に入れたそのものですが、少し余計な部分が入っていますね。それは各属性のtypemetadataです。紛らわしいですが、属性のtypeはエンティティのtypeとは別物です。属性のtypeはどんなデータ型かを示すものです。エンティティ登録の時にわざわざtypeを入れなくてもTextNumberか適切に決められるから今回はvalueだけ入れました。

ただし実際にtypeの名前は絶対ではなく、自分が勝手に作った任意のtypeでも何でもいいです。それに基本的にFIWARE Orion自体ではtypeが考慮されません。例えば文字列なのに"type": "Number"にしてもエラーが出ません。

だから属性のtypeはただ区別する為のものだと思ってもいいです。しかし一部のFIWAREの追加機能ではtypeが使われることもあります。

metadataに関してはただの追加で入れられる情報です。なくてもいいので、今回はとりあえず使いません。詳しい説明も割愛します。

指定のIDのエンティティの処理

1つのエンティティの情報を表示

entities/{エンティティID}getしたら指定のIDのエンティティを取得することになります。

import requests,json

url = "http://localhost:1026/v2/entities/hakataeki"
res = requests.get(url)
print(json.dumps(res.json(),indent=2,ensure_ascii=False))
{
  "id": "hakataeki",
  "type": "Eki",
  "ido": {
    "type": "Number",
    "value": 33.59,
    "metadata": {}
  },
  "keido": {
    "type": "Number",
    "value": 130.420611,
    "metadata": {}
  },
  "namae": {
    "type": "Text",
    "value": "博多駅",
    "metadata": {}
  }
}

このAPIには色んなパラメータを入れることで表示がかわるので紹介していきます。

表示の形式を調整

optionsというパラメータにkeyValuesを入れることで属性の表示は簡潔になります。つまりtypemetadataが省略されます。これはよく使われて便利です。

import requests,json

url = "http://localhost:1026/v2/entities/hakataeki"
param_dic = {"options": "keyValues"}
res = requests.get(url,params=param_dic)
print(json.dumps(res.json(),indent=2,ensure_ascii=False))
{
  "id": "hakataeki",
  "type": "Eki",
  "ido": 33.59,
  "keido": 130.420611,
  "namae": "博多駅"
}

表示する属性を選ぶ

attrsパラメータに属性名を入れたらその他の属性が表示されなくなります。複数の属性が欲しい場合はカンマ,で挟みます。ただしidtypeは指定しなくても常に表示されます。

import requests,json

url = "http://localhost:1026/v2/entities/hakataeki"
param_dic = {"options": "keyValues", "attrs": "ido,keido"}
res = requests.get(url,params=param_dic)
print(json.dumps(res.json(),indent=2,ensure_ascii=False))
{
  "id": "hakataeki",
  "type": "Eki",
  "ido": 33.59,
  "keido": 130.420611
}

エンティティを削除

entities/{エンティティID}deleteメソッドを使ったらそのIDエンティティを消すことになります。これは1つのエンティティを削除する基本的な方法となります。

import requests

url = "http://localhost:1026/v2/entities/hakataeki"
res = requests.delete(url)
print(res)

削除が成功したら204が返されます。

<Response [204]>

エンティティの属性の処理

属性を追加

entities/{エンティティID}/attrsで指定のIDのエンティティの属性を弄ることになります。まずpostメソッドで新しい属性を追加することができます。

例えば新しいエンティティを追加してからそのエンティティに新しい属性を追加してみます。

import requests,json

url = "http://localhost:1026/v2/entities"
data_dic = {
    "id": "hakataramen",
    "type": "Ramen",
    "namae": {"value": "博多ラーメン"}
}
res = requests.post(url,json=data_dic)

url = "http://localhost:1026/v2/entities/hakataramen/attrs"
data_dic = {"nedan": {"value": 290}}
res = requests.post(url,json=data_dic)

url = "http://localhost:1026/v2/entities/hakataramen"
res = requests.get(url,params={"options": "keyValues"})
print(json.dumps(res.json(),indent=2,ensure_ascii=False))
{
  "id": "hakataramen",
  "type": "Ramen",
  "namae": "博多ラーメン",
  "nedan": 290
}

今回のエンティティは「ラーメン」です。まず属性は名前だけ入れたが、その後「値段」を追加しました。因みに290円という値段は本当に存在します!

尚このentities/{エンティティID}/attrsのpostは既存の名前の所属を入れても問題ありません。その場合属性が書き換えられます。複数入れることもできます。

属性の値を取得

entities/{エンティティID}/attrsgetメソッドで指定のIDのエンティティの全部の属性が見られます。ただしエンティティのidtypeが表示されません。"options": "keyValues"で値だけ表示することもできます。

import requests,json

url = "http://localhost:1026/v2/entities/hakataramen/attrs"
res = requests.get(url,params={"options": "keyValues"})
print(json.dumps(res.json(),indent=2,ensure_ascii=False))
{
  "namae": "博多ラーメン",
  "nedan": 290
}

特定の属性だけ欲しい場合はentities/{エンティティID}/attrs/{属性名}でもいいです。

import requests,json

url = "http://localhost:1026/v2/entities/hakataramen/attrs/nedan"
res = requests.get(url,params={"options": "keyValues"})
print(json.dumps(res.json()))
{"nedan": 290}

属性を更新

一つだけの属性を更新

entities/{エンティティID}/attrs/{属性名}patchメソッドで指定のIDのエンティティのその属性を更新することができます。

import requests,json

data_dic = {"value": 440}
url = "http://localhost:1026/v2/entities/hakataramen/attrs/nedan"
res = requests.put(url,json=data_dic)

url = "http://localhost:1026/v2/entities/hakataramen/attrs"
res = requests.get(url,params={"options": "keyValues"})
# 更新した後の結果を見る
print(json.dumps(res.json(),ensure_ascii=False))
{"namae": "博多ラーメン", "nedan": 440}

複数の属性を更新/追加

上で書きましたが、entities/{エンティティID}/attrspostメソッドで既存の属性に使うこともできます。その場合は追加ではなく、更新となります。しかも同時に複数の属性の追加と更新ができます。

import requests,json

url = "http://localhost:1026/v2/entities/hakataramen/attrs"
data_dic = {
    "nedan": {"value": 600},
    "kcal": {"value": 358}
}
res = requests.post(url,json=data_dic)

url = "http://localhost:1026/v2/entities/hakataramen/attrs"
res = requests.get(url,params={"options": "keyValues"})
print(json.dumps(res.json(),indent=2,ensure_ascii=False))
{
  "kcal": 358,
  "namae": "博多ラーメン",
  "nedan": 600
}

属性を削除

entities/{エンティティID}/attrs/{属性名}deleteメソッドで指定の属性を削除することができます。

import requests

url = "http://localhost:1026/v2/entities/hakataramen"
res = requests.delete(url)
print(res)
<Response [204]>

エンティティのタイプに関して

登録された全部のタイプを取得

上述でも説明しましたが、FIWAREにおいてエンティティのtypeはエンティティを区別する為の存在です。同時に色んなエンティティを入れることができるからどんなエンティティか区別することが重要となります。

今までどんなtypeのエンティティが登録されているかhttp://localhost:1026/v2/typesで調べられます。(このAPIは読み取り専用なのでgetメソッドしかない)

これでそのtypeのエンティティの属性まで表示されますが、typeの名前だけ欲しい場合はパラメータに{"options": "values"}入れます。

違うタイプで同じIDを持つエンティティの問題

本来エンティティのidは重複不可であるべきですが、実はtypeが違ったらidが重複でも大丈夫です。だから実際に「typeidが同時に重複は不可」と言った方が正しいです。

試しに同じidを持つ違うtypeのエンティティ2つ追加してtype一蘭を見てみます。

import requests,json

url = "http://localhost:1026/v2/entities"
data_dic = {
    "id": "kaizukaeki",
    "type": "NishitetsuEki",
    "namae": {"value": "貝塚駅"}
}
res = requests.post(url,json=data_dic)

data_dic = {
    "id": "kaizukaeki",
    "type": "ChikatetsuEki"
}
res = requests.post(url,json=data_dic)

url = "http://localhost:1026/v2/types"
res = requests.get(url)
print(json.dumps(res.json(),indent=2))

# タイプの名前だけ取得
res = requests.get(url,params={"options": "values"})
print(json.dumps(res.json()))
[
  {
    "type": "ChikatetsuEki",
    "attrs": {},
    "count": 1
  },
  {
    "type": "NishitetsuEki",
    "attrs": {
      "namae": {
        "types": [
          "Text"
        ]
      }
    },
    "count": 1
  }
]
["ChikatetsuEki", "NishitetsuEki"]

このように同じkaizukaekiというidを持つ違うChikatetsuEkiNishitetsuEkiというtypeのエンティティが問題なく登録されましたが、これはややこしい問題の原因になるかもしれないので、注意する必要があります。

まず、重複のidがあると、entities/{エンティティID}でのアクセスがエラーになります。エラーコードは409であり、「矛盾がある」ということが示されます。

import requests,json

url = "http://localhost:1026/v2/entities/kaizukaeki"
res = requests.get(url)
print(res,json.dumps(res.json(),indent=2,ensure_ascii=False))
<Response [409]> {
  "error": "TooManyResults",
  "description": "More than one matching entity. Please refine your query"
}

このように同じidがあってどっちなのかわからなくなるからです。その場合idだけでなくtypeまでパラメータのとして指定する必要があります。

import requests,json

url = "http://localhost:1026/v2/entities/kaizukaeki"
res = requests.get(url,params={"type": "ChikatetsuEki"})
print(res,json.dumps(res.json(),indent=2,ensure_ascii=False))
<Response [200]> {
  "id": "kaizukaeki",
  "type": "ChikatetsuEki"
}

こうやって指定のエンティティにアクセスすることができます。

削除する時も同様です。typeを指定しないとエラーになります。

import requests

res = requests.delete(url)
print(res) # ここでエラー
res = requests.delete(url,params={"type": "NishitetsuEki"})
print(res) # type指定したから問題ない
res = requests.delete(url,params={"type": "ChikatetsuEki"})
print(res)
<Response [409]>
<Response [204]>
<Response [204]>

要するに、違うtypeのエンティティで同じidを持つことがないような命名をしていたらエンティティを指定する時にtypeを気にしなくてもidを指定するだけで十分なはずですが、重複の可能性があったらいつもtypeを指定しておいたら無難でしょう。

一気に処理

複数のエンティティを追加、又は更新

大きいデータを扱う時に何件もののデータを一つずつ扱うよりも、一気にいっぱい扱った方が効果的です。その為にFIWARE Orionではop/updatepostメソッドが使われます。

この方法は追加も更新も削除も同じpostメソッドを使いますが、actionTypeというパラメータで区別します。追加/更新の場合は"actionType": "append"とします。

使う例。

import requests

url = "http://localhost:1026/v2/op/update"
data_dic = {
    "actionType": "append",
    "entities": [
        {
            "id": "chashumen",
            "type": "Ramen",
            "namae": {"value": "チャーシューメン"},
            "nedan": {"value": 900}
        },
        {
            "id": "chahan",
            "type": "Gohan",
            "namae": {"value": "チャーハン"},
            "nedan": {"value": 750}
        }
    ]
}
res = requests.post(url,json=data_dic)
print(res)
<Response [204]>

これで2つのエンティティが一気に追加されます。追加したいエンティティのデータはこのように"entities": [ ]というリストの形で入れます。

今回まだ存在していないから追加となりましたが、指定のidのエンティティが既存の場合はそのidのエンティティを書き換えることになります。

複数のエンティティの属性を更新

既存のエンティティの更新は"actionType": "append"の他に、"actionType": "update"も使えます。ただしappendの場合が新しいエンティティに入れ替えられるのに対し、updateはただ指定の属性を更新するだけとなります。指定されていない属性はそのまま。

import requests,json

url = "http://localhost:1026/v2/op/update"
data_dic = {
    "actionType": "update",
    "entities": [
        {
            "id": "chashumen",
            "nedan": {"value": 950}
        },
        {
            "id": "chahan",
            "nedan": {"value": 800}
        }
    ]
}
res = requests.post(url,json=data_dic)

# 変更した後の結果を見てみる
url = "http://localhost:1026/v2/entities"
res = requests.get(url,params={"options": "keyValues"})
print(json.dumps(res.json(),indent=2,ensure_ascii=False))
[
  {
    "id": "chashumen",
    "type": "Ramen",
    "namae": "チャーシューメン",
    "nedan": 950
  },
  {
    "id": "chahan",
    "type": "Gohan",
    "namae": "チャーハン",
    "nedan": 800
  }
]

複数のエンティティを削除

"actionType": "delete"で指定の複数のidのエンティティを削除することができます。

import requests

url = "http://localhost:1026/v2/op/update"
data_dic = {
    "actionType": "delete",
    "entities" :[
        {"id": "chashumen"},
        {"id": "chahan"}
    ]
}
res = requests.post(url,json=data_dic)
print(res)
<Response [204]>

エンティティ取得のオプション

件数を取得

最初から説明したhttp://localhost:1026/v2/entitiesgetですが、実は色んなパラメータによって表示の調整ができるので、ここで補足します。

例えば"options": "count"を入れたら応答のヘッダーの中にエンティティの数が表示されます。どれくらいあるか知りたい時に使うと便利です。

例えばいっぱいエンティティを追加して数を表示させてみます。今回その為にPythonのforループを使いますが、詳しくは割愛します。要はこれで「x1, x2, x3, ..., x1003, x1004」というidを持つ1004個のエンティティをop/updateによって追加します。

import requests,json

url = "http://localhost:1026/v2/op/update"
entity_list = [{"id": f"x{i}", "type": "X"} for i in range(1,1005)]
data_dic = {
    "actionType": "append",
    "entities" : entity_list
}
res = requests.post(url,json=data_dic)

url = "http://localhost:1026/v2/entities"
res = requests.get(url,params={"options": "count"})
# ヘッダーを表示
print(json.dumps(dict(res.headers),indent=2))
{
  "Date": "Sat, 8 Mar 2025 13:04:40 GMT",
  "Fiware-Correlator": "93d0daa2-f11d-11ef-86de-0242ac110003",
  "Fiware-Total-Count": "1004",
  "Content-Type": "application/json",
  "Content-Length": "472"
}

正規表現でIDやタイプから検索

一部のidの名前のパターンを持つエンティティだけ欲しい場合はidPatternというパラメータを使うことでできます。パターンは正規表現で書きます。

前の例において追加されたエンティティで例を挙げます。

import requests,json

url = "http://localhost:1026/v2/entities"
res = requests.get(url,params={"idPattern": "x50.*"})
print(json.dumps(res.json()))
[{"id": "x50", "type": "X"}, {"id": "x500", "type": "X"}, {"id": "x501", "type": "X"}, {"id": "x502", "type": "X"}, {"id": "x503", "type": "X"}, {"id": "x504", "type": "X"}, {"id": "x505", "type": "X"}, {"id": "x506", "type": "X"}, {"id": "x507", "type": "X"}, {"id": "x508", "type": "X"}, {"id": "x509", "type": "X"}]

同じようにtypeの名前で絞りたい場合はtypePatternが使われます。

ページング

limitパラメータは表示されるエンティティの数を指定するものとなります。ただし既定値は20となっています。つまり普段特に指定しない限りどれくらい沢山エンティティを持っていても20しか表示されません。又、limitは最大1000でそれ以上入れても1000しか出てきません。

offsetというパラメータで何番目から表示されるか指定することができます。limitoffsetを一緒に使うことでページ分けでエンティティを表示することができます。

使う例。

import requests,json

url = "http://localhost:1026/v2/entities"
res = requests.get(url,params={"limit": 4})
print(json.dumps(res.json()))
res = requests.get(url,params={"limit": 4, "offset": 8})
print(json.dumps(res.json()))
[{"id": "x1", "type": "X"}, {"id": "x2", "type": "X"}, {"id": "x3", "type": "X"}, {"id": "x4", "type": "X"}]
[{"id": "x9", "type": "X"}, {"id": "x10", "type": "X"}, {"id": "x11", "type": "X"}, {"id": "x12", "type": "X"}]

"options": "count"を使った場合のヘッダーの中ではこのlimitと関係なく常に実際の数が表示されます。

[幕間]エンティティを全部削除

全部エンティティを削除するという便利な方法はFIWARE Orionの中で準備されていないらしいですが、今まで勉強した知識を使って、APIの組み合わせによって実装のコードが書けるでしょう。例えばPythonではこんな感じで書けばいいです。

import requests

while 1:
    url = "http://localhost:1026/v2/entities"
    # 最大の1000件でエンティティのIDを取得
    res = requests.get(url,params={"attrs": "id", "limit": 1000})
    entity_list = res.json()

    # エンティティが存在しない、又は何かのエラーが出た場合はもう終わりでいい
    if(res.status_code!=200 or len(entity_list)==0):
        break

    # 取得したエンティティのIDを入れて削除を行う
    url = "http://localhost:1026/v2/op/update"
    data_dic = {
        "actionType": "delete",
        "entities" : entity_list
    }
    res = requests.post(url,json=data_dic)

並べ替え

基本的に追加した順でエンティティが表示されますが、orderByパラメータで順番の基準にしたい属性を指定することができます。

例えばランダムのrという属性を持つエンティティを追加して、その順で表示させてみます。

import requests,random

url = "http://localhost:1026/v2/op/update"
entity_list = []
for i in range(1,6):
    entity = {
        "id": f"r{i}",
        "type": "R",
        "r": {"value": random.random()}
    }
    entity_list.append(entity)
data_dic = {
    "actionType": "append",
    "entities" : entity_list
}
res = requests.post(url,json=data_dic)

url = "http://localhost:1026/v2/entities"
res = requests.get(url,params={"orderBy": "r", "options": "keyValues"})
print(res.text)
# "!"を入れたら上からの順になる
res = requests.get(url,params={"orderBy": "!r", "options": "keyValues"})
print(res.text)
[{"id":"r3","type":"R","r":0.022399299},{"id":"r2","type":"R","r":0.18084051},{"id":"r4","type":"R","r":0.325210582},{"id":"r1","type":"R","r":0.332001331},{"id":"r5","type":"R","r":0.746004846}]
[{"id":"r5","type":"R","r":0.746004846},{"id":"r1","type":"R","r":0.332001331},{"id":"r4","type":"R","r":0.325210582},{"id":"r2","type":"R","r":0.18084051},{"id":"r3","type":"R","r":0.022399299}]

クエリーで検索

qというパラメータで指定の条件でエンティティを絞り込むことができます。使い方は色々ありますが、今回は例として数値の属性の値の範囲で絞り込むことを試してみます。

import requests,json

# まずはテストに使うデータを追加
url = "http://localhost:1026/v2/op/update"
data_dic = {
    "actionType": "append",
    "entities" :[
        {
            "id": "kitsunedon",
            "type": "Donburi",
            "namae": {"value": "きつね丼"},
            "nedan": {"value": 650}
        },
        {
            "id": "tanindon",
            "type": "Donburi",
            "namae": {"value": "他人丼"},
            "nedan": {"value": 700}
        },
        {
            "id": "tentojidon",
            "type": "Donburi",
            "namae": {"value": "天とじ丼"},
            "nedan": {"value": 800}
        }
    ]
}
res = requests.post(url,json=data_dic)

# 検索
url = "http://localhost:1026/v2/entities"
res = requests.get(url,params={"q": "nedan<=700", "options": "values"})
print(json.dumps(res.json(),ensure_ascii=False))
[["きつね丼", 650], ["他人丼", 700]]

ここでnedan<=700は要するに「値段は700以下」という条件となります。

[幕間]dockerの補足

サーバーの停止、起動、削除

ここまであまり説明せずに最初からdockerで立てたFIWARE Orionサーバーでやっていたのですが、ここでこう少し補足します。

今起動して使用していたサーバーを止めるにはこのコマンドを打つのです。

docker stop orionza
docker stop mongo600

これは一時的な停止となって、もう一度起動したいならこれを打つといいです。

docker start mongo600
docker start orionza

永遠に消したい場合はrmを使います。ただしこれはstopした状態でないとエラーになります。

docker rm orionza
docker rm mongo600

これを使うとmongodbに保存されたエンティティのデータも削除されて取り戻すことができなくなるので注意です。

docker-composeを使うという方法

今まで使っていた方法の他にもう一つの使い方をここで紹介しておきたいです。

まずこのようなymlファイルを作っておくのです。

docker-compose.yml
services:
  orionza:
    image: telefonicaiot/fiware-orion
    ports:
      - "1026:1026"
    depends_on:
      - mongo600
    command: -dbURI mongodb://mongo600

  mongo600:
    image: mongo:6.0
    command: --nojournal

書き方については割愛しますが、簡単にいうとymlでサーバーに関する設定をここに書いたのです。そしてこのymlを使ってこのように実行したら上の方法と同じようにサーバーが建てられます。

docker compose -f docker-compose.yml up -d

サーバーを止めて消したい時はこれを打つのです。

docker compose -f docker-compose.yml down

この方法を使うと、作りたいサーバーの設定は一つのファイルに纏められて使いやすいです。今回はただFIWARE Orionとmongodbの2つしかないのですが、特に沢山のサーバーを同時にある場合この方法を使った方が便利だというのは明らかになるでしょう。

次に説明する機能もそうだから、予めこれを説明しておくことにしました。

レジストレーション

レジストレーションの概要

FIWAREの中でレジストレーション(registration)というのは、別のデータ連携基盤からデータを取得することで複数のデータベースを連携する機能です。

例えば2のデータベースmongo-aとmongo-bを管理する2つのデータ連携基盤orion-aとorion-bがあるとしましょう。とあるデータ利用者はmongo-bの中のデータが欲しい場合、普段ならorion-bに対して要求を送る必要がありますが、もしorion-aがorion-bに対してレジストレーションをしておいたら、データ利用者はorion-aに要求を送ることでそのデータを取得することができます。

イメージとしてはこんな感じです。

このように、FIWAREサーバーがレジストレーションで繋がっているから一つのFIWAREサーバーに接続することで他のFIWAREサーバーのデータも入手できます。その為の仕組みです。

2つのサーバーの準備

レジストレーション機能を実際に使ってみる為にはまず2つのサーバーを立てます。今回はdocker-composeで準備します。このようなymlファイルを使います。

docker-compose.yml
services:
  orion-a:
    image: telefonicaiot/fiware-orion
    ports:
      - "1026:1026"
    depends_on:
      - mongo-a
    command: -dbURI mongodb://mongo-a

  mongo-a:
    image: mongo:6.0
    command: --nojournal

  orion-b:
    image: telefonicaiot/fiware-orion
    ports:
      - "1027:1026"
    depends_on:
      - mongo-b
    command: -dbURI mongodb://mongo-b

  mongo-b:
    image: mongo:6.0
    command: --nojournal

そしてこれを実行したら準備完了です。

docker compose -f docker-compose.yml up -d

ここでorion-aはデータ利用者が直接にやり取りするサーバーとして、orion-bが対象のデータが保存されてレジストレーションを通じて接続するサーバーとします。

こうやって2つのサーバーは立てられますが、デフォルトの1026ポートは1つのサーバーにしか使えないので、ここで2つ目のサーバーは1027を使います。
http://localhost:1027/v2でアクセスできます。

このように複雑になりますが、本番では2つのサーバーはこのように同じパソコンではなく、ちゃんと物理的に違う場所にあるはずなので設定は又別に違うでしょう。

レジストレーションを追加

準備が整ったら次は実際に使ってみます。レジストレーションを追加するにはhttp://localhost:1026/v2/registraionspostメソッドを使います。

import requests

url = "http://localhost:1026/v2/registrations"
data_dic = {
    "description": "ラーメンデータの連携",
    "dataProvided": {
        "entities": [
            {
                "idPattern": ".*",
                "type": "Ramen"
            }
        ],
        "attrs": ["namae"]
    },
    "provider": {
        "http": {
            "url": "http://orion-b:1026/v2"
        }
    }
}
res = requests.post(url,json=data_dic)
print(res)
<Response [201]>

そしてデータをorion-bの方に入れておきます。

import requests

url = "http://localhost:1027/v2/op/update"
data_dic = {
    "actionType": "append",
    "entities": [
        {
            "id": "tonkotsuramen",
            "type": "Ramen",
            "namae": {"value": "とんこつラーメン"},
            "nedan": {"value": 650}
        },
        {
            "id": "misoramen",
            "type": "Ramen",
            "namae": {"value": "みそラーメン"},
            "nedan": {"value": 750}
        }
    ]
}
res = requests.post(url,json=data_dic)

どのエンティティを要求するかを決めるのはdataProvidedのところです。その中でentitiestypeidを指定します。今回はあるtypeのあらゆるidのエンティティが欲しいということで"idPattern": ".*"にします。そしてattrsを入れることで取得したい属性だけ取ることができますが、これは省略できます。その場合全部の属性が取得されます。

そしてproviderでデータ元のサーバーのURLを指定します。

ただしここで注意して欲しいのは、データを追加する時にhttp://localhost:1027/v2というURLにアクセスするのに対し、レジストレーションの時は"url": "http://orion-b:1026/v2"と書いている、ということです。ややこしいですが、これはdockerを使っているからです。

実はどっちもorion-bサーバーを指すURLですが、http://orion-b:1026はdockerの間に使うURLです。レジストレーションで通じる時にorion-aとorion-bは勝手にやり取りするので、その時このURLを使うのです。それに対しデータを追加する時はそうではないので、普通にhttp://localhost:1027/を使います。

次は実際にデータ取得してみましょう。

import requests,json

url = "http://localhost:1026/v2/entities"
res = requests.get(url,params={"type": "Ramen", "options": "keyValues"})
print(json.dumps(res.json(),indent=2,ensure_ascii=False))
[
  {
    "id": "tonkotsuramen",
    "type": "Ramen",
    "namae": "とんこつラーメン"
  },
  {
    "id": "misoramen",
    "type": "Ramen",
    "namae": "みそラーメン"
  }
]

このように無事でorion-bのデータをorion-aから取得することができました。

レジストレーションを全部表示

registrationsgetメソッドで、追加したレジストレーションの詳細を全て表示することができます。

import requests,json

url = "http://localhost:1026/v2/registrations"
res = requests.get(url)
print(json.dumps(res.json(),indent=2,ensure_ascii=False))
[
  {
    "id": "67bef7f9a35f42af3e085d2f",
    "description": "ラーメンデータの連携",
    "dataProvided": {
      "entities": [
        {
          "idPattern": ".*",
          "type": "Ramen"
        }
      ],
      "attrs": [
        "namae"
      ]
    },
    "provider": {
      "http": {
        "url": "http://orion-b:1026/v2"
      },
      "supportedForwardingMode": "all",
      "legacyForwarding": false
    },
    "status": "active"
  }
]

レジストレーションを削除

registraions/{レジストレーションID}deleteメソッドレジストレーションを消すことができますが、ここでidが必要です。しかし追加の時にidは勝手に決められたものなので、私達はidがわかるわけではないですね。だったらまずidを調べた上でやるしかないでしょう。

例えば全部のレジストレーションを削除したい場合はPythonでこうしたらいいでしょう。

url = "http://localhost:1026/v2/registrations"
# レジストレーションの一蘭を取得
res = requests.get(url,params={"options": "keyValues"})
# IDだけ取って1つずつ削除する
for r in res.json():
    url = "http://localhost:1026/v2/registrations/"+r["id"]
    res = requests.delete(url)

終わりに

これでFIWAREの基本的な機能を一通り紹介できたと思います。それでもまだ触れていないところはいっぱいあります。全てはまだ始まったばかりです。

実はまだ沢山書きたい内容があるが、長すぎるので書くなら別の記事にします。サブスクリプションのこととか。

私は仕事でFIWAREを使うことになっているので、まだまだ勉強してFIWAREに関する記事を書いていきます。

もっと読みたい人は公式ドキュメントや下の載っている参考の記事や資料を読んでもいいと思います。

参考

FIWARE関連

その他に、一部の情報とサンプルコードはdeepseekに聞いて得られたものです。

その他

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?