アプリケーション開発

チュートリアル

開発の流れ

Symphony ダッシュボードの開発は以下の流れで進めていきます。

1. 認証機能の開発
ダッシュボードを利用するユーザーのサインアップおよびサインインの仕組みを開発します。
2. ゲートウェイの登録
ユーザーがダッシュボードにサインインしたら、最初にゲートウェイを登録しなければいけません。ユーザーが所有するゲートウェイを発見し、それを、ダッシュボードにサインインしているユーザーに関連付ける仕組みを開発します。このステップでは、ゲートウェイが認識しているデバイスを Symphony に登録し、各デバイスが提供するサービスも取得します。
3. アクションの実行
ゲートウェイ配下に登録されたデバイスが提供するアクションを実行する仕組みを開発します。

以上の開発項目が Symphony ダッシュボードの必要最小限の機能です。以降、上記の項目を順を追って解説していきます。

認証機能の開発

Symphony を利用するためには事前にサインインする必要があります。

サインイン状態の確認

SDK はサインイン状態を保持します。isAuthenticated() でサインイン済みどうかを確認し、 まだサインインしていなかった場合はサインイン用の画面を表示してください。

サンプルコード
dSymphony.isAuthenticated().thenAccept(user -> {
    if (user != null) {
        // サインイン済みならメインUIを表示
        ...
    } else {
        // サインイン済みでないならサインイン画面を表示
        ...
    }
}).exceptionally(ex -> {
    // エラーならサインイン画面を表示
    ...
});

サインイン済みの場合にコールバック関数に引き渡されるオブジェクトの内容は次のようになります。

{
  "userId": "wNrFkaOg",
  "userName": "あなたの名前",
  "accessToken": "HnTxM0wwo0dtGtnHKjkQy8lv3tNeWYB68ISi9TvtYoM"
}
サインイン用画面

本 SDK はサインイン用の画面を提供します。 initSigninPage()を実行するとブラウザが起動し、サインイン用の HTML ページが表示されます。ユーザの認可、拒否の結果は、利用申請時に登録したリダイレクト URI に返却されます。

サインイン画面を表示するために使用するブラウザは、Custom Chrome Tabs と WebView の2種類があります。
ブラウザによって、以下のようにそれぞれ使用方法が異なります。

・Custom Chrome Tabs でサインイン

Custom Chrome Tabs を使用してサインインを行う場合には、リダイレクト URI で起動される Activity を AndroidManifest.xml に設定します。

起動用の Activity は、本 SDK に実装してありますので、AndroidManifest.xml に記載するだけ使用することができます。

AndroidManifest.xml
<activity
    android:name="com.nttdocomo.symphony.android.SigninCallbackActivity"
    android:launchMode="singleInstance"
    android:noHistory="true"
    android:theme="@style/Theme.TranslucentBackground">
    <intent-filter>
        <action android:name="android.intent.action.VIEW"/>

        <!-- ブラウザから起動できるように設定します -->
        <category android:name="android.intent.category.DEFAULT"/>
        <category android:name="android.intent.category.BROWSABLE"/>

        <!-- リダイレクト URI を設定します -->
        <data
            android:host="{HOST}"
            android:scheme="{SCHEME}"/>
    </intent-filter>
</activity>

Symphony アプリケーション申請の際にリダイレクト URI を指定しますが、{HOST} と {SCHEME} の部分は、それぞれ、その URL のホストとスキームに置き換えてください。

例えば、リダイレクト URI に「oauth://dsymphony」を指定した場合には、以下のように置き換えます。

<data
        android:host="dsymphony"
        android:scheme="oauth"/>
サインイン処理
DSymphony dSymphony = new DSymphony(context);

SigninParams params = new SigninParams.Builder()
        .type(SigninParams.TYPE_CUSTOM_TAB_ACTIVITY)
        .addScope("management")
        .addScope("archive")
        .addScope("device")
        .clientId("{CLENT ID}")
        .state("chrome")
        .redirectUri("{REDIRECT URL}")
        .activity(MainActivity.class)
        .build();
symphony.initSigninPage(context, params);

{CLENT ID} と {REDIRECT URL} にはSymphony API 利用申請時のクライアント ID とリダイレクト URI を設定します。

サインインに成功した場合は、SigninParams.Builder#activity(Class) に設定した Activity の画面を起動します。
Custom Chrome Tabs は、プログラムで閉じることができませんので、 SigninParams.Builder#activity(Class) の設定し、Activity を起動します。

・WebView でサインイン

WebView を使用してサインインを行う場合は、リダイレクト URI で起動される Activity の AndroidManifest.xml への設定は不要です。

サインイン処理
DSymphony dSymphony = new DSymphony(context);

SigninParams params = new SigninParams.Builder()
        .type(SigninParams.TYPE_WEBVIEW)
        .addScope("management")
        .addScope("archive")
        .addScope("device")
        .clientId("{CLENT ID}")
        .state("webview")
        .redirectUri("{REDIRECT URL}")
        .activity(MainActivity.class)
        .build();
