ユーザ&プログラマ・マニュアル

インデックス

APIの概要

この節では、この IoTAgent によって実装されたサウスバウンド API について説明します。Configuration API および一般的な IoTAgent に関するその他の APIについては、API リファレンスのセクションをチェックしてください。

Ultralight 2.0 プロトコル

説明

Ultralight 2.0 は、帯域幅とデバイスのメモリが限られたリソースになる場合がある、制約のあるデバイスとの通信を目的とした、軽量のテキストベースのプロトコルです。

測定のペイロード構文

情報更新のリクエストのペイロードは、'|' キャラクタで区切られたキーと値のペアのリストで構成されます。例えば :

t|15|k|abc
この例では、2つの属性が送信されます。つまり、値 "15" の名前 "t" と値 "k" の名前 "abc" です。Ultralight 2.0の値は型を持ちません。すべてが文字列として扱われます。

'#'文字を使用して、複数の測定値グループを1つのリクエストにまとめることができます。その場合、測定値のそれぞれのグループに対して異なる NGSI リクエストが生成されます。例えば :

gps|1.2/3.4#t|10
これにより、同じエンティティに対して2つの NGSI リクエストが生成されます。値のそれぞれに対して1つです。これらのリクエストのそれぞれには、任意の数の属性を含めることができます。

測定値グループには、次の構文を使用してオプションのタイムスタンプを追加することができます :

2016-06-13T00:35:30Z|lle|100
タイムスタンプは、測定値自体のプレフィックスとして '|'で区切られて追加されます。属性は最終エンティティの TimeInstant 属性に変換されます。

アクティブ属性とパッシブ属性

現在のバージョンのエージェントは、アクティブな属性、つまりデバイスによってエージェントにアクティブにレポートされた属性のみをサポートします。パッシブまたはレイジー (lazy) な属性、つまり、エージェントからの明示的リクエストでのみ与えられる属性は実装されません。その実装に関する詳細と更新については、問題#23を確認してください。

コマンドの構文

コマンドは、IotAgent からデバイスに送信されるメッセージです。コマンドの形式は次のとおりです :

<device name>@<command name>|<command value>
これは、Context Brokerで device_name と名付けれたデバイスが、command_name コマンドを所定の値で実行する必要があることを示します。例えば :
Robot1@turn|left
この例では、ロボット1に左に向けるよう指示します。

パラメータを必要とする複雑なコマンドの場合、パラメータ渡しを実装するために command_value を使用できます。例えば :

weatherStation167@ping|param1:1|param2:2
この例では、weatherStation167 に提供されたパラメータでpingメッセージに返信するよう指示します。=Context Brokerの禁止文字のため、: の代わりに = を使用することができません。

コマンドがデバイスで実行されたら、サーバへのリプライは次の形式に従わなければなりません。

<device name>@<command name>|result
ここで、device_namecommand_name は、コマンド実行で使用されたものと同じものでなければならず、結果はコマンドの最終結果です。例えば :
weatherStation167@ping|Ping ok
この場合、Weather stationはすべてが正常に機能していることを示す文字列の値でリプライします。

双方向構文

Provisioning API の最新バージョンでは、Context Broker とデバイスの間で共有されるデータを同期して保持するために、リバース表現の定義が可能です。これは、データがデバイスからのプレーンデータか、IoTAgentのトランスフォーメーション表現かを問いません。この場合、リバース表現が定義されると、双方向属性が変更されるたびに、 IoTAgent は元のデバイスに、リバース表現の属性で定義された名前とデバイスのIDを持つコマンドを送信します。上のコマンド構文を参照してください。

トランスポート・プロトコル

Ultralight 2.0 は、デバイスとサーバ間で共有する測定値とコマンドを記述するペイロードを定義しますが、単一のトランスポートプロトコルは指定していません。代わりに、サマリシナリオでさまざまなトランスポートプロトコルバインディングを確立できます。

以下のセクションでは、現在サポートされているバインディングの HTTP, MQTT, AMQP について説明します。

HTTPバインディング

HTTPバインディングには、GET要求、POST要求、およびコマンドの3つの相互作用が定義されています。

GET要求によるリクエスト

デバイスは、次のクエリパラメータを使用して、/iot/d パスに HTTP GET 要求により、IoT Platform に新しい測定値を報告できます :

  • i (device ID) : デバイスID。APIキーで一意
  • k (API Key) : APIデバイスが登録されているサービスのキー
  • t (timestamp) : 測定値のタイムスタンプ。IoTAgentの 自動タイムスタンプを無効にします (オプション)
  • d (Data) : Ultralight 2.0 ペイロード

