MQTTデバイスインテグレーション

概要

Things CloudのMQTT実装には、次の利点があります。

MQTTセクションの構造は次のとおりです。

このセクションでは、MQTT通信の基本については説明しません。MQTTに慣れていない場合は、インターネットにある数多くの入門書の1つを参照することをお勧めします。参考文献のいくつかはMQTTのWebサイトにあります。

備考: プラットフォームへのすべてのMQTT接続は、最大許容メッセージサイズは16384バイト(約16キロバイト)です。メッセージヘッダーと本文の両方が含まれます。ヘッダーサイズはさまざまですが、最小サイズは2バイトです。本文のサイズはトピックとペイロードを合わせたサイズです。

MQTT実装

このセクションでは、MQTTプロトコルの実装の詳細をリストします。Things Cloudの実装は MQTTバージョン3.1.1をサポートしています。

MQTT標準接続

Things CloudはTCPとWebソケットの両方でMQTTをサポートしています。URLとして、利用しているテナントのドメイン(例: mytenant.je1.thingscloud.ntt.com/mqtt )、もしくは次の形式のインスタンスのドメイン mqtt.<instance_domain> を利用できます(例: mqtt.je1.thingscloud.ntt.com)。

使用可能なポート:

  TCP Webソケット
片方向SSL 8883 443

備考: Webソケットを使用するには、パスに/mqttをつなげる必要があり、MQTT標準に従ってWebソケット通信を行います。

SmartRESTペイロード

Things Cloud MQTT実装は、SmartRESTをペイロードとして使用します。

SmartRESTはCSVに似たメッセージプロトコルで、サーバーサイドのテンプレートを使用してThings Cloudでデータを作成します。 これは、REST APIの高い表現力を取り入れていますが、組み込みデバイスのJSON解析の複雑さを回避するために、JSONをコンマ区切り値(CSV)に置き換えています。 さらに、CSVのシンプルでコンパクトな構文により、モバイルネットワークを介したIoT通信でも非常に効率的です。 他のHTTP APIと比較して、モバイルトラフィックを最大80%節約できます。

情報: プラットフォームへのすべてのMQTT接続は、最大許容メッセージサイズは16384バイト(約16キロバイト)です。メッセージヘッダーと本文の両方が含まれます。ヘッダーサイズはさまざまですが、最小サイズは2バイトです。本文のサイズはトピックとペイロードを合わせたサイズです。

SmartRESTの基本

SmartRESTメッセージは、各パラメーターがコンマで区切られた1行です。最初のパラメーターは、メッセージを定義するIDです。メッセージ間に改行を使用すると、1度のパブリッシュで複数のメッセージを送信できます。

SmartRESTエスケープ

SmartRESTエンドポイントとの通信には、CSV(コンマ区切り値)形式を使用します。正常に通信するためには以下の規則に従う必要があります。

サーバーからクライアントに送信されるメッセージにも同様のエスケープ規則が適用されます。

パブリッシュの例:

100,"This value, needs escaping",This value does not need escaping

サブスクライブの例:

511,myDeviceSerial,"execute this\nand this\nand ""this"""

情報: \n は出力(例: コンソールやUI)中では新規の行を作成しません。新規の行を作成するには、改行文字(ASCII 0A)を使用する必要があります。

デバイス階層

MQTTセッションは1つのデバイスにリンクされますが、このデバイスの下には自由に設定可能なデバイス階層を持つことができます。

すべての子デバイスには、デバイスの作成時に定義された一意のIDが必要です。ルートデバイスの一意のIDと階層内の一意のIDを組み合わせて使用することをお勧めします。

ルートデバイスの代わりに子デバイスのデータを作成するには、子デバイスの一意のIDをトピックの別のセクションとして追加します(例: s/us/myChildDeviceIdentifier)。

クライアントは、それぞれのトピックをサブスクライブすることにより、階層内のすべての子デバイスに対するオペレーションを自動的に受信します。子デバイスごとにサブスクライブする必要はありません。

受信されたすべてのオペレーションには、テンプレートIDの後に、そのオペレーションが作成されたデバイス/子デバイスのIDが含まれます(その後に他のオペレーションパラメーターが続きます)。

MQTT機能

MQTT認証

MQTTでは、UsernameとPasswordによる認証をサポートしています。Things Cloudに接続するには、MQTTのUsernameには「tenantID/username」という形式でテナントIDとユーザー名の両方を含める必要があります。

MQTT ClientId

MQTT ClientIdは、接続されている各クライアントを一意に識別するフィールドです。Things Cloud実装もClientIdを使用して、クライアントを直接デバイスにリンクします。したがって、ClientIdには次の形式を使用する必要があります。

connectionType:deviceIdentifier:defaultTemplateIdentifier

フィールド 必須 説明
connectionType いいえ 接続タイプのデフォルト表示: d (デバイス)
deviceIdentifier はい デバイスの一意の識別子 (IMEI, シリアル番号など)
defaultTemplateIdentifier いいえ テンプレート識別子の詳細については、SmartRESTのセクションをご覧ください

クライアントの最も単純なバージョンでは、MQTT ClientIdは単に deviceIdentfier にすることができます。デバイス接続として自動的に解釈されます。

重要事項: コロン文字はThings Cloudでは特別な意味を持つため、deviceIdentfier では使用しないでください。

ClientIdの例:

mySerialNumber
d:mySerialNumber
d:mySerialNumber:myDefaultTemplate

MQTT ClientIdの一意性は、deviceIdentfier によってのみ決定されます。したがって、上記の例では、同時に接続できるクライアントは1つだけです。 証明書によるSSL接続では、deviceIdentfier は使用されている証明書(デバイスにより提供される証明書チェーンのうち最初のもの)のCommon Nameと一致している必要があります。

MQTTサービス品質

Things Cloud実装は、MQTT QoSの3つのレベルすべてをサポートします。

オペレーショントピックまたはエラートピックをサブスクライブする場合は、トピックのサブスクライブ時にクライアントが定義したQoS内のすべてのメッセージを配信します。

MQTTクリーンセッション

MQTTクライアントは、一般にクリーンセッションを「0」(false)に設定できます。これにより、クライアントが切断された場合でもサブスクリプションが動作し、クライアントに再接続したときに失われたメッセージが受信されます。

備考: Things Cloudはクリーンセッションを「1」(true)に設定する必要があります。現在のところ、クリーンセッションを無効にしても完全に動作することは保証できませんので、常にクリーンセッションを有効にすることを推奨します。

