デバイス制御
本書では、Things Cloudにおけるデバイス制御の仕組みについて説明します。
概要
IoTシステムにおいては、IoTデバイスからクラウドにデータを収集して可視化するだけでなく、クラウドからIoTデバイスの制御が求められる場合が多くあります。 これらの要請に対し、Things Cloud はデバイス制御のためのデータモデル、メッセージングの仕組み、状態管理のためのGUIを準備し、セキュアなIoTデバイス制御のための仕組みを提供しています。
Things Cloud は特定のデバイスや特定のプラットフォームに対する制御の仕組みは提供していません。あくまでオペレーションというデータモデルを活用したデバイス制御命令の管理の仕組みを提供するのみであることに注意してください。
デバイスからオペレーションを送信するには上図のようにいくつかのステップを踏む必要があります。例えば、あるユーザーが Things Cloud に登録済みのIoTデバイスの遠隔再起動の仕組みを実装することを考えてみます。
ユーザーはまず Things Cloud のデバイス管理アプリケーションに具備されている標準機能のGUIで再起動を促すオペレーションを発行します(ステップ1)。Things Cloud のGUIはこのオペレーションを実施するために Things Cloud 内部に発行されたオペレーションをキューイングします。このオペレーションはIoTデバイスの種類によらず共通的な形式で生成されます。
一方、IoTデバイスに搭載されたエージェントプログラムは、ある時点でデバイスにこのオペレーションをリクエストします(ステップ2)。これは Things Cloud のロングポーリングの仕組みを利用して即時で行われるかもしれませんし、定期的にスケジューリングされたREST APIの実行タイミングで行われるかもしれません。
エージェントプログラムはオペレーションを受信したら、その事実をクラウド側に示すためにオペレーションの状態を「実行中(EXECUTING)」に変更します(ステップ3)。これはユーザーに対する迅速なフィードバックを与えると共に、誤って同じオペレーションを複数回受信し実行してしまうような単純なエラーを防ぐためでもあります。
続いて、エージェントプログラムは受信したオペレーションに応じた処理を管理されたデバイスに対して実行します(ステップ4)。IoTデバイスがLinuxディストリビューションをOSに持っていれば $ sudo shutdown -r now
コマンドの実行になるかもしれません。そして実行が完了したら実行結果を Things Cloud に送信するため、オペレーションの状態を「成功(SUCCESSFUL)」または「失敗(FAILED)」に変更します(ステップ5)。
最後に、ユーザーはオペレーションの実行結果を Things Cloud のGUI上で確認することができます(ステップ6)。Things Cloud はオペレーションの発行時、および更新時に自動的に監視ログ(どのユーザーがいつどのような操作を行ったかの記録)を作成するため、オペレーションの実行結果だけでなくオペレーションが実行された過程もトレースすることができます。監視ログについては 開発者ガイドの「監視ログの表示」をご覧ください。
オペレーションのデータモデル
オペレーションの概要について記したところで、次にThings Cloud上の「オペレーション」のデータモデルについて触れます。
データモデル構造
オペレーションはjsonデータとして扱われます。以下はオペレーションの一例と、各要素についての説明となります。
{
"id" : "123",
"self" : "<<This Operation URL>>",
"deviceId" : "1243",
"status" : "PENDING",
"creationTime" : "2011-09-06T12:03:27.927+02:00",
"com_cumulocity_model_WebCamDevice" : {
"name" : "take picture",
"parameters" : {
"duration" : "5s",
"quality" : "HD"
}
}
}
名称 | 種別 | 発生回数 | 説明 | PUT/POST |
---|---|---|---|---|
id | String | 1 | オペレーションを一意に識別するIDです。Things Cloudが自動的に割り当てます。 | 指定不可 |
self | URI | 1 | このリソースへのリンクです。Things Cloudが自動的に割り当てます。 | 指定不可 |
creationTime | String | 1 | オペレーションが Things Cloud 内のデータベースに作成された時間。Things Cloudが自動的に割り当てます。 | 指定不可 |
deviceId | String | 1 | このオペレーションが実施されるべき対象デバイスを識別します。 | POST:必須、PUT:指定不可 |
deviceExternalIDs | ExternalIDCollection | 0..n | 対象デバイスの外部ID。識別情報インターフェース参照。 オペレーションのGETリクエスト時、検索パラメータとして agentId を指定することで表示されます。 |
指定不可 |
bulkOperationId | String | 1 | bulkOperationIdに対するリファレンス(このオペレーションが一括オペレーションから予定されていた場合)。 | POST:オプション、PUT:指定不可 |
status | String | 1 | オペレーションの状態。SUCCESSFUL、FAILED、EXECUTINGまたはPENDINGに設定可能。 オペレーション作成時は Things Cloudが自動的に “PENDING” を割り当てます。 |
POST:指定不可、PUT:必須 |
failureReason | String | 0..1 | オペレーション失敗の理由を表す文字列。 PUTリクエスト、かつstatusが “FAILED” の場合のみオプションとなります。その他の場合は指定不可です。 |
POST:指定不可、PUT:オプション |
* | Object | 1..n | デバイス上で実施予定のオペレーションを表わす付加的プロパティ(フラグメント)。 | オプション |
オペレーションはできる限り常に冪等性をもって構築されるべきです。冪等性とは何度オペレーションを走らせても同じ結果となること意味します。例えば、スイッチをある特定の状態にするオペレーションは冪等性があります。スイッチをオンにするオペレーションを何度走らせても結果はオンのままだからです。 しかし、スイッチを切り替える(変更する)オペレーションは冪等性がありません。何度このオペレーションを走らせてもその結果はスイッチの状態に依存するため、結果が同じにならないからです。
IoTシステムは大量のデバイスがネットワークを介してクラウドと接続するシステムです。このようなシステムにおいて、1つ1つのデバイスの現在の状態を常時確実に把握し続けることは容易ではありません。また、ネットワークの状態は常に安定しているとは限りません。IoTデバイスとクラウド間の通信が一時的に失敗することもあります。そのため、IoTシステムにおける制御において冪等性の考え方は非常に重要となります。
APIを利用してオペレーションを作成する場合、IoTシステムの要請に応じて独自のフラグメントをオペレーションに付加することが可能ですが、そのような場合にも冪等性の考え方を踏襲する必要があるでしょう。
オペレーションの状態管理
本節ではオペレーションを管理するために重要となる状態管理(status)の考え方を説明します。
Things Cloudにおけるオペレーションの状態管理は上図のように遷移するモデルとなっています。各状態の意味は以下の通りです。
- 保留(PENDING):オペレーションが作成され、未実行であることを表す状態。IoTデバイスがオペレーションを受信したとしても、IoTデバイスが実行を開始していなければ保留状態と考えるべきです。
- 実行中(EXECUTING):オペレーションが受け取られ、実行中であることを表す状態。
- 成功(SUCCESSFUL):オペレーションが正常に完了した状態。
- 失敗(FAILED):オペレーションが失敗した状態。
オペレーションが作成されると、必ず「保留(PENDING)」状態にマッピングされます。つまり、オペレーション実行のためにキューに入れられてはいても、まだ実行されていない状態です。
これ以降のオペレーション状態管理は(システムまたはエージェントに異常が発生し、制御不能なオペレーションをキャンセルする場合を除き)基本的にエージェントが管理主体と**なるべき(SHOULD)**です。それはオペレーションを実際に受け取り、実行する主体が最も正確にオペレーションの状態を適切に管理することができると考えられるためです。
エージェントがオペレーションを取得して実行を開始する時、そのオペレーションを Things Cloud で「実行中(EXECUTING)」という状態に変更します。 その後、エージェントは、IoTデバイスまたはその子に対して制御を実行します(たとえば、デバイスを再起動したり、照明を点灯したりします)。制御が終わったら、IoTデバイスまたはその子デバイスの新しい状態を反映してインベントリを更新するでしょう (例:インベントリ内の照明の現在の状態を更新します)。 最後に、エージェントはThings Cloud内の操作を「成功(SUCCESSFUL)」または「失敗(FAILED)」のいずれかとしてマークし、場合によってはエラーメッセージ(failureReason)を表示します。
この実行フローの利点は、オフラインで一時的に通信範囲外となってしまうデバイスをサポートできることです。また、再起動が必要な操作(ファームウェアのアップグレードなど)をデバイスでサポートすることも容易になります。
つまり、IoTデバイスがオペレーションの内容を実行して再起動を行った場合、IoTデバイスは再起動実施以前に実行していたオペレーションの内容を知っている必要があります。この場合、IoTデバイスは全ての実行中(EXECUTING)状態にあるオペレーションを照会することで、IoTデバイス上にオペレーション実行の記録を詳細に残すことなく自身の状態を把握することができます。
オペレーション発行の際の注意事項
オペレーションを発行するためには、オペレーションの対象となるデバイス(オペレーションの "deviceId"
として指定されるデバイス)となるマネージドオブジェクト、またはそのマネージドオブジェクトの親デバイス("parentDevice"
)が "com_cumulocity_model_Agent" : {}
のフラグメントを持つ必要があります。このフラグメントを付与していない場合、GUIにオペレーションを生成するためのメニューを表示させることはできますが、オペレーション生成を行った際に以下のエラーが発生します。
また、APIを利用してオペレーションを作成する場合には HTTP 422 Unprocessable Entity
のエラーが発生し、HTTP Response Bodyとして以下の例外メッセージが返されます。
{
"details": {
"exceptionMessage": "com.cumulocity.exception.database.UnprocessableEntityException: Agent for device 'ID [type=com_cumulocity_model_idtype_GId, value=<<ManagedObjectID>>]' does not exist in inventory!",
<<中略>>
}
}
オペレーションの利用方法
本節では、オペレーションの具体的な利用方法について深掘りしていきます。
オペレーション発行方法(ステップ1)
本節では概要で示したオペレーション実行のステップのうち、オペレーション発行(ステップ1)についてもう少し詳しく説明します。
すでに触れたとおり、Things Cloud でオペレーションを発行するには大きく2つの方法があります。
デバイス管理アプリ(GUI)を利用してオペレーションを発行する方法は、メンテナンスなどで保守運用者がデバイスに対して定型の制御を行いたい場合などに適しています。
一方、APIを利用してオペレーションを発行する方法は、既存システムが存在しておりThings Cloud のデバイス管理機能を他システムと統合して利用する必要がある場合、あるいは非定型の独自の制御を行いたい場合などに適しています。
1. デバイス管理アプリ(GUI)からオペレーションを発行する
デバイスを表すマネージドオブジェクトに対して、c8y_SupporedOperations:[]
のフラグメントに規定の値を付与することで、デバイス管理アプリの各デバイス詳細ページからオペレーションを発行するためのタブメニューを表示させることができます。
これらのタブメニューからはCumulocity IoTが定義済みのオペレーションを発行することができます。
GUIがサポートするタブメニューおよび発行できるオペレーションの内容については デバイス管理 を参照してください。
2. APIを利用してオペレーションを発行する
/devicecontrol/operations
のPOST APIを利用してオペレーションの送受信を行います。
この方法では発行するオペレーションの内容を自由に設定できるため、任意の制御内容を定義して扱うことが可能となります。
具体的なAPIの利用方法については 開発者ガイドの「リファレンス > デバイス制御」のページをご覧ください。
IoTデバイスによるオペレーションの取得(ステップ2)
本節では概要で示したオペレーション実行のステップのうち、オペレーションの取得(ステップ2)についてもう少し詳しく説明します。
IoTデバイスがオペレーションの内容を取得するためには、以下の2つの方法があります。
- リアルタイム通知API(Long-Polling)を利用して取得する方法
- HTTP GET を利用して取得する方法
オペレーションが発行された時に即時でデバイス制御を行いたい場合には、リアルタイム通知APIを利用した方法を利用することが推奨されます。一方、オペレーション発行後に実際の制御が行われるまで多少のタイムラグがあっても良い場合(運用上、1日に1回制御が実施されれば良い場合など)にはHTTP GETを利用することでネットワークやデバイス実装上の負荷を低減することができるでしょう。
以下、各方式の実装内容を説明します。
1. リアルタイム通知API(Long-Polling)の利用
Things CloudはIoTデバイスや外部アプリケーションとのリアルタイムな情報伝達を実現するため、リアルタイム通知APIを準備しています。このAPIはBayeuxプロトコルによるロングポーリングの仕組みを採用しており、擬似的なサーバーPUSHの仕組みを実現することができます。
オペレーションが発行されたことを即時にIoTデバイスが知る手段としてこのリアルタイム通知APIが利用可能です。利用方法の詳細は 「Things Cloud OpenAPI仕様 > リアルタイム操作」 のページをご覧ください。
2. HTTP GETの利用
HTTP GETを利用して取得する方法は、IoTデバイスがThings Cloud上の「保留」状態のオペレーションが存在するかどうかを定期的に問い合わせることで実現します。オペレーションが発行されてからIoTデバイスがオペレーションを受信するまでのタイムラグは、IoTデバイスがどのような頻度でThings Cloudへの問い合わせを行うかに依存します。
ステップ2. では、IoTデバイスが受け取っていないオペレーションが存在するかどうかを問い合わせることになります。具体的には、自デバイスまたは自身の子デバイスに対する保留(PENDING)状態のオペレーションを取得するためのAPIリクエストを行います。
- 利用するAPI
GET /devicecontrol/operations
- リクエスト例:
GET /devicecontrol/operations?agentId=142653&status=PENDING HTTP/1.1
Host: ...
Authorization: Basic ...
Accept: application/vnd.com.nsn.cumulocity.operation+json;ver=...
- 応答例:
HTTP/1.1 200 OK
Content-Type: application/vnd.com.nsn.cumulocity.operationCollection+json; charset=UTF-8; ver=0.9
...
上述のAPIリクエストにおけるクエリ文字列の意味は以下の通りです。
パラメータ | 説明 |
---|---|
agentId | オペレーションの制御対象となるデバイスのマネージドオブジェクトIDを指定します。このクエリパラメータで指定可能なマネージドオブジェクトは"com_cumulocity_model_Agent" : {} のフラグメントを持つ必要があります。このクエリパラメータが指定された場合、指定したデバイス及びその子デバイスに対するオペレーションのみを取得することができます。 |
status | オペレーションの状態を指定します。指定可能な値は PENDING / EXECUTING / SUCCESSFUL / FAILED のいずれか1つのみとなります。OR条件の指定はできません。 |
IoTデバイスによるオペレーションの更新(ステップ3/ステップ5)
本節では概要で示したオペレーション実行のステップのうち、オペレーションの更新(ステップ3およびステップ5)についてもう少し詳しく説明します。
ステップ3. 及びステップ5. で実施する手順については、オペレーションの制御内容によらず共通的な内容となります。
ステップ3. におけるオペレーションの更新は、受信したオペレーションの状態を「保留(PENDING)」から「実行中(EXECUTING)」に変更する操作となります。
具体的には以下のAPIリクエストを行うことになります。
- 利用するAPI
PUT /devicecontrol/operations/<<operationId>>
- リクエスト例:
PUT /devicecontrol/operations/143943 HTTP/1.1
Host: ...
Authorization: Basic ...
Accept: application/vnd.com.nsn.cumulocity.operation+json;ver=...
...
{
"status": "EXECUTING"
}
- 応答例:
HTTP/1.1 200 OK
Content-Type: application/vnd.com.nsn.cumulocity.operationCollection+json; charset=UTF-8; ver=0.9
...
また、ステップ5. におけるオペレーションの更新は、実行したオペレーションの状態を「実行中(EXECUTING)」から「成功(SUCCESSFUL)」または「失敗(FAILED)」に変更する操作となります。失敗した場合は、"failureReason"
の値も合わせて更新するとより詳細なエラーの状態を伝えることが可能となります。
具体的には以下のAPIリクエストを行うことになります。
- 利用するAPI
PUT /devicecontrol/operations/<<operationId>>
- リクエスト例:
PUT /devicecontrol/operations/143943 HTTP/1.1
Host: ...
Authorization: Basic ...
Accept: application/vnd.com.nsn.cumulocity.operation+json;ver=...
...
{
"status": "FAILED",
"failureReason": "received wrong parameter(s): \"lang\""
}
- 応答例:
HTTP/1.1 200 OK
Content-Type: application/vnd.com.nsn.cumulocity.operationCollection+json; charset=UTF-8; ver=0.9
...
GUIによるオペレーション管理
Things Cloudでは標準機能としてデバイスに対するオペレーションを管理するためのGUIを備えています。このメニューでは何らかの方法によって生成されたオペレーションの状態管理を行うことができます。
オペレーションは次の4つの状態のいずれかになり、それぞれのアイコンで示されます。
状態 | 説明 |
---|---|
保留 | 操作は作成されたばかりで、デバイスが操作を取得するのを待っています。 |
実行中 | 操作はデバイスによって取得され、実行中です。 |
成功 | 操作はデバイスによって正常に実行されました。 |
失敗 | デバイスで操作を実行できませんでした。 |
トップメニューバーの左側にあるステータスボタンの1つをクリックすると、対応する操作が非表示になります。もう一度クリックすると、操作が再度表示されます。
トップメニューバーの右側にあるリアルタイムをクリックすると、デバイスからの操作がリアルタイムで表示されます。
オペレーションは時間の降順で一覧表示されます。オペレーションごとに、次の情報が表示されます。
情報 | 説明 |
---|---|
状態 | 保留、実行中、成功、失敗のいずれかです(上記参照)。 |
名前 | オペレーションの名前。 |
行をクリックすると展開され、操作の詳細が表示されます。
- 詳細:操作名とステータスに関する情報を提供します。status=FAILEDの場合は、(オペレーション更新の際に設定されていれば)失敗の理由が表示されます。
- 変更履歴:操作の過去の変更に関する情報を提供します。
補足:一括オペレーション
IoTシステムは大量のIoTデバイスを構成要素として持ちます。それら大量のIoTデバイスに対する制御は、個々のデバイスに対して制御指示を出すのではなく、特定のグループに対して一括して実施したいという要請は当然のものです。また、ファームウェアの更新といった制御命令は計画されたメンテナンスウインドウで行いたいという要請もあるでしょう。
Things Cloudでは、これらの要望に応える手段として一括オペレーション(Bulk Operations)という仕組みを準備しています。一括オペレーションはThings Cloud上のグループに対して発行することができます。
一括オペレーションの利用方法の詳細は デバイス管理>一括制御 のページをご覧ください。