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

目次

API の概要

JSON プロトコルでは、プレーンな JSON オブジェクトを使用して、受け入れられたトランスポート (HTTP, MQTT または AMQP) のいずれかで、key-value マップとしてフォーマットされた情報を送信します。

このドキュメントでは、"プレーンな JSON オブジェクト" または "単一レベルのJSONオブジェクト" に言及します。これは、次のことを意味します :

  • エスケープされていない文字列としてシリアル化された有効な JSON オブジェクト
  • 単一レベルのJSONオブジェクト、つまり、JSON オブジェクトのすべての第 1 レベルの属性は、配列やその他のオブジェクトではなく、文字列または数値です

重要な注意 : エージェントの現在のバージョンは、アクティブな属性、つまりデバイスがエージェントにアクティブに報告した属性のみをサポートしています。受動的 または レイジー属性、つまり、エージェントからの明示的なリクエストでのみ値が与えられる属性は実装されません。その実装に関する詳細と更新については、問題 #89 を確認してください。

HTTP バインディング

HTTP バインディングは、デバイス内の HTTP クライアントからのエージェントとの直接インタフェースに基づいています。したがって、Json ペイロードは Http メッセージに直接入れられます。

測定値のレポート

ペイロードは、オブジェクトの各属性が NGSI エンティティの属性にマップされる単純なプレーンな JSON オブジェクトで構成されます。NGSIv1 のすべての単純な属性値は文字列であるため、すべての属性の値は文字列としてコピーされます。例えば :

{
  "h": "45%",
  "t": "23",
  "l": "1570"
}

ペイロード内の属性名は、デバイス・プロビジョニングでエイリアスを使用することで、エンティティ内のさまざまな属性名にマッピングできます。詳細については、Provisioning API for details) を参照してください。

デバイスは、次のクエリパラメータを使用して /iot/json パスへの HTTP POST リクエストを使用して、IoT プラットフォームに新しい測定値を報告できます :

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

コマンド

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

  • プッシュ・コマンド : この場合、デバイスには IoT Agent が受信したコマンドを送信する URL を含む endpoint 属性をプロビジョニングする必要があります。リクエストのペイロード・フォーマットは、"ペイロード"のセクションで説明されているように、プレーンな JSON になります。デバイスは、JSON 結果フォーマットのコマンドの結果を含む 200 OK のレスポンスを返します

  • ポーリング・コマンド : この場合、IoT Agent はメッセージをデバイスに送信しません。デバイスは、デバイスがコマンドを取得する準備ができたら、IoT Agent からメッセージを取得する責任があります。IoT Agent からコマンドを取得するために、デバイスは、通常の測定値の一部として、値 '1' を持つクエリパラメータ 'getCmd' を送信します。このアクションの結果、IoT Agent は、空のボディ (測定値レポートへの典型的なレスポンス) を返す代わりに、デバイスで使用可能なすべてのコマンドのリストを JSON 形式で返します。各属性はコマンドを表し、その値はコマンド値です。JSON 戻りオブジェクトを使用すると、各コマンドに対して1つの値しか返されないことを意味します。最後の値が返されます。インプリメンテーションでは、コマンドに使用できる値に別の制限があります。コマンドの値は空文字列や、空白文字列で構成された文字列にすることはできません。デバイスがコマンドの実行を完了すると、デバイスは測定結果が報告されるのと同じ方法でレスポンスを送信しますが、 コマンドの結果フォーマットプロトコルのセクションで公開しています

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

  • 測定値を送信することなくコマンドを取得することもできます。言い換えると、デバイスは、蓄積されたコマンドを取得するために測定値を送信するよう強制されません。しかし、この場合、GET メソッドが getCmd=1 クエリ・パラメータを運ぶのに使用されることに 注意してください。実際の測定値のペイロードは存在しないため、POST は、あまり意味がありません。

設定の取得

プロトコルは、デバイスがその設定、または Context Broker に格納されている値から必要なその他の値を取り出すためのメカニズムを提供します。このメカニズムは、IoT Agent HTTP エンドポイントへのコールと、提供されたデバイスのエンドポイントへの直接コールを組み合わせます。

設定コマンド

IoT Agent は、このパスでデバイスからの設定リクエストをリッスンします :

http://<iotaURL>:<HTTP-Port>/configuration/commands

メッセージには、次の属性を持つ JSON ドキュメントが含まれている必要があります :

  • type : デバイスが送信しているコマンドのタイプを示します。受け入れられる値については以下を参照してください
  • fields : デバイスを表す Context Broker のエンティティから検索される値の名前を持つ配列