MQTT保持フラグ

現在のThings Cloud実装では、デバイスがデータをパブリッシュするトピックへのサブスクリプションは許可されていません。このトピックに保持フラグを付けてデータをパブリッシュすることはできますが、フラグを付けずにデータを送信することと実質的な違いはありません。 Things Cloudがパブリッシュするオペレーションやエラーなどのメッセージには、保持フラグは含まれません。

MQTT遺言

MQTTでは、「遺言」は接続時に指定し、クライアントが接続を失ったときに実行されるメッセージです。たとえば、遺言メッセージとして 400,c8y_ConnectionEvent,"Device connection was lost." 、遺言トピックとしてs/usを指定すると、デバイスが接続を失うたびにイベントが発生します。

備考: 「遺言」が実行されると、デバイスの可用性が更新されます。

デバッグ

開発中に開発者をサポートするために、トピックs/eをサブスクライブできます。このトピックでは、デバイスからパブリッシュ中に発生するデバッグメッセージおよびエラーメッセージを取得できます。

備考: このトピックは、クライアントの開発をサポートするために純粋に設計されています。メッセージが冗長であり、データ使用量を大幅に増加させる可能性があるため、常にこのチャネルをサブスクライブすることはお勧めしません。また、このトピックを使用して、そのトピックで受信した内容に基づいてデバイスのアクションをトリガーしないでください。応答チャネルではありません。

デバイスインテグレーション

概要

デバイスをThings Cloud に統合するための基本的なライフサイクルについては、デバイスのインターフェースで説明しています。

このセクションでは、MQTT実装を使用してこのライフサイクルを管理する方法を説明します。

ライフサイクルは、起動フェーズとサイクルフェーズの2つのフェーズで構成されます。

起動フェーズは、認証情報を確認するだけですみます。

サイクルフェーズは、次の2種類のアクションで構成されます。

MQTTフェーズ

スタートアップフェーズ

ステップ0: デバイスの認証情報をリクエストする

Things Cloudでは、すべてのMQTT接続を認証する必要があります。MQTT実装のデバイス認証トピックを使用して、デバイスの新しい認証情報を生成できます。

Things Cloudが提供している静的認証情報を使いデバイスが認証情報を取得したら、その認証情報をローカルに保存して、取得した認証情報を使い接続する必要があります。

接続を確立するには、次のパラメータを構成する必要があります。

詳細については、Hello MQTTセクションをご覧ください。

プロセスは次のとおりです。

認証情報を受信した後、デバイスはMQTT接続を閉じて、受信した認証情報で新しい接続を作成できます。

ステップ1: デバイスを確認する

クライアントがデータを送信しデバイスが存在しない場合に、MQTTはデバイスの自動作成をサポートするため、このステップは、デバイスを手動で作成する場合にのみ必要です。

デバイスの作成は、静的テンプレート100を使用することで実現できます。このテンプレートは、デバイスがまだ存在しない場合にのみ作成するため、デバイスのブートのたびに何もせずに使用できます。

デバイスは、クライアントがMQTT ClientIdで使用するIDに自動的にリンクされます。

100,Device Name,Device Type

備考: Things Cloudがあらかじめ用意している静的テンプレートに使われているトピックはs/usです。

ステップ2: 子デバイスを確認する

ルートデバイスと同様に、その子デバイスも自動デバイス作成の対象となります。

このステップを手動で行うには、子デバイスを作成するための静的テンプレート101を送信します。テンプレートは、子デバイスが存在しない場合にのみ作成します。

101,Unique Child ID,Child Name,Child Type

ステップ3: トピックをサブスクライブする

デバイスがオペレーションをサポートしている場合は、必要なすべてのトピック(静的テンプレートおよびSmartREST 2.0)をサブスクライブする必要があります。

サイクルフェーズ

ステップA: CSVデータを送信する

デバイスはアクティブなMQTT接続を保持していますが、静的テンプレートのトピックまたはSmartRESTテンプレートのトピックのいずれかでパブリッシュして、サーバーにデータを送信できます。

MQTT ClientIdに基づいて、物理デバイスはThings Cloud内のデバイスオブジェクトに直接接続されます。したがって、送信するデータは自動的にデバイスに接続されます。

子デバイスにデータを送信するには、デバイス階層で説明されているトピックにデータをパブリッシュします。

ステップB: CSVオペレーションを受信する

トピックをサブスクライブすると、デバイスは自動的にThings Cloudにオペレーションを受け取りたいことを伝えます。作成されたオペレーションは、静的テンプレートまたはデバイスが定義するテンプレートを使用して自動的に解析されます。

SmartREST 1.0

このセクションでは、既存のSmartREST 1.0テンプレートをMQTTで使用する方法について説明します。

SmartREST 1.0はHTTP要求/応答用に設計されており、MQTTとのIDレス通信をサポートしていないことに注意してください。HTTPを使用して送信する場合とまったく同じリクエストを送信するためにMQTT接続を使用するだけです。したがって、MQTT要求/応答用の設計ではないため、いくつかの制限があります。

SmartREST 1.0のサポートは、既存のSmartREST1.0テンプレートを使い実装している場合に移行を容易にするために追加されました。

備考: 新しいデバイスのインテグレーションを開始する場合は、SmartREST 2.0を使用することを強くお勧めします。

SmartREST 1.0の一般的な情報については、RESTインターフェイスの使用法 > SmartRESTの使用 をご覧ください。

MQTT ClientId

SmartREST 1.0では各メッセージの本文のIDを送信する必要がありますが、正しいMQTT ClientIdで接続することは依然として重要です。

MQTT ClientIdは、デバイスのc8y_SerialのexternalIdと一致する必要があります。正しいオペレーションと応答を割り当てるために使用されます。

SmartREST 1.0を送信する

サーバーにデータを送信するには、SmartRESTエンドポイント/sにPOSTするのと同じコンテンツにパブリッシュできます。

X-IDヘッダーは、クライアントがパブリッシュする必要のあるトピックの一部です。

s/ul/<X-ID>

処理モード

Things Cloud SmartRESTプロトコルは、送信されたデータをデータベースに保存しないようにTRANSIENT処理モードをサポートしているため、トピックs/ではなくMQTTトピックt/にパブリッシュすると、データはリアルタイム処理にのみ渡されます。

t/ul/<X-ID>

