本文へジャンプします。

ニフクラ ユーザーガイド

デバイスでのAPI利用

これまでのチュートリアルで説明した通り、IoTデバイスハブで構成されたシステムでは、
デバイスはイベント(デバイスからIoTデバイスハブに送信される)/コマンド(IoTデバイスハブからデバイスに送信される)を介してアプリ/スマートモジュールと通信します。

このチュートリアルでは、デバイスソフトウエアで使用する可能性が最も高い、IoTデバイスハブ-APIのエンドポイントについて説明します。

IoTデバイスハブ APIは、iot-device.jp-east-1.api.cloud.nifty.comでホストされている、HTTPベースのRESTful APIです。 任意のプログラミング言語のいずれのHTTPライブラリでも使用できます。また、TCP接続を通して未加工のHTTPリクエストを送信することもできます。
このチュートリアルでは、cURLコマンドの例を示します。
cURLプログラムは、LinuxやMac OS Xなど、ほとんどのUnix系環境にデフォルトでインストールされています。

IoTデバイスハブは、一般的なハードウエアプラットフォーム上でデバイスソフトウエアを構築するための、デバイスクライアントライブラリも提供しています。

デバイスのプロビジョニング

デバイスを、システムの接続済みノードとして機能させるには、まず以下の2つの操作を行う必要があります。

IoTデバイスハブにより、デバイスに固有のデバイスIDおよびAPIキーを割り当てる。

デバイスをエンドユーザーのホームに追加する。

IoTデバイスハブでは、プロジェクトに対して、デバイスをプロビジョニングするために、2つのオプションが用意されています。
デバイスの機能やシステムのユーザーエクスペリエンスによって、最適なオプションを選択してください。

オプション1 : デバイスの事前プロビジョニング

基本のオプションです。
事前にIoTデバイスハブのデータベースにデバイスのインスタンスを作成してください。

デバイスの構築時に、割り当てられたデバイスIDおよびAPIキーをコピー/フラッシュします。
エンドユーザーがデバイスを自分のホームに取り込むには、デバイスの所有権を「クレーム」(要求)し、ホームにリンクする必要があります。

この手順は以下の通りです。

まず、デバイスはクレームモードを有効にするために、/deviceRegistrationエンドポイントに対してPOSTリクエストを行う必要があります。

以下の例では、デバイスのクレームモードは300秒間アクティブになります。
(_DEVICE_IDと_YOUR_API_KEYは実際のデバイスIDとAPIキーで置き換えてください)

$ curl -i -N -H "Authorization: ModeCloud _YOUR_API_KEY_" --data "deviceId=_DEVICE_ID_&claimable=1&duration=300"
https://iot-device.jp-east-1.api.cloud.nifty.com/deviceRegistration

未加工のHTTPリクエストは以下の通りです。

POST /deviceRegistration HTTP/1.1
Host: iot-device.jp-east-1.api.cloud.nifty.com
Authorization:
ModeCloud _YOUR_API_KEY_
Content-Type: application/x-www-form-urlencoded
deviceId=_DEVICE_ID_&claimable=1&duration=300

成功すると、以下のようなレスポンスが表示されます。

HTTP/1.1 200 OK
Access-Control-Allow-Credentials: false
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: X-Xsrf-Guard
Content-Type: application/json; charset=utf-8
Date: Sun, 26 Jun 2016 05:06:10 GMT
Content-Length: 62

{"claimExpirationTime":"2016-06-26T14:11:10.164446027+09:00"}

クレームモードは、返されたJSONオブジェクトのclaimExpirationTimeプロパティにより、指定された日時に期限が切れます。
クレームモードの期限が切れる前に、デバイスの登録プロセスを完了する必要があります。

間違ったデバイスIDを指定すると、以下のメッセージが表示されます。

HTTP/1.1 403 Forbidden
Access-Control-Allow-Credentials: false
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: X-Xsrf-Guard
Content-Type: application/json; charset=utf-8
Date: Sun, 26 Jun 2016 05:08:15 GMT
Content-Length: 34

