ラズパイとNode-REDでスマートリモコンを作ってみた

先日[Developers Boost 2019](https://event.shoeisha.jp/devboost/20191130)に参加したのですが、そこで講演・展示されていた[株式会社マイクロアド](https://www.microad.co.jp/)さんのブースでRaspberry Pi用拡張基板(赤外線学習リモコン & 温湿度気圧センサー)を無料配布していたので、ありがたく頂きました。
ちょうど自宅にラズパイがあったので、拡張基板の赤外線学習リモコンとNode-REDを使用してスマホから家電を操作するスマートリモコンを作ってみました。

# 構成図
完成系は以下のような感じになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428874/dd6f651a-038c-ad48-7242-497c9b210b80.png)
1. [Node-RED Dashboard](https://flows.nodered.org/node/node-red-dashboard)を使用して画面を作成し、それをスマホで表示する
2. ボタンを押すとラズパイ上のNode-RED上でフローが走る
3. フロー上でボタンに対応する赤外線送信プログラムが実行される
4. 赤外線が送信され、各種家電を制御する

今回は[Node-RED](https://nodered.jp/)を使ってリモコンの画面と赤外線送信部分をサクッと作ってみます。

# 環境
- Raspberry Pi 3 Model B+
- 赤外線学習リモコン & 温湿度気圧センサ HAT[^hat]
- Node-RED v1.0.2
- Node-RED Dashboard v2.19.0
- Python 3.5.3

[^hat]: Developers Boost 2019 会場で頂いたもの。温湿度気圧センサは取り付けず、赤外線学習リモコン部分のみ使用しています。[こちら](https://qiita.com/takjg/items/e6b8af53421be54b62c9)の記事で紹介されているものとほぼ同等の構成です。

# 準備
## はんだ付け
今回頂いた物はプリント基板+各種パーツ(抵抗・コンデンサ・赤外線受光モジュール・赤外線LED等)だったので、基板に各種パーツをはんだ付けします。
はんだごてはAmazonで一式キットで2000円くらいで売っています。

## インストール
### [pigpio](http://abyz.me.uk/rpi/pigpio/)
ラズパイの高精度なGPIO制御ライブラリ

```sh:RaspberryPi
sudo apt install pigpio python3-pigpio
sudo systemctl enable pigpiod.service
sydo systemctl start pigpiod
sudo crontab -u root -e 
# crontabファイルの末尾に以下を追記
@reboot until echo ', 17 w  w 17 0  m 18 r  pud 18 u' > /dev/pigpio; do sleep 1s; done
```

### [IR Record and Playback](http://abyz.me.uk/rpi/pigpio/examples.html#Python_irrp_py)
赤外線の学習・送信を行うPythonライブラリ

```sh:RaspberryPi
wget http://abyz.me.uk/rpi/pigpio/code/irrp_py.zip
unzip irrp_py.zip
```

解凍した`irrp.py`を適当なフォルダ(例：`/home/pi`)に配置します。

### Node-RED
フローベースプログラミングツール。コードを書かなくてもノードを繋げていくだけでシステムが作れるのが特徴です。
また、サードパーティのノード(Twitter, Slack, etc.)も充実しているので、各種外部システムとの連携も簡単に行えます。

ラズパイ上に構築する場合は、以下のようにインストールスクリプトを実行するだけで簡単にインストールできます。

```sh:RassberryPi
bash <(curl -sL https://raw.githubusercontent.com/node-red/linux-installers/master/deb/update-nodejs-and-nodered)
sudo systemctl enable nodered.service
```

### Node-RED Dashboard
Node-RED上でUIを簡単に作れるAngularベースのライブラリです。
ダッシュボード用のチャートやグラフだけでなくボタンやフォームも配置できるので、今回はこのボタンを使用してリモコン画面を作っていきます。

1. `http://[ラズパイのIP]:1880`にアクセス
2. 右上メニュー→「パレットの管理」→「ノードを追加」から`node-red-dashboard`を検索しノードを追加する  
   ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428874/dc2c3473-2045-2926-c242-2c2535e6914d.png)
3. 左側にDashboardのノードが出てきたらOK  
   ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428874/a66b2cac-bd98-dea9-67b5-bda5a6142dff.png)

# 実装

## 基板取り付け
はんだ付けした基板をラズパイと接続します。
今回はピンヘッダを差し込むだけで接続できる基板だったので、上からピンヘッダ部分を被せて繋ぎます。

接続したものが以下になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428874/89f3dd03-452d-5e91-f8a5-b74790716219.png)
はんだ付けが汚かったりパーツが斜めってたりしますが[^led]、ショート・断線さえしていなければ動くはずです。

[^led]: 右上の赤外線LED(4つあるやつ)に限っては斜めに取り付けられているのが正常です。


## 赤外線学習
IR Record and Playbackを使って、家にあるリモコンの赤外線メッセージを学習していきます。
学習は以下のコマンドで実行できます。

```sh:RaspberryPi
python3 irrp.py -r -g18 --no-confirm --post 130 -f (保存ファイル名) (識別子)
```

保存ファイル名・識別子は適当に設定できますが、例えばライトの点灯の場合は