Things Cloud SmartRESTプロトコルはQUIESCENT処理モードもサポートしており、トピックs/ではなくMQTTトピックq/にパブリッシュすることで、リアルタイム通知を回避できます。現在、QUIESCENT処理モードはメジャーメントとイベントにのみ適用可能です。

q/ul/<X-ID>

Things Cloud SmartRESTプロトコルはCEP処理モードもサポートしており、トピックs/ではなくMQTTトピックc/にパブリッシュすることで、データはリアルタイム通知があるリアルタイムイベント処理エンジンにのみ送信されることを無効にします。現在、CEP処理モードはメジャーメントとイベントにのみ適用可能です。

c/ul/<X-ID>

SmartREST 1.0の受信

テンプレートが応答テンプレートを起動する場合、サーバーは次のトピックで返されるメッセージをパブリッシュします。

s/dl/<X-ID>

このトピックはクライアントがサブスクライブできます。

オペレーションの受信

HTTP経由のSmartREST 1.0はエンドポイント/devicecontrol/notificationsを提供し、リアルタイムのオペレーションを監視します。次のMQTTトピックでも同じ内容を受け取ることができます。

s/ol/<X-ID>

制限事項

MQTTは現在、要求/応答をサポートしていません。したがって、パブリッシュトピックで要求を送信し、サブスクライブトピックで応答を受信した場合、クライアントはそれらが要求に対する応答であることを安全に照合できません。

この制限に対処するには、どの要求が応答をトリガーしたかを知る必要がないようにテンプレートを設計することにより、クライアントがmessageIdによって自動的に認識するようにします。

SmartREST 2.0

概要

このセクションでは、Things Cloud MQTT実装で使用できるSmartREST 2.0ペイロード形式について説明します。

SmartREST 2.0はMQTTプロトコルを利用するように設計されているので、HTTP経由のSmartREST 1.0よりもペイロードを削減できる可能性があリます。

SmartREST 2.0はMQTT経由でのみ利用可能であり、主な通信のために以下のMQTTトピックを提供しています。

メッセージをパブリッシュするするには:

s/uc/<X-ID>

TRANSIENTモードでメッセージをパブリッシュするには:

t/uc/<X-ID>

QUIESCENTモードでメッセージをパブリッシュするするには:

q/uc/<X-ID>

CEPモードでメッセージをパブリッシュするには:

c/uc/<X-ID>

TRANSIENT、QUIESCENT、およびCEPデータ処理の詳細については、リファレンスガイドの SmartREST > 処理モードをご覧ください。

応答をサブスクライブするするには:

s/dc/<X-ID>

テンプレートの作成に関するトピックは、MQTT経由のテンプレートの作成で説明しています。

SmartREST 1.0からの変更点

SmartREST 2.0のベースは以前のバージョンと同じで、CSVに似たペイロード形式で、以前に作成されたテンプレートによってサポートされ、最終的にターゲットとするJSON構造を作成します。

機能にいくつかの変更が加えられました。

サポートされているテンプレート

SmartREST 2.0では、次の一致するHTTPメソッドのテンプレートを作成できます。

API GET POST PUT
インベントリ
アラーム  
イベント    
メジャーメント    
オペレーション    

さらに、応答およびオペレーションから特定の値を返すテンプレートを作成できます。

テンプレートコレクション

テンプレートコレクションは、デバイス通信プロトコルを指定する要求テンプレートと応答テンプレートのセットです。各コレクションは、一意のID(X-IDと呼ばれる)によって参照されます。

MQTT経由のテンプレートの作成

SmartREST 1.0と同様に、コレクション内のすべてのテンプレートをひとつのメッセージで渡す必要があります。テンプレートコレクションの作成後は、MQTTを使用して変更することはできなくなります。

テンプレートを作成する場合、クライアントは次のトピックにパブリッシュする必要があります。

s/ut/<X-ID>

テンプレートコレクションが存在するかどうかを確認するために、クライアントは次のトピックをサブスクライブできます。

s/dt

サブスクライブすると、クライアントは作成トピックに空のメッセージを送信し、このX-IDの作成ステータスに関する新しいメッセージをトリガーできます。

s/ut/myExistingTemplateCollectionへの空のパブリッシュ

20,myExistingTemplateCollection,<ID of collection>

s/ut/myNotExistingTemplateCollectionへの空のパブリッシュ

41,myNotExistingTemplateCollection

要求テンプレート

要求テンプレートには、次の基本フィールドが含まれます。

フィールド データ型 必須 説明
messageId String   はい コレクション内のテンプレートを参照する一意のID
method String GET
PUT
POST
はい データを取得、更新、または作成するかどうか
api String INVENTORY
MEASUREMENT
ALARM
EVENT
OPERATION
はい 使用する Things Cloud API
response Boolean true
false
いいえ リクエストがレスポンステンプレートをトリガーするかどうか
GETテンプレートの場合はデフォルトでtrue、それ以外の場合はデフォルトでfalse
mandatoryValues List<String>   はい APIの必須フィールドの値
値は、テンプレートが使用するAPIおよびメソッドによって異なります
customValues List<CustomValue>   いいえ オブジェクトに追加するカスタム値

要求テンプレートには、データの作成時または更新時に追加されるオブジェクト構造内のすべてのフラグメント(必須およびカスタム)がリストされます。 テンプレートに固定値を設定し、サーバーで置き換えることができます。テンプレートに値が設定されていない場合は、その値をパブリッシュメッセージに含める必要があります(これにはmandatoryValuesが含まれます)。

備考: 1秒あたりのメッセージレートの制限を超えると、要求は遅延され、キューに保持されます。キュー制限数を超えると、クライアントメッセージは拒否され、クライアントは切断されます。

このようなメジャーメントを作成するためのテンプレートを作成します(メジャーメントには、typeとtimeの2つの必須値があります)。

# 10,msgId,method,api,response,type,time,custom1.path,custom1.type,custom1.value
10,999,POST,MEASUREMENT,,c8y_MyMeasurement,,c8y_MyMeasurement.M.value,NUMBER,

このテンプレートでは、メジャーメントのカスタムプロパティを1つ追加定義します。テンプレート宣言の2つのフィールドを空のままにしているので(timeとカスタムプロパティ)、テンプレートを使うためにクライアントはこれら2つの値を送信する必要があります。

999,2016-06-22T17:03:14.000+09:00,25
# We can also use server time by leaving the time empty
999,,25

次のセクションでは、さまざまなテンプレートの作成方法と使用方法について詳しく説明します。