{"reason":"MATCHING_DEVICE_ONLY"}

以上で、デバイスのクレームモードが有効になったため、/devicesエンドポイントにPOSTリクエストを送信して、登録プロセスを完了します。

このAPIリクエストは、本来アプリにより呼び出されるものですが、テストの場合は、アプリシミュレーターを使用して呼び出します。
デバイスのクレームコードをコピーしてアプリシミュレーターに貼り付けると、デバイスはホームに追加され、イベントの送信とコマンドの受信をする準備が整います。

デバイスの事前プロビジョニング

オプション2 : オンデマンドデバイスプロビジョニング

このオプションでは、IoTデバイスハブのデータベースに、事前にデバイスインスタンスを作成する必要がありません。
ユーザは新しいデバイスをオンデマンドで追加することができます。このプロビジョニング方法はユーザークライアント(通常はモバイルアプリ)が直接ハードウェアデバイスにプロビジョニングされたトークンを送る機能を用いて実現されます。

このオプションを使用してデバイスをプロビジョニングする手順は、以下の通りです。

コントロールパネルでプロジェクトの「設定」画面を開き、 「詳細なオプション」セクションで、「オンデマンドデバイスプロビジョニング」オプションを有効にします。

「詳細なオプション」セクション

ユーザーのホームにデバイスを追加するために、デバイスクラスとデバイスのタグを指定して、/homes/_HOME_ID_/deviceProvisioningエンドポイントに対してPOSTリクエストを送信します。
アプリシミュレーターを使用してこの手順をテストできます。

アプリシミュレーター

アプリシミュレーター

ユーザークライアントから発行されたプロビジョニング・トークンは、今度はおそらくWiFiやBluetooth接続などを経由して対象のハードウェアデバイスに渡るでしょう。ハードウェアデバイスはプロビジョニング・トークンを入手後、IoTデバイスハブのAPIに接続し、リクエストボディにトークンパラメータを指定して、/deviceのエンドポイントにPOSTリクエストを行うことで、プロビジョニングプロセスを完了する必要があります。
デバイスが正常にプロビジョニングされ、ホームに追加された場合、リクエストによって返されるJSONは、デバイスに割り当てられたデバイスIDとAPIキーが含まれています。デバイスはローカルストレージに情報を格納し、IoTデバイスハブとの今後すべての通信にAPIキーを含める必要があります。

IoTデバイスハブイメージ

APIキーの確認

デバイスからIoTデバイスハブ APIに送信される各HTTPリクエストでは、Authorization HTTPヘッダーにAPIキーを含める必要があります。

デバイスのAPIキーは、IoTデバイスハブのコントロールパネルで確認することができます。

デバイスのAPIキーが機能していることを確認するには、以下のコマンドを実行します。
(_YOUR_API_KEY_は実際のAPIキーで置き換えてください)

$ curl -i -N -H "Authorization: ModeCloud _YOUR_API_KEY_" https://iot-device.jp-east-1.api.cloud.nifty.com/auth

未加工のHTTPリクエストは以下の通りです。

GET /auth HTTP/1.1
Host: iot-device.jp-east-1.api.cloud.nifty.com
Authorization:
ModeCloud _YOUR_API_KEY_

成功すると、以下のようなレスポンスが表示されます。
実際に返されるJSONオブジェクトは、デバイスの構成により異なる場合があります。

HTTP/1.1 200 OK
Access-Control-Allow-Credentials: false
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: X-Xsrf-Guard
Content-Type: application/json; charset=utf-8
Date: Sun, 26 Jun 2016 05:39:40 GMT
Content-Length: 50

{"type":"device","deviceId":1303,"projectId":408}

使用したAPIキーが間違っている場合は、以下のようなレスポンスが表示されます。

HTTP/1.1 200 OK
Access-Control-Allow-Credentials: false
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: X-Xsrf-Guard
Content-Type: application/json; charset=utf-8
Date: Sun, 26 Jun 2016 05:42:03 GMT
Content-Length: 18

