Raspberry Piで家電をコントロールするリモコンアプリをコンテナ化して運用した話



## 経緯
自宅で4年前に作ったRaspberry Piで動く家電リモコンのアプリが、残念なことにマシン側の故障で逝ってしまった。データは吸い出せたものの、様々な動作基盤を入れていたので復旧が大変面倒だった。
またGPIO制御の精度が低く、リモコン操作できない家電もあった。なのでこの機会にライブラリも見直すことにした。

- 問題のリモコンアプリ。LAMP環境やPython環境などをOSの上に直接インストールして動いていた頃。
![oldremocon.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27488/b1cb8dc8-e7e0-ff93-7be9-74c9804bbbdf.jpeg)

## 目標
- どのマシンでも即時起動できるようにリモコンシステムを丸ごとDocker化する。
- Alpineのベースイメージを使ってできる限り軽量化する。
- Pythonライブラリのpigpioを使ってGPIO制御を高精度化する。
- 他システムから制御できるようにWebAPIを設置する。

## 動作環境

- RaspberryPi
 - Docker
 - docker-compose

### Pigpioとは
マイナーなのか、あまり情報がネットに載ってないGPIO制御ライブラリ。でもどのサイトにも高精度と書かれている。
この開発者が送受信用のソースコードを公開してるので、今回はそれを利用してリモコンを制御する。