GETテンプレート

インベントリのGETテンプレートには、必須またはカスタムの値は必要ありません。代わりに、2つの異なるフィールドを使用します。

SmartREST 2.0では、IDによってインベントリからオブジェクトを取得するか、External IDによってオブジェクトを直接取得するかを選択できます。したがって、mandatoryValuesおよびcustomValuesフィールドの代わりに、次の2つのフィールドが使用されます。

フィールド データ型 必須 説明
byId Boolean true
false
はい GETをThings Cloud ID(= true)またはExternal ID(= false)のどちらで実行するか
externalIdType String   いいえ テンプレートがexternalIdによって呼び出された場合、固定externalIdTypeを設定します

これにより、次の3つの異なる方法でインベントリを照会することができます。

Things Cloud ID (マネージドオブジェクトID)

# Creation:
10,999,GET,INVENTORY,,true
# Usage:
999,123456

テンプレートに固定タイプをもつExternal ID

# Creation:
10,999,GET,INVENTORY,,false,c8y_Serial
# Usage:
999,myDeviceImei

テンプレートに固定タイプがないExternal ID

# Creation:
10,999,GET,INVENTORY,,false
# Usage:
999,c8y_Serial,myDeviceImei
POSTテンプレート

POSTテンプレートには、APIに基づいて必須値の組み合わせが異なります。

API 必須値
メジャーメント type, time
イベント type, text, time
アラーム type, text, status, severity, time
インベントリ externalIdType

これにより、次の最小限のテンプレートが作成されます。

# Creation:
10,100,POST,MEASUREMENT,false,c8y_MyMeasurement,,c8y_MyMeasurement.M.value,NUMBER,
10,101,POST,EVENT,,c8y_CustomEvent,mytext,,
10,102,POST,ALARM,,c8y_CustomAlarm,mytext,ACTIVE,MAJOR,

# Usage:
100
101
102

インベントリでのデータの作成には、オプションでそのオブジェクトのexternalIdの作成が含まれます。 これは、必須値externalIdTypeによって制御されます。

重要: POSTインベントリテンプレートは、messageIdの後のexternalIdの値で始まります。この列を空のままにすると、External IDが作成されなくなります。

# Creation:
10,100,POST,INVENTORY,,c8y_MySerial
10,101,POST,INVENTORY,,
# Usage:
# Create object with externalId c8y_MySerial/myImei
100,myImei
# Create object with externalId c8y_MySerial/myImei
101,myImei,c8y_MySerial
# This message will result in not creating an external ID
101,,c8y_MySerial
PUTテンプレート

インベントリのPUTテンプレートはGETテンプレートと同じロジックに従いますが、さらにPUTにカスタム値を使用することもできます。

# Creation:
# 10,msgId,method,api,response,byId,externalIdTyoe,custom1.path,custom1.type,custom1.value
10,999,PUT,INVENTORY,,false,c8y_Serial,c8y_MyCustomValue,STRING,
# Usage:
999,myDeviceImei,myValue

アラームのPUTテンプレートは、アラームのタイプを使用して更新するアラームを見つけます。

# Creation:
# 10,msgId,method,api,response,type,custom1.path,custom1.type,custom1.value
10,999,PUT,ALARM,,c8y_MyCustomAlarm,status,ALARMSTATUS
# Usage:
999,CLEARED

オペレーションのPUTテンプレートは、オペレーションのフラグメントを使用してオペレーションを見つけます。最初にEXECUTINGオペレーションをチェックし、EXECUTINGオペレーションがない場合はPENDINGオペレーションをチェックします。

# Creation:
# 10,msgId,method,api,response,fragment,custom1.path,custom1.type,custom1.value
10,999,PUT,OPERATION,,c8y_MyOperation,status,OPERATIONSTATUS,SUCCESSFUL,c8y_Fragment.val,NUMBER,
# Usage:
999,24
カスタムプロパティの追加

すべてのPOSTおよびPUT値を使用すると、テンプレートの結果にカスタムプロパティを追加できます。

1つのカスタムプロパティでは、テンプレートの作成に次の3つの値を追加する必要があります。

フィールド 説明
path  設定する値のJsonパス
type 値のオプションのデータ型   デフォルト:STRING
value 設定する値
このフィールドを空のままにすると、クライアントはテンプレートを使用するときに値を送信する必要があります。
説明
STRING デフォルトの型   値の追加検証はありません。
DATE ISO 8601形式のタイムスタンプ
日付を使用し、タイムスタンプを送信しないと、サーバー時刻が使用されます。
NUMBER 整数または小数点以下の数字
INTEGER 整数
UNSIGNED 整数(正のみ)
FLAG 空のマップ(例:c8y_IsDevice:{})
クライアントはこの値に対して何も送信する必要はありません。
SEVERITY アラームの重大度   アラームの重要度フィールドを更新するために使用します。
ALARMSTATUS アラームの状態   アラームのステータスフィールドを更新するために使用します。
OPERATIONSTATUS オペレーションの状態   オペレーションのステータスフィールドを更新するために使用します。

追加のカスタムプロパティを使用してアラームをクリアするためのテンプレート

# Creation:
10,999,PUT,ALARM,,c8y_MyCustomALarm,status,ALARMSTATUS,CLEARED,c8y_CustomFragment.reason,STRING,
# Usage:
999,Device resolved alarm on its own

カスタムメジャーメントを作成するためのテンプレート

# Creation:
10,999,POST,MEASUREMENT,,c8y_CustomMeasurement,,c8y_CustomMeasurement.custom.value,NUMBER,,c8y_CustomMeasurement.custom.unit,STRING,X
# Usage:
999,30.6

デバイスのプロパティを更新するためのテンプレート

# Creation:
10,999,PUT,INVENTORY,,false,c8y_Serial,c8y_MyCustomValue,STRING,
# Usage:
999,myDeviceImei,updatedValue

応答テンプレート

SmartREST 2.0応答テンプレートは、SmartREST 1.0と同じ構造を使用します。

フィールド データ型 必須 説明
messageId String はい コレクション内のテンプレートを参照する一意のID
base String いいえ すべてのパターンが使用するJsonパスプレフィックス
condition String いいえ パターンを使用するためにオブジェクトに存在する必要があるJsonパス
pattern List<String> はい オブジェクトから抽出されてデバイスに返されるJsonパスのリスト

