Philips Hue Android SDK を使って光を操る


Philips社から発売しているLEDライトのHueと、公開されているAndroid SDKを使ってみました。Hueは単なるLEDライトではなくスマートフォンから様々なコントロールができる照明システムで、色やパワーのON/OFFはもちろん、タイマー設定や位置情報、センサーとの連動も可能です。またアプリ間連携のサービス IFTTTを使って、例えばメールを受信したらHueライトが点灯するような連携も可能です。

今回は下記の開発者サイトで公開されているAndroid SDKを使って、特定のライトの電源のOn・Offと、RGB指定で色をコントロールするところまでご紹介したいと思います。

公式製品説明サイト:Meet hue
公式開発者サイト:Philips Hue API

Hueの利用準備

まず、Hueのスターターセットを購入すると、3つのLEDランプとブリッジと呼ばれる丸い機器が入ってます(その他、電源ケーブルなど)。今回はローカルネットワーク内でのコントロールを目的とするので、以下のような構成になります。インターネットを経由したコントロール(例:外出先からスマホで、家のHueをコントロール)するには、MY hue ポータルサイトで登録などの準備が必要になります。

Hue_1

スマホとブリッジ間はルーター経由での接続となりますが、ブリッジとHueランプ間はZigBee Light Linkという無線規格で接続しています。上記のセットアップを完了すると、Philips社から出ている公式アプリサードパーティ製アプリなどで、Hueランプのコントロールが出来るか試してみましょう。アプリを起動すると、ブリッジのボタンを押すように指示があるので、ボタンを押すとコントロールができるようになります。

開発準備

JAVA/Android SDKは開発者サイトから取得することができ、ライブラリ単体のほか、サンプルプロジェクトがGitHubにて公開されているようです。ちなみに、サードパーティ製のActionScriptやC#などのいろんなライブラリも公開されているようです。

また、この開発者サイトにて開発者登録をすると、各プラットフォームのAPIドキュメントを閲覧することができるので、この登録も済ませておく事をおススメします。

今回は、事前に作成したプロジェクトのlibsフォルダに、上記の開発者サイトから取得した、huelocalsdk.jar と huesdkresources.jarをセットして、インターネット接続許可のマニフェストを設定して準備完了とします。ちなみに今回作ったサンプルアプリはかなり省力化してますので以下のような画面です。

Hue_2

ブリッジの検索

まず最初に同じネットワーク内のブリッジを検索するのですが、その前にSDKの初期化や、ブリッジからのコールバックを受け取るリスナー登録を行います。

        // HueSDKインスタンス作成
        phHueSDK = PHHueSDK.create();

        // API(ブリッジ?)へのアクセスを許可するホワイトリストに登録する際のアプリ名を設定
        phHueSDK.setDeviceName("MyHueTestApp");

        // ブリッジからのコールバックを受け取るリスナー(PHSDKListener)を登録
        phHueSDK.getNotificationManager().registerSDKListener(sdkListener);

次に、ボタン押下時にブリッジ検索を開始します。

        searchBridgeBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // ブリッジの検索開始
                PHBridgeSearchManager searchManager = (PHBridgeSearchManager) phHueSDK.getSDKService(PHHueSDK.SEARCH_BRIDGE);
                searchManager.search(true, true);
            }
        });

検索を完了してブリッジを見つけると、先ほど登録したリスナー(PHSDKListener)の以下のメソッドで情報を受け取る事ができます。

    
    // 登録したリスナーのインスタンス
    private PHSDKListener sdkListener = new PHSDKListener() {

        @Override
        public void onAccessPointsFound(List<PHAccessPoint> phAccessPoints) {

            // ブリッジ検索結果の取得
            // phAccessPoints:見つかったブリッジたち
            if (phAccessPoints != null && phAccessPoints.size() > 0) {
                // 見つかったブリッジ一覧をリスト表示する為に、Adapterに追加したりの処理
            }
        }
        
        // その他色々メソッドあり
        
    };

ブリッジとの接続