このコマンドは、Context Broker へのクエリをトリガし、その結果、以下で説明する configuration/values パスを使用して、デバイスのエンドポイントへの新しいリクエストが生成されます。

例えば :

{
  "type": "configuration",
  "fields": [
    "sleepTime",
    "warningLevel"
  ]
}

設定コマンドの種類には、次の2つの値があります :

  • subscription : このコマンドは、選択された値のいずれかが変更されるたびにトリガされる Context Broker でサブスクリプションを生成します。値が変更された場合は、すべての属性が取得されます
  • configuration : このコマンドは、IoT Agent から Context Broker への単一のリクエストを生成します。これにより、デバイスのエンドポイントへの単一のリクエストがトリガーされます
設定情報の取得

すべてのデバイスは、次のパスでリッスンする必要があるため、設定情報を受け取ることができます :

<device_endpoint>/configuration/values

デバイスが IoT Agent からの情報をリクエストするたびに、情報はこのパスに掲載されます。情報は、複数の測定値のレポートで使用されているのと同じフォーマットで送信されます。リクエストされた値ごとに属性を持つプレーンな JSON です。dt という追加パラメータがシステムの現在時刻とともに追加されます。

例えば :

{
  "sleepTime": "200",
  "warningLevel": "80",
  "dt": "20160125T092703Z"
}

MQTT バインディング

MQTT バインディングは、MQTT Broker の存在と、さまざまな宛先およびメッセージのタイプを分離するためのさまざまなトピックの使用法に基づいています。異なる可能性のある対話については、以降のセクションで説明します。

プロトコルで使用されるすべてのトピックには、デバイスグループの API Key と相互作用に関与するデバイスの DeviceID のプレフィクスが付けられます。すなわち、各サービスごとに異なるトピックのセットがあります。例 : /FF957A98/MyDeviceId/attrs。API Key は、サービスのすべてのデバイス間で共有される秘密の識別子であり、DeviceIDは、サービス内のデバイスを一意に識別する ID です。 API Key は IoT Agent Configuration API で設定することも、IoT Agent の public default API Key を代わりに使用することもできます。情報が送信される前に、IoT Agentに DeviceID を事前にプロビジョニングする必要があります。

測定値のレポート

測定値のレポートには2つ方法があります :

  • Multiple measures : 複数の測定値を送信するために、デバイスは次の構造を持つ MQTT トピックに JSON ペイロードをパブリッシュできます :
/{{api-key}}/{{device-id}}/attrs

この場合のメッセージには、単一レベルの有効な JSON オブジェクトが含まれている必要があります。key/value ペアごとに、Key は属性名を表し、value は属性値を表します。属性タイプは、デバイス提供情報から取得されます。

たとえば、 ID が id_sen1、API Key が ABCDEF 、属性IDが ht を持つデバイスで Mosquitto を使用すると、すべての測定値 (湿度と温度) が次のようにレポートされます :

$ mosquitto_pub -t /ABCDEF/id_sen1/attrs -m '{"h": 70, "t": 15}' -h <mosquitto_broker> -p <mosquitto_port> -u <user> -P <password>
  • Single measures : 単一の測定値を送信するために、デバイスは以下の構造を持つ MQTT トピックに直接、値をパブリッシュできます :
/{{api-key}}/{{device-id}}/attrs/<attributeName>

変更する属性の名前をトピック内に示します。

どちらの場合も、キーは Configuration API を通じて、IoT Agent にプロビジョニングされ、Device ID は Provisioning API を使用してプロビジョニングされた ID です。 API Key は存在しなければなりませんが、特定の構成へのリンクなしでデバイスがプロビジョニングされた場合の任意の文字列であってもかまいません。

たとえば、ID が id_sen1、API Key が ABCDEF 、属性IDが ht を持つデバイスで Mosquitto を使用すると、湿度の測定値が次のように報告されます :

$ mosquitto_pub -t /ABCDEF/id_sen1/attrs/h -m 70 -h <mosquitto_broker> -p <mosquitto_port> -u <user> -P <password>

設定の取得

プロトコルは、デバイスがその設定、または Context Broker に格納されている値から必要なその他の値を取り出すためのメカニズムを提供します。この機能をサポートするために、設定コマンドのトピックと設定情報を受け取るトピックの2つのトピックが作成されています。このメカニズムは、設定フラグ configRetrieval を使用して有効または無効にすることができます。

このメカニズムと双方向性プラグインは同時にアクティブにすることはできません。

構成コマンドのトピック
/{{apikey}}/{{deviceid}}/configuration/commands