symphony.initSigninPage(context, params);

サインインに成功した場合は、SigninParams.Builder#activity(Class) に設定した Activity の画面を起動します。
SigninParams.Builder#activity(Class) が設定されていない場合には、WebiView 表示用 Activity を終了して、前の画面に戻ります。

WebView でサインインする場合には、ユーザエージェントを設定することができます。
WebView のユーザエージェントを変更したい場合には、以下のように設定してください。

ユーザエージェント変更したサインイン処理
DSymphony dSymphony = new DSymphony(context);

SigninParams params = new SigninParams.Builder()
        .type(SigninParams.TYPE_WEBVIEW)
        .userAgent("Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36")
        .addScope("management")
        .addScope("archive")
        .addScope("device")
        .clientId("{CLENT ID}")
        .state("webview")
        .redirectUri("{REDIRECT URL}")
        .activity(MainActivity.class)
        .build();
dSymphony.initSigninPage(context, params);

ゲートウェイの登録

ゲートウェイの電源を入れる、または、スマートフォンのゲートウェイアプリを起動すると、自動的に Symphony にそのゲートウェイが一時的に登録されます。しかし、そのゲートウェイはどのユーザーにも関連付けられておらず、しばらくすると、Symphony から削除されます。ゲートウェイの電源を入れた、または、スマートフォンのゲートウェイアプリを起動したら、ユーザーと関連付ける処理を実行する必要があります。

ゲートウェイには必ず個体を識別するための UUID が割り当てられています。ダッシュボードでは、その UUID を登録する仕組みが必要となります。この処理には、setupGateway() メソッドを使います。

以下のサンプルでは、setupGateway() メソッドを呼び出し、その結果を Logcat に出力します。

// 登録ボタンが押されたときの処理
private void registerGateway() {
    // ユーザーが入力した UUID を取得
    String gw_uuid = ...;

    // ゲートウェイの登録を実行
    SymphonyObject param = new SymphonyObject.Builder()
        .put("uuid", gw_uuid)
        .build();
    dSymphony.setupGateway(param).thenAccept(res -> {
        // 成功したら結果をログに出力
        Log.d(TAG, res.toString());
    }).exceptionally(ex -> {
        // 失敗したらエラーをログに出力
        Log.e(TAG, "", ex);
		return null;
    });
}

処理が成功すると、次のような結果が得られます。

{
  ...
  "deviceList": [
    {
      "deviceName": "REX-WFIREX1",
      "thingId": "th-2D0AB85CB301495FED4821D22D1737C1",
      "actionInfo": {
        "actionId": "ac-08F0886260D516A34403730D4EAAE378",
        "summary": "湿度センサー計測値の取得",
        ...
      },
      ...
    },
    {
      "deviceName": "REX-WFIREX1",
      "thingId": "th-2D0AB85CB301495FED4821D22D1737C1",
      "actionInfo": {
        "actionId": "ac-CAAB6578B6C72A420CDB396B6DDCA899",
        "summary": "湿度センサー計測値の取得",
        ...
      },
      ...
    },
    ...
  ]
}

ご覧の通り、ゲートウェイが認識しているデバイスの情報、そして、そのデバイスが提供するアクション情報が得られます。ここで重要な情報は actionId です。actionId はアクションの識別子ですが、後にアクションを実行する際に必要となります。

アクションの実行

アクション情報が得られたら、そのアクション ID (actionId) を使って、そのアクションを実行することができます。以下のサンプルでは、requestAction() メソッドを呼び出し、その結果を Logcat に出力します。

// 実行ボタンが押されたときの処理
private void execAction() {
    // ユーザーが入力したアクション ID を取得
    String id = ...;

    // アクションを実行
    SymphonyObject param = new SymphonyObject.Builder()
        .put("actionId", id)
        .build();
    dSymphony.requestAction(param).thenAccept(res -> {
        // 成功したら結果をログに出力
        Log.d(TAG, res.toString());
    }).exceptionally(ex -> {
        // 失敗したらエラーをログに出力
        Log.e(TAG, "", ex);
		return null;
    });
}

例えば、アクション ID に ac-CAAB6578B6C72A420CDB396B6DDCA899 (この例では湿度センサー計測値の取得) を入力して実行ボタンを押すと、Logcat に次のような結果が出力されます。

{
  ...
  "humidity": 60.4,
  ...
}

以上の例ではパラメータが不要なサービスを例に挙げましたが、多くのサービスではパラメータを必要とします。requestAction() は、自由にパラメータを与えることも可能です。

アーキテクチャ