応答テンプレートはすべてのオペレーションと、trueで応答フィールドを定義するすべての要求テンプレートに使用されます。いずれの場合も、サーバーは登録されたすべての応答テンプレートを試行するため、1つのオペレーションまたは要求に対して複数の応答行がある場合があります。

SmartREST 2.0は、条件が真(または条件が定義されていない)の場合、常に応答テンプレートを返します。解決されなかったパターンは、空の文字列として返されます。

条件フィールドを使用して、応答テンプレートを返すタイミングを制御する必要があります。

次の例では、データのクエリ方法とカスタムオペレーションの解析方法を示します。

デバイスオブジェクトからのクエリデータ

デバイスオブジェクト:

{
  "id": "12345",
  "type": "myMqttDevice",
  "c8y_IsDevice": {},
  "c8y_Configuration": "val1=1\nval2=2"
}

テンプレート作成:

10,999,GET,INVENTORY,,true
11,888,,c8y_IsDevice,type,c8y_Test,c8y_Configuration

クライアントからのパブリッシュ:

999,12345

クライアントへの受信情報:

888,myMqttDevice,,"val1=1\nval2=2"
カスタムオペレーションの解析

オペレーションオブジェクト:

{
  "id": "12345",
  "deviceId": "67890",
  "agentId": "67890",
  "status": "PENDING",
  "c8y_CustomConfiguration": {
    "val1": "1",
    "val2": "2",
    "customValues": ["a", "b", "c"]
  },
  "description": "Send custom configuration"
}

テンプレート作成:

11,111,c8y_CustomConfiguration,deviceId,val1,val2,customValues[*]
11,222,,deviceId,c8y_CustomConfiguration.val1,c8y_CustomConfiguration.val2
11,333,,deviceId,val1,val2,customValues[*]
11,444,c8y_CustomConfiguration,c8y_CustomConfiguration.val3,val1,val2,customValues[*]

クライアント受信情報(ClientIdが「myMqttTestDevice」であると仮定):

111,myMqttTestDevice,1,2,a,b,c
222,myMqttTestDevice,1,2
333,myMqttTestDevice,,,

条件がオペレーションと一致しないため、テンプレート444は返されません。

複数のオブジェクトを持つキーを含むデバイスオブジェクトからのクエリデータ

デバイスオブジェクト:

{
  "id": "12345",
  "name": "test",
  "type": "c8y_MQTTdevice",
  "c8y_IsDevice": {},
  "myList": [
      {
          "pid": 12345,
          "type": "test"
      },
      {
          "pid": 123456,
          "type": "test2"
      }
  ]
}

テンプレート作成:

10,999,GET,INVENTORY,,true
11,888,,,"$.myList[*].type"

クライアントからのパブリッシュ:

99,12345

クライアントへの受信情報:

888,test,test2

デフォルトコレクションの使用

トピックの一部としてX-IDを使用すると、複数のテンプレートコレクションを簡単に使用できますが、メッセージごとにバイトが追加されます。 いずれにしても、デバイスがほとんど(または完全に)単一のコレクションを使用する場合は、このコレクションをデフォルトのコレクションとして指定することをお勧めします。

デフォルトのコレクションを指定すると、クライアントはX-IDを必要としない特別なトピックを使用でき、代わりにサーバーは前に指定されたX-IDを使用します。トピックは、パブリッシュの場合はs/ud、サブスクライブの場合はs/ddです。

MQTT ClientId内でX-IDを指定できます(MQTT実装をご覧ください)。

MQTT ClientIdは次のようになります。

d:myDeviceSerial:myDefaultTemplateXID

備考: デフォルトのX-IDを使用する場合、クライアントがデバイスであることを指定するために、ClientIdの先頭にd:を含める必要があります。

MQTT接続の確立時にデフォルトのテンプレートが存在する必要はありません(クライアントが使用すると検証されます)。

MQTT静的テンプレート

概要

デバイスの統合を容易にするために、Things Cloudはすでに、独自のテンプレートを作成することなく任意のクライアントで使用できる多くの静的テンプレートをサポートしています。これらのテンプレートは、デバイス管理の目的で最も一般的に使用されるメッセージに焦点を当てています。

下記のテンプレートを使用するには、トピックs/us(TRANSIENTモードはトピックt/us、QUIESCENTモードはトピックq/us、CEPモードはトピックc/us)にメッセージをパブリッシュする必要があります。詳細については、リファレンスガイドのSmartREST > 処理モードをご覧ください。

静的テンプレートを使用してオペレーションを受信するには、トピックs/dsをサブスクライブする必要があります。

デバイスの自動作成

静的テンプレートのトピックは、デバイスの自動作成をサポートしています。MQTT ClientIdに関連付けられた子デバイスがなく、データを送信すると、Things Cloudは自動的にMQTT ClientId用のデバイスを作成します。独自にデバイスを作成する場合、最初のメッセージはデバイスの作成でなければなりません。この場合、Things Cloudはテンプレートからデバイスを作成します。

デバイスの自動作成は、第1レベルの子デバイスでもサポートされています。下位レベルの子デバイスの場合は、子デバイスを作成するためのテンプレートを使用して、新しい子デバイスの下にある子デバイスのトピックにそのテンプレートを送信する必要があります。

必須パラメータなしの処理

パラメータが必須として宣言されていない場合、クライアントはその場所に空の文字列を送信できます。

100,,myType

末尾のコンマは必要ありません。次の2行では、同じメッセージになります。

100,,
100

テンプレートのパブリッシュ

次のテンプレートを使用して、トピックs/ust/usに関するデータをパブリッシュできます。TRANSIENTデータ処理のトピックt/の詳細については、SmartREST > 処理モードをご覧ください。

インベントリテンプレート (1xx)

デバイスの作成 (100)

インベントリにシリアル番号に対するデバイスがまだ存在していない場合は、新しいデバイスを作成します。デバイスのc8y_SerialのexternalIdとMQTT ClientIdのデバイス識別子としての値が作成されます。

位置 パラメーター 必須 デフォルト値
1 device name いいえ MQTT Device <serialNumber>
2 device type いいえ c8y_MQTTDevice

100,myDevice,myType
子デバイスの作成 (101)

現在のデバイスの新しい子デバイスを作成します。新しく作成されたオブジェクトは子デバイスとして追加されます。さらに、子デバイスのexternalIdがc8y_Serialに作成され、値はルートデバイスのシリアルと一意の子デバイスIDの組み合わせになります。