IoT Agent は、デバイスからのリクエストをこのトピックでリッスンします。メッセージには、次の属性を持つ JSON ドキュメントが含まれている必要があります :

  • type : デバイスが送信しているコマンドのタイプを示します。受け入れられる値については以下を参照してください
  • fields : デバイスを表す Context Broker のエンティティから取り出されるされる値の名前を持つ配列

このコマンドは Context Broker へのクエリをトリガし、その結果、設定情報のトピックに新しいメッセージがポストされます。下記を参照してください。

例えば :

{
  "type": "configuration",
  "fields": [
    "sleepTime",
    "warningLevel"
  ]
}

設定コマンドの種類には、次の2つの受け入れられる値があります :

  • subscription : このコマンドは、選択された値のいずれかが変更されたときにトリガされるサブスクリプションを Context Broker で生成します。値が変更された場合は、すべての属性が取得されます
  • configuration : このコマンドは、IoT Agent から Context Broker への単一のリクエストを生成します。これは、値のトピックで単一の公開メッセージをトリガーします
設定情報のトピック
/{{apikey}}/{{deviceid}}/configuration/values

すべてのデバイスはこのトピックをサブスクライブする必要があるため、設定情報を受信できます。デバイスが IoT Agent からの情報をリクエストするたびに、情報がこのトピックに掲載されます。情報は、複数の測定値のレポートで使用されているのと同じフォーマットで公開されます。リクエストされた値ごとに属性を持つプレーンな JSON です。dt という追加パラメータがシステムの現在時刻とともに追加されます。

例えば :

{
  "sleepTime": "200",
  "warningLevel": "80",
  "dt": "20160125T092703Z"
}

コマンド

IoT Agent は、IoT Agent library で指定されているように、IoT Agent コマンドを実装します。

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

コマンドが IoT Agent で受信されると、次のトピックでメッセージが発行されます :

/<APIKey>/<DeviceId>/cmd

メッセージのペイロードは、コマンドごとの属性を持つプレーンな JSON オブジェクトであり、コマンドのパラメータはその属性の値です。

デバイスがコマンドを実行すると、デバイスは結果情報を報告して、次のトピックで新しい測定値を公開できます :

/<APIKey>/<DeviceId>/cmdexe

このメッセージには、更新するコマンドごとに1つの属性が含まれていなければなりません。その属性の値はコマンドの結果とみなされ、エンティティに対応する _result 属性として渡されます。

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

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

デバイスに関連付けられている API Key が ABCDEF で、sen1 エンティティに関連する デバイス ID が id_sen1の場合、/ABCDEF/id_sen1/cmd トピックに次のペイロードを含むメッセージが生成されます :

{"ping":{"data":"22"}}

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

$ mosquitto_sub -v -t /# -h <mosquitto_broker> -p <mosquitto_port> -u <user> -P <password>
/ABCDEF/id_sen1/cmd {"ping":{"data":"22"}}

Context Broker は、sen1 エンティティの ping_status の値を PENDING に更新します。ping_infoping も更新されません。

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

{"ping": "1234567890"}

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

$ mosquitto_pub -t /ABCDEF/id_sen1/cmdexe -m '{"ping": "1234567890"}' -h <mosquitto_broker> -p <mosquitto_port> -u <user> -P <password>

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

双方向の構文 (Bidirectionality Syntax)

Provisioning API の最新バージョンでは、デバイスからのプレーンデータか IoT Agent のトランスフォーメーション式かのどちらのデータであるかにかかわらず、Context Broker とデバイスの間で共有されるデータを同期させたままにするための逆式 (reverse expression) の定義が可能です。この場合、逆式が定義されると、双方向属性が変更されるたびに、IoT Agent は元のデバイスに、逆式属性で定義された名前とデバイスの ID を持つコマンドを送信します。コマンド構文を参照してください。

AMQP バインディング

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

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

測定値のレポートとコマンド・ステータスの更新の両方のメカニズムは、MQTT バインディングの場合とほぼ同じです。すべてのメッセージは、次のルーティング・キーを使用して、選択したエクスチェンジに公開する必要があります :

キー・パターン 意味
...attrs 複数の測定値のレポート
...attrs. 単の測定値のレポート
...cmd コマンド受信
...cmdexe コマンド更新メッセージ

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

値の変換

IoT Agent は、デバイス内の解析ロジックを最小限に抑えるために、特定のタイプの値に対していくつかのアドホック変換を実行することがあります。このセクションでは、これらの変換について説明します。

タイムスタンプ圧縮

"timeInstant" という名前で IoT Agent に送られる属性は、ISO8601 の完全な基本カレンダ表現 (例: 20071103T131805) のタイムスタンプであると予想されます。Context Broker とのあらゆる対話 (更新とクエリ) のために、IoT Agent は自動的にこの値を拡張表現 (例: +002007-11-03T13:18:05) に変換します。