{"type":"nobody"}

間違ったAPIキーが渡されたため、IoTデバイスハブは呼び出し元をデバイスとして認識できませんでした。
HTTPトランザクション全体を表示するには、-vオプションを指定してcURLコマンドを実行します。

デバイスAPIキーの保存

セキュリティ強化のため所持しているデバイスのAPIキーをIoTデバイス側で保管するのではなく、自分自身で保管することを選ぶことができます。
プロジェクトのデバイスAPIキーをサービス側で保管しないようにするには、コントロールパネルでデベロッパーコンソールで、[プロジェクトの設定]に移動し、「キーの保管をオフにする」をクリックします。

「キーの保管をオフにする」をクリック

このオプションを選択すると、2つの効果があります。

  1. すべての既存のデバイスキーがIoTデバイスハブのデータベースから削除されます。
  2. 今後生成されるデバイスキーは、IoTデバイスハブのデータベースに格納されません。

またこのオプションは不可逆なものですので、設定には注意してください。このオプションを設定する前には必ず事前にすべてのデバイスキーのバックアップをしてください。バックアップを行うにはコントロールパネルから関連するデバイスクラスに移動し、[デバイスリスト]セクションで「エクスポート」をクリックします。

[デバイスリスト]セクションで「エクスポート」をクリック

APIキーなど、デバイスクラスのデバイスインスタンスのすべてのメタデータがJSONファイルとしてエクスポートされます。
その後オプションを設定した場合、新しいデバイスインスタンスを作成する際は必ずAPIキーを安全な場所に保管する必要があります。IoTデバイスハブからは再度キーを取得することはできません。

イベントの送信

デバイスからイベントを送信するには、/devices/_DEVICE_ID_/eventエンドポイントに対してPUTリクエストを行います。
下記が例です。

$ curl -XPUT -i -N -H "Authorization: ModeCloud _YOUR_API_KEY_" -H "Content-Type: application/json" --data '{ "eventType":"foo", "eventData": {} }' https://iot-device.jp-east-1.api.cloud.nifty.com/devices/_DEVICE_ID_/event

未加工のHTTPリクエストは以下の通りです。(_YOUR_API_KEY_および_DEVICE_ID_はデバイス設定に応じて正しく置き換えてください。)

PUT /devices/_DEVICE_ID_/event HTTP/1.1
Host: iot-device.jp-east-1.api.cloud.nifty.comt
Authorization:
ModeCloud _YOUR_API_KEY_
Content-Type: application/json

{ "eventType":"foo", "eventData":{} }

以下のレスポンスが返されます。
HTTPステータスコードが204であることを確認してください。

HTTP/1.1 204 No Content
Access-Control-Allow-Credentials: false
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: X-Xsrf-Guard
Date: Sun, 26 Jun 2016 05:44:27 GMT

アプリシミュレーターを使用して、イベントが正しく配信されたかどうかを確認できます。
アプリシミュレーターで「着信: イベント」ウィンドウを開き、送信したイベントが実際にアプリに配信されていることを確認します。

以下のような内容がイベントログに記録されています。
返されるJSONの、homeID、originDeviceId、timestampプロパティは、構成に応じて異なります。
ログを表示できない場合は、_YOUR_API_KEY_および_DEVICE_ID_が正しいことを確認してください。

{"homeId":9,"timestamp":"2016-06-26T14:47:26.044+09:00","eventType":"foo","eventData":{},"originDeviceId":1303,"originDeviceClass":"smart_light","originDeviceIp":"111.111.111.111"}

WebSocketを介したコマンドの受信

コマンドを受信するには、デバイスはIoTデバイスハブへのWebSocket接続を確立する必要があります。

WebSocket接続を開始するには、デバイスは/devices/_DEVICE_ID_/commandエンドポイントに対してGETリクエストを行います。
以下のコマンドを実行します。

