Bluetooth対応のHue(スマートライト)をRubyとBLEで制御してみた
去年くらいに、PhilipsからBluetooth LEに対応したHue (スマート電球) が発売されました。
HueはもともとZigbeeを使用しており、色や明るさの制御にはHueブリッジという装置をLANに接続する必要があったのですが、Bluetooth LEに対応したことでブリッジがなくともスマートフォンの専用アプリから操作することができるようになり、導入がしやすくなったということです。
Philips Hue フルカラー シングルランプ Bluetooth + Zigbee対応|E26 LED電球 スマートライト
これを、スマートフォンアプリを介さずにRaspberry Pi等から制御できないか試してみました。
結論から言えば操作は可能でした。
ただし、古いバージョンのbluezだとペアリングがうまくいかなかったり、スマートフォンアプリからファクトリーリセットを行わないとペアリングができなかったりするなど、ハマりどころが結構多く、やや面倒だなという感じです。
また、PhilipsはBLEでの制御インターフェースは正式サポートしているわけではないので今後アップデートで変わる可能性もあるかも、としているようで、素直にブリッジを導入してそのHue APIを使うのが無難ではあります。
やり方
先に、制御する側のPCやRaspberry Pi等に最新版のbluezを導入し、Bluetooth LEが使えるようにしておいてください。
5.50-1.2~deb10u1 というバージョンでは動作を確認できましたが、これより古い物では動作しませんでした。
sudo apt upgrade bluez
sudo systemctl start bluetooth
sudo hcitool lescan
を実行して、ずらずらとBLEデバイスが検出されればOKです。うまくいかない場合、
sudo hciconfig hci0 down sudo hciconfig hci0 up
とBluetoothアダプタをOFF/ONしてみるとうまく動作することがあります。
制御用のスクリプトはRuby gemにしてあるので、まずはgemをinstallします。(gemのコードはこちらです → https://github.com/NeoCat/ruby_hue_ble )
まず適当なディレクトリに Gemfile を作って以下のように記述します。
ble gemに依存していますが、これが割と古くて現在のbluezのインターフェースと変更があるので、パッチを当てたバージョンを指定する必要があります。(Merge Requet取り込んでくれないかなあ)
source 'https://rubygems.org' gem 'hue_ble' # ruby_ble-1.0.0 is not compatible with recent bluez DBus interface, so use patched version... gem 'ble', git: 'https://gitlab.com/NeoCat/ruby-ble.git'
そしてgemをインストールします。
gem install bundler # bundler が入っていない場合 bundle install --path vendor/bundle
bundle exec irb を起動して試すのが簡単です。
まずライブラリを require し、Hueデバイスをスキャンします。
スキャンの前に、以下のペアリングが可能な条件を満たすようにする必要があります。
- スマートフォンアプリ "Phillips Hue Bluetooth" を使って電球を登録したあと、「リセット」を実行する
- リセットから時間が経っている場合、電球の電源をOFF/ONし直す
- RasPi等のBLEアダプターと電球を十分に(<90cm)接近させる
ペアリングは一台のホストとしかできませんので、 "Hue Bluetooth"アプリとRasPi両方から制御するといったことはできません。
> require 'hue_ble' => true > HueBLE::scan_cli Scanning devices ... Found 1 Hue devices: C1:23:45:67:89:AB Hue Lamp Found a new Hue Lamp E2:34:56:78:9A:BC : Do you want to pair? (Y/n)> y
ペアリング済みのHue電球の一覧が(あれば)表示されます。
新規に見つかったHue電球がある場合、ペアリングするか聞いてきます。
なお、このアドレスはファクトリーリセットするとランダムに変わります。
ここで y を選択するとペアリングを試み、上記の条件が満たされていれば成功するはずです。
うまくいかない場合、
sudo hciconfig hci0 down sudo hciconfig hci0 up
で改善されることもあります。
(しかし systemctl restart bluetooth するとすでにペアリングしていたデバイスが消えてしまいます…。こうなるとまた電球をスマートフォンアプリからリセットしてやり直すしかありません。
リセット時は HueBLE::scan_cli(true) とすると、全デバイスがbluezから一旦削除されるので、これでやり直しができます。)
スキャンが成功すると、 HueBLE クラス内にHue電球の一覧が登録され、 HueBLE.hues でハッシュとして取得できるようになります。(keys = BLEアドレス、values = デバイス制御用のオブジェクト)
登録されたら、
HueBLE.hues.each_value { |hue| hue.on } HueBLE.hues.each_value { |hue| hue.off }
で全部まとめてON/OFFしたり、色(色温度またはフルカラー電球の場合は色)や明るさを取得したり制御したりできます。
> hue = HueBLE.hues['C1:23:45:67:89:AB'] > hue.brightness # 明るさ: 1 - 254 254 > hue.brightness = 200 > hue.color_temperature = 100 # 色温度: 1 (白) - 511 (黄) > hue.color = [16000, 1] # 色: x, y. それぞれ 1 - 65534 , 範囲外だとエラーとなる。この例は紫色
色は、CIE XYZのx, yを、1〜65534までのいずれかの値に変換した数値で指定するようです。色空間の範囲外だとエラーが返ってきます。
CIE 1931 色空間 - Wikipedia
party!
# 全電球をカラフルにランダム変化させる def party! 30.times do HueBLE.hues.each_value do |hue| hue.brightness = rand(253) + 1 hue.color_temperature = rand(510) + 1 10.times do hue.color = [rand(65533) + 1, rand(65533) + 1] break rescue BLE::Characteristic::NotFound break rescue next end end sleep 1 end end party!
部屋のHue電球をBLEでランダムに制御してカラフルに光らせてみた。ド派手w pic.twitter.com/INzisyq6qD
— NeoCat (@NeoCat) 2020年8月15日
とかやって楽しみましょう。