この機能は、compressTimestamp 設定フラグを使用して有効または無効にすることができます。

Thinking Things プラグイン

このIoT Agent は、あるプロトコルから他のプロトコルへの移行を容易にするために Thinking Things Protocol IoT Agent のいくつかの機能を保持しています。この機能は、mqtt.thinkingThingsPlugin フラグを使用してアクティブ化できるプラグインに組み込まれています。プラグインがアクティブ化されると、次の規則がすべての着信 MQTT-JSON リクエストに適用されます :

  • P1 という名前の属性が見つかった場合、その内容はここで説明するように Phone Cell の位置として解析されます
  • C1 という名前の属性が見つかった場合、その内容は P1 属性のように解析されますが、すべてのフィールドは4桁の固定長の16進数で、カンマ区切りではなくコード化されています
  • B という名前の属性が見つかった場合、その内容はここで説明するように、バッテリ情報であるかのように解析されます。この実装では、この属性の拡張バージョンも認められ、"batteryType" と "percentage" フィールドがエンティティに追加されます

開発ドキュメント

コントリビューション

このプロジェクトへのコントリビューションはすべて歓迎します。コントリビューションすることを計画している開発者は、コントリビューション・ガイドライン に従う必要があります。

プロジェクトビルド

プロジェクトは 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

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

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

# Use git-bash on Windows
grunt coverage

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

# 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 に次の行を追加することで、開発者ごとにこのタスクを自動実行することを強くお勧めします :

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

サイト生成

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

grunt init-pages

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

grunt site

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

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

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

概要

この IoT Agent は、MQTT、HTTPなどの複数のトランスポートプロトコル上で Plain JSON プロトコルを提供する用意ができており、さまざまなプロトコル間でほとんどのコードを共有します。そうするために、すべてのトランスポート固有のコードは、一連のプラグインにカプセル化され、./bindings/ フォルダに追加されます。各プラグインは、以下のセクションで定義されている API を持つ単一の Node.js モジュールで構成されている必要があります。IoT Agent は開始時に総てのディレクトリをスキャンするため、新しいモジュールを登録する必要はありません。単純な再起動で十分です。

どのデバイスがどの属性を使用するかを区別するために、新しいフィールド transport がデバイス・プロビジョニングに追加されます。コマンドまたは通知が IoT Agent に到着すると、このフィールドは、リクエストされたタスクを実行するために呼び出すプラグインを推測するために読み込まれます。フィールドが見つからない場合は、設定パラメータの値 defaultTransport が代わりに使用されます。モジュールをデバイスに関連付けるには、デバイスプロビジョニングの transport 属性の値がバインディングの protocol フィールドの値と一致している必要があります。

API

plugins/ フォルダ内のすべてのプラグインは、次の API に準拠している必要があります。次の関数と属性のエクスポートします。

start 関数 (コールバック)

説明

バインディングを開始し、適切な初期化をすべて行います。設定はパラメータとして渡されないため、設定サービスから取得する必要があります。

すべての関数にはコールバックが渡されます。コールバックはアクションが完了した後に呼び出される必要がありますが、コールバック自体は記述されていません。その場合、コールバックの標準 Node.js が適用されます。

stop 関数 (コールバック)

説明

start() 関数で作成されたすべてのリソースを停止し、必要に応じてリソースを解放します。

sendConfigurationToDevice (apiKey, deviceId, results, callback) 関数

説明

Context Broker からリクエストされた設定情報をデバイスに送信します。

パラメータ
  • API Key : 情報を要求しているデバイスの API Key
  • deviceId : 情報を要求しているデバイスの Device ID
  • results : Context Broker へのクエリの結果を含む配列

executeCommand(apiKey, device, serializedPayload, callback) 関数

説明

指定されたペイロードを持つリモート・デバイスでコマンドを実行します。

パラメータ
  • API Key : 情報を要求しているデバイスの API Key
  • device : 情報を要求しているデバイスのすべてのデータを含むオブジェクト
  • serializedPayload : トランスポート・プロトコルを使用して送信されるコマンド識別およびパラメータの文字列シリアル化

プロトコル

protocol 属性は、特定のデバイスのためのトランスポートを識別するために使用される単一の定数文字列の属性です。このパラメータは、主に、コマンドまたは通知が IoT Agent に到着したときに使用されます。デバイス自体が着信するアクティブな測定値またはアクションのエンドポイントを選択しているためです。バインディングの protocol 属性の値は、IoT Agent を使用する各デバイスのプロビジョニングの transport フィールドと一致する必要があります。