【解説】スマート電球HueのAPIをNodejsで呼び出してみた!プログラムからHueを操作する方法

2018年12月24日プログラミング

こんにちは!しずかなかずしです。

スマート電球という、スマホで操作できる電球があるのをご存知ですか?

そして、フィリップスのHueというスマート電球は、プログラミングで自由に操作できるって知っていましたか?

こういうのIoTというのです。

そうなんです。IoTってすごいのです。

本日は、HueのAPIをプログラムから操作する解説をしていきたいと思います。

Hueスマート電球とは

スマート電球というものがあります。普通の電球のように見えて、実は賢いのでスマート電球。

世は、IoT(Internet of Things: もののインターネット)が流行っています。モノとモノがインターネットを介してつながる世界です。

今までもパソコン同士がインターネットで繋がってたじゃん、という方もいるかも知れません。

でも、そういう意味ではないのです。電球とかコンセントとか、掃除機(!)とか単品機能のモノがインターネットアドレスを持ちます。そして、ネットワークを介してそれぞれの機能が有機的に影響し合いながら便利なことができる世の中です。

本日は、IoTの機器の中でもちょっとイカしたフィリップス(Philips)のHueという電球を取り上げます。

「フィリップスって、むかしソニーと一緒にCDを開発した、あのフィリップですか??」という方、イエスですが、想い出が古いですね。今や、フィリップスはIoT最先端企業。Hueは、「IoTといえば、Hue」と言えるほど代表的なデバイスなんです。

Hueは普通の電球に使うE26ソケットに差し込んで使うものです。

もちろんLED電球として光るのですが、単なる電球色ではなく、さまざまな色で発色する機能を持っています。その色はどのように変えるかと言うと、スマホのアプリから操作して変更できます。ネット経由で操作できるのです。

最初に使ったときはちょっと感動しますよ。

そのネットワークで動作するための電源をどこから取るかと言うと電球のE26ソケットです。なので、例えばご自宅のどこかの電球をこのHue電球に取り替えることは可能なのですが、照明用のスイッチは常時オンの状態にしておく必要があります。スイッチはオンですが、スマホから「消す」事ができるのです。

APIでプログラムから操作してみよう

フィリップスはAPIを開発者向けに公開しています。

Webベース(JSONベース)のAPIでHTTPプロトコルを使って操作できます。SDKもあるようですが、APIは、HTTP+JSONなので、JavascriptやPythonなどから簡単に操作できますね。

ちょっと実験をして見たいと思います。

広告

HueのAPIの仕組み

スマート電球Hueは、実は電球だけでは動作しません

下記のように、「ブリッジ」と呼ばれれる中間装置が必要です。Hueを購入するときには、電球だけでも購入できますが、まずは、ブリッジとセットになったパッケージを購入するのが良いででしょう。

Hueの接続図。ブリッジと電球はZigBeeという無線規格で通信。APIから操作するのは、ブリッジに対してHTTP+JSONで行う
Hueの接続図。ブリッジと電球はZigBeeという無線規格で通信。APIから操作するのは、ブリッジに対してHTTP+JSONで行う

操作するには、以下の2つの段階が必要になります。

  • ホームネットワークから「ブリッジ」を探す
  • 「ブリッジ」からHTTP+JSONでUsernameを得る
  • 「ブリッジ」経由でHTTP+JSONを呼び出し電球を操作する

それぞれ説明していきます。

ブリッジをホームネットワークから探すには?

まずは、ホームネットワークにあるブリッジのアドレスを得る必要があります。いわゆる、デバイス「ディスカバリ(discovery)」という手順です。

なんらかの方法で、操作対象となるブリッジのIPアドレスを見つけなければなりません。

フィリップスの開発者サイトには、ディスカバリについて詳しく書かれています。

フィリップスの開発者向けサイト: Hue Bridge Discovery

上記のページにあるやり方をざっと整理しますと、以下の方法のようにブリッジのIPアドレスがアドレスを見つけるのに複数の方法が用意されています。

  • UPnPで探す: SSDP(simple service discovery protocol)を使って、マルチキャストに応答するブリッジからIPアドレスを取得します。
  • N-UPnPで探す: ブリッジは、定期的にフィリップスのサーバに「生きてますよ」メッセージを投げるようです。その中にローカルのIPアドレスが含まれていて、https://discovery.meethue.com にアクセスすることでそれがJsonで得られます。
  • IP scanで探す: ホームネットワークのIPアドレスをスキャンしてブリッジを探します(時間がかかります)
  • 手動でIPアドレスを設定する: 使っている人自身がブリッジのIPアドレスを決めているような場合は、それを使います。
  • mDNSで探す: multicast DNSを使って取得するHueのホスト名からIPアドレスを割り出します。