位置 パラメーター 必須 デフォルト値
1 unique child ID はい  
2 device name いいえ MQTT Device <serialNumber>
3 device type いいえ c8y_MQTTChildDevice

101,uniqueChildId,myChildDevice,myChildType
子デバイスの取得 (105)

デバイスの子デバイスの送信をトリガーします。

105
デバイスのフラグメント削除 (107)

1つ以上のフラグメントをデバイスから削除します。

位置 パラメーター 必須
1… fragmentName はい

107,c8y_Position,c8y_Configuration
ハードウェアの構成 (110)

デバイスのハードウェアプロパティを更新します。

位置 パラメーター 必須
1 serialNumber いいえ
2 model いいえ
3 revision いいえ

110,1234567890,myModel,1.2.3
モバイルの構成 (111)

デバイスのモバイルプロパティを更新します。

位置 パラメーター 必須
1 imei いいえ
2 iccid いいえ
3 imsi いいえ
4 mcc いいえ
5 mnc いいえ
6 lac いいえ
7 cellId いいえ

111,1234567890,,54353
位置の構成 (112)

デバイスの位置プロパティを更新します。

位置 パラメーター 必須
1 latitude いいえ
2 longitude いいえ
3 altitude いいえ
4 accuracy いいえ

112,50.323423,6.423423
構成の設定 (113)

デバイスの構成プロパティを更新します。

位置 パラメーター 必須
1 configuration いいえ

Example

113,"#
val1=1
val2=2"
サポートされているオペレーションの設定 (114)

デバイスでサポートされているオペレーションを設定します。

位置 パラメーター 必須
1… supported operations 配列 いいえ

114,c8y_Restart,c8y_Configuration,c8y_SoftwareList
ファームウェアの設定 (115)

デバイスにインストールされているファームウェアを設定します。

位置 パラメーター 必須
1 name いいえ
2 version いいえ
3 url いいえ

115,firmwareName,firmwareVersion,firmwareUrl
ソフトウェアリストの設定 (116)

デバイスにインストールされているソフトウェアのリストを設定します。

位置 パラメーター 必須
1… 下記の 3 values(ソフトウェア毎) 配列 いいえ
1.1 name いいえ
1.2 version いいえ
1.3 url いいえ

116,software1,version1,url1,software2,,url2,software3,version3
必要な可用性を設定 (117)

可用性の監視に必要な間隔を設定します。存在しない場合のみ値を設定します。UIなどで入力した値は上書きされません。

位置 パラメーター 必須
1 Required interval いいえ

117,60
サポートされているログの設定 (118)

デバイスがサポートしているログを設定します。

位置 パラメーター 必須
1… supported logs 配列 いいえ

118,ntcagent,dmesg,logread
サポートされている構成の設定 (119)

デバイスがサポートしている構成を設定します。

位置 パラメーター 必須
1… supported configurations 配列 いいえ

119,modbus,system

メジャーメントテンプレート (2xx)

カスタムメジャーメントの作成 (200)

指定したフラグメントとシリーズでメジャーメントを作成します。

位置 パラメーター 必須 デフォルト値
1 fragment はい  
2 series はい  
3 value はい  
4 unit いいえ  
5 time いいえ 現在のサーバー時刻

200,c8y_Temperature,T,25
信号強度メジャーメントの作成 (210)

c8y_SignalStrengthのメジャーメントを作成します。

位置 パラメーター 必須 デフォルト値
1 rssi value 2が未設定なら、はい  
2 ber value 1が未設定なら、はい  
3 time いいえ 現在のサーバー時刻

210,-90,23,2016-06-22T17:03:14.000+09:00
温度メジャーメントの作成 (211)

c8y_TemperatureMeasurementのメジャーメントを作成します。

位置 パラメーター 必須 デフォルト値
1 temperature value はい  
2 time いいえ 現在のサーバー時刻

211,25,2016-06-22T17:03:14.000+09:00
バッテリーメジャーメントの作成 (212)

c8y_Batteryのメジャーメントを作成します。

位置 パラメーター 必須 デフォルト値
1 battery value はい  
2 time いいえ 現在のサーバー時刻

212,95,2016-06-22T17:03:14.000+09:00

アラームテンプレート (3xx)

クリティカルアラームの作成 (301)

クリティカルアラームを作成します。

位置 パラメーター 必須 デフォルト値
1 type はい  
2 text いいえ Alarm of type alarmType raised
3 time いいえ 現在のサーバー時刻

301,c8y_TemperatureAlarm
メジャーアラームの作成 (302)

メジャーアラームを作成します。

位置 パラメーター 必須 デフォルト値
1 type はい  
2 text いいえ Alarm of type alarmType raised
3 time いいえ 現在のサーバー時刻

302,c8y_TemperatureAlarm,"This is an alarm"
マイナーアラームの作成 (303)

マイナーアラームを作成します。

位置 パラメーター 必須 デフォルト値
1 type はい  
2 text いいえ Alarm of type alarmType raised
3 time いいえ 現在のサーバー時刻

303,c8y_TemperatureAlarm
警告アラーム (304)

警告アラームを作成します。

位置 パラメーター 必須 デフォルト値
1 type はい  
2 text いいえ Alarm of type alarmType raised
3 time いいえ 現在のサーバー時刻

304,c8y_TemperatureAlarm,,2013-06-22T17:03:14.000+09:00
既存アラームの重要度の更新 (305)

既存アラームの重要度を更新します。

位置 パラメーター 必須
1 type はい
2 severity はい

305,c8y_TemperatureAlarm,CRITICAL
既存アラームのクリア (306)

既存アラームをクリアします。

位置 パラメーター 必須
1 type はい

306,c8y_TemperatureAlarm
アラームのフラグメント削除 (307)

特定タイプのアラームのフラグメントを1つ以上削除します。

位置 パラメーター 必須
1 alarmType はい
2… fragmentName はい

307,c8y_TemperatureAlarm,c8y_Position,c8y_Configuration

イベントテンプレート (4xx)

基本イベントの作成 (400)

指定したタイプとテキストのイベントを作成します。

位置 パラメーター 必須 デフォルト値
1 type はい  
2 text はい  
3 time いいえ 現在のサーバー時刻

400,c8y_MyEvent,"€Something was triggered"
位置更新イベントの作成 (401)

c8y_Positionを含む一般的な位置更新イベントを作成します。

位置 パラメーター 必須 デフォルト値
1 latitude いいえ  
2 longitude いいえ  
3 altitude いいえ  
4 accuracy いいえ  
5 time いいえ 現在のサーバー時刻

