SmartRESTの使用

Things Cloud REST APIは、ほとんどの環境から簡単に使用できる汎用IoTプロトコルを提供します。これはどのようなIoTユースケースにもアドホックに適応させることができ、また標準的なインターネット通信およびセキュリティーメカニズムを利用します。適切な標準技術を利用しているため、独自IoTプロトコルと比べ先進的である一方、ローエンドのマイクロコントローラまたは低帯域幅通信チャネルなど、非常に制約の多い環境には課題をもたらすことがあります。

こうした環境向けに、Things Cloud はいわゆる「SmartREST」プロトコルを提供します。SmartRESTは以下のように、標準技術の利点と特別仕様のプロトコルの利点を同時に提供するものです。

次のセクションでは、SmartRESTの背景にある概念と、使用する基本プロトコルについて説明します。SmartRESTは後述の通り、テンプレートを使ってメタデータをペイロードデータから分離する処理を基本としています。最後に、SmartRESTを使用してデータを送受信する方法を説明します。プロトコル詳細はSmartRESTリファレンスをご覧ください。

SmartRESTの動作方法

下記の画像は、SmartRESTの動作を図示したものです。デバイスおよび他のクライアントは Things Cloud 上の専用SmartRESTエンドポイントに接続し、それぞれのデータをコンマ区切り値からなる行として送信します。これらの行は Things Cloud のSmartRESTプロキシにより、標準の Things Cloud REST APIリクエストへと展開されます。同様に、Things Cloud からの応答は通常のJSON形式からプロキシによってコンマ区切り値に圧縮された後、デバイスに返却されます。

SmartREST architecture

Things Cloud はコンマ区切り値をどのようにして意味のあるRESTリクエストとして解釈するのか?

まず、これを行うためにデバイスはテンプレートを Things Cloud に登録します。テンプレートは、展開されたRESTリクエスト形式をプレースホルダと一緒に保持しており、その中へ Things Cloud の SmartREST プロキシが連続的にコンマ区切り値を挿入します。応答の場合、テンプレートはコンマ区切り値を構築するために、構造化されたREST応答からどの値を抽出するを記述します。

テンプレートは、デバイスのソフトウェアまたはファームウェアのバージョンに関連付けられます。通常、デバイスまたはアプリケーションに固有な実装は、用途に応じたリクエストタイプに対応しており、決まった範囲の要求を発行します。同じ実装のデバイスはすべて、同じ一連のリクエストタイプを共有するのです。したがって、テンプレートは実装段階で定義できます。テンプレートを Things Cloud で使用できるようにするため、特定の実装を伴う最初のデバイスがそのテンプレートを送信し、すべての同様のデバイスで利用できるようにします。

以下の図は、このプロセスを表したものです。「Device_1.0」のバージョンを実装したデバイスがSmartREST経由での通信を開始すると仮定します。デバイスは認証情報を取得した後、SmartRESTプロキシに対し、テンプレートが登録済みであるかを問い合わせます。テンプレートがサーバー上で見つからない場合、デバイスはテンプレートを単一の静的テキストリクエストとして Things Cloud へ送信します。この手順が完了したら、このテンプレートを使用する同類のデバイスはすべて、テンプレートをサーバーに再送しなくても、SmartRESTを使用する通信を開始することができます。

SmartREST templates

この例は、変換プロセス概要も例示しています。「Template 1」において、「%%」はプレースホルダであり、これをSmartRESTプロキシが埋めます。「time」はサーバー側タイムスタンプに置き換えられます(下記参照)。残りのプレースホルダはリクエストデータに置き換えられます。リクエスト例における行「1,200,20.5」は以下のように解釈されます。

基本的なSmartRESTプロトコル

すべてのSmartRESTリクエストの基本構造は次のとおりです。

上記の例で言えば、SmartRESTリクエストは以下の通りとなります。

POST /s HTTP/1.1
Authorization: Basic ...
X-Id: Device_1.0

1,200,20.5

これに呼応する応答例として以下が挙げられます。

HTTP/1.1 200 OK
Transfer-Encoding: chunked

