
Phillips Hue のAPIで広がるスマートホーム・プログラミング APIの仕組みをざっくり解説
本ブログ「テック大家さん」では、スマートホームデバイスとしてSwitchBotを推し活してきました。その理由は Web APIはBluetoothなどの仕様がオープンだから。今回は、オープンなAPIを持つIoT機器としてPhillips Hue電球を取り上げます。
SwitchBot同様、Hueの電球はAPIをつかってプログラマーが自由に操作できるのが特徴です。スマートホームを実現するIoTデバイスとして外せない存在。そんなHueのAPIについて「いろは」を解説していきます。
今回はその第1回目。まずはAPIがどんな仕組みでできているか、から解説していきます。
Hue APIを操るには”Hue ブリッジ"が必要
Hue APIは基本的にはWebベースのAPIになっています。つまり、HTTP (またはHTTPS)プロトコルをベースにしています。HTTP上をJSONのペイロードを流すという、よくあるWeb APIの形式です。
しかし、プログラマがHue電球を操作するためのHue APIを呼び出すためには、実は電球だけ持ってても駄目なのです。”Hue ブリッジ”と呼ばれる別の製品が必要になります。

というのも、Hue電球自体はZigBeeという近距離無線の仕組みを使っています。したがって、電球単体ではIPアドレスを元にしたHTTP通信を行えません。
この仕組みは、公式サイトにも記載されています。
“Hue ブリッジ"がHTTPベースの呼び出しを仲介、つまり橋渡し(ブリッジ)をしてZigBeeの通信で電球を操作する、という仕組みになっているわけです。だからHue ブリッジと呼ぶのですね。わかりやすいです。
当然ながら、Hue ブリッジにはIPアドレスが必要なので、購入したらホームネットワークなど何かしらのネットワークに接続する必要があります。通常は、ご家庭のホームネットワークにつなげるでしょう。つなげると、ルーターからDHCPで自動的にIPアドレスが割り当てられる、というのが一般的な動作。難しいところはありません。
というわけで、APIを使いたければ、何にしろ"Hue ブリッジ“と"Hue電球“の両方を用意しましょう。
電球とブリッジが一緒になった「スターターセット」というのも売られているので、初めて購入するならこちらがおすすめです。
APIのエンドポイントは2箇所
さて、一言でHue APIといっても、実は2通りの仕組みがあります。
- ローカルネットワークから呼び出す仕組み
- リモートネットワークから呼び出す仕組み
ひとつづつ見ていきましょう。
一つ目は、ローカルネットワーク内部で直接Hue ブリッジのAPIを呼び出すような仕組みです。
この方法では、呼び出すプログラム(スマホのプログラムでも、ESP32などの組み込みプログラムでも)も同じローカルネットワークに接続されていることを前提としています。後述する方法で同じネットワークにつながるHue ブリッジのIPアドレスを見つけ出し、Hue ブリッジの持つWebサーバー機能を直接呼び出すことになります。
2つ目の方法は、リモートネットワークからクラウドのAPIを呼び出すケースです。例えば、外出先から家の電球を消したい、とか、民泊などで予約表に基づいて電球を点けたい、というユースケースが考えられます。このようなケースでは、APIを使用するプログラムは、Hueブリッジのあるネットワークとは異なるアドレス体系のネットワークに存在することになります。このようなユースケースにおいては1つ目の方法は、NAT(関連記事を参照ください)が障壁になり、機能しません。そこで、リモートネットワークからもAPIを利用できるようにPhillips Hueのクラウドサービスがあります。
クラウドを経由する方法は、ローカルネットワークからでも利用可能ではあります。ただ、一般にクラウド経由になると遅延が発生します。ですので、ローカルネットワークからしか使わないことがわかっているようなユースケースだと1つ目の方法(直接 Hue ブリッジを叩く)がベスト。ユースケースによって使い分ける必要があります。
Hue APIの仕組み、全体像を図示すると以下のようになります。