$ curl -i -N -H "Authorization: ModeCloud _YOUR_API_KEY_" -H "Upgrade: websocket" -H "Connection: Upgrade" -H "Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==" -H "Sec-WebSocket-Version: 13" https://iot-device.jp-east-1.api.cloud.nifty.com/devices/_DEVICE_ID_/command

未加工のHTTPリクエストは以下の通りです。

GET /devices/_DEVICE_ID_/command HTTP/1.1
Host: iot-device.jp-east-1.api.cloud.nifty.com
Authorization: ModeCloud _YOUR_API_KEY_
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Version: 13

WebSocket接続を開始するには、Authorizationヘッダーに加えて、Upgrade、Connection、Sec-WebSocket-Key、Sec-WebSocket-Versionヘッダーを送信する必要があります。

Sec-WebSocket-Keyヘッダーには、base64エンコードのランダムバイトが含まれ、サーバーは、Sec-WebSocket-Acceptヘッダーにキーのハッシュを入れて応答します。
WebSocketについて詳しくは、RFC6455をご覧ください。

リクエストが成功すると、以下のレスポンスが表示されます。
接続はインバウンドデータストリーム用に維持されます。

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection:
Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=

コマンドを受信していることを確認するために、アプリシミュレーターを使用してコマンドを送信できます。
アクションとしてlightを、パラメーターとして{"on":true}を送信すると、以下の出力が表示されます。

{"action":"light","parameters":{"on":true}}

JSONテキストの前に奇妙な文字が表示される場合があります。
これらはWebSocketフレームヘッダーです。実際のデバイスソフトウエアでは、ヘッダーを解析する必要があります。

プログラミング言語には多数のWebSocketライブラリー(ws、libwebsocketsなど)が含まれています。
一部のWebSocketライブラリーは、カスタムHTTPヘッダーを受け付けることができません。
この場合は、authToken URL照会パラメーターを使用してサーバーにAPIキーを渡すことができます。

$ curl -G -L -i -N -H "Upgrade: websocket" -H "Connection: Upgrade" -H "Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==" -H "Sec-WebSocket-Version: 13" -d "authToken=_YOUR_API_KEYi_" "https://iot-device.jp-east-1.api.cloud.nifty.com/devices/_DEVICE_ID_/command"
WebSocketの再接続

WebSocket接続が予期せずシャットダウンすることがあります。
例えば、Wi-Fiルーターが突然ダウンしたり、ISPやほかのアップストリームゲートウェイがダウンしたりするような場合です。
このような場合、データベースは再度WebSocket接続を確立する必要があります。
通常、WebSocketライブラリーは、接続が切断されていることを検出し、エラーを処理できます。

デバイスが再接続を試みる場合は、しばらく待ってから次の再接続を試す必要があります。
具体的には、最初の試行が失敗した後、一定の秒数(10秒間など)待機し、接続が成功するまで、再接続を試行し続けます。

ただし、この方法は電力の消耗が激しく、バッテリー駆動式のデバイスでは問題となる場合があります。
この改善案として、待機時間にフィボナッチ数列を使用する方法があります。
例えば、最初の接続の試行が失敗した後、デバイスは1秒後に接続を再度試みます。
これも失敗した場合は、2秒後に再試行し、それ以降は、3秒後、5秒後というようになります。
数字は無限に続くため、60秒など上限を設定する必要があります。

WebSocket Ping Frames

IoTデバイスハブは、WebSocket接続が失効することを防ぐために、各WebSocket接続を通して定期的にping制御フレームを送信します。

RFC6455セクション5.5.2に基づき、WebSocketクライアントは、pingを受信するたびにpongフレームを返す必要があります。

ただし、pongフレームがIoTデバイスハブに返されなくても、WebSocket接続はシャットダウンされません。
WebSocketライブラリの中にはpingフレームを正しく処理できないものがあるためです。
例えば、ほとんどのブラウザーはpingを無視し、pongを返すことはできません。

推奨画面サイズ 1024×768 以上