自作格安スマートリモコンとHomebridgeを組み合わせたら幸せになった件

# はじめに
以前[こちら](https://qiita.com/takjg/items/e6b8af53421be54b62c9 "格安スマートリモコンの作り方")の記事を参考に格安スマートリモコンを自作しましたが、使用しているうちに以下のことを感じるようになってきました。
(念の為書いておきますが、参考元の記事をディスるわけではありません。素晴らしい記事です。)

<dl>
 <dt>動作(アプレット)が3つ以上の場合、IFTTTの無償枠に収まらない。</dt>
  <dd>動作が3つ以内なら大丈夫。</dd>
 <dt>Slackをメッセージ数を食い潰してしまう。</dt>
  <dd>一人だけの個人Slackなら問題にならないかも。</dd>
 <dt>障害があると切り分けがしづらい。</dt>
  <dd>IFTTT側か、Slack側なのか切り分けが難しい。</dd>
 <dt>IFTTTの登録ワードとGoogle Assistantのショートカットが被ると誤動作する。</dt>
  <dd>例えば「おはよう」というワードで登録した場合、Google Assistantで用意されている「おはよう」のルーティングが開始されてしまう。</dd>
 <dt>そのとき、電気がついているかどうか分からない。</dt>
</dl>

## 対象読者

- [格安スマートリモコンの作り方](https://qiita.com/takjg/items/e6b8af53421be54b62c9)を読んで、`ラズパイで回路を制御`まで作成済みの方
- MQTTの基本的な用語を理解している方 (e.g. Publisher, Subscriber, Broker, Topic ...)
- 簡単なPythonを読める方

# 全体の構成
今回製作した全体構成です。
![homebridge構成図.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145838/709ff719-c9ca-5b46-8884-1bd4c149bc42.jpeg)

※家の外からHomekitを使うには、HomepodもしくはAppleTV、ハブに設定したiPadが必要です。

# 用意するもの
- 自作した格安スマートリモコン
    - この記事中では **自作リモコン(IR-Remo)**と表記します。
- Homebirdge
    - この記事中では **HBホスト(HB-Host)**と表記します。
    - Linuxが動くマシン（Raspberry Piでも可）
    - 今回の記事では転がっていた野良Raspberry Pi4にUbuntuを焼いています。

# Homebridgeを構築する
**HBホストで操作**
今回はUbuntu上にHomebirdgeを構築するので、[Install Homebridge on Debian or Ubuntu Linux](https://github.com/homebridge/homebridge/wiki/Install-Homebridge-on-Debian-or-Ubuntu-Linux)を読みながらインストールを進めます。
※RaspberryPiで構築する場合は、[Homebridge構築済みのRaspbianイメージ](https://github.com/homebridge/homebridge-raspbian-image)がHomebridge公式で配布されているので、そちらを使うのが一番楽かもしれません。

```bash:HBホストでHomebridgeインストール
# setup repo
(HB-Host) $ curl -sL https://deb.nodesource.com/setup_14.x | sudo bash -

# install Node.js
(HB-Host) $ sudo apt-get install -y nodejs gcc g++ make python net-tools

# test node is working
(HB-Host) $ node -v

# Install Homebridge and Homebridge UI
(HB-Host) $ sudo npm install -g --unsafe-perm homebridge homebridge-config-ui-x
(HB-Host) $ sudo hb-service install --user homebridge
```
インストールが終わったら`http://<インストールしたRaspberryPiのIP>:8581`にアクセスすると、下の画面が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145838/88ce5f71-c561-3522-2819-1b6bec016541.png)

# MQTTで赤外線を操作する
今回はリビングの照明と寝室の照明を操作することを目標にします。
それぞれのTopicは以下のとおりとします。（ON/OFFの制御情報が流れてくるMQTTのスレッド的なもの）

- Living/Light
- Bedroom/Light

## 赤外線を学習させる
**自作リモコンで操作**
[元記事](https://qiita.com/takjg/items/e6b8af53421be54b62c9#%E3%83%A9%E3%82%BA%E3%83%91%E3%82%A4%E3%81%A7%E5%9B%9E%E8%B7%AF%E3%82%92%E5%88%B6%E5%BE%A1)を参考に赤外線を学習させます。
ここで重要なのは一番最後の引数です。今回のシステムでは`各機器のTopic/{On|Off}`にしています。（後からPythonで赤外線を発信するときに重要になってきます。）

```bash:リビングの照明をONにするときの赤外線学習コマンド
(IR-Remo) $ python3 irrp.py -r -g18 -f codes --no-confirm --post 130 Livingroom/Light/On
```

## MQTTを受信して、赤外線を発信するプログラム
**自作リモコンで実行**
今回導入するMQTTプラグインでは、例えばリビングの照明をONにする場合、Topicに`true`という文字列が流れてきます。逆にOFFにする場合、`false`という文字列が流れてきます。
なので受信したMQTTの**Topic** `Livingroom/Light`の **payload** が`true`なら、`Livingroom/Light/On`の赤外線を発信するPython（命名：lightman）を作成します。

今回作成したプログラムは[Github](https://github.com/jp7eph/lightman)に置いてありますが、ここでは簡単にプログラムの説明をします。

```python:lightman/main.py
import paho.mqtt.client as mqtt     # MQTTのライブラリをインポート
import irrp_play                    # 赤外線送信のインポート

topic_list = [("Livingroom/Light", 0), ("Bedroom/Light", 0)]
```
今回はリビングと寝室のTopicを受信するので、`topic_list`リストに格納しています。
他のTopicに対応させたいときはここを編集してください。

```python:lightman/main.py
# メッセージが届いたときの処理
def on_message(client, userdata, msg):
  # msg.topicにトピック名が，msg.payloadに届いたデータ本体が入っている
  print("Received message '" + str(msg.payload) + "' on topic '" + msg.topic + "' with QoS " + str(msg.qos))
  payload = msg.payload.decode('utf-8')

  if payload == 'true':
    irrp_play.send(msg.topic + "/On")
  else:
    irrp_play.send(msg.topic + "/Off")
```
`payload`の中身に応じて、赤外線発信関数`irrp_play.send()`を呼び出しています。

## MQTTブローカーの準備
**HBホストで実行**
MQTTを送受信する場合、送信側と受信側だけでは通信が成り立たず、仲介役であるBrokerが必須になります。
[公式ページ](https://mosquitto.org/download/)を見ながら**Mosquitto**をインストールします。

```bash:HBホストでMosquittoインストール
# レポジトリ追加
(HB-Host) $ sudo apt-add-repository ppa:mosquitto-dev/mosquitto-ppa

# パッケージ更新
(HB-Host) $ sudo apt-get update

# Broker(mosqitto)と動作確認とデバック用にクライアント(mosquitto-clients)をインストール
(HB-Host) $ sudo apt-get install -y mosquitto mosquitto-clients
```

## 動作確認
ここまでできたらHBホストからMQTTをPublishして、正しく赤外線が制御されるか確認してみましょう。

```bash
# MQTT Brokerを起動
(HB-Host) $ sudo systemctl start mosquitto

# 受信側のPythonを起動しておく。
(IR-Remo) $ python3 main.py

# リビングの照明をONにする制御情報をPublishする
(HB-Host) $ mosquitto_pub -d -t Living/Light -m "true"
# これで電気がつけばOK！

# リビングの照明をOFFにする制御情報をPublishする
(HB-Host) $ mosquitto_pub -d -t Living/Light -m "false"
# これで電気が消えればOK！
```

## 自動起動＆デーモン化する
### MQTT Brokerを自動起動させる
HBホストが起動した時にMosquittoを自動で起動させるようにします。

```bash:Mosquittoの自動起動ON
# サービス開始
(HB-Host) $ sudo systemctl start mosquitto

# 自動起動ON
(HB-Host) $ sudo systemctl enable mosquitto
```

### 赤外線送信Pythonをデーモン化する
今回作成したlightmanをデーモン化させて、ラズパイ起動時に自動起動させるようにします。
下のserviceファイルを作成してください。

```systemd:/etc/systemd/system/lightman.service
[Unit]
Description=Light bulb control by MQTT

[Service]
ExecStart=/usr/bin/python3 /home/pi/lightman/main.py
Restart=always
User=pi
Group=pi

[Install]
WantedBy=multi-user.target
```
systemdファイルの書き方などは以下の記事を参考にしてください。
[Systemd入門(1) - Unitの概念を理解する](https://enakai00.hatenablog.com/entry/20130914/1379146157)
[Systemd入門(4) - serviceタイプUnitの設定ファイル](https://enakai00.hatenablog.com/entry/20130917/1379374797)

serviceファイルを作成したら、自動起動をさせるようにします。

```bash:lightmanの自動起動
# サービス再読み込み
(IR-Remo) $ sudo systemctl daemon-reload

# サービス起動
(IR-Remo) $ sudo systemctl start lightman

# 自動起動ON
(IR-Remo) $ sudo systemctl enable lightman
```
# Homebridgeから赤外線を操作する

## MQTTプラグインのインストール
Homebridgeのメニューから`プラグイン`を選択して、上の検索バーに `Mqttthing`と入力してください。
`Homebridge Mqttththig`が表示されたらインストールを選択してください。
※下図は既にインストール済みのため、`アンインストール`と表示されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145838/5131fc56-4ad1-1ffd-266e-32af79b9d3d3.png)

## MQTTプラグインの設定
インストールしたら、`設定`から`ADD ACCESSORY`を選択して以下のように入力してください。
`Set On`に指定したTopicに`true/false`が流れてきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145838/9d021db8-741e-b662-7637-cea375e50d60.png)

## 動作確認
Homebirdgeの`アクセサリ`を選択すると先程設定した照明が追加されているので、クリックして照明がON/OFFできるか確認しましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145838/6352b836-e5d6-06c8-3af7-3331101e3194.png)

# Homekitから操作する
Homebridgeの`状態`を選択すると表示されるQRコードをiPhoneやiPadで読み込ませるだけです。
これでiPhoneやiPadの`ホーム`アプリで操作できるようになりました。

# Google Assistantから操作する
AndroidやGoogle Homeから操作するためには`Homebridge Google Smart Home`というプラグインが必要になります。
詳しいインストール方法や設定方法は[公式Github](https://github.com/oznu/homebridge-gsh#readme)を見てください。

簡単にインストール方法と接続設定だけ書いておきます。

1. 下図に従ってプラグインをインストールして、GoogleアカウントもしくはGithubアカウントを紐付けます。
![image.png](https://user-images.githubusercontent.com/3979615/62948031-ff228d80-be26-11e9-9e07-ef1023f28fa8.gif)
1. スマートフォンの`Google Home`アプリの左上`+`を選択します。
2. `デバイスのセットアップ`から`Googleと連携する`を選択します。
3. `Homebridge`を探して、1.で紐付けたアカウントでログインします。

# おわりに
IFTTTが有料化したからどうしようかなー。と悩んでいたら今回のシステムを完成しました。
今回は照明のON/OFFだけでしたが、HomebirdgeやGoogle homeプラグインは照明の明るさや色の変更、他の家電にも対応しているので、いろんなものに応用できます。
Homebirdge対応のスマートロックも作ったので、そのうち記事を書きたいと思います。

またGoogle Homeに対応したおかげで、Google Homeアプリから操作できるだけでなく、
GPSによる在宅、外出モードやAndroid11以降の電源ボタン長押し時の家電操作もできるようになりました。

今回の記事はPythonのプログラムから、Homebirdgeの設定まで結構広範囲になってしまったので、記事が読みづらくなってしまったかもしれません。すみません。。。