お知らせ

(本サイトは、アフィリエイト広告を利用しています)

Phillips Hue のAPIで広がるスマートホーム・プログラミング APIの仕組みをざっくり解説

IoT・スマートホーム

本ブログ「テック大家さん」では、スマートホームデバイスとして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 ブリッジ”と呼ばれる別の製品が必要になります。

画像はwww.philips-hue.comより転載

というのも、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アドレスを知るための工程を「ディスカバリ(発見)」といいます。ディスカバリについては、開発者向け情報として公式サイトにて解説されています。

画像は「developers.meethue.com」より転載

「ディスカバリ」プロセスのフローチャート内部では、具体的にIPアドレスを得るための3つの方法が提示されています。

  1. mDNSによる探索
  2. https://discovery.meethue.comの参照
  3. (なんとかして)別の手段で見つけたものを使用する

前者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」と呼ばれる認証シーケンスに則って使われるのですが、この記事では長くなるので別途解説したいです。お楽しみに!

メールマガジンにて本サイト(Tech Landlordテック大家さん)の更新情報をご連絡します。
本サイトのプライバシーポリシーをご確認の上、是非メールアドレスをご登録下さい!


プロフィール

テック大家さん
ソフトエンジニア兼不動産オーナー。
某超有名日本メーカーにおいてソフトウエア開発畑を30年近く勤務。
かつてはWindowsのアプリ開発や、組み込み機器のソフト開発を行う。プロジェクトマネジメント・オフショア開発・要件管理などの経験あり。現在は、個人開発で、JavaScript/TypeScript/React/Express、PHP/Laravel、Firebase、Google cloud、Arduino(C++)などでプログラミングを楽しむ。
サラリーマンの傍ら不動産経営を始め、現在、1棟モノの賃貸4物件を東京・神奈川に所有。夫婦でおよそ20年の賃貸経営の実績。
最近の物件では、入居者向けフリーWiFiなど、テック系の設備はDIYで自ら構築。
海外MBA取得。