以上で、ユーザー認証、ゲートウェイ登録、アクション実行の一連の流れを解説してきましたが、とりわけゲートウェイ登録からアクション実行では、紹介したメソッドが必要な処理を自動的に行い、Symphony の仕組みを隠ぺいしています。より洗練された処理フローをダッシュボードで実現するためには、Symphony が内部で保持しているデータの構造、そして、Web API を知る必要があります。以下、ゲートウェイの発見からサービス実行に至るまでの詳細な処理フローを解説します。

前述のチートリアルでは、setupGateway() メソッドを使って、いきなりゲートウェイが提供するアクションの情報を取得しましたが、この結果を得るためは、いくつかの処理を行っています。

  1. ゲートウェイの登録

    ゲートウェイの電源を入れる、または、スマートフォンのゲートウェイアプリを起動すると、自動的に Symphony にそのゲートウェイが一時的に登録されます。しかし、そのゲートウェイはどのユーザーにも関連付けられておらず、しばらくすると、Symphony から削除されます。

  2. ゲートウェイの検索

    ユーザーがゲートウェイの UUID を指定して、そのゲートウェイを自身のアカウントと関連付けます。この関連付けが完了して、初めて自分のゲートウェイとして、そのゲートウェイにアクセスが可能になります。ダッシュボードでは、ユーザーからゲートウェイの UUID を取得し、Symphony から指定の UUID を持ったゲートウェイを検索する必要があります。この処理は searchGateway() メソッドが担います。

  3. ゲートウェイの関連付け

    指定の UUID を持ったゲートウェイが見つかったら、getGateways() メソッドを使って、それがすでに登録済みの UUID かどうかを確認する必要があります。もし未登録のゲートウェイであれば、それをユーザーに関連付けます。この関連付けには registerGateway() メソッドを使います。

  4. デバイスの発見と登録

    ゲートウェイの登録が完了した時点では、まだ Symphony は該当のゲートウェイが扱えるデバイスおよびアクションを認識していません。このデバイスおよびアクションの登録には registerDevice() メソッドを使います。このメソッドは、未登録のデバイスを自動的に登録してしまうモードと、個別に一つずつデバイスを登録するモードがありますが、setupGateway() メソッドは、前者のモードを使っています。もし未登録のデバイスを事前に知りたい場合は、getUnregisteredDevices() メソッドを使うことができます。ここから得られた未登録デバイスの情報をもとに、registerDevice() メソッドを使って 1 つずつ取捨選択しながらデバイス登録することもできます。

  5. アクションの取得

    デバイスの登録が完了したら、そのデバイスがどのようなアクションを提供しているのかを取得する必要があります。前述のデバイス登録の際に使う registerDevice() メソッドのレスポンスには、登録されたデバイスのアクションの情報が含まれます。しかし、デバイス登録後に利用可能なアクションを知りたい場合は getActions() メソッドを使うことができます。

  6. アクションの解析と実行

    アクション情報には、アクションの概要だけでなく、リクエストに必要なパラメータ情報を含んでいます。サービスを利用するためには、このパラメータ情報を解析して、Symphony に対して適切なパラメータを与えてリクエストする必要があります。アクションの実行には、requestAction() メソッドが便利です。アクション ID を指定するだけでアクションを実行することができます。この requestAction() メソッドは、内部的には、ローレベル API の request() メソッドを使っています。もしゲートウェイ配下のデバイスが提供するアクションをきめ細かく制御したい場合は、request() メソッドを使うこともできます。

本来、上記の手順を踏んで Symphony 経由でゲートウェイおよびその先にあるデバイスを操作するわけですが、前述のチュートリアルで紹介した setupGateway() メソッドは、上記手順の 2 ~ 5 の処理をまとめて行っています。

このように、チュートリアルで紹介した 統合 API を使って簡単に処理を行うのか、Symphony の Web API と一対一で対応しているそれ以外のメソッドを使うのかは、状況に応じて使い分けてください。

Symphony には、ゲートウェイやデバイスやサービスを扱う API のほか、以下の機能も用意されています。

  • ユーザー管理

    自分のアカウントの修正や削除、また、共有ユーザーの登録や削除などが提供されています。共有ユーザーを登録することで、サービスをその共有ユーザーに利用させることが可能になります。

  • ロール管理

    前述の共有ユーザーに対して、利用可能なサービスを制限することができます。また、そのサービスを利用できる期間なども詳細に設定することができます。

  • アーカイブ管理

    ゲートウェイの先のデバイスからの応答を Symphony に保存しておくことができます。保存の開始、取得、停止といった API が提供されています。

  • チーミング管理

    もし 2 つのゲートウェイが同じデバイスを認識していると、Symphony では別々のデバイスとして認識されます。しかし、チーミング機能を使うと、それら 2 つをあたかも 1 つのデバイスであるかのように扱うことができます。

  • イベントメッセージ

    デバイスによっては、リクエスト・レスポンス型のサービスだけでなく、非同期に情報を通知してくるサービスもあります。本 SDK は、この非同期のイベントメッセージを受信する枠組みを提供しています。