Skip to content

Manager Plugin Communication Format

TakayukiHoshi1984 edited this page Jul 18, 2018 · 2 revisions

Managerとプラグイン間の通信について

ここでは、Device Connect Managerとプラグインの間で行われる通信のフォーマットについて説明を行います。

Device Connect Managerは、HTTPリクエストで受信した命令を、Intentに変換して、各プラグインに配送します。

各プラグインは、Device Connect Managerから送れてきたIntentからリクエスト情報を取得して、処理を行います。
そして、処理の結果をレスポンスをIntentに格納して、Device Connect Managerに返却します。

Device Connect Managerは、プラグインから送られてきたIntentからレスポンス情報を取得し、JSONに変換して、HTTPレスポンスのボディに格納してアプリに返却します。

HTTPリクエストからIntentへ変換

Device Connect システムのWebAPIでは、以下のようにHTTPリクエストが定義してあります。

{METHOD} http://localhost:4035/{api}/{profile}/{interface}/{attribute}?{key1}={value1}&{key2}={value2}

Device Connect Managerでは、HTTPリクエストを解析し、Intentに変換して、各プラグインに配送します。
ここでは、HTTPリクエストからIntentに変換する方法を解説します。

変換方法

  1. HTTPメソッドをIntentのActionパラメータに格納します。
  2. URLパスは、api, profile, interface, attributeから成り立ち、それぞれIntentのExtraのパラメータに格納します。
  3. URLのクエリパラメータは、そのままIntentのExtraのパラメータとしてします。

1. HTTPメソッド

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

2. URLパス

HTTPリクエストのパスは、各セグメントを以下のようにapi、profile、interface、attributeのパラメータ名に変換して、IntentのExtraに格納します。

Extraのキー Extraのバリュー
api {api}
profile {profile}
interface {interface}
attribute {attribute}

interface、attributeについては、省略されることがあります。
省略された時には、これらの要素はIntentには含みません。

3. URLクエリパラメータ

HTTPリクエストのクエリパラメータは、そのままIntentのExtraに格納します。

Extraのキー Extraのバリュー
{key1} {key1}
{key2} {key2}

4. マルチパート

HTTPリクエストがマルチパートで画像などのデータが送られてきた場合には、大容量となるために、Broadcastで送ることができません。

その問題を回避するために、Device Connect Managerが一時的にファイルを保存して、Extraにキーをuriとした保存したファイルへのURLを格納してプラグインに送信します。

プラグインは、送られてきたuriにアクセスして、画像データを取得します。

Extraのキー Extraのバリュー
uri マルチパートで送られてきたデータへのURL

変換例1

例) アクセストークンを要求する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の定義ファイルを用いて確認を行っています。

変換例2

例) 画面描画を要求する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というキーになっていますので、注意が必要になります。

IntentからHTTPレスポンス(JSON)への変換

Device Connect Managerでは、プラグインからのIntentのレスポンスを受け取るとIntent#getExtra()の値をJSONに変換して、レスポンスボディとして返却します。

ここでは、IntentからJSONに変換する方法を説明します。

変換方法

  1. Extraは、JSONのルートオブジェクト(JSONObject)として格納します。
  2. Extraに格納されたkey-valueは、JSONのルートオブジェクトにkey-valueとして格納します。
  3. Bundleは、JSONのオブジェクト(JSONObject)として格納します。
  4. 配列は、JSONの配列(JSONArray)として格納します。

1. Extra型

IntentのExtraは、JSONObjectのルートオブジェクトになります。
何も追加しない場合には、JSONObjectのみになります。

{
}

2. プリミティブ型

プリミティブは、そのままJSONObjectに格納します。

intent.putExtra("result", 0);
intent.putExtra("level", 0.5f);
intent.putExtra("name", "name");
{
    "result": 0,
    "level": 0.5,
    "name": "name"
}

3. Bundle型

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
        }
    }
}

4. 配列、もしくはList型

配列もしくは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
        }
    ]
}

5. ContentProviderのURL

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"
}

変換例1

例) Bundleを配列に持つレスポンスをJSONオブジェクトに変換します。

変換前のIntentデータ
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);

変換後のJSON
{
    "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
        }
    ]
}

変換例2

例) ContentProviderへのURLを持つレスポンスをJSONオブジェクトに変換します。

変換前のIntentデータ
intent.putExtra("result", 0);
intent.putExtra("uri", "content://org.deviceconnect.android.plugin.xxxx/test.png");

変換後のJSON
{
    "result": 0,
    "uri": "http://localhost:4035/files?uri=content://org.deviceconnect.android.plugin.xxxx/test.png"
}
  1. Manager・プラグイン間通信フォーマット
  2. 開発マニュアル
  3. ビルドマニュアル
  4. ユーザーマニュアル
Clone this wiki locally