都市OS FIWARE を使って、外部データと連携しようと思ったが

基本は、

https://fiware-tutorials.letsfiware.jp/

とりわけ

アプリケーション・マッシュアップの作成

https://fiware-tutorials.letsfiware.jp/Application-Mashup/

を参考にさせていただいています。

## FIWAREの構造

チュートリアルで何度か目にする、
「アプリケーションが "Powered by FIWARE" と認定するには、Orion Context Broker を使用するだけで十分 です。」
ということは何を意味するか。

orion（NGSI）を使って、データ（コンテキスト・データ 情報）を入れる。
orion（NGSI）を使って、データを見せる。
これが本質。

データを入れないとだめなのか？というと、そうではない。

Twitter とか、Open Weather Map API の例が示されている。
データを入れる代わりに使うのがProxy。

Orion は、コンテキスト・プロバイダ を経由してデータを見せる方法を持っている。
Orion に、コンテキスト・プロバイダを登録する。
プロバイダの存在を認識していることで、Orionn は外部にあるデータをプロバイダに依頼して取得して、見せることができる。

この辺で説明されていることです。

https://fiware-tutorials.letsfiware.jp/Context-Providers/#_18


現在どんなプロバイダが登録されているか。

http://xxx.xxx.xxx.xxx:1026/v2/registrations

最初は何も登録されていません。


## チュートリアル環境を整理

チュートリアル：アプリケーション・マッシュアップの作成

https://fiware-tutorials.letsfiware.jp/Application-Mashup/#_2

このページのアーキテクチャ図からは外れてしまっているが、
チュートリアルアプリが Port:3000 で動いている。
こちらのページで説明されている。

チュートリアル：コンテキスト・プロバイダ

https://fiware-tutorials.letsfiware.jp/Context-Providers/

要するに、「アプリケーション・マッシュアップの作成」チュートリアル環境で、Orion がデータを取得する元は、mongoDB 、IoT Agent 以外に、コンテキスト・プロバイダ 経由での外部サービスもある。

「NGSI proxy」という同じ言葉が使われているが、別物。

(1)「アプリケーション・マッシュアップの作成」チュートリアルでのNGSI proxy

https://github.com/conwetlab/ngsi-proxy

Wirecloud とのつなぎ役（Wirecloud は直接 Orion に繋ぐこともできるのですが、 CORS の問題を回避するために経由）

(2)「コンテキスト・プロバイダ」チュートリアルでのNGSI proxy

https://github.com/FIWARE/tutorials.NGSI-v2/tree/master/context-provider

nodejs Express で構築されたアプリケーション。
アプリケーションモニター、デバイスモニターなどの、チュートリアルで使う、サンプルアプリケーションであり、
さらに、Twitter とか、Open Weather Map API とかのデータを NGSI に変換して提供する枠割も持っている。

```
      - "OPENWEATHERMAP_KEY_ID=<ADD_YOUR_KEY_ID>"
      - "TWITTER_CONSUMER_KEY=<ADD_YOUR_CONSUMER_KEY>"
      - "TWITTER_CONSUMER_SECRET=<ADD_YOUR_CONSUMER_SECRET>"
```

これらを指定することにより、
http://xxx.xxx.xxx.xxx:3000/health/weather
http://xxx.xxx.xxx.xxx:3000/health/twitter
が動作するようになる。

そして、これを、コンテキスト・プロバイダ として登録することで、Orion 経由で扱えるようにする。

## コンテキスト・プロバイダの動作確認

最初の状態。

```sh
curl -X GET \
   'http://xxx.xxx.xxx.xxx:1026/v2/entities/urn:ngsi-ld:Store:001/attrs/relativeHumidity/value'

{"error":"NotFound","description":"The requested entity has not been found. Check type and id"}

curl -X GET \
   'http://xxx.xxx.xxx.xxx:1026/v2/entities/urn:ngsi-ld:Store:001?type=Store'

{"error":"NotFound","description":"The requested entity has not been found. Check type and id"}

```

プロバイダ登録

```sh
curl -iX POST \
  'http://xxx.xxx.xxx.xxx:1026/v2/registrations' \
  -H 'Content-Type: application/json' \
  -d '{
  "description": "Relative Humidity Context Source random",
  "dataProvided": {
    "entities": [
      {
        "id": "urn:ngsi-ld:Store:001",
        "type": "Store"
      }
    ],
    "attrs": [
      "relativeHumidity"
    ]
  },
  "provider": {
    "http": {
      "url": "http://xxx.xxx.xxx.xxx:3000/random/weatherConditions"
    }
  }
}'


HTTP/1.1 201 Created
Connection: Keep-Alive
Content-Length: 0
Location: /v2/registrations/613961a1e86c5d27d566fecb
Fiware-Correlator: 4788e670-110c-11ec-86ed-0242ac120103
Date: Thu, 09 Sep 2021 01:21:37 GMT
```

```sh
curl -X GET \
  'http://xxx.xxx.xxx.xxx:1026/v2/entities/urn:ngsi-ld:Store:001?type=Store'
{"id":"urn:ngsi-ld:Store:001","type":"Store","relativeHumidity":{"type":"Number","value":14,"metadata":{}}}

curl -X GET \
  'http://xxx.xxx.xxx.xxx:1026/v2/entities/urn:ngsi-ld:Store:001/attrs/relativeHumidity/value'
27
```

取得できるようになりました。