GET要求のペイロードには、複数の測定値グループを含めることはできません。

POST要求によるリクエスト

測定値の報告方法のもう1つの方法は、POST 要求を使用して報告することです。この場合、ペイロードはリクエスト・ペイロードとして渡されます。2つのクエリ・パラメータは必須です :

  • i (device ID) : デバイスID。API キーで一意
  • k (API Key) : デバイスが登録されているサービスの API キー
  • t (timestamp) : 測定値のタイムスタンプ。IoTAgent の自動タイムスタンプを無効にします(オプション)
コマンドの送信

HTTPトランスポートを使用する場合、コマンド処理には2種類があります :

  • Push commands : この場合、デバイスには、Iot Agent が受信したコマンドを送信するURLを含む、 endpoint 属性をプロビジョニングする必要があります。リクエスト・ペイロード形式は、UL プロトコル記述に記述された形式になります。デバイスは、UL2.0 結果形式のコマンドの結果を含む 200 OK レスポンスで応答します。

  • Polling commands : この場合、エージェントはデバイスにメッセージを送信せず、デバイスがコマンドを取得する準備ができたらいつでも IoT Agent からメッセージを取得する責任があります。Iot Agent からコマンドを取得するために、デバイスは、通常の測定値の一部として値 '1' を持つクエリパラメータ 'getCmd' を送信します。このアクションの結果、 IoTAgent は、空のボディ(測定レポートへの典型的な応答)を返す代わりに、文字 '#'で区切られた、デバイスで利用可能なすべてのコマンドのリストを返します。コマンド・ペイロードは、プロトコルセクションおよびプッシュコマンドとの共有に記述されています。デバイスがコマンドの実行を完了すると、デバイスは測定結果が報告されるのと同じ方法で応答を送信しますが、プロトコルセクションで公開している、コマンドの結果形式を使用します。

ポーリングコマンドに関するいくつかの追加の注釈 :

  • 測定値を送信することなくコマンドを取得することもできます。言い換えれば、デバイスは、蓄積されたコマンドを得るために測定値を送信するよう強制さません。

MQTTバインディング

MQTT は、マシン間(M2M) / IoT 接続プロトコルであり、ピア間の軽量な相互作用にフォーカスしてます。MQTTは、ユーザによって定義された階層的なトピック・セットに対するパブリッシュ/サブスクライブ・メカニズムに基づいています。

このセクションでは、MQTT をUltralight 2.0 のトランスポート・プロトコルとして使用する場合に許可されるトピックとメッセージを指定します。MQTT プロトコルで使用されるすべてのトピックには、同じプレフィックスが含まれています :

<apiKey>/<deviceId>
ここで、<apiKey> はサービスに割り当てられたAPIキー、<deviceId> はデバイスのIDです。

このトランスポート・プロトコル・バインディングはまだ開発中です。

1つの測定値を1つのメッセージで送信

サーバに単一の測定値を送信するには、デバイスはプレーン値を次のトピックにパブリッシュする必要があります :

<apiKey>/<deviceId>/attrs/<attrName>
ここで、ここで、<apiKey><deviceId> は典型的な意味を持ち、<attrName> はデバイスが送信している測定の名前です。

また、たとえば、IDが id_sen1、APIキーが ABCDEF、属性IDが ht のデバイスで Mosquitto を使用している場合、湿度の測定値は次のように報告されます :

$ mosquitto_pub -t /ABCDEF/id_sen1/attrs/h -m 70 -h <mosquitto_broker> -p <mosquitto_port> -u <user> -P <password>
1つのメッセージで複数の測定値を送信

1つのメッセージで複数の測定値を送信するには、次のトピックでメッセージを発行する必要があります :

<apiKey>/<deviceId>/attrs
ここで、<apiKey><deviceId> は一般的な意味を持っています。このようなメッセージのペイロードは、測定値グループの有無にかかわらず、Ultralight 2.0 ペイロードでなければなりません。

たとえば、IDが id_sen1 のデバイスで Mosquitto を使用している場合、ABCDEF のAPIキーと ht の属性 ID を入力すると、すべての測定値(湿度と温度)が次のように報告されます :

$ mosquitto_pub -t /ABCDEF/id_sen1/attrs -m 'h|70|t|15' -h <mosquitto_broker> -p <mosquitto_port> -u <user> -P <password>
コマンド