これら2つの方法は、それぞれ技術的に注意すべきポイントがあります。以降では、それを説明します。
ローカルのHue ブリッジを「発見」する
1つ目の方法、ローカルネットワークから呼び出す場合のポイントから見ていきましょう。
先ほど、Hue ブリッジを買ってきてホームネットワークにつなぐと自動的にルーターがアドレスを割り当てると言いました。
一方、プログラムがHue ブリッジのAPIを直接コールするためには、ルーターがHue ブリッジに割り当てた動的なIPアドレスを知る必要があります。このIPアドレスを知るための工程を「ディスカバリ(発見)」といいます。ディスカバリについては、開発者向け情報として公式サイトにて解説されています。
「ディスカバリ」プロセスのフローチャート内部では、具体的にIPアドレスを得るための3つの方法が提示されています。
- mDNSによる探索
- https://discovery.meethue.comの参照
- (なんとかして)別の手段で見つけたものを使用する
前者2つは自動検出で、最後のは手動による方法です。一つづつ見ていきましょう。
mDNSによる探索
マルチキャストDNS(mDNS)という一般的な仕組みがあります。機器に名前をつける仕組みのひとつです。例えば、ブラウザのアドレスバーにはIPアドレスではなくGoogle.comやAmazon.comのような名前(DNS名)を指定するでしょう。これを行うのがDNS(Domain Name System)という仕組みです。mDNSが、一般的なDNSと大きく異なるのは、DNSサーバーのような中央集権的な機能が不要ということです。
機器自身が、ネットワーク内で通用する名前を自分で宣言するような仕組みなのです。
mDNSの仕様に則って、"Hue ブリッジ"が起動してIPアドレスを割り当てられると、自ら「名乗り」ます。なので、プログラムはmDNSの仕組みを使ってHue ブリッジを探せばよいわけです。
ちょっと実際にやってみました。
以下のプログラムはNodeJSのプログラムです。(実行するには、あらかじめプログラムのあるフォルダでnpm install mdnsとしてmdnsパッケージのインストールが必要です)
const mdns = require("mdns");
const browser = mdns.createBrowser(mdns.tcp("_hue"));
const getHueConfig = (ipV4addr) => {
const url = `http://${ipV4addr}/api/0/config`;
return fetch(url)
.then((response) => response.json()).then((json) => {
return json;
});
};
const isIpv4 = (ip) => {
return ip.match(/^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/);
};
browser.on("serviceUp", function(service) {
if (service.addresses) {
service.addresses.forEach((ip) => {
if (isIpv4(ip)) {
console.log("IP: ", ip);
getHueConfig(ip);
}
});
}
});
browser.start();
2行目にあるように、_hue._tcpというサービスをもった機器を見つける、といった流れのプログラムになっています。_hue._tcpがあればHueブリッジだとわかるので、そこから機器に割り当てられたIPアドレスを探そう、という作戦です。
discovery.meethue.comの参照
もし、mDNSによる探索に失敗したら、次の方法は「discovery.meethue.com」というエンドポイントにアクセスする、というものです。
実は、Hue ブリッジは自身に割り当てられたローカルネットワークのIPアドレスを、定期的にクラウドに投げてしまっています。そのようにして登録されたIPアドレスを返してくれるのが、「discovery.meethue.com」です。
Hueが接続されたローカルエリアネットワークからこのエンドポイントを呼び出すと以下のようなJSONが返ってきます。この中に書かれている internalipaddressを使おう、という作戦です。
[
{"id":"AABBCCDD","internalipaddress":"10.0.0.12","port":443}
]
こちらもちょっとNodeJSでプログラムを書いてみました。単に、fetch()で「discovery.meethue.com」を呼んでいるだけですけど…
const getHueIps = async () => {
const response = await fetch('https://discovery.meethue.com');
const json = await response.json();
let ips = [];
json.forEach((bridge) => {
console.log("bridge: ", bridge);
ips.push(bridge.internalipaddress);
});
return ips;
};
getHueIps().then((ips) => {
ips.forEach((ip) => {
console.log("ip: ", ip);
});
}
);
別の手段で見つけたものを使用する
最後の手段は、「マニュアル」です。自動ではありません。
例えば、ルーターの管理画面でDHCPの排出IPアドレスをリスト化してくれるようなものがあります。そのリスト上でHueブリッジが登録された時に排出された一番最後のIPアドレスが、Hueブリッジのアドレスかも知れません。
そのような探索はもはやプログラミングの対象外です。ネットワーク管理者か誰かがなんとかしてHueブリッジのIPアドレスを見つける必要があるのです。
もし、あなたが書こうとするプログラムが最終的に上記2つの方法(mDNSとdiscovery.meethue.com)でIPアドレスを見つけられなかったとしたら、ユーザーにIPアドレス入力の手段を用意してね、と開発者ガイドラインは言っています。
リモートAPIのoAuthによる認証
さて、これまではローカルネットワーク内部でHueブリッジを呼び出すためのポイントを見てきました。ここからは、リモートAPIを呼び出す、つまり、クラウドAPIを使用する方法のキモを述べます。
それは、APIを使う場合のユーザー認証です。
プログラムがリモートから家の電球を操作する場合、誰か知らない人の家のHue電球がついてしまうようなことがあってはなりません。そこで誰のHueを操作しようとしているのか、というユーザの認証が必要になるのです。
この手順では、Hueのクラウドのアカウントページで設定(下図)があります。
ここで、これから呼び出そうとするプログラムを登録する必要があります。プログラム毎に「トークン」と「シークレット」を発行してもらい、API呼び出しの際にそれを使っていくわけです。
これらの情報は、所謂「oAuth」と呼ばれる認証シーケンスに則って使われるのですが、この記事では長くなるので別途解説したいです。お楽しみに!

ディスカッション
コメント一覧
まだ、コメントがありません