本記事では、IoT Agent for JSON を使用して、温度、湿度、気圧の情報を定期的に、FIWARE Orion にプッシュし、コンテキスト情報を更新する、IoT デバイスを作成します。
FIWARE IoT Agent for JSON (http) 対応デバイス
FIWARE には、IoT Agent と呼ばれる、既存の IoT プロトコルと NGSI の橋渡しをする Generic Enabler があります。これを利用すると、既存 IoT プロトコルを使用して、エンティティ情報を更新することができます。各種 IoT プロトコルに対応した、複数の IoT Agent があり、IDAS と呼ばれています。
IoT Agent for JSON を使用して、温度、湿度、気圧の情報を定期的に、FIWARE Orion にプッシュし、コンテキスト情報を更新する、IoT デバイスを作成します。このプロトコルは、属性と値のペアをコード化する単純な単一レベル JSON オブジェクトに基づいています。トランスポート・プロトコルとして、http を使用します。
サーバ側には、Orion と IoT Agent for JSON, WireCloud をデプロイします。JSON-http に対応した IoT デバイスには、Raspberry Pi を使用します。
前提条件
次の環境が必要となります。
- FIWARE Orion, IoT Agent, WireCloud が稼働する Linux サーバ環境
- Raspberry Pi (i2c を有効化)
- 環境センサ Enviro for Raspberry Pi (Pimoroni)
- git, curl, jq コマンド
Raspberry Pi の種類は、Raspberry Pi Zero WH, 3, 4 等です。Raspberry Pi 4 を使用すると、FIWARE Orion と 環境情報を収集するプログラムを1台で稼働できます。環境センサの Enviro は、発売元の Pimoroni から購入するか、国内では秋月電子通商、スイッチサイエンス等から購入できるようです。
ソースコード
使用するソースコードは、Github の https://github.com/lets-fiware/lets-fiware.tutorials から入手できます。git コマンドで、リポジトリをクローンして、”raspberrypi/06.json-http-sensor” ディレクトリに移動してください。
git clone https://github.com/lets-fiware/lets-fiware.tutorials.git
cd ./lets-fiware.tutorials/raspberrypi/06.json-http-sensor
システム構成
Linux サーバには、Orion と IoT Agent for JSON, WireCloud をデプロイします。Raspberry Pi は、JSON-http に対応した FIWARE IoT Device として動作します。
サーバ環境の作成
docker-compose ファイル
Orion, IoT Agent for JSON, WireCloud は、Docker コンテナを利用して、サーバ上にデプロイします。クローンしたリポジトリには、x86_64 (amd64) 用 と Raspberry Pi (aarch64) 用の dokcer-compose.yml ファイルがあります。環境に応じて、以下の設定を行います。
x86_64 (amd64)
ln -s docker-compose-arm64.yml docker-compose.yml
Raspberry Pi (aarch64)
ln -s docker-compose-aarch64.yml docker-compose.yml
Docker コンテナの起動
次のコマンドで、Docker コンテナを起動します。これで、Orion, Iot Agent, WireCloud に関連する一連のコンテナが実行されます。
docker-compose up -d
Raspberry Pi での環境変数の設定
Raspberry Pi で Orion と IoT agent にアクセスするための環境変数を設定します。コンテナが稼働するサーバの IP アドレスを 192.168.1.1 として説明しています。環境に合わせて、値を変更してください。
export IOTA_IP=192.168.1.1
export ORION_URL=http://192.168.1.1:1026
正常性の確認
Raspberry Pi から Orion や IoT Agent のバージョン取得を実行して、正しくデプロイされたことを確認してください。IoT Agent の場合、以下のクエリで正常性を確認できます。
GET /iot/about
次のコマンドを実行して、レスポンスが返ってくることを確認してください。
./00.version.sh
結果
1 2 3 4 5 6 |
{ "libVersion": "2.12.0", "port": "4041", "baseRoot": "/", "version": "1.14.0" } |
JSON-http 対応デバイスの作成
プログラム全体
Raspberry Pi を利用して、JSON-http 対応デバイスの作成します。プログラムは次のとおりです。一定間隔でセンサからデータを取得し、JSON のペイロードを作成して、温湿度、気圧の情報を IoT Agent に送信します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import os import signal import datetime import time import requests import json from bme280 import BME280 try: from smbus2 import SMBus except ImportError: from smbus import SMBus EXIT = False def handler(signum, frame): global EXIT EXIT = True def main(): signal.signal(signal.SIGTERM, handler) signal.signal(signal.SIGINT, handler) iotagent = 'http://' + os.environ.get('IOTA_IP', 'iot-agent').rstrip('/') + ':7896/iot/json' key = os.environ.get('IOTA_KEY', '4jggokgpepnvsb2uv4s40d59ov') device = os.environ.get('DEVICE_ID', 'sensor006') debug = not not os.environ.get('DEBUG_FLAG', '') if (debug): print(iotagent) print(key) print(device) bus = SMBus(1) bme280 = BME280(i2c_dev=bus) url = '{}?k={}&i={}'.format(iotagent, key, device) headers = {'Content-Type': 'application/json'} if (debug): print (url) while True: date = datetime.datetime.utcnow().isoformat(timespec='seconds') temperature = bme280.get_temperature() pressure = bme280.get_pressure() humidity = bme280.get_humidity() measures = { 'd': '{}+0900'.format(date), 't': float('{:05.2f}'.format(temperature)), 'h': float('{:05.2f}'.format(humidity)), 'p': float('{:05.2f}'.format(pressure)) } if (debug): print(measures) r = requests.post(url, data=json.dumps(measures), headers=headers) if r.status_code != 200: print(r.status_code) print(r.text) break time.sleep(1) if (EXIT): break if __name__ == '__main__': main() |
JSON-http 対応デバイスの実行
Docker コンテナ内での実行
Docker コンテナ・イメージの取得
JSON-http 対応デバイス用のコンテナ・イメージを Docker Hubから取得します。次のコマンドで、fisuda/json-http-sensor-01 という名前のコンテナ・イメージを取得できます。
./pull.sh
Docker コンテナのビルド
プログラムをDocker コンテナ内で実行するため、JSON-http 対応デバイス用コンテナをビルドします。ビルドには以下のコマンドを実行してい下さい。fisuda/json-http-sensor-01 という名前のコンテナ・イメージが作成されます。
./build.sh
Docker コンテナの起動
Dokcer コンテナを起動することで、プログラムを実行できます。
./run.sh
コンソールの出力
次のコマンドを実行することで、コンソールの出力を確認できます。
./logs.sh
コンテナの停止
次のコマンドを実行することで、コンテナを停止できます。
./stop.sh
JSON-http 対応デバイスの接続
JSON-http 対応デバイスを IoT Agent に登録します。このため、最初にサービス・グループをプロビジョニングし、次にデバイスをプロビジョニングします。
サービス・グループのプロビジョニング
次のようなクエリを IoT Agent の ポート 4041 に POST することで、サービス・グループのプロビジョニングができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#!/bin/sh curl -iX POST \ 'http://192.168.1.1:4041/iot/services' \ -H 'Content-Type: application/json' \ -H 'fiware-service: openiot' \ -H 'fiware-servicepath: /' \ -d '{ "services": [ { "apikey": "4jggokgpepnvsb2uv4s40d59ov", "cbroker": "http://192.168.1.1:1026", "entity_type": "Thing", "resource": "/iot/json" } ] }' |
次のコマンドを実行して、サービス・グループをプロビジョニングしてください。正常に実行できると、201 Created のステータス・コードが返されます。
./01.create_service_group.sh
次のコマンドを実行すると、プロビジョニングされたサービス・グループの一覧を表示できます。
./02.list_service_group.sh
結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
{ "count": 1, "services": [ { "commands": [], "lazy": [], "attributes": [], "_id": "5ed1e2dbae3045000636e744", "resource": "/iot/json", "apikey": "4jggokgpepnvsb2uv4s40d59ov", "service": "openiot", "subservice": "/", "__v": 0, "static_attributes": [], "internal_attributes": [], "entity_type": "Thing" } ] } |
JSON-http 対応デバイスのプロビジョニング
次のようなクエリで、動的な属性値として、温度、湿度、気圧、取得時刻を、静的な属性値として位置情報をもつデバイスとして、JSON-http 対応デバイスをプロビジョニングします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
#!/bin/sh curl -iX POST \ 'http://192.168.1.1:4041/iot/devices' \ -H 'Content-Type: application/json' \ -H 'fiware-service: openiot' \ -H 'fiware-servicepath: /' \ -d '{ "devices": [ { "device_id": "sensor006", "entity_name": "urn:ngsi-ld:WeatherObserved:sensor006", "entity_type": "Sensor", "timezone": "Asia/Tokyo", "attributes": [ { "object_id": "d", "name": "dateObserved", "type": "DateTime" }, { "object_id": "t", "name": "temperature", "type": "Number" }, { "object_id": "h", "name": "relativeHumidity", "type": "Number" }, { "object_id": "p", "name": "atmosphericPressure", "type": "Number" } ], "static_attributes": [ { "name":"location", "type": "geo:json", "value" : { "type": "Point", "coordinates" : [ 139.7671, 35.68117 ] } } ] } ] } ' |
次のコマンドを実行して、JSON-http 対応デバイスをプロビジョニングしてください。正常に実行できると、201 Created のステータス・コードが返されます。
./11.create_device.sh
次のコマンドを実行すると、プロビジョニングされたデバイスの一覧を表示できます。
./12.list_device.sh
結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
{ "count": 1, "devices": [ { "device_id": "sensor006", "service": "openiot", "service_path": "/", "entity_name": "urn:ngsi-ld:WeatherObserved:sensor006", "entity_type": "Sensor", "transport": "HTTP", "attributes": [ { "object_id": "d", "name": "dateObserved", "type": "DateTime" }, { "object_id": "t", "name": "temperature", "type": "Number" }, { "object_id": "h", "name": "relativeHumidity", "type": "Number" }, { "object_id": "p", "name": "atmosphericPressure", "type": "Number" } ], "lazy": [], "commands": [], "static_attributes": [ { "name": "location", "type": "geo:json", "value": { "type": "Point", "coordinates": [ 139.7671, 35.68117 ] } } ] } ] } |
センサデータの送信
サーバ環境の作成、デバイスのプロビジョニングが完了したら、JSON-http 対応デバイスのコンテナを起動するため、Raspberry Pi で ./run.sh コマンドを実行します。./logs.sh コマンドでコンソール出力を確認します。次のような出力があれば、IoT Agent に正しくデータが送信できています。
1 2 3 4 5 6 7 8 9 10 |
http://192.168.1.1:7896/iot/json 4jggokgpepnvsb2uv4s40d59ov sensor006 http://192.168.11.79:7896/iot/json?k=4jggokgpepnvsb2uv4s40d59ov&i=sensor006 {'d': '2020-05-30T04:43:56+0900', 't': 25.47, 'h': 92.09, 'p': 661.89} {'d': '2020-05-30T04:43:57+0900', 't': 35.78, 'h': 20.31, 'p': 1012.79} {'d': '2020-05-30T04:43:58+0900', 't': 35.78, 'h': 20.29, 'p': 1012.79} {'d': '2020-05-30T04:43:59+0900', 't': 35.79, 'h': 20.25, 'p': 1012.79} {'d': '2020-05-30T04:44:00+0900', 't': 35.79, 'h': 20.18, 'p': 1012.78} {'d': '2020-05-30T04:44:01+0900', 't': 35.81, 'h': 20.11, 'p': 1012.75} |
エンティティの確認
Orion に対して次のようなクエリを実行して、エンティティ sensor006 のコンテキスト情報が正しく更新されているかを確認します。
GET /v2/entities/urn:ngsi-ld:WeatherObserved:sensor006
クエリの実行
次のコマンドを実行して、コンテキスト情報を確認します。
./21.get_entity.sh
実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
{ "id": "urn:ngsi-ld:WeatherObserved:sensor006", "type": "Sensor", "TimeInstant": { "type": "DateTime", "value": "2020-05-30T04:45:14.00Z", "metadata": {} }, "atmosphericPressure": { "type": "Number", "value": 1012.75, "metadata": { "TimeInstant": { "type": "DateTime", "value": "2020-05-30T04:45:14.00Z" } } }, "dateObserved": { "type": "DateTime", "value": "2020-05-29T19:45:19.00Z", "metadata": { "TimeInstant": { "type": "DateTime", "value": "2020-05-30T04:45:14.00Z" } } }, "location": { "type": "geo:json", "value": { "type": "Point", "coordinates": [ 139.7671, 35.68117 ] }, "metadata": { "TimeInstant": { "type": "DateTime", "value": "2020-05-30T04:45:14.00Z" } } }, "relativeHumidity": { "type": "Number", "value": 20.83, "metadata": { "TimeInstant": { "type": "DateTime", "value": "2020-05-30T04:45:14.00Z" } } }, "temperature": { "type": "Number", "value": 35.64, "metadata": { "TimeInstant": { "type": "DateTime", "value": "2020-05-30T04:45:14.00Z" } } } } |
WireCloud でのエンティティ情報の表示
次に、WireCloud でエンティティの情報を表示するダッシュボードを作成ます。WireCloud の環境設定の詳細は「WireCloud のセットアップ」を参照してください。
Widget のインストール
マーケットプレイスから以下の2つのウィジェットをインストールします。
- FISUDA/ngsi-source/4.2.0b2
- CoNWeT/spy-wiring/1.0.3
Widgetのワイヤーリング
新しいワークスペースを作成して、Spy wiring をワークスペースに追加します。次に、ワイヤーリング画面で、NGSI source と Spy wiring を以下のようにワイヤーリングします。
Widget の設定
NGSI Source の設定値を以下のように設定します。
- NGSI server URL: http://192.168.1.1:1026/
- NGSI proxy URL: http://192.168.1.1:3000
- FIWARE-Service: openiot
- FIWARE-ServicePath: /
- Id pattern: urn:ngsi-ld:WeatherObserved:sensor006
- Monitored NGSI: temperature,relativeHumidity,atmosphericPressure
NGSI server URL には Orion の IP アドレスとポートを NGSI proxy URL には ngsiproxy の IP アドレスとポートをそれぞれ、稼働している環境に合わせて指定してください。
Monitored NGSI には、Orion に対してサブスクリプションを設定する属性名を指定します。ここでは温度、湿度、気圧の属性名を指定しています。エンティティ中のこれらの属性値が変化したときに、クライアントのWeb ブラウザが Orion からノーティフィケーションを受け取ります (ノーティフィケーションは、ngsiproxy を経由します)。ノーティフィケーションを受けると、Spy wiring の表示値が更新されます。
ワークスペースの表示
Widget の設定を終えた後、WeatherObserved エンティティを更新するプログラムを稼働させて、ワークスペースを表示すると、Spy wiring の表示値が変化することを確認できるはずです。
環境設定のクリーンアップ
JSON-http 対応デバイス・コンテナの停止
次のコマンドで、JSON-http 対応デバイス・コンテナを停止できます。
./stop.sh
デバイスの削除
次のコマンドで、Iot Agent にプロビジョニングしたデバイスを削除できます。
./13.delete_device.sh
サービス・グループの削除
次のコマンドで、Iot Agent にプロビジョニングしたサービス・グループを削除できます。
./03.delete_service_group.sh
エンティティの削除
次のコマンドで、Orion にある、sensor006 のエンティティを削除できます。
./22.delete_entity.sh