このチュートリアルでは、カスタム XML メッセージ形式を使用して応答する ダミー IoT デバイスを接続します。Custom IoT Agent は、Orion Context Broker に送信された NGSI-v2 リクエストを使用して測定値を読み取り、 コマンドを送信できるように、IoT Agent Node.js ライブラリ と IoT Agent for Ultralight デバイスにあるフレームワークに基づいて作成されます。
チュートリアルでは、全体を通して cUrl コマンドを使用していますが、 Postman ドキュメントとしても利用できます。
カスタム・メッセージ形式を渡す¶
"And the whole earth was of one language, and of one speech."
— Genesis 11:1
以前に定義したように、IoT Agent は、デバイスのグループが独自のネイティブ・プロトコルを使用して Context Broker に データを送信し、Context Broker から管理できるようにするコンポーネントです。すべての IoT Agent は単一のペイロード形式に 対して定義されていますが、そのペイロードには複数の異なるトランスポートを使用できる場合があります。
多くの標準ペイロード用の IoT Agent が存在しますが、コンテキスト・データの多くの潜在的なソースには、システムの周りに データを渡すための明確なデファクトまたはデジュール標準が既にあるため、追加のペイロードが必要になる場合があることを 想定することは可能です。例として、ISOXML 標準 iso:11783 は農業機械で頻繁に使用されます。
独自の IoT Agent を作成するプロセスは比較的簡単です。これは、必要なデータ転送を使用する IoT Agent を選択し、 ペイロード処理コードを書き換え/修正して、問題のペイロードを処理することにより、最もよく達成されます。
このチュートリアルでは、既存の Ultralight IoT Agent のコードを修正して、同様のカスタム XML 形式を処理します。 2つの IoT Agent の直接比較を以下に示します:
IoT Agent for Ultralight | IoT Agent for XML | プロトコルの関心領域 |
---|---|---|
測定値のサンプル c\|1 |
測定値のサンプル <measure device="lamp002" key="xxx"> <c value="1"/> </measure> |
メッセージ・ペイロード |
コマンドのサンプル Robot1@turn\|left=30 |
コマンドのサンプル <turn device="Robot1"> <left>30</left> </turn> |
メッセージ・ペイロード |
Content Type は text/plain |
Content Type は application/xml |
メッセージ・ペイロード |
3つのトランスポートを提供 - HTTP, MQTT and AMPQ | 3つのトランスポートを提供 - HTTP, MQTT and AMPQ | トランスポート・メカニズム |
HTTP はデフォルトで iot/d の測定値をリッスン |
HTTP はデフォルトで iot/xml の測定値をリッスン |
トランスポート・メカニズム |
HTTP デバイスはパラメータ ?i=XXX&k=YYY によって識別 |
HTTP デバイスはペイロード <measure device="XXX" key="YYY"> によって識別 |
デバイスの識別 |
既知の URL にポストされた HTTP コマンド - レスポンスはリプライにある | 既知の URL にポストされた HTTP コマンド - レスポンスはリプライにある | 通信ハンドシェイク |
MQTT デバイスはトピック /XXX/YYY のパスによって識別 |
MQTT デバイスはトピック /XXX/YYY のパスによって識別されます |
デバイスの識別 |
cmd トピックに投稿された MQTT コマンド |
cmd トピックに投稿された MQTT コマンド |
通信ハンドシェイク |
cmdexe トピックに投稿された MQTT コマンド・レスポンス |
cmdexe トピックに投稿された MQTT コマンド |
通信ハンドシェイク |
ご覧のとおり、サポートされている通信トランスポート (HTTP, MQTT, AMPQ) は同じままです。これは、XML デバイスが IoT Agent と通信できるように適応させる必要があるカスタム・ペイロードの処理です。
ユースケースによっては、通信用に追加のミドルウェアを作成する必要がある場合もあります。この例では、devices は、 2つの別個の通信チャネルで直接測定値を送信し、コマンドをリッスンおよびレスポンスすることができます。 LoRaWAN および OPC-UA IoT Agent 内では別のパラダイムが使用され、HTTP ミドルウェアが IoT Agent にレスポンスし、デバイスが使用する低レベルの CoAP トランスポートに通信を変換します。
このチュートリアルの目標¶
このチュートリアルの目的は、独自のカスタム IoT Agent を作成する方法について開発者の理解を深めることです。一連の簡単な 変更が Ultralight IoT Agent のコードに加えられ、変更方法が示されています。このチュートリアルは、関連するコードの ウォークスルーと、新しい IoT Agent に接続するための一連の HTTP リクエストで構成されています。コードは、現在、 GitHub リポジトリ にあります。
共通機能の再利用¶
既存の IoT Agent を変更する利点は、開発者がすべての IoT Agent にある共通の機能を再利用できることです。これには、 次のような機能が含まれます:
- デバイスの更新をリッスンするための標準的な場所を提供
- コンテキスト・データの更新をリッスンする標準の場所を提供
- デバイスのリストを保持し、コンテキスト・データ属性をデバイス構文にマッピング
- セキュリティ認証
この基本機能は、共通の IoT Agent framework library に抽象化されています。
デバイス・モニタ¶
このチュートリアルのために、一連のダミー IoT デバイスが作成され、Context Broker に接続されます。使用されている
アーキテクチャとプロトコルの詳細は、IoT センサのチュートリアル
をご覧ください。各デバイスの状態は、XML デバイス・モニタの 次の Web ページで確認できます:
http://localhost:3000/device/monitor
アーキテクチャ¶
このアプリケーションは、以前のチュートリアル で作成された コンポーネントに基づいて構築されています。これは、1つの FIWAREコンポーネント Orion Context Broker と Custom IoT Agent for XML を使用します。 アプリケーションが “Powered by FIWARE” として認定されるには、Orion Context Broker の使用で十分です。Orion Context Broker と IoT Agent の両方が、オープンソースの MongoDB テクノロジを利用して、 保持している情報の永続性を維持しています。以前のチュートリアル で作成されたダミー IoT デバイスも使用しますが、カスタム XML メッセージング形式に応答するようにすでに調整されています。
したがって、全体的なアーキテクチャは次の要素で構成されます:
- FIWARE Orion Context Broker は NGSI-v2 を使用してリクエストを受信します
- Custom IoT Agent for XML は NGSI-v2 を使用してサウスバウンド・リクエストを受信し、デバイスの XML コマンドに変換します
- 基礎となる MongoDB データベース:
- Orion Context Broker がデータ・エンティティ、サブスクリプション、レジストレーションなどの コンテキスト・データ情報を保持するために使用
- IoT Agent がデバイスの URL やキーなどのデバイス情報を保持するために使用
- HTTP で実行されているカスタム XML メッセージング・プロトコルを使用する ダミー IoT デバイスのセットとして機能する Web サーバ
要素間のすべての対話は HTTP リクエストによって開始されるため、エンティティをコンテナ化し、 公開されたポートから実行できます。
IoT デバイスと IoT Agent を接続するために必要な構成情報は、関連する docker-compose.yml
ファイルの
services セクションで確認できます。
ダミー IoT デバイスの構成¶
tutorial:
image: fiware/tutorials.context-provider
hostname: iot-sensors
container_name: fiware-tutorial
networks:
- default
expose:
- "3000"
- "3001"
ports:
- "3000:3000"
- "3001:3001"
environment:
- "DEBUG=tutorial:*"
- "PORT=3000"
- "IOTA_HTTP_HOST=iot-agent"
- "IOTA_HTTP_PORT=7896"
- "DUMMY_DEVICES_PORT=3001"
- "DUMMY_DEVICES_API_KEY=4jggokgpepnvsb2uv4s40d59ov"
- "DUMMY_DEVICES_TRANSPORT=HTTP"
- "DUMMY_DEVICES_PAYLOAD=XML"
tutorial
コンテナは2つのポートでリッスンしています:
- ポート
3000
が公開されているので、ダミー IoTデ バイスを表示する Web ページを見ることができます - ポート
3001
は、純粋にチュートリアル・アクセスのために公開されています。そのため、cUrl または Postman は、 同じネットワークに属さなくても JSON コマンドを実行できます
tutorial
コンテナは、次のように環境変数によって駆動されます:
キー | 値 | 説明 |
---|---|---|
DEBUG | tutorial:* |
ロギングに使用されるデバッグ・フラグ |
WEB_APP_PORT | 3000 |
ダミー IoT デバイスのデータを表示する Web アプリが使用するポート |
IOTA_HTTP_HOST | iot-agent |
XML の IoT Agent のホスト名。以下を参照してください |
IOTA_HTTP_PORT | 7896 |
XML 用の IoT Agent がリッスンするポート。7896 は XML over HTTP の一般的なデフォルトです |
DUMMY_DEVICES_PORT | 3001 |
コマンドを受信するために ダミー IoT デバイスが使用するポート |
DUMMY_DEVICES_API_KEY | 4jggokgpepnvsb2uv4s40d59ov |
IoT インタラクションに使用される ランダム・セキュリティ・キー。デバイスと IoT Agent 間のインタラクションの完全性を保証するために使用されます |
DUMMY_DEVICES_TRANSPORT | HTTP |
ダミー IoT デバイスで使用されるトランスポート・プロトコル |
DUMMY_DEVICES_PAYLOAD | XML |
ダミー IoT デバイスによるメッセージ・ペイロード・プロトコル |
YAML ファイルに記述されている他の tutorial
コンテナ設定値は、このチュートリアルでは使用されません。
カスタム XML IoT Agent の構成¶
カスタム XML IoT Agent のコードは、このチュートリアルに関連付けられている
GitHub リポジトリにあります。これは、
IoT Agent for Ultralight の 1.12.0 バージョンのコピーであり、以下に説明するように少し変更されています。関連する
Dockerfile は、Node.js
を実行している Docker コンテナ内の適切な場所にコードをコピーするだけです。これにより、docker-compose.yaml
ファイルを使用してコンポーネントをインスタンス化できます。必要な設定は次のとおりです:
iot-agent:
image: fiware/iotagent-xml
build:
context: iot-agent
dockerfile: Dockerfile
hostname: iot-agent
container_name: fiware-iot-agent
depends_on:
- mongo-db
networks:
- default
expose:
- "4041"
- "7896"
ports:
- "4041:4041"
- "7896:7896"
environment:
- IOTA_CB_HOST=orion
- IOTA_CB_PORT=1026
- IOTA_NORTH_PORT=4041
- IOTA_REGISTRY_TYPE=mongodb
- IOTA_LOG_LEVEL=DEBUG
- IOTA_TIMESTAMP=true
- IOTA_CB_NGSI_VERSION=v2
- IOTA_AUTOCAST=true
- IOTA_MONGO_HOST=mongo-db
- IOTA_MONGO_PORT=27017
- IOTA_MONGO_DB=iotagentxml
- IOTA_HTTP_PORT=7896
- IOTA_PROVIDER_URL=http://iot-agent:4041
- IOTA_DEFAULT_RESOURCE=/iot/xml
iot-agent
コンテナは Orion Context Broker の存在に依存し、MongoDB データベースを使用してデバイスの URL やキーなどの
デバイス情報を保持します。コンテナは2つのポートでリッスンしています:
- ポート
7896
が公開され、ダミー IoT デバイスから HTTP 経由で XML 測定値を受信します - ポート
4041
は、純粋にチュートリアル・アクセス用に公開されています。そのため、cUrl または Postman は、 同じネットワークに属さなくてもプロビジョニング・コマンドを実行できます
iot-agent
コンテナは、次のように環境変数によって駆動されます:
キー | 値 | 説明 |
---|---|---|
IOTA_CB_HOST | orion |
コンテキストを更新する Context Broker のホスト名 |
IOTA_CB_PORT | 1026 |
Context Broker がコンテキストを更新するためにリッスンするポート |
IOTA_NORTH_PORT | 4041 |
IoT Agent の構成と Context Broker からのコンテキスト更新の受信に使用されるポート |
IOTA_REGISTRY_TYPE | mongodb |
IoT デバイス情報をメモリまたはデータベースのどちらに保持するか |
IOTA_LOG_LEVEL | DEBUG |
IoT Agent のログレベル |
IOTA_TIMESTAMP | true |
接続されたデバイスから受信した各測定でタイムスタンプ情報を提供するかどうか |
IOTA_CB_NGSI_VERSION | v2 |
アクティブな属性の更新を送信するときに NGSI v2 を使用するかどうか |
IOTA_AUTOCAST | true |
XML の数値が文字列ではなく数値として読み取られるようにする |
IOTA_MONGO_HOST | context-db |
mongo DB のホスト名。デバイス情報を保持するために使用されます |
IOTA_MONGO_PORT | 27017 |
mongoDB がリッスンしているポート |
IOTA_MONGO_DB | iotagentxml |
mongoDB で使用されるデータベースの名前 |
IOTA_HTTP_PORT | 7896 |
IoT Agent がHTTP 経由で IoT デバイスのトラフィックをリッスンするポート |
IOTA_PROVIDER_URL | http://iot-agent:4041 |
コマンドの登録時に Context Broker に渡される URL。ContextBroker がデバイスにコマンドを発行するときにフォワーディング URL の場所として使用されます |
IOTA_DEFAULT_RESOURCE | /iot/xml |
IoT Agent がカスタム XML 測定値のリッスンに使用するデフォルトパス |
前提条件¶
Docker¶
シンプルにするために、すべてのコンポーネントは Docker を使用して実行されます。Docker は、それぞれの環境に分離されたさまざまなコンポーネントを可能にするコンテナ・テクノロジです
- Windows に Docker をインストールするには、こちらの指示に 従ってください
- Mac に Docker をインストールするには、こちらの指示に従ってください
- Linux に Docker をインストールするには、こちらの指示に従ってください
Docker Compose は、マルチ・コンテナの Docker アプリケーションを定義して実行するためのツールです。 YAMLファイル を使用して、アプリケーションに必要なサービスを構成します。つまり、すべてのコンテナ・サービスを1つのコマンドで 起動できます。Docker Compose は、デフォルトで Docker for Windows および Docker for Mac の一部としてインストール されますが、Linux ユーザはこちら にある指示に従う必要があります。
次のコマンドを使用して、現在の Docker および Docker Compose のバージョンを確認できます:
docker-compose -v
docker version
Docker version 20.10 以降と Docker Compose 1.29 以降を使用していることを確認し、 必要に応じてアップグレードしてください。
Cygwin¶
簡単な bash スクリプトを使用してサービスを起動します。Windows ユーザは、cygwin を ダウンロードして、Windows 上の Linux ディストリビューションと同様のコマンドライン機能を提供する必要があります。
起動¶
開始する前に、必要な Docker イメージをローカルで取得またはビルドしたことを確認する必要があります。 以下のコマンドを実行して、リポジトリのクローンを作成し、必要なイメージを作成してください:
git clone https://github.com/FIWARE/tutorials.Custom-IoT-Agent.git
cd tutorials.Custom-IoT-Agent
git checkout NGSI-v2
./services create
その後、リポジトリ内で提供される services Bash スクリプトを実行することにより、コマンドラインからすべてのサービスを初期化できます:
./services start
注: クリーンアップしてやり直したい場合は、次のコマンドで実行できます:
./services stop
カスタム IoT Agent の作成¶
次のセクションは、IoT Agent をプロビジョニングし、測定値を受信してコマンドを送信するために使用される一連の HTTP コマンドで構成されています。Custom IoT Agent 内の関連する修正されたコードは、各アクションが処理されるときに説明します。
チュートリアルを正しく実行するには、ブラウザーでデバイス・モニタのページを利用できることを確認し、ページをクリックして オーディオを有効にしてから、cUrl コマンドを入力してください。デバイス・モニタは、XML 構文を使用してダミー IoT デバイスの配列の現在の状態を表示します。
デバイス・モニタ (Device Monitor)¶
デバイス・モニタは次の場所にあります: http://localhost:3000/device/monitor
IoT Agent サービス の健全性の確認¶
公開されたポートに HTTP リクエストを送信することで、IoT Agent が実行されているかどうかを確認できます:
1 リクエスト:¶
curl -X GET \
'http://localhost:4041/iot/about'
レスポンスは次のようになります:
{
"libVersion": "2.6.0-next",
"port": "4041",
"baseRoot": "/",
"version": "1.12.0-next"
}
これは、IoT Agent Node.js ライブラリから直接提供される標準機能であり、コードの変更は必要ありません。
サービス・グループのプロビジョニング¶
各プロビジョニングで常に認証キーを提供する必要があり、IoT Agent は最初に Context Broker がレスポンスしている URL を認識しないため、グループ・プロビジョニングの呼び出しは常にデバイス接続の最初のステップです。
すべての匿名デバイスに対してデフォルトのコマンドと属性を設定することもできますが、このチュートリアルでは、 各デバイスを個別にプロビジョニングするため、これは行いません。
この例では、デバイスの匿名グループをプロビジョニングします。一連のデバイスがメッセージを IOTA_HTTP_PORT
に送信することを IoT Agent に通知します (ここで、IoT Agent は Northbound 通信をリッスンします)
2 リクエスト:¶
curl -iX POST \
'http://localhost:4041/iot/services' \
-H 'Content-Type: application/json' \
-H 'fiware-service: openiot' \
-H 'fiware-servicepath: /' \
-d '{
"services": [
{
"apikey": "4jggokgpepnvsb2uv4s40d59ov",
"cbroker": "http://orion:1026",
"entity_type": "Thing",
"resource": "/iot/xml"
}
]
}'
この例では、IoT Agent に、/iot/xml
エンドポイントが使用され、デバイスがトークン 4jggokgpepnvsb2uv4s40d59ov
を含めることで自身を認証することが通知されます。Custom XML IoT Agent の場合、これはデバイスが POST
リクエストを以下に送信することを意味します:
http://iot-agent:7896/iot/xml
ここで <measure>
は関連するデバイス ID と API キーを保持します。
<measure device="motion001" key="4jggokgpepnvsb2uv4s40d59ov">
<c value="3"/>
</measure>
この構文は、デバイス ID と API キーが URL パラメータとして送信される Ultralight IoT Agent とは異なります。
関連する変更は、XML パーサーがインスタンス化される HTTPBindings.js
ファイルにあります。
const xmlBodyParser = require("express-xml-bodyparser");
httpBindingServer.router.post(
config.getConfig().iota.defaultResource || constants.HTTP_MEASURE_PATH,
...xmlBodyParser({ trim: false, explicitArray: false }),
checkMandatoryParams(false),
...etc
);
つまり、角括弧構文を使用して、XML リクエストの属性にアクセスできます。apiKey
と deviceId
は両方とも
必須パラメータであるため、受信した <measure>
内で見つけることができます。
function checkMandatoryParams(queryPayload) {
return function (req, res, next) {
var notFoundParams = [],
error;
req.apiKey = req.body["measure"]["$"]["key"];
req.deviceId = req.body["measure"]["$"]["device"];
if (!req.apiKey) {
notFoundParams.push("API Key");
}
if (!req.deviceId) {
notFoundParams.push("Device Id");
}
// CHeck if retrievingParam
if (queryPayload && !req.query.d && req.query.getCmd !== "1") {
notFoundParams.push("Payload");
}
if (req.method === "POST" && !req.is("application/xml")) {
error = new errors.UnsupportedType("application/xml");
}
if (notFoundParams.length !== 0) {
next(new errors.MandatoryParamsNotFound(notFoundParams));
} else {
next(error);
}
};
}
この関数は、適切な MIME タイプが受信されたことを確認し、着信メッセージに十分な情報が含まれていない場合はすぐに 失敗します。
センサのプロビジョニング¶
エンティティを作成するときは、NGSI-LD 仕様 に従って URN を使用するのが一般的です。さらに、データ属性を定義するときに、意味のある名前を理解しやすくなります。 これらのマッピングは、デバイスを個別にプロビジョニングすることで定義できます。
3種類の測定属性をプロビジョニングできます:
attributes
はデバイスからのアクティブな読み取り値ですlazy
属性はリクエスト時にのみ送信されます。IoT Agent は測定値を返すようにデバイスに通知しますstatic_attributes
は、その名前が Context Broker に渡されるデバイスに関する静的データ (リレーションシップなど) を示唆しているものです
注: 個々の
id
が必要ない場合、または集約されたデータで十分な場合、attributes
は個別ではなくプロビジョニング・サービス内で定義できます。
3 リクエスト:¶
curl -iX POST \
'http://localhost:4041/iot/devices' \
-H 'Content-Type: application/json' \
-H 'fiware-service: openiot' \
-H 'fiware-servicepath: /' \
-d '{
"devices": [
{
"device_id": "motion001",
"entity_name": "urn:ngsi-ld:Motion:001",
"entity_type": "Motion",
"timezone": "Europe/Berlin",
"attributes": [
{ "object_id": "c", "name": "count", "type": "Integer" }
],
"static_attributes": [
{ "name":"refStore", "type": "Relationship", "value": "urn:ngsi-ld:Store:001"}
]
}
]
}
'
予想通り、元の Ultralight IoT Agent と同じ HTTP トランスポートを使用しているため、デバイスをプロビジョニングする
HTTP コマンドは、基になるペイロードまたはトランスポート・プロトコルに基づいて変更されません。internal_atttributes
を使用して、必要に応じて Custom IoT Agent の追加情報を提供できます。リクエストでは、デバイス motion001
を URN
urn:ngsi-ld:Motion:001
に関連付け、デバイスの c
をコンテキスト属性 count
(Integer
として定義されている)
にマッピングしています。refStore
は static_attribute
として定義され、デバイスを Store
urn:ngsi-ld:Store:001
内に配置します。
次の XML リクエストを行うことで、Motion Sensor デバイス motion001
からのダミー IoT デバイスの測定を
シミュレートできます。
4 リクエスト:¶
curl -L -X POST 'http://localhost:7896/iot/xml' \
-H 'Content-Type: application/xml' \
--data-raw '<measure device="motion001" key="4jggokgpepnvsb2uv4s40d59ov">
<c value="3"/>
</measure>'
ペイロードと Content-Type
の両方が更新されました。ダミー IoT デバイスは、ドアがロックされていないときに、
以前のチュートリアルで同様の Ultralight リクエストを行いました。各 Motion sensor の状態が変化し、
ノースバウンド・リクエストがデバイス・モニタに記録されます。
これで IoT Agent が接続され、サービス・グループは IoT Agent がリッスンするリソース (iot/xml
) を定義し、
リクエストの認証に使用される API キー (4jggokgpepnvsb2uv4s40d59ov
) が本文に見つかりました。
これらは両方とも認識されているため、測定値は有効です。
次のステップは、ペイロードを解析して属性を抽出することです。これは xmlparser.js
ファイルの修正された
parse
メソッドにあります。
function parse(payload) {
let result = [];
const keys = Object.keys(payload["measure"]);
for (let i = 0; i < keys.length; i++) {
if (keys[i] !== "$") {
let obj = {};
obj[keys[i]] = payload["measure"][keys[i]]["$"].value;
result.push(obj);
}
}
return result;
}
parse()
は、キーと値のペアの JSON 配列を返します。これは、デバイスの属性名 (c
など) からエンティティの属性名 (count
など) にマッピングできます。明らかに、マッピングは元のプロビジョニングで送信された値に基づいています。
Context Broker からエンティティ・データを取得すると、測定値が記録されていることがわかります。fiware-service
および
fiware-service-path
ヘッダを追加することを忘れないでください。
5 リクエスト:¶
curl -X GET \
'http://localhost:1026/v2/entities/urn:ngsi-ld:Motion:001?type=Motion' \
-H 'fiware-service: openiot' \
-H 'fiware-servicepath: /'
レスポンス:¶
{
"id": "urn:ngsi-ld:Motion:001",
"type": "Motion",
"TimeInstant": {
"type": "ISO8601",
"value": "2018-05-25T10:51:32.00Z",
"metadata": {}
},
"count": {
"type": "Integer",
"value": "3",
"metadata": {
"TimeInstant": {
"type": "ISO8601",
"value": "2018-05-25T10:51:32.646Z"
}
}
},
"refStore": {
"type": "Relationship",
"value": "urn:ngsi-ld:Store:001",
"metadata": {
"TimeInstant": {
"type": "ISO8601",
"value": "2018-05-25T10:51:32.646Z"
}
}
}
}
レスポンスは id=motion001
の Motion Sensor デバイスが IoT Agent によって正常に識別され、エンティティ
id=urn:ngsi-ld:Motion:001
にマップされたことを示しています。この新しいエンティティは、コンテキスト・データ内に
作成されています。ダミー IoT デバイスの測定リクエストの c
属性は、コンテキスト・データ内のより意味のある count
属性にマッピングされています。
アクチュエータのプロビジョニング¶
アクチュエータのプロビジョニングは、センサのプロビジョニングに似ています。今回、 endpoint
属性は、IoT Agent が
XML コマンドを送信する必要がある場所を保持し、commands
配列には、呼び出すことができる各コマンドのリストが
含まれています。以下の例では、 deviceId=bell001
でベルをプロビジョニングします。エンドポイントは
http://iot-sensors:3001/iot/bell001
で、ring
コマンドを受け入れることができます。transport=HTTP
属性は、使用する通信プロトコルを定義します。
6 リクエスト:¶
curl -iX POST \
'http://localhost:4041/iot/devices' \
-H 'Content-Type: application/json' \
-H 'fiware-service: openiot' \
-H 'fiware-servicepath: /' \
-d '{
"devices": [
{
"device_id": "bell001",
"entity_name": "urn:ngsi-ld:Bell:001",
"entity_type": "Bell",
"transport": "HTTP",
"endpoint": "http://iot-sensors:3001/iot/bell001",
"commands": [
{ "name": "ring", "type": "command" }
],
"static_attributes": [
{"name":"refStore", "type": "Relationship","value": "urn:ngsi-ld:Store:001"}
]
}
]
}
'
センサのプロビジョニングの場合と同様に、このリクエストは変更されません。IoT Agent の構造内で暗黙的に、 コマンドのプロビジョニングは次の暗黙の契約を満たします:
- Custom IoT Agent が属性を登録します
- Custom IoT Agent が
/v2/op/update
エンドポイントで、コンテキストを更新するための各リクエストをします - リクエストの処理方法が決定されます。Custom IoT Agent と Ultralight Agent の両方で、これは
<command>State
属性を設定し、/cmd
エンドポイントでリクエストを修正して、デバイス (またはデバイスの責任を負うミドルウェア) にフォワーディングするというパラダイムに従います
最初の2つの項目は Context Broker からのコンテキスト変更のリスニングは、明確に定義された NGSI 構文に従うため、 すべての IoT Agent に共通です。ただし、3番目の項目は、継続的に消費するメッセージを準備するために何をすべきかは、 抽象化されているプロトコルによって異なります。
Context Broker を接続する前に、/v2/op/update
エンドポイントを使用して IoT Agent のノースポートに直接 REST
リクエストを送信することにより、コマンドがデバイスに送信できることをテストできます。接続すると、最終的に
Context Broker によって呼び出されるのは、このエンドポイントです。
構成をテストするには、次のようにコマンドを直接実行します:
7 リクエスト:¶
curl -iX POST \
http://localhost:4041/v2/op/update \
-H 'Content-Type: application/json' \
-H 'fiware-service: openiot' \
-H 'fiware-servicepath: /' \
-d '{
"actionType": "update",
"entities": [
{
"type": "Bell",
"id": "urn:ngsi-ld:Bell:001",
"ring" : {
"type": "command",
"value": ""
}
}
]
}'
デバイス・モニタのページを表示している場合は、ベルの変化の状態も確認できます。
ベルを鳴らすコマンドの結果は、Orion Context Broker 内のエンティティをクエリすることで読み取ることができます。
Custom IoT Agent 内で、start()
関数は、リクエストが Context Broker から到着したときに起動する一連のハンドラ関数を
設定します。
iotAgentLib.setProvisioningHandler(deviceProvisioningHandler);
iotAgentLib.setConfigurationHandler(configurationHandler);
iotAgentLib.setCommandHandler(commandHandler);
iotAgentLib.setDataUpdateHandler(updateHandler);
これは適切なトランスポート・バインディングに渡され、この場合、HTTPBindings.js
内の commandHandler()
メソッドが呼び出されます。HTTP エラー・ハンドラを提供しますが、コマンドを作成してデバイスに送信する実際の作業を
generateCommandExecution()
に委任します。
function generateCommandExecution(apiKey, device, attribute) {
...
const options = {
url: device.endpoint,
method: 'POST',
body: xmlParser.createCommandPayload(device, cmdName, cmdAttributes),
headers: {
'fiware-service': device.service,
'fiware-servicepath': device.subservice
}
};
... etc
ペイロード自体、つまりデバイスで解釈できるようにコマンドを作成する方法は、カスタム XML
メッセージング・プロトコルに固有であり、 xmlParser.js
の createCommandPayload()
メソッドで生成されます。
function createCommandPayload(device, command, attributes) {
if (typeof attributes === "object") {
let payload = "<" + command + ' device="' + device.id + '">';
Object.keys(attributes).forEach(function (key, value) {
payload = payload + "<" + key + ">" + value + "</" + key + ">";
});
payload = payload + "</" + command + ">";
return payload;
} else {
return "<" + command + ' device="' + device.id + '"/>';
}
}
これは Ultralight プロトコルの修正であり、 @
および |
記号が Ultralight デバイス用に生成されます。
ただし、ペイロードの作成はジョブの半分にすぎず、デバイスに送信して理解する必要があるため、明確に定義された
通信ハンドシェイクを使用して通信を完了する必要があります。そのため、ペイロードを生成した後、 HTTPBindings.js
の sendXMLCommandHTTP()
メソッドがメッセージを送信し、レスポンスを xmlParser.js
の result()
メソッドに渡して、デバイスからのコマンド・レスポンスを解釈します。
function result(payload) {
const xmlToJson = require("xml-parser");
const data = xmlToJson(payload);
const result = {};
result.deviceId = data.root.attributes.device;
result.command = data.root.attributes.command;
result.result = data.root.name;
return result;
}
最後に、コマンドの成功または失敗は、IoT Agent node ライブラリの共通コードを使用して Context Broker に更新されます。
IoT Agents の典型であるように、ペイロードの作成と通信のハンドシェイクは、メンテナンスを容易にするために2つの個別の 問題に分割されています。したがって、今回のケースではペイロードのみが変更されているため、カスタムのユースケースを 満たすために変更が必要なのは、コードの XML ペイロード側のみです。
アクチュエータ・コマンドの結果は、標準の NGSI コマンドを使用して Context Broker で読み取ることができます。
8 リクエスト:¶
curl -X GET \
'http://localhost:1026/v2/entities/urn:ngsi-ld:Bell:001?type=Bell&options=keyValues' \
-H 'fiware-service: openiot' \
-H 'fiware-servicepath: /'
レスポンス:¶
{
"id": "urn:ngsi-ld:Bell:001",
"type": "Bell",
"TimeInstant": "2018-05-25T20:06:28.00Z",
"refStore": "urn:ngsi-ld:Store:001",
"ring_info": " ring OK",
"ring_status": "OK",
"ring": ""
}
ring
コマンドの結果は ring_info
属性の値で確認できます。
Custom IoT Agent を開発すると、ユーザは標準の NGSI リクエストを Context Broker に送信するだけでデバイスを 作動させることができますが、低レベルの基礎となるプロトコルは不明であり、IoT Agent に正常に抽象化されます。
License¶
MIT © 2020-2022 FIWARE Foundation e.V.