[pigpio](http://abyz.me.uk/rpi/pigpio/)

### Dockerについて
今回はRaspbrry Piで動作させることを前提とするので、超軽量で爆速のAlpineをベースイメージに使用する。

RaspberryPiで動作するものを探したところ、どうやらARM用のベースイメージがある。

[armhf/alpine](https://hub.docker.com/r/armhf/alpine/)

### GPIOの接続構成
今回は送信用の赤外線LEDを25番ピン、受信用に24番ピンを充てる。

※このピンは後述するソースコード内の「env」ファイルで指定できる。
![kairo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27488/3eab33e0-4991-e0fc-b1c3-02bcbfc48757.png)


- 部品は秋月電子で大体手に入る。

| 部品                                                         | 値段        |
| ------------------------------------------------------------ | ----------- |
| [赤外線受信モジュール](http://akizukidenshi.com/catalog/g/gI-04659/) | 150円くらい |
| [赤外線LED](http://akizukidenshi.com/catalog/g/gI-03261/)    | 100円くらい |
| [トランジスタ](http://akizukidenshi.com/catalog/g/gI-00881/)    | 40円くらい |

## 出来上がったもの


![remocon_preview.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27488/2f2721e4-2d99-a687-18ea-896b3f049115.jpeg)


### ソースコード

[RemoteControl-RPI](https://github.com/souri-t/RemoteControl-RPI)

### 全体構成

![container.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27488/cae0529c-8b36-1f61-cfeb-7d4bba24343c.jpeg)


#### コンテナ

- コンソール用httpdコンテナ

    管理用のコンソールページを提供し、ユーザーが指定した情報をソケット通信（29920番）でリモコン制御用コンテナへ送る。

  WebAPIを設置し、他システムからの連携手段を提供する。

- リモコン制御用コンテナ
   
     GPIOを制御し、赤外線LEDを発光させる。

     httpdコンテナからソケット通信（29920番）で命令を受信し、結果を返す。

  

## 実行

1. GitHubからクローンする。

    ```shell
    $ git clone https://github.com/souri-t/RemoteControl-RPI.git
    ```

2. 中に移動して、docker-composeで起動する。

    ```shell
    $ cd RemoteControl-RPI
    $ docker-compose up -d
    ```

    おわり！

## 使い方

### コンソールページ
- ブラウザで以下にアクセスする。

    ```URL
    http://(マシンのIPアドレス):20080
    ```

![console_top.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27488/b2e4a71d-e229-ebea-b7d7-46460c35d28c.png)


#### 赤外線送信
  赤外線ファイル一つにつき、複数の送信コマンドを含めることができる。
  サンプルの1種類の赤外線ファイルには2つの送信コマンドが入っている。

プルダウンメニュー内に表示される赤外線ファイルとコマンドの候補は、GPIO制御用コンテナから受信している。


![console_select.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27488/648c1a4c-f11e-72b2-9851-b06946b7f6b6.png)



「execute」を押下すると、指定した赤外線ファイルのコマンドに対応するパルスで赤外線LEDが発光し、実行結果がログに出力される。

![console_executed.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27488/62f0e032-195d-b8c3-7d51-14259527d605.png)


### 赤外線ファイルの作り方

こればかりは未だコンソールページではできません(´Д⊂

1. リモコン制御用コンテナの中に入る。

    ```shell
    $ docker-compose exec remote sh
    ```



2. 以下のコマンドを実行する。直後に待機状態になるため、受信モジュールに向けてリモコンの登録したいボタンを押す。
    
    ```shell
    $ addir (赤外線ファイル名) （送信コマンド名）
    ```
    
    例、「tv」というファイルに「power_on」というコマンド名で登録する。
    コマンド実行直後から待機中になるため、そこでセンサーに向けて登録したいリモコンのボタンを押下する。
    しばらくして"Okey"が表示されると成功。
   
    ```shell
    $ addir tv power_on
    -- リモコンのボタンを押す --
    Recording Press key for 'power_on' Okay
    ```

3. Ctrl + P と Ctrl + Qを同時に押下してコンテナを出る。
4. コンソールページのプルダウンの中に、登録した赤外線ファイルとコマンドが登録されたことを確認する。



### 他システム連携（WebAPI）
WebAPIで赤外線送信コマンドを実行することもできる。
残念ながらREST APIの形式ではない...

- 「~/api/remotecontrol.php?」の後にパラメータを入力する。

| パラメータ | 指定文字列 |
| ------------------------------------------------------------ | ------------------------------------------------------------ |
| filename | 赤外線ファイル名 |
| command | 送信コマンド名 |
  
  
   ```URL
   http://(マシンのIPアドレス):20080/api/remotecontrol.php?filename=(赤外線ファイル名)&command=（赤外線送信コマンド名）
   ```
  
  - 例

  ```URL
  http://(マシンのIPアドレス):20080/api/remotecontrol.php?filename=samplefile&command=samplecommand1
  ```



  - 実行後はjson形式で結果が返却される。

|種別|内容|
| ------------------------------------------------------------ | ------------------------------------------------------------ |
|commandstatus|実行結果（success / error）|
|filename|赤外線ファイル名|
|command|送信コマンド名|
    
    
  ```json
  {
    "commandstatus":"success",
    "filename":"samplefile",
    "sendcommand":"samplecommand1"
  }
  ```

### WebAPIでの連携例
- Webリモコン
  
    コンソールページだけではリモコンを操作しにくいので、別のWebサーバーでリモコン用のページを作ると扱い易い。この場合は、onClick()時のhttpリクエストに、WebAPIを含んだコンソールページのURLを指定する。
  
  ![remocon.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27488/e2ff9448-0043-1fb0-5dcc-8ce44c0441b1.jpeg)


- Alexa連携
	Node-REDの「node-red-contrib-alexa-home-skill」を使うとAlexaと連携できるようになる。
	
	そのhttpリクエストの送信先にWebAPIを含んだURLを指定するとAlexaから操作可能になる。
	
	- Alexaスマートホームスキル『Node-RED』を使ってみた https://chasuke.com/alexa_nodered1/ 
	
	![nodered.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27488/3a25a1aa-0a68-ae95-d7e9-4ce6d6e165e4.png)

- Siri連携
  早い話、iOSのショートカットアプリにhttpリクエストを実行するユニットがあるので、iOS端末内にボタンを簡単に作ることができる。作ったショートカットは設定次第でSiriでも実行させることができる。
もし外出先からでも操作したい場合はIFTTTのWebhockと連携すると良い。

    ![siri.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27488/5842c916-6894-debf-b4d5-1c0eeaaf9dcb.png)

## 参考

[Raspberry PiのGPIO制御の決定版 pigpio を試す](https://karaage.hatenadiary.jp/entry/2017/02/10/073000)