homebridgeでsiriから家電コントロール

#はじめに

siriから家電制御がしたくなったので、raspberry piでhomebridgeを動かし、かつIRKitを組み合わせて、テレビのon/offをsiriからできるようにしてみた。
irkitを利用すれば、エアコンや部屋の電気もon/off可能。
機器を追加したら記事を更新する予定。

今回は、irkitでテレビのon/off、PS4のon/off、netatmoから測定値の取得、philips hueのon/offをできるようにした。

#仕組みと登場人物

##HomeKit
siriはAppleが提唱する[HomeKit](http://www.apple.com/jp/ios/homekit/)と連携して、機器のコントロールができるようになっています。
iPhoneにHomeKit対応アプリケーションを入れることにより、siriから制御が可能になります。
「**テレビ**を**オン**にして」「**ブルーム**を**オフ**にして」など、「何を」「どうする」という言葉を解釈して、命令を実行してくれるようになります。

##homebridge
[homebridge](https://www.npmjs.com/search?q=homebridge)はそんなHomeKitと同じ動きをするnode.jsのライブラリ。
pluginによって、豊富なデバイスと連携が可能となっています。

##IRKit

![31MfCSF9ujL.jpg](https://qiita-image-store.s3.amazonaws.com/0/95484/7ee58b66-ee9e-6510-8e40-fdb9a14c2e5f.jpeg)

[IRKit](http://www.amazon.co.jp/maaash-jp-IRKit-001-IRKit-iPhone-iPad%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E5%A4%96%E5%87%BA%E5%85%88%E3%81%8B%E3%82%89%E3%82%A8%E3%82%A2%E3%82%B3%E3%83%B3%E7%AD%89%E3%81%AE%E5%AE%B6%E9%9B%BB%E3%82%92%E6%93%8D%E4%BD%9C%E3%81%A7%E3%81%8D%E3%82%8B%E5%AD%A6%E7%BF%92%E3%83%AA%E3%83%A2%E3%82%B3%E3%83%B3/dp/B00H91KK26/ref=sr_1_1?s=electronics&ie=UTF8&qid=1454251994&sr=1-1&keywords=irkit)は学習リモコンです。
webapi経由で、学習したリモコン信号を発信することができるスグレモノ。
curlコマンドで、受信したリモコン信号を取得することもできるため、homebridgeと連携するために、この機能を活用して任意の信号を取得して設定ファイルに書き込んでいます。

#手順
参考にしたのは[Siriで部屋中の家電を操作できるようにして未来のお部屋を作ってみた](http://senyoltw.hatenablog.jp/entry/2015/12/07/052951)と[Raspberry Pi + HomeKit + IRKit = Siriで家電を音声操作できるようにする](https://datahotel.io/archives/725)です。
丁寧に解説されているので、この２つを見ながら進めれば問題なく動くはず。

念のため、標準的な作業フローを示しておきます。

1.IRKitのセットアップ
2.raspberry piにhomebridgeを導入
3.homebridgeのpluginを導入
4.HomeKit対応アプリ（Insteon+）を導入
5.Insteon+の設定（siriが認識できるコマンド）
6.siriから試してみる

以降は若干細かい点について、上記２サイトに記載されていない点を追記。

#追加情報集

##sudo不要、foreverを使う
[過去記事](http://qiita.com/FePlus/items/a01e6059b9942f1f86b2)でnvmを導入済みの環境を利用しているため、sudoせずにhomebridgeを導入した。
公式でもsudo導入が記載されているが不要だった。（普通に動く・・・動いてる・・・はず）

またプロセス常駐もforeverで動いたので、config.jsonを設定し終わったら、foreverを使う方が良いと思う。
（追記：記事の最後に起動スクリプトのやり方を書きましたので参考にしてください。）

##config.jsonについて
homebridgeの設定は/home/pi/.homebridge/config.jsonなどに配置される。
uernameにはraspberry piのMacアドレスを入れておくと良さそう。特に変更をしなくてもいいが、気になる人は設定しておこう。
PINに関しても任意のコードを設定しておくといい。（私は面倒だったので、サンプルそのまま）

今回は以下のプラグインを導入した。(npm install -gで入れようね）
IFTTTはMakerチャンネルと連携するので、今後の発展としてお楽しみ領域。

homebridge-philipshue
homebridge-netatmo
homebridge-cmd
homebridge-irkit
homebridge-ifttt

```json:config.json
{
    "bridge": {
		"name": "Homebridge",
		"username": "<MAC_ADDRESS>",
		"port": 51826,
		"pin": "031-45-154"
    },
    
    "description": "<DESCRIPTION>",

    "platforms": [
        {
			"platform" : "PhilipsHue",
			"name" : "Philips Hue",
			"ip_address": "<BRIDGE_IP>",
			"username": "<USERNAME>"
        },
        
		{
			"platform": "netatmo",
			"name": "netatmo weather",
			"ttl": 5,
			"auth": {
				"client_id": "<CLIENT_ID>",
				"client_secret": "<CLIENT_SECRET>",
				"username": "<USERNAME>",
				"password": "<PASSWORD>"
           }
       }
    ],
    
    "accessories": [
       {
			"accessory": "CMD",
			"name": "PlayStation4",
			"on_cmd": "ps4-waker",
			"off_cmd": "ps4-waker standby"
       },
       
		{
			"accessory": "IRKit",
			"name": "Regza",
			"irkit_url": "http://<IRKIT_ADDRESS>/messages",
			"on_form": {"format":"raw","freq":38,"data":[<COMMAND>]},
			"off_form": {"format":"raw","freq":38,"data":[<COMMAND>]}
		}
   ]
}
```

##Insteon+の設定

siriはInsteon+の「SIRI CONTROL」に記載のキーワードを聞き取り、機器を制御する。
そのため、デフォルトの設定から、わかりやすいキーワードにしておいた方がよい。

###IRKitのプラグイン(homebridge-irkit)でテレビ制御
siriが反応するキーワードを「**テレビ**」にする
<img width="375" alt="IMG_4156.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/95484/6bb48cb9-73da-882b-d003-ab61c7c85b25.png">

「**テレビ**をオン」をしゃべると、反応してくれる。
<img width="375" alt="IMG_4152.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/95484/8c124e35-3bbf-df78-0c7e-943af4fd9359.png">

同じく「**テレビ**をオフ」と言っても反応してくれる。
<img width="375" alt="IMG_4151.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/95484/a7443b14-4724-1e3b-b66d-d8250b373417.png">

###Philips hueのプラグイン(homebridge-philipshue)でライト（ブルーム）制御
siriが反応するキーワードを「**ブルーム**」にする
<img width="375" alt="IMG_4157.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/95484/344f2053-8267-4a32-e23d-ab8054c1a13d.png">

「**ブルーム**をオン」をしゃべると、反応してくれる。
<img width="375" alt="IMG_4154.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/95484/c6877f35-39e5-fb27-0c34-93956faa860d.png">

同じく「**ブルーム**をオフ」と言っても反応してくれる。
<img width="375" alt="IMG_4153.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/95484/f78bab61-e718-7ab5-6018-641e76a12fd5.png">

##ps4-wakerの設定(2016/03/06追加)
ちょいと手順と準備が必要。
[PlayStation App](https://play.google.com/store/apps/details?id=com.scee.psxandroid&hl=ja)を利用するため、アプリが動作可能な対応デバイスを持っていないとできない。

原理は、PlayStation Appを利用して、本物のPS4に接続させるのではなく、ps4-wakerを起動したRaspberry Piにつなぎ、PS4と通信するためのクレデンシャル情報を取得してから、本物のPS4とつなぐ。

以下手順。
1.Rapsberry Piからps4-waker実行
2.Android端末からPlayStation Appを実行
3.ps4-wakerに接続してクレデンシャルを取得(以降の通信は、ここで取得したクレデンシャルを使って通信する）
4.本物のPS4で「PlayStation App接続設定」から「機器登録」を選択してPINコードを表示する
5.「ps4-waker --pin xxxxxxxx」と入力してPS4で表示したPINコードを入力する

クレデンシャル情報を取得した所（手順3に相当)

```bash
root@raspberrypi2:/home/pi/.nvm/versions/node/v5.1.1/bin# ps4-waker
No credentials; Use Playstation App and try to connect to PS4-Waker
Got credentials! { 'client-type': 'a',
  'auth-type': 'C',
  'user-credential': '<CREDENTIAL>' }
Unable to connect to PS4 at xxx.xxx.xxx.xxx { [Error: connect ECONNREFUSED xxx.xxx.xxx.xxx:997]
  code: 'ECONNREFUSED',
  errno: 'ECONNREFUSED',
  syscall: 'connect',
  address: 'xxx.xxx.xxx.xxx',
  port: 997 }
```

PINコードを入力して「本物のPS4」に機器登録した所（手順5に相当)

```shell-session
root@raspberrypi2:/home/pi/.nvm/versions/node/v5.1.1/bin# ps4-waker --pin XXXXXXXX
Logged into device! Future uses should succeed
```

##起動時設定(2016/04/24追加)
最初はforeverでデーモン化していたが、/etc/init.dに入れることにした。
nvm環境だったので、結構面倒でした。
nvm環境でない場合には、大変じゃないと思うので、私同様にnvm環境で自動起動をやりたい方は参考にしてください。

###起動スクリプトの準備
[Running HomeBridge on a Raspberry Pi](https://github.com/nfarina/homebridge/wiki/Running-HomeBridge-on-a-Raspberry-Pi#running-homebridge-on-bootup-initd)を参考にしながらスクリプトを用意しましょう。

一点注意事項。
上記では`sudo update-rc.d homebridge defaults`を使えと書いてありますが、Debian系の場合insservを使うことが推奨されているので、以下のようになります。

```bash
pi@raspberrypi2 ~ $ sudo insserv -d homebridge
```

`-d`で有効、`-r`で無効なので覚えておくと良いと思います。
[こちら](http://at-j.co.jp/blog/?tag=insserv)が参考になりました。

先ほど書いたように、nvm環境だったため起動スクリプトが結構面倒でした。
なので動いた起動スクリプトをそのままので載せておきます。

ポイントは以下です。
1.Required-Startを`$all`にした。（起動時の最後に実行）
2.nvm環境の設定`nvm.sh`の実行。
3.nodeパス`/home/pi/.nvm/versions/node/v5.1.1/bin/node`の明示。（個人の環境に合わせてください）
4.homebridgeパス`/home/pi/.nvm/versions/node/v5.1.1/lib/node_modules/homebridge/bin/homebridge`の明示。（個人の環境に合わせてください）

```bash:/etc/init.d/homebridge
#!/bin/sh
### BEGIN INIT INFO
# Provides: homebridge
# Required-Start:    $all
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start daemon at boot time
# Description:       Enable service provided by daemon.
### END INIT INFO

dir="/home/pi"
cmd="DEBUG=* /home/pi/.nvm/versions/node/v5.1.1/bin/node /home/pi/.nvm/versions/node/v5.1.1/lib/node_modules/homebridge/bin/homebridge"
user="pi"

name=`basename $0`
pid_file="/var/run/$name.pid"
stdout_log="/var/log/$name.log"
stderr_log="/var/log/$name.err"

# load nvm
export NVM_DIR="$dir/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"  # This loads nvm

get_pid() {
    cat "$pid_file"
}

is_running() {
    [ -f "$pid_file" ] && ps `get_pid` > /dev/null 2>&1
}

case "$1" in
    start)
    if is_running; then
        echo "Already started"
    else
        echo "Starting $name"
        cd "$dir"
        if [ -z "$user" ]; then
            sudo $cmd >> "$stdout_log" 2>> "$stderr_log" &
        else
            sudo -u "$user" $cmd >> "$stdout_log" 2>> "$stderr_log" &
        fi
        echo $! > "$pid_file"
        if ! is_running; then
            echo "Unable to start, see $stdout_log and $stderr_log"
            exit 1
        fi
    fi
    ;;
    stop)
    if is_running; then
        echo -n "Stopping $name.."
        kill `get_pid`
        for i in {1..10}
        do
            if ! is_running; then
                break
            fi

            echo -n "."
            sleep 1
        done
        echo

        if is_running; then
            echo "Not stopped; may still be shutting down or shutdown may have failed"
            exit 1
        else
            echo "Stopped"
            if [ -f "$pid_file" ]; then
                rm "$pid_file"
            fi
        fi
    else
        echo "Not running"
    fi
    ;;
    restart)
    $0 stop
    if is_running; then
        echo "Unable to stop, will not attempt to start"
        exit 1
    fi
    $0 start
    ;;
    status)
    if is_running; then
        echo "Running"
    else
        echo "Stopped"
        exit 1
    fi
    ;;
    *)
    echo "Usage: $0 {start|stop|restart|status}"
    exit 1
    ;;
esac

exit 0
```

###sudo nodeをできるようにする
nvmを導入すると`sudo node`や`sudo npm`などsudoコマンドから実行ができない。
[Raspberry Pi に Node.js をインストールする](http://make.kosakalab.com/make/electronic-work/nodejs_raspi/)を参考にしつつ、visudoを編集する。
編集が完了したら`sudo node -v`などで動作確認をしておく。

```bash
pi@raspberrypi2 ~ $ sudo node -v
v5.1.1
```

#さいごに
小学生の息子が「テレビがついたー」と驚いていたので、結構インパクトがある模様。

StarTrekの世界がまさに実現した感じ。
![(120509145449)Star_Trek_IV_1.jpg](https://qiita-image-store.s3.amazonaws.com/0/95484/279f5b94-f16d-62c9-46b4-27982088eb9d.jpeg)
「ハロー、コンピュータ」([参考](http://saitouyuki.blogspot.jp/2011/07/iv.html))

IRKitのおかげで、赤外線リモコンで制御できる家電が制御対象になり、homebridgeのpluginの豊富さで、webサービス(homebridge-http)との連携も可能。
IFTTTのMakerチャンネルとの連携で遊ぶ予定なので、できたら記事を更新します。