暫定 - 技術メモなど

今のところはRaspberry Piを使ったIoTが話題の中心です

Amazon Dash ButtonでHueをON/OFF

#2017年11月11日(土)に一部更新しました。

f:id:yrn7:20170903205719j:plain
Philips Hueというスマートフォンからコントロールできる電球シリーズがあるのですが、なかなかにいいお値段で、最初はあまり手を伸ばすつもりもありませんでした。
それが、価格もお手頃なホワイトグラデーションスターターセットの存在を知り、一気に気が変わりました。使い始めてみると便利で、現在はホワイトグラデーションの電球を2つ買い足して計4つで運用しています。

Philips Hue(ヒュー) ホワイトグラデーション スターターセット【Works with Alexa認定製品】

Philips Hue(ヒュー) ホワイトグラデーション スターターセット【Works with Alexa認定製品】

ホワイトグラデーションスターターセットにはDimmerスイッチという物理スイッチが一つついてくるのですが、うちの場合はこのスイッチを玄関にマグネットで貼っているので、室内ではiPhoneのホームアプリかSiri、Hueの公式アプリでの操作に限られます。寝る前にちょっと電気をつけたいときなど、やはり物理ボタンがもう一つくらいあった方がいいな、と思うのですが、Dimmerスイッチを追加するのも割高だなあ、という気持ちになり、何かいい方法がないか考えていたところ、なんとスイッチを自作されている方がいることを知りました。
Hue Tapスイッチが高いのでESP-WROOM-02で物理スイッチを自作する 前編

※現在はDimmerスイッチも価格がこなれて来ています。

これにはとても興味を惹かれたのですが、むき出しにしておくこともできないし、カバーどうするんだ...などと考え出すと重い腰がなかなか上がらないものです。
ふと、以前こちらを参考にAmazon Dash Buttonを押すとRaspberry Piが再起動するしくみを組み込んだことを思い出し、この機能を拡張すればHueのスイッチにできるんじゃない、と思い至りました。
tane-maki.net

かくして、この記事はAmazon Dash Buttonをアマゾンが望まない形で使用してHueのスイッチに仕立てたときの記録となります。
なお、Hueの基本的な設定はできており、iPhoneのホームアプリ、あるいはHueの公式アプリで操作できるようになっていることが前提です。また、Raspberry PiMacなど、シェルスクリプトが稼働して常時起動できるマシンがあることも前提としています。


1.Hueブリッジの準備

参考資料は「Philips hueをAPIで制御してみる」です。
Hueシリーズは、電球自体がWiFiを介してスマートフォンと直接やりとりをしているわけではなく、Hueブリッジという親玉にあたる部分が電球とスマートフォンの仲立ちをします。
まずはこのブリッジ上でAmazon Dash Buttonが使用するユーザーを作成します。
そのためにはHueブリッジのIPアドレスを知る必要がありますが、方法はいくつかあります。

  • 自宅ルータにログインしてIPアドレスを調べる
  • パソコンから arp -a コマンドを入力してあたりをつける
  • Hueの公式アプリを使用して調べる(設定 > Hue ブリッジ > i > ネットワーク まで進めてDHCPを一時的にオフするとIPアドレスが表示される)

IPアドレスがわかったら、パソコンもしくはスマートフォンのブラウザからHueブリッジにアクセスします。

http://(HueブリッジのIPアドレス)/debug/clip.html

(例では172.16.1.2)
f:id:yrn7:20170903144101p:plain
参考資料に従い、下記のように入力します。

URL: /api
Message Body: {"devicetype":"dash_hue_app"}

※上記 dash_hue_app の部分は何でもよいようです。
この状態でHueブリッジの上にある大きなボタンを押し、[POST]をクリックします。
するとusernameが返ってきます。

[{"success":{"username":"xxxx〜xxxx"}}]

上記の xxxx〜xxxx の部分を使用することになります。

ここまでできたら、Amazon Dash ButtonでON/OFFしたいHueのIDを確認します。
ホームアプリやSiriで対象のHueだけを消灯しておきましょう。
先ほどの画面に下記のように入力します。

URL: /api/xxxx〜xxxx/lights/
Message Body: なし

これで[GET]をクリックするとHueの情報が出てきます。
f:id:yrn7:20170903150346p:plain
この中で

"on": false,

となっているIDを探します。
※写真の中では 3 が対象のIDです。

念のため、このIDで間違いないか確認をします。
先ほどの画面で下記のように入力します。

URL: /api/xxxx〜xxxx/lights/(先ほどのID)/state
Message Body: {"on": true}

これで[PUT]をクリックし、対象のHueが点灯すればOKです。

2.Amazon Dash Buttonの準備

Hueブリッジの準備が終わったら、次はAmazon Dash Buttonの準備を行います。
こちらのサイトの「ボタンセットアップ」を参考に、スマホのアマゾン公式アプリを使ってAmazon Dash Buttonを単なるIoTボタンとして使用できるようにします。
http://qiita.com/jsoizo/items/3b8bba4160f41aef20f4qiita.com
Amazon Dash Buttonが自宅のWiFiに接続できるようになったら、Amazon Dash ButtonMACアドレスを調べます。
方法はいくつかありますが、今回はRaspberry PiもしくはMactcpdump を使用します。