401,51.151977,6.95173,67
デバイス更新を伴う位置更新イベントの作成 (402)

c8y_Positionを含む一般的な位置更新イベントを作成します。さらに、デバイスは同じc8y_Positionフラグメントで更新されます。

位置 パラメーター 必須 デフォルト値
1 latitude いいえ  
2 longitude いいえ  
3 altitude いいえ  
4 accuracy いいえ  
5 time いいえ 現在のサーバー時刻

402,51.151977,6.95173,67
イベントのフラグメント削除 (407)

特定タイプのイベントのフラグメントを1つ以上削除します。

位置 パラメーター 必須
1 eventType はい
2… fragmentName いいえ

407,c8y_MyEvent,c8y_Position,c8y_Configuration

オペレーションテンプレート (5xx)

PENDINGオペレーションの取得 (500)

エージェントに対するすべてのPENDINGオペレーションの送信をトリガーします。

500
オペレーションをEXECUTINGに設定 (501)

指定されたフラグメントの最も古いPENDINGオペレーションをEXECUTINGに設定します。

位置 パラメーター 必須
1 fragment はい

501,c8y_Restart
オペレーションをFAILEDに設定 (502)

指定されたフラグメントの最も古いEXECUTINGオペレーションをFAILEDに設定します。

位置 パラメーター 必須
1 fragment はい
2 failureReason いいえ

502,c8y_Restart,"Could not restart"
オペレーションをSUCCESSFULに設定 (503)

指定されたフラグメントの最も古いEXECUTINGオペレーションをSUCCESSFULに設定します。

デバイスはフラグメントとして送信されたオペレーションのタイプに基づいて、追加のステップをトリガーする追加パラメーターを送信できます。(オペレーションの更新のセクション参照)

位置 パラメーター 必須
1 fragment はい
2… parameters いいえ

503,c8y_Restart

サブスクライブテンプレート

クライアントは、s/dsをサブスクライブするときに次のテンプレートを受け取ることができます。

インベントリテンプレート (1xx)

子デバイスの取得 (106)

デバイスのすべての子デバイスをリストします。

位置 パラメーター
1… child 配列

106,child1,child2,child3

オペレーションテンプレート (5xx)

すべてのオペレーション応答は同じ基本構造を持ち、messageIdから始まり、その後にオペレーションを処理するルートデバイスまたは子デバイスのIDが続きます。

再起動 (510)

デバイスを再起動します。

510,DeviceSerial
コマンド (511)

オペレーションで送信されるコマンドを実行します。

位置 パラメーター
1 Command text

511,DeviceSerial,execute this
構成 (513)

オペレーションで送信される構成を設定します。

位置 パラメーター
1 configuration

513,DeviceSerial,"val1=1\nval2=2"
ファームウェア (515)

URLからファームウェアをインストールします。

位置 パラメーター
1 firmware name
2 firmware version
3 url

515,DeviceSerial,myFimrware,1.0,http://www.my.url
ソフトウェアリスト (516)

オペレーションで送信されたソフトウェアをインストールします。

位置 パラメーター
1… 下記の 3 values(ソフトウェア毎) 配列
1.1 name
1.2 version
1.3 url

516,DeviceSerial,softwareA,1.0,url1,softwareB,2.0,url2
メジャーメント要求オペレーション (517)

リクエスト名で指定されたメジャーメントを送信します。

位置 パラメーター
1 request name

517,DeviceSerial,LOGA
リレー (518)

リレーを開閉します。

位置 パラメーター
1 Relay state

518,DeviceSerial,OPEN
リレーリスト (519)

リスト内のリレーを開閉します。

位置 パラメーター
1… relay state 配列

519,DeviceSerial,OPEN,CLOSE,CLOSE,OPEN
構成ファイルのアップロード (520)

現在の構成はThings Cloudからデバイスにアップロードされます。

520,DeviceSerial
構成ファイルのダウンロード (521)

URLから構成ファイルをダウンロードします。

位置 パラメーター
1 url

521,DeviceSerial,http://www.my.url
ログファイルの要求 (522)

指定したパラメーターのログファイルをアップロードします。

位置 パラメーター
1 Log file name
2 Start date
3 End date
4 Search text
5 Maximum lines

522,DeviceSerial,logfileA,2013-06-22T17:03:14.000+09:00,2013-06-22T18:03:14.000+09:00,ERROR,1000
通信モード (523)

通信モードを変更します。

位置 パラメーター
1 mode

523,DeviceSerial,SMS

オペレーションの更新

テンプレートを使用してオペレーションをSUCCESSFUL状態に設定すると、サーバーで追加の呼び出しをトリガーする追加のパラメーターの送信がサポートされます。 次の表に、この機能をサポートするオペレーションと、パラメーターを使用して実行されるオペレーションを示します。

フラグメント パラメーター トリガーされるアクション
c8y_Command result 結果がオペレーションに追加されます。
c8y_RelayArray relay states デバイスオブジェクトはステータスで更新されます。
c8y_CommunicationMode no parameter needed デバイスオブジェクトはモードで更新されます。
c8y_LogfileRequest file url ファイルURLがオペレーションに追加されます。
c8y_DownloadConfigFile (optional) timestamp デバイスオブジェクトは構成ダンプのIDとタイムスタンプ(またはサーバー時刻)で更新されます。

IDの取り扱い

IDレス通信の概念

Things CloudのMQTT実装は、特にデバイス通信用に設計されています。そのため、クライアント側から不要なロジックをできるだけ削除しようとします。

REST(またはSmartREST)プロトコルを使用するには、更新するすべてのオブジェクト、アラーム、およびオペレーションのIDを知っている必要があります。したがって、クライアントはこれらのIDの状態を保持する必要があります。たとえば、アラームを作成する場合、あとでクリアできるように、アラームのIDを知る必要があります。

MQTT実装では、このようなアクションを実行し、ロジックをサーバーに移動するためにデバイスで必要なロジックを減らしたいと考えています。

例1: デバイスのID

RESTを経由してデバイスオブジェクトのデータを更新するには、デバイスオブジェクトのID(マネージドオブジェクトID)を知る必要があります。また、このIDは、デバイスに関連付ける必要がある他のすべてのデータ (メジャーメント、アラーム、イベントのソースなど) にも必要です。