```sh:RaspberryPi
python3 irrp.py -r -g18 --no-confirm --post 130 -f light.irdata power:on
```

のようにするとよいでしょう。
各種オプションの意味は概ね以下の通りです。

```
-r: 学習(Record)モード
-p: 実行(Play)モード
-g: GPIO番号(今回は赤外線受光モジュール(受信)を18, 赤外線LED(送信)を17にしています)
--no-confirm: 再確認しない(デフォルトだと同じ信号を確認のため2回受信します)
--post: 学習終了判定するまでの時間間隔(ms)
-f: 保存先ファイル名
```

`--post`の値に関しては、デフォルト値だと一部リモコン(エアコン等)の赤外線メッセージが途中で途切れて学習されてしまう場合があるため、少し長めに取っています。

## 赤外線送信

学習した赤外線メッセージは以下のコマンドを実行することで送信できます。

```sh:RaspberryPi
python3 irrp.py -r -g17 -f light.irdata power:on
```

## Node-REDでスマートリモコン作成

学習した赤外線メッセージをスマホ上から実行できるようにしてみます。
ボタン押下をトリガーに上記の赤外線送信コマンドを叩けばよいのですが、これはNode-REDの`exec`ノードとNode-RED Dashboardの`button`ノードを使うと簡単に実現できます。

試しに`button`ノードと`exec`ノードを以下のような感じで繋いでみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428874/63d5e174-d37a-72dd-d932-6217ca4a0fd4.png)
`button`ノードの`Payload`に保存ファイル名と識別子を入力しておきます。こうすることで、引数だけ変えた別のボタンも簡単に追加できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428874/405b6c4c-df72-ad0b-30fe-d74956bbc463.png)
`exec`ノードでは、引数に`msg.payload`を指定して、コマンドには保存ファイル名より前の部分を記入します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428874/77331b0e-2cae-732f-008b-98d94cc6c0c6.png)
こうすることで、ボタンを押したら`python3 /home/pi/irrp.py -p -g17 -f light.irdata power:on`がラズパイ上で実行されます。

他のボタンを追加する際は、以下のようにボタンの`Payload`だけ変えて同じ`exec`ノードに繋げばOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428874/74ee20bb-f865-7872-0b7f-d1347fa5bae9.png)

ボタンのレイアウト・順番については、右側の「ダッシュボード」タブから設定できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428874/650212f7-b31d-17be-ec91-28abb8ec1a19.png)

「レイアウト」ボタンをクリックすると、以下のようにグリッドレイアウトを直感的に配置できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428874/03719269-487a-9ddc-f8fd-3861e82484e2.png)

完成したら「デプロイ」をクリックすればOKです。画面は、ダッシュボードタブの![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428874/02544ab5-d767-6ebe-0a43-e6dc35547cb0.png)をクリックすれば確認できます。
`http://[ラズパイのIP]:1880/ui`にアクセスしても表示できます。スマホから表示する際はこのURLをブックマークに入れておくとよいでしょう。

## 画面
最終的に以下のような画面になりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428874/f3033528-226f-1877-6a35-b32904c2e99f.png)
`button`ノードのプロパティから各ボタンの背景色を変えたり、アイコンを設定したり等もできます。

また、テレビのリモコンも同様に作ってみました。
電気よりボタン数が多いですが、やっていることは同じです。
電源ボタン等は`Label`プロパティを設定する代わりに、`Icon`プロパティに[Angular Material Icons](https://klarsys.github.io/angular-material-icons/)のアイコン名を設定しています(画像2枚目)。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428874/8a3e616d-1321-d83f-fd91-03d55332bb7e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428874/bb0db427-8f5e-3f36-607c-2df77c84be32.png)

フローはこんな感じです。ボタン数が多いので線がだいぶカオスですが。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428874/4155e09f-18f6-b4a4-af0b-394a585d1e4c.png)
`link in / link out`ノードで仮想リンクを作成して見やすくしていたり、`template`ノードを利用してファイル名をまとめたりしていますが、基本的には上でやったことを繰り返していくだけで作れます。

ちなみに間に挟んでいる`template`ノードは以下のようになっていて、各ボタンの`payload`には識別子のみを入れてファイル名を共通化できるようにしています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428874/74315f87-baec-a122-1c15-5e1528dda4bd.png)

# まとめ
Node-REDを使って、ほぼプログラミングレスでスマートリモコンを作成してみました。
Node-REDのうまみはサクサク作れることと拡張性にあると思っています。
例えば上のテレビリモコンくらいだったら慣れれば1時間弱で作成できます。
また、後から「やっぱSlackをトリガーに電源ONにできるようにもしたい」となった時でも、上のフローに[Slackノード](https://flows.nodered.org/node/node-red-contrib-slack)を繋げるだけでよいので(Slack Appの作成等はありますが)、かなり拡張性が高いと個人的には思っています。

# 参考
- [格安スマートリモコンの作り方 - Qiita](https://qiita.com/takjg/items/e6b8af53421be54b62c9)  
  今回使用したpigpio/IRRPや、回路製作について非常に詳しく解説されています。