$ sudo tcpdump -i wlan0 | grep BOOTP/DHCP

※上記はRaspberry Piを使用した場合ですが、Macの場合は wlan0 の部分が en0 などになります。
ifconfig等で確認ください。
この状態でWiFiに接続したAmazon Dash Buttonを押します。

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on wlan0, link-type EN10MB (Ethernet), capture size 262144 bytes
15:20:39.964358 IP 0.0.0.0.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from fc:a6:xx:xx:xx:yy (oui Unknown), length 261

わかりづらいですが、fc:a6〜yy がMACアドレスになります。
ここまでできれば必要な情報は揃いました。

3.シェルスクリプトの作成

参考資料は「Amazon Dash Button ハックで、コーヒー豆を(人力で)取り寄せる」です。
前置きなしに行きます。Raspberry Piにログインし、下記のとおり、シェルスクリプトを /usr/local/bin/ 配下に作成します。

$ sudo vim /usr/local/bin/dash_button_script.sh

#!/bin/bash

sudo tcpdump udp -nl | while read line; do

  if [[ `echo ${line} | grep "(Amazon Dash ButtonのMACアドレス)"` ]]; then

#hueのブリッジに対象ライトのステータスを取得しに行く
    statesearch=`curl -XGET 'http://(HueブリッジのIPアドレス)/api/(1.で作成したHueのusername)/lights/(1.で確認したHueのID。通常数字一桁)'`

#文字列比較用の変数
    state=\"on\":true\,\"bri\"

#取得したhueのステータスがtrueだった場合
    if [[ ${statesearch:10:15} = ${state} ]]; then

#hueのブリッジに対象ライトをOFFさせに行く
      curl -XPUT 'http://(HueブリッジのIPアドレス)/api/(1.で作成したHueのusername)/lights/(1.で確認したHueのID。通常数字一桁)/state' -d '
      {"on": false}'
    else

#ステータスがtrue以外の場合はONする
      curl -XPUT 'http://(HueブリッジのIPアドレス)/api/(1.で作成したHueのusername)/lights/(1.で確認したHueのID。通常数字一桁)/state' -d '
      {"on": true}'
    fi
  else
    echo "dash_button_script is running."
  fi
done

一旦上記のスクリプトを作成したら、スクリプトのアクセス権を変更します。

$ chmod 755 /usr/local/bin/dash_button_script.sh

起動してテストをします。

$ sudo /usr/local/bin/dash_button_script.sh

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on wlan0, link-type EN10MB (Ethernet), capture size 262144 bytes

上記のような画面が出て止まっていれば、正しく起動しています。
この状態でAmazon Dash Buttonを押して、HueがON/OFFできればOKです。
ON/OFFする間隔は20秒ほど空けないとうまくいきません。
目安は、Amazon Dash ButtonのLEDの点滅が終わってから10秒ほどです。

これで動作すれば、あとはhomebridgeと同様、自動起動の設定をすればOKです。
確認が取れれば、一旦スクリプトはCtrl + Cで終了させておきます。

4.シェルスクリプト自動起動設定

下記のとおり、自動起動用のファイルを作成します。

$ sudo vim /etc/systemd/system/dash_button_script.service

Description=dash_button_script.service
#サービス名を記述
After=syslog.target

[Service]
Type=simple
WorkingDirectory=/usr/local/bin/
#ディレクトリ名
ExecStart=/usr/local/bin/dash_button_script.sh
#スクリプトのパス
Restart=always
TimeoutStopSec=5
StandardOutput=null
RestartSec=10

[Install]
WantedBy = multi-user.target

ファイルが作成できたら、homebridgeのときと同様に下記コマンドを実行してsystemdに登録し、Raspberry Pi起動時にスクリプト自動起動するようにします。

$ sudo systemctl daemon-reload
$ sudo systemctl enable dash_button_script
$ sudo systemctl start dash_button_script

Raspberry Piを再起動します。

$ sudo shutdown -r now

再起動後、下記コマンドでスクリプトが起動しているか確認します。

$ sudo systemctl status dash_button_script

● dash_button_script.service
   Loaded: loaded (/etc/systemd/system/dash_button_script.service; enabled)
   Active: active (running) since Sun 2017-09-03 20:47:26 JST; 6min ago
 Main PID: 2447 (dash_button_scr)
   CGroup: /system.slice/dash_button_script.service
           ├─2447 /bin/bash /usr/local/bin/dash_button_script.sh
           ├─2450 sudo tcpdump udp -nl
           ├─2451 /bin/bash /usr/local/bin/dash_button_script.sh
           └─2456 tcpdump udp -nl

二行目の最後が enable となっていて、三行目が active (running) となっていればOKです。
Amazon Dash Buttonを押してHueがON/OFFされるか確認してください。
これで問題なければ設定は完了です。
お疲れ様でした。

#2017年11月11日(土)に下記追加

Amazon Dash Buttonを運用していると、正しく動作するときとしないときがあり、systemctl status を確認しても、とくに落ちているということもなさそうです。
仕方がないので、crontabで15分に一度 systemctl restartするようにしましたが、とりあえず今は問題なく動作しています。