検索で見つかったブリッジ一覧から、特定のブリッジへの接続を行います。

        // ListViewなどでブリッジのリスト表示で、特定のブリッジを選択した場合
        public void onItemClick(AdapterView<?> adapterView, View view, int position, long id){
            // 選択したブリッジに接続する
            PHAccessPoint accessPoint = (PHAccessPoint) bridgeListAdapter.getItem(position);
            // ブリッジに通知するユーザーネーム。一旦認証を通ると、ブリッジが覚えている
            accessPoint.setUsername(PHBridgeInternal.generateUniqueKey());
            phHueSDK.connect(accessPoint);
        }

上記の接続処理をキックすると、リスナーの以下のメソッドで情報を受け取る事ができます。

        @Override
        public void onAuthenticationRequired(PHAccessPoint phAccessPoint) {
            // 選択したブリッジと認証開始
            // 30秒以内にブリッジのボタンを押す
            phHueSDK.startPushlinkAuthentication(phAccessPoint);
        }

30秒以内にブリッジのボタンを押すとブリッジとの接続が完了し、リスナーの以下のメソッドで情報を受け取る事ができます。

        @Override
        public void onBridgeConnected(final PHBridge phBridge) {
            // 接続したブリッジをSDKにセット。ブリッジとの通信インターバルなどを設定
            // 接続したブリッジのIPアドレスや、ユーザネームをSharedPreferencesに保存しておき、以降のアプリ起動の際は自動的にブリッジ接続するようにしておくとよい。
            // phBridge:接続したブリッジ
            phHueSDK.setSelectedBridge(phBridge);
            phHueSDK.enableHeartbeat(phBridge, PHHueSDK.HB_INTERVAL);
            phHueSDK.getLastHeartbeat().put(phBridge.getResourceCache().getBridgeConfiguration() .getIpAddress(), System.currentTimeMillis());
        }

ライトを取得し、コントロールする

認証も終わって接続したブリッジから、ライトを取得していきます。各ライトのステータス情報を得る事で、今は点灯しているのか、どんな色で発光しているのかが分かります。

            // 接続ブリッジから取れる全ライト取得
            List<PHLight> allLights = phBridge.getResourceCache().getAllLights();

            // 特定のライトを選択
            PHLight currentLight = (PHLight) lightListAdapter.getItem(0);

            // 現在のライトの状態を確認
            PHLightState currentState = currentLight.getLastKnownLightState();

            // 現在のライトの点灯状態に合わせてスイッチをセット
            lightingSwitch.setChecked(currentState.isOn());

            // 現在のライトの発光色に合わせてRGBスライダーの値をセット
            float xy[] = new float[2];
            xy[0] = currentState.getX();
            xy[1] = currentState.getY();
            int color = PHUtilities.colorFromXY(xy, currentLight.getModelNumber());
            redSeekBar.setProgress(Color.red(color));
            greenSeekBar.setProgress(Color.green(color));
            blueSeekBar.setProgress(Color.blue(color));

逆に、新しい値に設定する場合は、以下のようなコードになります。

        // 点灯スイッチの操作で、ライトの点灯状態を変える
        lightingSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean isTurnON) {
                // ステートに点灯状態を設定
                PHLightState lightState = new PHLightState();
                lightState.setOn(isTurnON);
                // 接続中にブリッジに、対象となるライトと、新しいステートと、ライトの状態変化をブリッジ経由で受け取るリスナー(PHLightListener)を引数として、アップデート
                PHBridge bridge = phHueSDK.getSelectedBridge();
                bridge.updateLightState(currentLight, lightState, lightListener);
            }
        });
    // ライトの状態変化をブリッジ経由で受け取るリスナー
    PHLightListener lightListener = new PHLightListener() {

       @Override
        public void onSuccess() {
        }

        @Override
        public void onStateUpdate(Map<String, String> arg0, List<PHHueError> arg1) {
            // bridge.updateLightStateでアップデートした際
        }

        @Override
        public void onError(int arg0, String arg1) {}

        @Override
        public void onReceivingLightDetails(PHLight arg0) {}

        @Override
        public void onReceivingLights(List<PHBridgeResource> arg0) {}

        @Override
        public void onSearchComplete() {}
    };

以上のように、今回はブリッジ検索から接続、特定のライトの電源のOn・Offと、RGB指定で色をコントロールするところまでご紹介しました。
APIを見ていると、ライトをグループ化してのコントロールや、スケジュール設定、センサーとの連携など、より幅広い操作がスマホアプリや他の機器から行えるようなので、他のAPIもトライしてみたいと思います。