Google Home mini買ったので、テレビと照明を操作してみた 〜購入から実現まで〜

# はじめに

12月上旬にGoogle Home miniが半額セールだったので興味本位で購入してみました。
音声で天気を知れたり、Youtubeを再生できたりなど非常に便利だったので、ついでにテレビとか照明とかを連携してみたくなってしまいました。
そこで、機器の購入から赤外線機器の音声による操作の実現までの過程をざっくりと記載していこうと思います。

# 構成

- Google Home mini
- [IFTTT](https://ifttt.com/discover)
- [dataplicity](https://www.dataplicity.com) または [ngrok](https://ngrok.com/)
- Raspberry Pi3 または Raspberry Pi Zero W
    - [Raspbian](https://www.raspberrypi.org/downloads/raspbian/)
    - [broadlinkrm-ifttt](https://github.com/jor3l/broadlinkrm-ifttt)
    - [homebridge](https://github.com/nfarina/homebridge) または [RM Bridge](http://rm-bridge.fun2code.de/rm_manage/code_learning.html)
- RM mini3（赤外線学習リモコン）

![whole.png](https://qiita-image-store.s3.amazonaws.com/0/60325/236ceae7-60de-1f41-95a4-8a5f333da6df.png)

上図のように、Google Home miniからIFTTTに登録してあるAppletで公開されているRaspberry Pi上のbroadlinkrm-iftttのAPIを叩いて、RM mini3に赤外線のコマンドを送信をして機器を操作します。

# 準備物

RM mini3ではなく、日本のOEM版の[eRemote mini](https://www.amazon.co.jp/dp/B01MA4W1YD)でも良いのですが、価格差が5000円ほどあるのでRM mini3を利用することにしました。
[GEARBEST](https://www.gearbest.com)のセールのときですと、1600円ほどでRM mini3を購入することができます。
Raspberry Pi3はGEABESTで購入すると安いので、RM mini3とまとめて購入すると良いかもしれません。
Raspberry Pi Zero Wを購入する場合は、AmazonのStarter Kitが変換アダプタなども同梱されている状態で購入できるので、そちらが良いかもしれません。
GEARBESTで購入する際は、出荷方法を__Priority Line__にすると5〜9日で手元に届きます。

Broadlink RM mini3 Universal WIFI / IR Remote Controller
<img src="https://qiita-image-store.s3.amazonaws.com/0/60325/d3e79c6e-277d-89e6-3bec-5ea986bdc874.jpeg" width="320px">
https://www.gearbest.com/living-appliances/pp_357329.html

Raspberry Pi 3 Model B Motherboard
<img src="https://qiita-image-store.s3.amazonaws.com/0/60325/7994c6a7-747a-6387-c8aa-ac042d2ede6a.jpeg" width="320px">
https://www.gearbest.com/raspberry-pi/pp_354347.html

Raspberry Pi Zero W
<img src="https://qiita-image-store.s3.amazonaws.com/0/60325/b45618cd-63ee-424a-1101-96eea5390a55.jpeg" width="320px">
https://www.amazon.co.jp/gp/product/B0746H9881

# RM mini3をwi-fiに接続する

RM mini3を__BroadLink e-Control__([iOS](https://itunes.apple.com/jp/app/broadlink-e-control/id793152994?mt=8) / [Android](https://play.google.com/store/apps/details?id=com.broadlink.rmt&hl=ja))を利用してwi-fiに接続します。
iPhoneまたはAndroidの言語設定が日本語の場合、対応していない機種であるという内容のメッセージが表示されますが、wi-fiに接続する分には問題ありません。
iPhoneまたはAndroidの言語設定を英語にすると、上記のエラーは出なくなります。
ちなみに、eRemote miniの場合は、言語設定が日本語であってもエラーは出ません。

# Raspberry Piの準備

## Raspbianのインストール

1\. Raspbianの[ダウンロードページ](https://www.raspberrypi.org/downloads/raspbian/)から__RASPBIAN STRETCH WITH DESKTOP__をダウンロードします。

<img width="427" alt="スクリーンショット 2017-12-25 0.44.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/60325/a114aef5-8bbc-5b37-30af-16d784dcd56b.png">

2\. MacのDisk UtilityからSDカードをMS-DOS(FAT)でフォーマットをします。

3\. フォーマットが完了したら、SDカードをアンマウントします。diskutilコマンドでSDカードのデバイスファイル名を確認します。（/dev/disk2などになるかと思います）

```
$ diskutil list
```

4\. デバイスファイル名が確認できたら、アンマウントを下記のコマンドで行います。

```
$ diskutil unmountDisk /dev/disk2
```

5\. SDカードにRaspbianのイメージを書き込みます。

```
$ sudo dd bs=1m if=2017-11-29-raspbian-jessie.img of=/dev/disk2
```

コピーに時間がかかりますが、`control+t`で進捗を確認することができます。

## VNCの設定

VNCでRaspberry Piの操作ができると、本体にキーボードやマウスなどを繋げずに置きっぱなしにできるのでVNCの設定をはじめにしておきます。
Raspbianには最初からVNCサーバーがインストールされているので、設定画面からVNCを有効にします。

![vnc.png](https://qiita-image-store.s3.amazonaws.com/0/60325/dd123e69-f23d-8f7b-de1f-87e334de383c.png)

VNCを有効にすると、ツールバーにVNCアイコンが現れます。

![tool.png](https://qiita-image-store.s3.amazonaws.com/0/60325/5acbbf29-40a9-5f00-b001-36575405731b.png)

VNCアイコンから、ローカルIPを確認してください。

![vnc-con.png](https://qiita-image-store.s3.amazonaws.com/0/60325/4c189e6c-de1d-bd6e-4727-9094656b66c6.png)

ローカルIPが確認できたら、[VNCViewer](https://www.realvnc.com/en/connect/download/viewer/)を利用してRaspberry Piに接続してください。
ちなみに、デフォルトのid/passwdはpi/raspberryになっていると思います。

### Raspberry Piをスリープさせてない

何の操作もしなかった場合、10分が経過するとスリープしてしまうので、スリープさせないための設定をします。

`/etc/xdg/lxsession/LXDE/autostart`に

```
@xset s off
@xset -dpms
@xset s noblank
```

を追記します。そして、`/etc/lightdm/lightdm.conf`には

```
xserver-command=X -s 0 -dpms
```

を追記して、再起動してください。


### 解像度の変更

ディスプレイに接続していなくても、Raspberry Piを操作できるようにするためにVNCを利用しているので、HDMIが接続されていない状態でも解像度を設定しておきます。

`/boot/config.txt`の__hdmi_force_hotplug=1__のコメントアウトを外します。
そして、`hdmi_group=2`を追記し、適した`hdmi_mode=x`を追記します。
xの部分に関しては、[http://elinux.org/RPiconfig#Video_mode_options](http://elinux.org/RPiconfig#Video_mode_option)の`These values are valid if hdmi_group=2 (DMT)`の該当する番号を当てはめてください。

## node.jsを再インストールする

Pasberry Piに最初から入ってるnode.jsは古いので、アップデートします。
まずは、デフォルトのnode.jsを削除しましょう。

```
$ sudo apt-get autoremove nodejs
```

次にnodebrewをインストールします。

```
$ curl -L git.io/nodebrew | perl - setup
出力された"export PATH～"の行をコピーする。

ログインしたときにパスに追加されるようにする。
$ vi ~/.bashrc
先ほどコピーした行を最終行に張り付ける。

設定を反映
$ source ~/.bashrc

確認
$ nodebrew help
```

nodebrewのインストールが完了したら、node.jsをインストールします。
今回は、v7.10.1を利用します。

```
インストールできるリストを確認
$ nodebrew ls-remote

v7.10.1をインストール
$ nodebrew install-binary v7.10.1

v7.10.1をデフォルトで使用する
$ nodebrew use v7.10.1
```

# リモコンを学習する

iOS端末を利用してリモコンを学習する場合はHomeBridgeを、Android端末を利用してリモコンを学習する場合はRM Bridgeを利用するのが良いかと思います。

## [HomeBridge](https://github.com/nfarina/homebridge)を利用

iOS端末でリモコンを学習するために、HomeBridgeをインストールします。RM mini3と連携するためには[homebridge-broadlink-rm](https://github.com/lprhodes/homebridge-broadlink-rm)も必要なので、インストールしましょう。

```
# HomeBridgeに必要なものをインストール
$ sudo apt-get install libavahi-compat-libdnssd-dev

# HomeBridgeのインストール
$ sudo npm install -g --unsafe-perm homebridge

# Homebridge Broadlink RMのインストール
$ npm install -g homebridge-broadlink-rm
```

次にリモコンを学習するために、RM mini3のMACアドレスと`~/.homebrige/config.json`に記載します。
`username`にMACアドレスと記載してください。ここでの注意点としては、アルファベット大文字にしないとうまく作動しません。
また、RM mini3のMACアドレスは、e-controlのDevice Listから確認することができます。

```json:config.json
{
    "bridge": {
        "name": "HomeBridge",
        "username": "34:EA:34:XX:XX:XX",
        "port": 51826,
        "pin": "031-45-123"
    },
    "description":"HomeBridge",
    "platforms": [
        {
            "platform": "BroadlinkRM",
            "name": "Broadlink RM mini3",
            "accessories": [
                {
                    "name": "Light",
                    "type": "switch",
                    "data": {
                        "on": "",
                        "off": ""
                    }
                }
            ]
        }
    ]
}
```

HomeBridgeを起動します。

```
$ homebridge
```

コマンドライン上にQRコードが表示されると思うので、そのQRコードをiOSのホームアプリから読み取って登録をしてください。
登録が完了すると、下記のようなLearnボタンが表示されると思います。

<img width="171" alt="スクリーンショット 2017-12-25 2.24.27.png" src="https://qiita-image-store.s3.amazonaws.com/0/60325/12e6d73c-5920-23f1-9f27-03718d95bc40.png">

Learnボタンをタップすると学習の待機状態になるので、RM mini3に向けてリモコンのボタンを押してみてください。
下記のようなcodeが表示されると思います。
このcodeを後ほど利用するので、メモしておくと良いです。

![lean.png](https://qiita-image-store.s3.amazonaws.com/0/60325/5145c746-7783-2e8d-d7c4-abcf87c1797e.png)

## RM Bridgeを利用

Android端末でリモコンを学習するために、[RM Bridge](https://play.google.com/store/apps/details?id=de.fun2code.android.rmbridge&hl=ja)をGoogle PlayからAndroid端末にインストールしてください。

RM Bridgeを起動すると`Stopped`になっていると思うので、`Started`にしてRM mini3と接続してください。
ここで表示されているIPアドレスは、後ほど利用します。

![rm-bridge.png](https://qiita-image-store.s3.amazonaws.com/0/60325/8262db6a-20bc-2bba-4aeb-0208a0a019ad.png)

[RM Bridgeのリモコン学習ページ](http://rm-bridge.fun2code.de/rm_manage/code_learning.html)で、先程RM Bridge上で表示されていたIPアドレスを入力し、`Load Device`をクリックします。
`Load Device`をクリックしても表示に変化がない場合は、MACアドレスを入力し、typeを`RM2`にしてマニュアルで検索をしてみてください。

![rm-bridge.png](https://qiita-image-store.s3.amazonaws.com/0/60325/6784c3d0-acf8-2eca-a051-0b779b1eece1.png)

<img width="595" alt="スクリーンショット 2017-12-30 17.22.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/60325/06aa14cb-394b-3bb1-4e65-895698206605.png">

ネットワーク内にあるRM mini3が表示されるかと思います。

<img width="320" alt="スクリーンショット 2017-12-25 2.07.01.png" src="https://qiita-image-store.s3.amazonaws.com/0/60325/50f5a5af-79bc-f8ed-b2b0-02eb61be9265.png">

`Learn Code`をクリックして、RM mini3にリモコンを向けてボタンを押してください。

<img width="497" alt="スクリーンショット 2017-12-25 2.07.01.png" src="https://qiita-image-store.s3.amazonaws.com/0/60325/ce8b1843-e784-015f-2d96-069070072ccb.png">

学習したリモコンのボタンが、下記のようにcodeとして表示されるかと思います。
このcodeを後ほど利用するので、メモしておくと良いです。

![rm-bridge.png](https://qiita-image-store.s3.amazonaws.com/0/60325/1a772f72-dc37-d605-bda1-81323c0b5640.png)

# リモコンのデータをbroadlinkrm-iftttでRM mini3に送信する

[broadlinkrm-ifttt](https://github.com/jor3l/broadlinkrm-ifttt)を利用して、RM mini3をRaspberry Piから操作できるようにします。


まず、任意のディレクトリにbroadlinkrm-iftttをcloneします。

```
$ git clone https://github.com/jor3l/broadlinkrm-ifttt.git
```

cloneが完了したら、`command.js`を編集します。
リモコンを学習した際に取得したcodeを、dataに記載してください。
`command`がAPIでアクセスする際のPathになります。
`secret`を設定すると、POSTでアクセスする際に、bodyにsecretをキーとしたjsonが入っていないとエラーになります。

```javascript:command.js
/*
Example:

    {
        "command": "YOUR_COMMAND_HERE",
        "secret": "SET_A_RANDOM_HASH_HERE",
        "ip": "YOUR_DEVICE_IP_HERE",
        "mac": "MAC_ADDRESS_HERE", // Use mac instead of IP when possible.
        "sequence": ["command", "command"], // If sequence is defined, all the commands inside the array will be run in sequence.
        "data": "RM_BRIDGE_DATA_HERE" // only runs if there is no sequence defined.
    }
*/

module.exports = [{
        "command": "light_on",
        "secret": "xxxx",
        "mac":"34:ea:34:xx:xx:xx",
        "data": "26009c0100011d8c150f15101410150f15101410150f15351510143615351535151014361535151014101410153515101410141015101436143615351510143614361535153614101400059b00014ea5163c173c163c17131613173b173c173c16131712173c163c1713161317121613173c173c163c17121713171217121713161317121713163c173c163c173c163c1800063d71350f280f0c0e0d0f0c0f0c0f0c0f0c0f0c0f0c0f0c0f0c0f0c0f280f0c0f0c0f0c0f0c0f0c0f0c0f0c0f271027100b1"
    }
]
```

`command.js`の編集が完了したら、server.jsを起動してみましょう。

```
$ npm start server.js
```

`https://localhost:1880/command/light_on`で照明をオンにすることができるようになっているはずです。

# ローカルを外部に公開する

ここまでで、赤外線をコマンド化してAPIとして叩くことができるようになりました。
dataplicityまたはngrokを経由して、Google Home miniからRM mini3にコマンドを送れるようにしていきます。

## dataplicityを利用

[dataplicity](https://www.dataplicity.com)を利用することで、__60秒で__Paspberry PiをWebブラウザからアクセスできるようになります。
ちなみに、デバイスが1台まで無料で利用できます。
登録方法はメールアドレスを登録して、②に表示されるコマンドをRaspberry Piのターミナルで実行するだけです。

<img width="1136" alt="スクリーンショット 2017-12-26 2.31.05.png" src="https://qiita-image-store.s3.amazonaws.com/0/60325/adf54a4b-4366-1775-34ac-fa2248f1ec3e.png">

```
curl https://www.dataplicity.com/xxx.py | sudo python
```

のようなコマンドが表示されるかと思います。このコードをRaspberry Pi上で実行してください。
コマンドを実行し処理が完了すると、下記のようにWebからRaspberry Piにアクセルできるようになっていると思います。

![wormhole.png](https://qiita-image-store.s3.amazonaws.com/0/60325/0cba8af2-4ceb-a7c8-bb8e-716bea973e71.png)


ダッシュボードから`Wormhole`を`Enabled`にすると、Raspberry Pi上でサーバーを起動することで`https://xxx.dataplicity.io`からアクセスできるようになります。

broadlinkrm-iftttのデフォルトのポートは1880ですが、dataplicityで公開されているポートは80なので下記このコマンドでリダイレクトしましょう。

```
sudo iptables -t nat -A OUTPUT -o lo -p tcp --dport 80 -j REDIRECT --to-port 1880
```

## [ngrok](https://ngrok.com/)を利用

ngrokを利用して、外部からRaspberry Piにアクセスできるようにします。
ngrokの無料プランの場合、ngrokを起動するごとにホストが変わってしまいます。
有料プランの場合は、ホストを固定することが可能です。

下記のコマンドでngrokをインストールします。

```
$ wget https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-arm.zip
$ sudo unzip ngrok-stable-linux-arm.zip -d /usr/local/bin/
```

broadlinkrm-iftttのデフォルトのポートは1880なので、下記のコマンドでngrokを起動します。

```
$ ngrok http 1880
```

コマンドラインに表示されているURLからアクセスすることができるようになります。

ちなみに、ngrokにsignupすることでhttpsでのリクエストができるようになるので、signupをしてauthtokenを取得すると良いでしょう。（signupしてautotokenを取得することは、無料でできます）

# IFTTTでコマンドを実行する

IFTTTを利用して、音声コマンドからAPIを叩けるようにするために、My Appletを追加します。

音声コマンドによって実行させたいので、__Google Assistant__を利用します。

<img width="765" alt="スクリーンショット 2017-12-25 1.28.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/60325/ce14e7ba-1fd4-6581-2237-cfbb478a8264.png">

例として、照明をつける音声コマンドに対して、`照明つけて`、`電気つけて`、`ライトつけて`のように最大３つまでを同じコマンドに対して設定することができます。
Languageを`Japanese`にするのは忘れないようにしましょう。

<img width="462" alt="スクリーンショット 2017-12-25 1.28.51.png" src="https://qiita-image-store.s3.amazonaws.com/0/60325/ed1befbc-a6ec-2398-94b4-c8eeb02d3397.png">

次に__Web Hooks__を利用して、APIを叩く設定をしていきます。

<img width="744" alt="スクリーンショット 2017-12-25 1.29.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/60325/da650d09-7b2e-8784-d95d-3c0b469b740d.png">

URLを設定し、POSTでリクエストをします。Raspberry Pi側で実行されるコマンドに対してsecretがある場合には、`applicatino/json`でsecretをbodyとしてリクエストします。

<img width="468" alt="スクリーンショット 2017-12-25 1.29.38.png" src="https://qiita-image-store.s3.amazonaws.com/0/60325/6491c46b-75f9-a074-5efd-ffd3e17916eb.png">

ここまで設定することで、Google Home miniから赤外線で操作する系の機器を音声で操作できるようになります。

# 最後に

本投稿ではセキュリティ面に関する記載はしていませんが、最低限Raspberry Piのユーザーを変更したり、basic認証をかけたりなどが必要になるかと思います。

また、現在はAPIを叩けば赤外線で操作する系の機器は動くようになっているので、現在はリモコンアプリを製作中です。