製品化レベルのアプリケーションでは上記のフローを一通りトライしてみて、アドレスを解決するようにガイドラインにはフローチャートが書かれています。

ただ、今回は実験レベルなので、もっとも簡単に実装できそうなN-UPnPでの方法をご説明します。

N-UPnPでブリッジを探す

この方法では、ブラウザで、https://discovery.meethue.comにアクセスすると、以下のようにJSONでIDと、internalipaddressが返ってきます。複数ブリッジが存在するケースを想定して、リスト形式になっています。

[{"id":"XXXXXXX","internalipaddress":"10.0.0.11"}]

ちょっとしたJavaScriptのプログラムを書くと、こんな風にブリッジのアドレスがとれます。

var request = require('request');

request.get({ url: "https://discovery.meethue.com/" },
  function (error, response, body) {
    if (!error) {
      var myhue = JSON.parse(body);
      console.log('ipaddress: ' + myhue[0].internalipaddress);
    }
  }
);

このスクリプトをNode.Jsで実行すると、以下の様のにアドレスが取得できます。(上記スクリプトがtest_hue_discover.jsに記載されています)

kazushi$ nodejs test_hue_discovery.js 
ipaddress: 10.0.0.11

広告

開発者向けのツールを操る

IPアドレスがわかったら、Webブラウザで、そのアドレスのページを開くことが出来ます。(ここでは、上記のブリッジを探した結果として、ブリッジのローカルのIPアドレスが10.0.0.11だとわかった場合を想定てしいます)

http://10.0.0.11/debug/clip.html

これをブラウザで叩くとブリッジの開発者向けの画面が出てきます。

HTTP+JSONでUsernameを得る

さて、次に行うことは、上記の開発者向け画面を使って、Usernameというものを得ることです。ブリッジはさまざまなアプリケーションがブリッジにつながることを想定して、電球を操作するAPIのURLをユーザ毎に用意する仕組みになっているようです。

例えば、電球の情報を得るためには、
https://<bridge ip address>/api/<username>/lights

のように、APIのURLをにusernameを指定する必要があります。username(ユーザ名)とは名ばかりで、アルファベットと数字・記号の複雑なIDです。このIDはブリッジがクライアント(アプリ)毎に生成するので、それを一番最初に取得する必要があります。

実際の方法です。

まず、URLとして、以下を入力し、

/api/newdeveloper

画面上のPOSTボタンを押します。

HueのAPI呼び出し。Auth error

このような感じで、unauthorized userというエラーが表示されます。(Command Responseの枠に表示されるのがブリッジからのレスポンスです)

ここで、おもむろに、ブリッジ本体の「丸い」ボタン(画面上のボタンではなく、本物のボタンのことです)を押します。

次に、以下を入力し、

/api

画面上のPOSTボタンを押します。

HueのAPI呼び出し。usernameの取得

successとなり、"username"として、謎の文字列が返ってきます。以降、Hueの電球を操作するときに使うURLにはこのUsernameが必須になりますので、書き留めておいてください。

HTTP+JSONで電球を操作する

これでいよいよ、電球を操作する準備ができました。

まずは、ブリッジに紐付いている電球の情報を取得してみましょう。以下を入力して

/api/IEEFt3GjndPzYURRIVwDlz42NCiJIuHbd-UMTh07/lights

画面上のGETボタンを押します。/api/と/lightsの間の謎な文字列が、先程の工程でブリッジから取得したUsername文字列です。

以降、この文字列をURLに含めてAPIを呼び出すことになります。

Hue APIを呼び出す。電球の情報を取得

電球が光っていない("state"の"on"がfalseになっている)事がわかります。

Node.jsでHueのAPI呼んでみよう

では、この辺りから、Node.jsのプログラムでHue電球のAPIを呼んでみることにします。APIの仕様は、以下にあります。

