-
Notifications
You must be signed in to change notification settings - Fork 22
Manager Plugin Communication Format
ここでは、Device Connect Managerとプラグインの間で行われる通信のフォーマットについて説明を行います。
Device Connect Managerは、HTTPリクエストで受信した命令を、Intentに変換して、各プラグインに配送します。
各プラグインは、Device Connect Managerから送れてきたIntentからリクエスト情報を取得して、処理を行います。
そして、処理の結果をレスポンスをIntentに格納して、Device Connect Managerに返却します。
Device Connect Managerは、プラグインから送られてきたIntentからレスポンス情報を取得し、JSONに変換して、HTTPレスポンスのボディに格納してアプリに返却します。
Device Connect システムのWebAPIでは、以下のようにHTTPリクエストが定義してあります。
{METHOD} http://localhost:4035/{api}/{profile}/{interface}/{attribute}?{key1}={value1}&{key2}={value2}
Device Connect Managerでは、HTTPリクエストを解析し、Intentに変換して、各プラグインに配送します。
ここでは、HTTPリクエストからIntentに変換する方法を解説します。
- HTTPメソッドをIntentのActionパラメータに格納します。
- URLパスは、api, profile, interface, attributeから成り立ち、それぞれIntentのExtraのパラメータに格納します。
- URLのクエリパラメータは、そのままIntentのExtraのパラメータとしてします。
HTTPメソッドは、以下のように変換して、IntentのActionに格納します。
HTTPメソッド | IntentのAction |
---|---|
GET | org.deviceconnect.action.GET |
PUT | org.deviceconnect.action.PUT |
POST | org.deviceconnect.action.POST |
DELETE | org.deviceconnect.action.DELETE |
HTTPリクエストのパスは、各セグメントを以下のようにapi、profile、interface、attributeのパラメータ名に変換して、IntentのExtraに格納します。
Extraのキー | Extraのバリュー |
---|---|
api | {api} |
profile | {profile} |
interface | {interface} |
attribute | {attribute} |
interface、attributeについては、省略されることがあります。
省略された時には、これらの要素はIntentには含みません。
HTTPリクエストのクエリパラメータは、そのままIntentのExtraに格納します。
Extraのキー | Extraのバリュー |
---|---|
{key1} | {key1} |
{key2} | {key2} |
HTTPリクエストがマルチパートで画像などのデータが送られてきた場合には、大容量となるために、Broadcastで送ることができません。
その問題を回避するために、Device Connect Managerが一時的にファイルを保存して、Extraにキーをuriとした保存したファイルへのURLを格納してプラグインに送信します。
プラグインは、送られてきたuriにアクセスして、画像データを取得します。
Extraのキー | Extraのバリュー |
---|---|
uri | マルチパートで送られてきたデータへのURL |
例) アクセストークンを要求するHTTPリクエストをIntentに変換します。
HTTPリクエスト
GET http://lcoalhost:4035/gotapi/authorization/accessToken?clientId=xxxxx&scope=battery,serviceDiscovery,serviceInformation&applicationName=アプリ名
Intentリクエスト
Action |
---|
org.deviceconnect.action.GET |
Extraキー | Extraバリュー |
---|---|
api | gotapi |
profile | authorization |
attribute | accessToken |
clientId | xxxxx |
scope | battery,serviceDiscovery,serviceInformation |
applicationName | アプリ名 |
URLパスは、/gotapi/authorization/accessToken
と定義されており、interfaceが省略されています。
HTTPリクエストから送られてくるデータには、型データがありません。
その為に、型のチェックは、各プラグインがプロファイルに配送する時に、Swaggerの定義ファイルを用いて確認を行っています。
例) 画面描画を要求するHTTPリクエストをIntentに変換します。
HTTPリクエスト
マルチパートサンプル |
POST /canvas/drawImage HTTP/1.1 Host: localhost:4035 Content-Type: multipart/form-data;boundary=WebKitFormBoundaryp7MA4YWxkTrZu0gW --WebKitFormBoundaryE19zNvXGzXaLvS5C Content-Disposition: form-data; name="accessToken" xxxxx --WebKitFormBoundaryE19zNvXGzXaLvS5C Content-Disposition: form-data;name="serviceId" xxxxx.localhost.deviceconnect.org --WebKitFormBoundaryE19zNvXGzXaLvS5C Content-Disposition: form-data; name="path" /test/test.png --WebKitFormBoundaryE19zNvXGzXaLvS5C Content-Disposition: form-data; name="mimeType" image/png --WebKitFormBoundaryE19zNvXGzXaLvS5C Content-Disposition: form-data; name="data"; filename="ic_launcher.png" Content-Type: image/png <binary省略> --WebKitFormBoundaryE19zNvXGzXaLvS5C-- |
Intentリクエスト
Action |
---|
org.deviceconnect.action.POST |
Extraキー | Extraバリュー |
---|---|
api | gotapi |
profile | canvas |
attribute | drawImage |
serviceId | xxxxx |
path | /test/test.png |
uri | {dataを保存したファイルへのURL} |
プラグインに渡される時には、dataではなくuriというキーになっていますので、注意が必要になります。
Device Connect Managerでは、プラグインからのIntentのレスポンスを受け取るとIntent#getExtra()の値をJSONに変換して、レスポンスボディとして返却します。
ここでは、IntentからJSONに変換する方法を説明します。
- Extraは、JSONのルートオブジェクト(JSONObject)として格納します。
- Extraに格納されたkey-valueは、JSONのルートオブジェクトにkey-valueとして格納します。
- Bundleは、JSONのオブジェクト(JSONObject)として格納します。
- 配列は、JSONの配列(JSONArray)として格納します。
IntentのExtraは、JSONObjectのルートオブジェクトになります。
何も追加しない場合には、JSONObjectのみになります。
{
}
プリミティブは、そのままJSONObjectに格納します。
intent.putExtra("result", 0);
intent.putExtra("level", 0.5f);
intent.putExtra("name", "name");
{
"result": 0,
"level": 0.5,
"name": "name"
}
Bundle型がExtraに格納されていた場合には、JSONObjectに変換します。
Bundleの中身は、Intentと同じように変換され格納します。
Bundle b = new Bundle();
b.putInt("result", 0);
intent.putExtra("bundle", b);
{
"bundle": {
"result": 0
}
}
Bundleの中にBundleが格納された場合には、JSONObjectが階層になります。
Bundle innerBundle = new Bundle();
innerBundle("result", 0);
Bundle b = new Bundle();
b.putInt("bundle", innerBundle);
intent.putExtra("bundle", b);
{
"bundle": {
"bundle": {
"result": 0
}
}
}
配列もしくはList型がExtraに格納されていた場合には、JSONArrayに変換します。
String[] list = { "AA", "BB", "CC" };
intent.putExtra("name", list);
{
"name": [
"AA", "BB", "CC"
]
}
配列の中に、Bundle型が格納されていた場合には、JSONObjectの配列にして格納します。
Bundle[] b = new Bundle[2];
b[0] = new Bundle();
b[0].putInt("result", 0);
b[1] = new Bundle();
b[1].putInt("result", 1);
intent.putExtra("bundle", b);
{
"bundle": [
{
"result": 0
},
{
"result": 1
}
]
}
ContentProviderへのURL(content://)が含まれている場合には、FilesプロファイルへのURLに変換して格納します。
HTTPリクエスト先がブラウザや外部IPからの場合には、ContentProvider経由ではアクセスすることができません。
その問題を回避するためにDevice Connect Managerでは、ContentProviderへのURLをDevice Connect Managerのサーバ経由でアクセスできるように変換して返却します。
intent.putExtra("uri", "content://api.example.com/abcdef012344567");
{
"uri": "http://localhost:4035/files?uri=content://api.example.com/abcdef012344567"
}
例) Bundleを配列に持つレスポンスをJSONオブジェクトに変換します。
Bundle[] b = new Bundle[2];
b[0] = new Bundle();
b[0].putString("path", "xxxx/xxxx.png");
b[0].putString("mimeType", "image/png");
b[0].putInt("fileType", 0);
b[0].putString("fileName", "xxxx.png");
b[0].putLong("updateDate", 1234567890);
b[1] = new Bundle();
b[1].putString("path", "xxxx/oooo.png");
b[1].putString("mimeType", "image/png");
b[1].putInt("fileType", 0);
b[1].putString("fileName", "oooo.png");
b[1].putLong("updateDate", 1234567890);
intent.putExtra("bundle", b);
intent.putExtra("result", 0);
{
"result": 0,
"bundle": [
{
"path": "xxxx/xxxx.png",
"mimeType": "image/png",
"fileType": 0,
"fileName": "xxxx.png",
"updateDate": 1234567890
},
{
"path": "xxxx/oooo.png",
"mimeType": "image/png",
"fileType": 0,
"fileName": "oooo.png",
"updateDate": 1234567890
}
]
}
例) ContentProviderへのURLを持つレスポンスをJSONオブジェクトに変換します。
intent.putExtra("result", 0);
intent.putExtra("uri", "content://org.deviceconnect.android.plugin.xxxx/test.png");
{
"result": 0,
"uri": "http://localhost:4035/files?uri=content://org.deviceconnect.android.plugin.xxxx/test.png"
}