IDをデバイスに保持する必要性をなくすために、Things Cloudは Identity APIを提供しており、External ID(例えばシリアル番号)をオブジェクトにリンクできるため、いつでもIDを照会することができます。

一般的なデバイスの起動は次のようになります。

REST受信デバイスID

MQTTでは、MQTT ClientIdで Identity APIを自動的に使用します。 これにより、デバイスにIDを通知する必要がなくなり、クライアントはこの接続で他のデータも送信するため、すべてのメジャーメント、アラーム、イベントなどを正しいデバイスに関連付けることができます。

MQTT IDを自動的に解決

例2: アラームのID

クライアントがREST APIを使用してアラームを作成する場合、Things Cloudによって生成されたアラームのIDを取得する必要があります。

クライアントは、後でアラームを更新するためにこのIDを必要とします。たとえば、アラームがアクティブでなくなった場合、ステータスをCLEAREDに更新します。

RESTアラームの取り扱い

Things Cloudでは、デバイスはステータスがACTIVEのタイプごとに1つのアラームしか持つことができません。同じタイプで別のアラームを作成すると、重複除外されます。 したがって、MQTT実装ではアラームのタイプを識別子として使用します。クライアントは解決されたアラームのタイプを送信するだけで、サーバーは正しいアラームオブジェクトを見つけます。

MQTTアラームの取り扱い

MQTT経由のJSON

このセクションでは、Things Cloud MQTT実装で使用できるJSONペイロード形式について説明します。

固定テンプレートでのみ動作するSmartREST 2.0と比較して、MQTTに対するJSONのサポートは、REST APIのペイロードの柔軟性とMQTTの低いプロトコルオーバーヘッドを組み合わせるように設計されています。

ペイロードを最小限に抑えることが重要な場合(モバイルトラフィック、低能力デバイス)は、SmartRESTの方法をお勧めします。

トピック構造

JSON MQTTのトピック構造はRESTエンドポイントに非常に似ています。主な違いは、トピックに含まれる<action>アクション操作部分です。

メッセージをパブリッシュするには:

<api>/<resource>/<action>/<id>

TRANSIENTモードでメッセージをパブリッシュするには:

t/<api>/<resource>/<action>/<id>

QUIESCENTモードでメッセージをパブリッシュするには:

q/<api>/<resource>/<action>/<id>

CEPモードでメッセージをパブリッシュするには:

c/<api>/<resource>/<action>/<id>

TRANSIENT、QUIESCENTおよびCEPデータ処理の詳細については、処理モードをご覧ください。

アクション操作トピック

アクション操作トピックは、content-typeヘッダーと組み合わせたHTTPメソッドに対応しています。

次のアクション操作を実行可能:

エンドポイントのサポート

現在のJSON MQTT実装はすべてのSmartREST 2.0操作をカバーしていないため、たとえばデバイスブートストラッププロセス全体をSmartREST 2.0を使用して実行する必要があります。

次のエンドポイントおよびアクション操作がサポートされています。

エンドポイント create createBulk update delete
event/events
alarm/alarms  
measurement/measurements  
inventory/managedObjects    
inventory/managedObjects/<DeviceID>/childDevices      

操作がサポートされていない場合は、適切なエラーメッセージがトピックerrorに送信されます。

上記のすべてのエンドポイントに対して、REST APIと同じペイロードを使用することができます。唯一の違いは、「source」フィールドにあります。RESTでは、このフィールドは必須ですが、JSON MQTTでは、ここでデバイスIDを設定する必要はありません。 sourceのデバイスIDは、MQTT ClientIdに基づいて自動的に解決されます。この値は、すでにそこで何かが定義されている場合でも常に使用されます。

注記:
inventory/managedObjectsで新しいデバイスを作成する場合は、インベントリにシリアル番号に対するデバイスがまだ存在していない場合でもデバイスのc8y_SerialのexternalIdとMQTT ClientIdのデバイス識別子としての値は作成されません。
・エンドポイントに対する基本フィールドは各リファレンスガイドをご覧ください。(たとえば、メジャーメントのPOSTには、typeとtimeの2つの必須値がありますが、SmartREST2.0のようにtimeを省略することはできません。)

新しいイベントの作成

トピックevent/events/createにペイロードを含むメッセージをパブリッシュするには:

{
  "type": "TestEvent",
  "text": "sensor was triggered",
  "time": "2014-03-03T12:03:27.845Z"
}

多くのイベントの作成

トピックevent/events/createBulkにペイロードを含むメッセージをパブリッシュするには:

{
  "events": [
    {
      "type": "TestEvent1",
      "text": "sensor was triggered",
      "time": "2014-03-03T12:03:27.845Z"
    },
    {
      "type": "TestEvent2",
      "text": "sensor was triggered",
      "time": "2014-03-04T12:03:27.845Z"
    }
  ]
}

イベントの更新

トピックevent/events/update/<event_id>にペイロードを含むメッセージをパブリッシュするには:

{
  "text": "new text"
}

イベントの削除

トピックevent/events/delete/<event_id>に空のペイロードを含むメッセージをパブリッシュします。

エラー処理

JSON MQTT実装に関連するエラーをサブスクライブするには、トピックerrorを使用します。無効なペイロード、間違ったトピック、またはその他の例外が発生した場合、このトピックに通知がパブリッシュされます。ペイロードはJSON形式です。標準的なエラーメッセージの他に、どのメッセージが失敗したのかをクライアントが見つけるのに役立つmessageIdも含まれています。

ペイロードの例:

{
  "error": "undefined/validationError",
  "message": "Following mandatory fields should be included: severity,text,time",
  "messageId": 3
}

オペレーションの受信

通知クライアントは、トピックdevicecontrol/notificationsをサブスクライブして、新しく作成されたオペレーションの通知を受信できます。サブスクライブ開始時に、まだ転送されていないすべてのオペレーションがパブリッシュされます。

さらに、このファイルにはExternal IDが含まれているため、クライアントはどの子デバイスに対してオペレーションが実行されるかを識別できます。

通知の例:

{
  "agentId": "1",
  "creationTime": "2018-05-17T07:33:15.555Z",
  "delivery": {
    "log": [

    ],
    "status": "PENDING",
    "time": "2018-05-17T07:33:15.575Z"
  },
  "deviceId": "2",
  "id": "123",
  "status": "PENDING",
  "c8y_Command": {
    "text": "Do something"
  },
  "description": "Execute shell command",
  "externalSource": {
    "externalId": "3",
    "type": "c8y_Serial"
  }
}