20,0

リクエストと応答を照合するため、応答行には、エラーコードの次に、応答に対応するリクエストを示す行が含まれます。この例で言えば、「20」は「OK」を意味し、「0」はリクエストの1行目を指します。

テンプレートの登録方法は?

前述の通り、クライアントは SmartREST を使用する場合、まず、SmartRESTテンプレートがすでにサーバーにとって既知であるかどうかを尋ねます。これは以下のような空のSmartRESTリクエストを使用して行われます。

POST /s HTTP/1.1
Authorization: Basic ...
X-Id: Device_1.0

デバイス実装が既知であれば、応答はIDを返し、このIDはその後のリクエストにおける「X-Id」ヘッダーの「簡略表現」として使用することができます。

HTTP/1.1 200 OK

20,<id>

デバイス実装が未知の場合、応答は以下のようになります。

HTTP/1.1 200 OK

40,"No template for this X-ID"

この場合、あなたのデバイス実装で使用する全てのテンプレートを作成します。

POST /s HTTP/1.1
Authorization: Basic ...
X-Id: Device_1.0

10,1,POST,/measurement/measurements,application/vnd.com.nsn.cumulocity.measurement+json,,%%,NOW UNSIGNED NUMBER,{ "time": "%%", "type": ... }
...

この例では、「10」はリクエストテンプレートを指します(一方、「11」は応答テンプレートを指します)。このテンプレートは「1」番ですから、このテンプレートを使用するSmartRESTリクエストは最初のカラムに「1」が付くことになります。このテンプレートはエンドポイント「/measurement/measurements」宛の「POST」リクエストを参照し、コンテンツ種別は「application/vnd.com.nsn.cumulocity.measurement+json」となります。このテンプレートで使用されるプレースホルダは「%%」です。プレースホルダはタイムスタンプ(「NOW」)と、符号なし数値および一般数値です。最後に、最終カラムは、入力され送信されることになるリクエストの本体を格納します。

応答はどのように扱われますか?

上記の例ではリクエストとリクエストテンプレートの取り扱いを例示しました。応答の場合、JSONPath表現がThings Cloud REST応答をCSVに変換します。例えば、デバイスにディスプレイ画面があり、メッセージをその画面に表示できるとしましょう。メッセージを更新するためのオペレーションは以下となります。

{
	"c8y_Message": {
		"text": "Hello, world!"
	},
	"creationTime": "2019-02-25T08:32:45.435+01:00",
		"deviceId": "8789602",
		"status": "PENDING",
		...
}

クライアント側では、デバイスは主に表示されることになるテキストを知る必要があります。JSONPathでは、以下の構文を使用して「text」プロパティを抽出します。

$.c8y_Message.text

この構文において、「$」はデータ構造のルートを指し、「.」はデータ構造からの要素を選択します。オプションについて詳しくはJSONPathリファレンスをご覧ください。

デバイスは通常、自らに関連するオペレーションと、PENDING状態のオペレーションをすべて問い合わせます。そうしたクエリに対する Things Cloud の標準応答は以下の通りです。

{
	"operations": [{
		"c8y_Message": {
				"text": "Hello, world!"
		},
		"creationTime": "2014-02-25T08:32:45.435+01:00",
		"deviceId": "8789602",
		"status": "PENDING",
		...
	}, {
		"c8y_Relay": {
			...
		}
	...
	}]
}

つまり、応答にはオペレーションのリストが含まれ、これらのオペレーションはさまざまな種類を有する場合があります。そうした構造に対処するには、以下の応答テンプレートを使用します。

11,2,$.operations,$.c8y_Message,$.c8y_Message.text

これは値ごとに説明すると、以下を意味します。

結果、SmartRESTクライアントは以下の応答を返されることになります。

HTTP/1.1 200 OK

2,0,"Hello, world!"

この応答は、表示メッセージを変換するためのテンプレートであるテンプレート2を使用して作成されました。応答は最初に送られたリクエストを参照します。実際に設定されるメッセージは「Hello, world!」です。