MQTTトランスポート・プロトコル・バインディングを使用するコマンドは、常にプッシュ・モードで動作します。サーバは、デバイスによるサブスクライブされているトピック、つまり、コマンド・トピックにメッセージをパブリッシュします。デバイスがコマンドを終了すると、その結果が別のトピックにパブリッシュされます。

コマンド・トピック、ここでサブスクライブされたクライアントは、次の形式を持ちます :

<apiKey>/<deviceId>/cmd

コマンドの結果は、次のトピックで報告する必要があります :

<apiKey>/<deviceId>/cmdexe
コマンドの実行とコマンド・レポートのペイロード形式は、上記の"Ultralight 2.0コマンド構文"で指定されています。

例えば、ユーザが data = 22 パラメータを有する ping コマンドを送信したい場合、ユーザは、sensor型の sen1 と呼ばれるエンティティに関する以下のリクエストを Context Broker に送信します :

{
  "updateAction": "UPDATE",
  "contextElements": [
    {
      "id": "sen1",
      "type": "sensor",
      "isPattern": "false",
      "attributes": [
        {
          "name": "ping",
          "type": "command",
          "value": "22"
        }
      ]
    }
  ]
}

デバイスに関連付けられたAPIキーが ABCDEF で、sen1 エンティティに関連するデバイスIDが id_sen1 である場合、これにより、/ABCDEF/id_sen1/cmd トピックのメッセージが次のペイロードとともに生成されます :

id_sen1@ping|22

Mosquitto を使用している場合、mosquitto_sub スクリプトを実行することによってそのようなコマンドが受信されます :

$ mosquitto_sub -v -t /# -h <mosquitto_broker> -p <mosquitto_port> -u <user> -P <password>
/ABCDEF/id_sen1/cmd id_sen1@ping|22

この時点では、Context Brokerは、sen1エンティティの ping_status の値を PENDINGに更新します。ping_infoping はどちらも更新されません。

デバイスがコマンドを実行すると、その結果を次の形式のペイロードを持つ /ABCDEF/id_sen1/cmdexe トピックにパブリッシュできます :

id_sen1@ping|1234567890

Mosquitto を使用している場合、そのようなコマンドの結果は、mosquitto_pub スクリプトを実行して送信されます :

$ mosquitto_pub -t /ABCDEF/id_sen1/cmdexe -m 'id_sen1@ping|1234567890' -h <mosquitto_broker> -p <mosquitto_port> -u <user> -P <password>

最後に、Context Brokerは、ping_infoping_status の値をそれぞれ 1234567890OK に更新します。ping 属性は更新されません。

AMQPバインディング

AMQP は、Advance Message Queuing Protocol の略で、メッセージ・キュー・システムで最も一般的なプロトコルの1つです。プロトコル自体はソフトウェアに依存せず、優れたアーキテクチャ上の柔軟性を実現しますが、このトランスポート・バインディングは、RabbitMQ Broker と連携するように設計されています。前の項の MQTT バインディングに非常に似ています。実際、スケーラブルな MQTT Broker を必要とするIoT Platform のデプロイメントでは、MQTT プラグインを使用した RabbitMQ が使用され、AMT を介して Iot Agent を RabbitMQ に接続し、クライアントをMQTTを介して RabbitMQ に接続します。

バインディングは Iot Agent をエクスチェンジ (通常は amq.topic) に接続し、2つのキュー(クラスタ環境の IoTAgent のすべてのインスタンス間で共有する)を作成します。1つは着信測定値用、もう1つはコマンド結果更新メッセージ用(_commands サフィックスを追加し、測定値キューとして名付ける)。

バインディングは Iot Agent をエクスチェンジ (通常は amq.topic) に接続し、2つのキュー(クラスタ環境の IoTAgent のすべてのインスタンス間で共有する)を作成します。1つは着信測定値用、もう1つはコマンド結果更新メッセージ用(_commands サフィックスを追加し、測定値キューとして名付ける)。

Key pattern Meaning
...attrs Multiple measure reporting
...attrs. Single measure reporting
...cmd Command reception
...cmdexe Command update message

ペイロードは他のバインディングと同じです。

新しいトランスポートの開発