フィリップス開発者向けサイト: Hue API – 1. Lights API (英語)

最もシンプルにNode.jsで、On/offするには以下のようなプログラムで可能です。

var request = require('request');

var command = {on: false};
command.on = true;
command.bri = 50;
command.hue = 1200;

request.put({
    url: "http://10.0.0.11/api/IEEFt3GjndPzYURRIVwDlz42NCiJIuHbd-UMTh07/lights/2/state",
    headers: {
        'Content-Type':'application/json'
    },
    body: JSON.stringify(command)
  },
  function (error, response, body) {
    console.log(body);
  }
);

上記のプログラムの解説を簡単にします。

'request’というのは、Node.jsでHTTPを使うモジュールです。request.put()としている部分(8行目)は、実際にHTTPのリクエストを出しています。リクエストを出す先の"url"で指定しているURL。ここが1番目のポイントになりますが、API仕様で以下のようなURLの説明を見てみてください。

http://<bridge IP address/api/<username>/lights/2/state

これは2番目の電球のstateを操作するURLをになります。2のところを1にすれば1番目の電球の操作するURLになります。簡単かつ、よくできていますね。

2番目のポイントは、commandと書いている変数です。

12行目にJSON.stringify()でJSON形式の文字列に変換して、HTTP requestのbodyに指定しています。JSON(JavaScript Object Notation)形式なので、JavaScriptで扱うには非常に便利。commandオブジェクトのフィールドにAPIが定義しているパラメータをそのまま使って操作することが出来ます。

上記のAPI説明ページに一覧があります。その中のいくつかを抜粋して以下で説明します。

名前 タイプ 意味
on bool trueで電球がつく、falseで電球が消える
bri uint8 1から254までの値で明るさを表現(明度)
hue uint16 0から65535の範囲で色相を表現
sat uint8 0から254の範囲で彩度を表現
xy floatの配列 [0.5,0.5]のように0から1の浮動小数点配列で、CIE色空間の座標を表現
colormode string 色の指定が、hsでHue,Satuationのモード。xyでXY座標系のモード指定

ですので、上のcommandの変数のフィールドを追加して、 例えばcommand.xy = [0.5, 0.5]のように記載すると、そのままサーバに値を送れる、という訳です。(JSONって便利!)

広告

Hue電球の色の指定しよう

色の指定はいくつか方法がありますが"xy"というフィールドで指定してみましょう。xyはCIE色空間の座標値、ということなので、Wikipediaにある色空間の2次元マップから、適当にxとyの値を取り出してみます。Wikipedia: CIE 1931 色空間

ざっくり、座標から、[0.7, 0.3]くらいが赤っぽい色だってことがわかります。ですので、例えば、command = {on: true, bri: 128, xy:[0.7, 0.3]} みたいに記載すると、赤で明るさが半分ぐらいで光ってくれます。

別のやり方として、RGBから変換する方法もフィリップスの開発者向けサイトにあります。

フィリップス開発者向けサイト: Color Conversion Formulas RGB to XY and back(英語)

ただ、値がHue電球の色域(gamut)からはみ出ちゃったときの処理が面倒そうです。Hueは電球だけではなく、いろんな製品があってそれらをサポートするように作ろうとすると、各製品がサポートしている色域を考慮してね、ということでした。

セキュリティ対策もばっちり

話は変わりますが、2020年2月にHue ブリッジに脆弱性が見つかったことがニュースになりました。

しかし、さすがは大手のフィリップ。あっという間に解決。ネットにつながるHueブリッジは、自動的に更新プログラムでアップデート。ユーザが知らぬ間に対策されているいう状況です。セキュリティ対策もばっちり、という記事も合わせてごらんください。

まとめ

  • スマート電球HueをNode.jsを使って、JavaScriptで操作してみました。電球のオフ・オンだけではなく、色もAPIで変えられます
  • 電球のAPIはWebベースで、HTTP+JSONなので、JavaScriptから簡単にパラメータを指定して呼び出すことが可能です
  • 準備として、ブリッジのIPアドレスの取得、続いて、APIを呼び出すためのUsernameという謎の文字列の取得が必要です
  • 電球の色の指定はちょっとめんどくさい。CIE色空間を使って見ましょう
  • IoT大手のフィリップスの商品だけあって、セキュリティ対策もばっちり