provider として、"http://140.227.122.221:3000/random/weatherConditions" を登録したましたが、これをブラウザで直接叩いても、NOT FOUND 画面が表示されます。

内部的には、こんな感じで投げているのですね。

```sh
curl -iX POST \
  'http://xxx.xxx.xxx.xxx:3000/random/weatherConditions/op/query' \
  -H 'Content-Type: application/json' \
  -d '{
    "entities": [
        {
            "type": "Store",
            "isPattern": "false",
            "id": "urn:ngsi-ld:Store:001"
        }
    ],
    "attrs": [
        "temperature",
        "relativeHumidity"
    ]
} '

HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: application/json; charset=utf-8
Content-Length: 137
ETag: W/"89-iI6LY8sJK0HMvFtZT2CNASXQ36k"
Set-Cookie: connect.sid=s%3AHFNNZRj1P0cHco-aRJwVi9oy8bpBIHp5.AabEH9BRQCaLmRj3T2zJfZGLAZHjXhcbPJyXdoZdZ8I; Path=/; HttpOnly
Date: Thu, 09 Sep 2021 04:18:07 GMT
Connection: keep-alive
Keep-Alive: timeout=5

[{"id":"urn:ngsi-ld:Store:001","type":"Store","temperature":{"type":"Number","value":13},"relativeHumidity":{"type":"Number","value":9}}]
```

ただ、これは、実際は外部データを見ているわけではない。
せっかくAPIキーまで登録しているのだから、外部連携して欲しかった・・・

外部データを見る場合は、こんな感じで取れる。

```sh
curl -iX POST \
  'http://xxx.xxx.xxx.xxx:3000/weather/weatherConditions/op/query' \
  -H 'Content-Type: application/json' \
  -d '{
    "entities": [
        {
            "type": "Store",
            "isPattern": "false",
            "id": "urn:ngsi-ld:Store:001"
        }
    ],
    "attrs": [
        "temperature",
        "relativeHumidity"
    ]
} '
```

ここで、マッピングを行なっている。

https://github.com/FIWARE/tutorials.NGSI-v2/blob/93ee273660d8f9bc31f94582281d2c1421727b26/context-provider/routes/proxy-v2.js

queryString = 'berlin,de' が固定になっているのが残念だけど、下記と比較すれば実際の値が取れることは確認できる。

https://openweathermap.org/city/2950159


なので、下記のようにエンティティを登録すれば、こちらの温度はランダムではなく、外部から取得した温度を見せられることになる。

```sh
curl -iX POST \
  'http://xxx.xxx.xxx.xxx:1026/v2/registrations' \
  -H 'Content-Type: application/json' \
  -d '{
  "description": "Relative Humidity Context Source 123 berlin",
  "dataProvided": {
    "entities": [
      {
        "id": "urn:ngsi-ld:Store:123",
        "type": "Store"
      }
    ],
    "attrs": [
      "relativeHumidity"
    ]
  },
  "provider": {
    "http": {
      "url": "http://xxx.xxx.xxx.xxx:3000/weather/weatherConditions"
    }
  }
}'

HTTP/1.1 201 Created
Connection: Keep-Alive
Content-Length: 0
Location: /v2/registrations/613993a2e86c5d27d566fecd
Fiware-Correlator: 156d14ae-112a-11ec-9b14-0242ac120103
Date: Thu, 09 Sep 2021 04:54:58 GMT
```

データ取得

```sh
curl -X GET \
  'http://xxx.xxx.xxx.xxx:1026/v2/entities/urn:ngsi-ld:Store:123?type=Store'

{"id":"urn:ngsi-ld:Store:123","type":"Store","relativeHumidity":{"type":"Number","value":84,"metadata":{}}}

curl -X GET \
  'http://xxx.xxx.xxx.xxx:1026/v2/entities/urn:ngsi-ld:Store:123/attrs/relativeHumidity/value'

84

```

これをWirecloudの地図に繋げようと思いましたが、それはそれで難しそうなので一旦宿題。

## 結局・・・

本当は、別のオープンデータの情報を繋げるところまでやりたいと思ったのですが、まだ先は長そう。

結局、外部データを Orion に繋げようと思ったら、NGSIにする必要がある。
チュートリアルでは、それを、チュートリアルアプリが行っている。
ということは、別のデータを繋げようと思ったら、そのようなアプリを作る必要がある。
あるいは、データ変換して、Orionn 配下の mongoDB に登録する必要がある。

データ変換の例

https://github.com/NEC-FIWARE/fiware-covid-19

その解説

https://cio.go.jp/sites/default/files/uploads/documents/01_od100_cases_35_Coronataisakusite.pptx

データごとにソースコードを修正しなくて良くなるというのがメリットと。
しかし、データごとに変換ツールが必要だ。
そうやって、マッピングツールが乱立する世界？しばらくはやむを得ないのか。
標準データモデルが整備され、それにしたがってあらゆるデータが作られるまでの我慢なのか。

しかし、リアルタイムデータの連携は、変換して登録するのではなく、Proxy的変換アプリが必要ですよね。

なんだろう・・・何かに似ている・・・
標準化って甘くないですよね・・・

奇しくも昨日、「NEC都市OS」提供開始のニュース。

https://jpn.nec.com/press/202109/20210908_02.html

「スーパーシティに必要」の表現はちょっとどうかと思いますが・・・
こういうパッケージイメージにまとまっていないと導入は難しい気がします。

さてさて。