Ultralight 2.0 Iot Agent は、同じ Ultralight 2.0 ペイロードに対して複数の異なるトランスポートを処理できます。これらのトランスポートは、エージェントの起動時に、Node.js モジュールの lib/bindings フォルダを調べることで動的にロードされます。これらのモジュールは、次のフィールドをエクスポートする必要があります :

  • deviceProvisioningHandler(device, callback) : このハンドラは、新しいデバイスが Iot Agent にプロビジョニングされるたびに呼び出されます。デバイスオブジェクトには、デバイス登録で提供されたすべての情報が含まれます

  • configurationHandler(configuration, callback) : デバイスグループ内の変更(プロビジョニングまたは更新)のハンドラ。このハンドラは、構成グループがプロトコル・バインディングで初期化または登録を必要とする場合に使用する必要があります

  • start(newConfig, callback) : 指定された構成でバインディングモジュールを開始します。newConfig オブジェクトは、グローバルエージェント設定が含まれています。モジュールは、グローバルスコープ内の特定の属性を使用して、グローバル構成スコープ自体を使用する代わりに、すべての構成値を保持する必要があります

  • stop(callback) : バインディングモジュールを停止します

  • protocol : このフィールドには、プロトコルを識別する文字列キーが含まれていなければなりません。サーバからのリクエスト(コマンドとパッシブ属性)は、デバイスの protocol フィールドとモジュール内の対応する protocol 属性を使用して、どのモジュールをリクエストに参加させるべきかを識別します

すべてのメソッドは、エラーの有無にかかわらず、終了する前にコールバックを呼び出す必要があります。バインディングは、 Iot Agent Node.js ライブラリのメソッドを使用して、着信リクエストを処理するために使用します。

開発ドキュメント

プロジェクトビルド

プロジェクトはGrunt Task Runnerを使用して管理されます。

使用可能なタスクのリストについては、次のように入力します。

grunt --help

次のセクションでは、使用可能なオプションについて詳しく説明します。

コーディング・ガイドライン

jshint, gjslint

提供された .jshintrc および .gjslintrc フラグファイルを使用します。後者は Python を必要とし、grunt-init を使用してプロジェクト・スケルトンを作成する際にその使用を無効にすることができます。ソースコードのスタイルを確認するには、次のように入力します。

grunt lint

Checkstyle レポートは Jenkins と一緒に使用して、Checkstyle プラグインと Violations プラグインを使用してプロジェクト品質メトリックを監視することができます。report/lint/ 下に Checkstyle と JSLint のレポートを生成するには、次のように入力します。

grunt lint-report

継続的なテスト

src ファイルまたはテストを変更して、継続的なテストをサポートします。連続テストの場合は、次のように入力します。

grunt watch

ソースコードのドキュメント

dox-foundation

HTML ドキュメントを site/doc/ の下に生成します。DocLinks プラグインを使用して jenkins と一緒に使用できます。ソースコードのドキュメントをコンパイルするには、以下を入力します。

grunt doc

コードカバレッジ

Istanbul

テストのコードカバレッジを分析します。

site/coverage/ の下にHTMLカバレッジレポートを生成し、サマリを出力するには、次のように入力します。

# Use git-bash on Windows
grunt coverage

report/coverage/cobertura-coverage.xmlCobertura プラグインを使用して Jenkins でプロジェクト品質メトリクスを監視するために使用できる Cobertura レポートを生成するには、次のように入力します。

# Use git-bash on Windows
grunt coverage-report

コードの複雑さ

Plato

Plato を使用してコードの複雑さを分析し、そのレポートを site/report/ の下に保存します。DocLinksプラグインを使用して jenkins と一緒に使用できます。複雑さのレポートでは、次のように入力します。

grunt complexity

PLC

プロジェクトの貢献者を更新

grunt contributors

開発環境

git hooks で環境を初期化してください

grunt init-dev-env

すべての開発者のためにこのタスクを自動的に実行することを強くお勧めします。package.json に次の行を追加するだけです。 lines to your package.json

{
  "scripts": {
     "postinstall": "grunt init-dev-env"
  }
}

サイト生成

プロジェクトの GitHub ページを生成し、カバレッジ、複雑さ、および JSDocs のページを公開するという面倒な作業があります。GitHub ページを初期化するには、以下を使用します :

grunt init-pages

これにより、リポジトリのルートの下にサイトフォルダも作成されます。このサイトフォルダはリポジトリの履歴から切り離され、公開のために作成された gh-pages ブランチに関連付けられています。この初期化アクションは、プロジェクト履歴で一度だけ実行する必要があります。サイトが初期化されたら、次のコマンドで公開します :

grunt site

このコマンドは、開発者が init-dev-env を実行した後にのみ動作します。これは、分離サイトを作成することが目的です。

このコマンドは、カバレッジ、ドキュメント、および複雑なタスクも起動します。上記のセクションを参照してください。