Google Home + IFTTT + Beebotte(MQTT Broker) + ESP32でLチカしてみた

[MQTT](https://ja.wikipedia.org/wiki/MQ_Telemetry_Transport)はPub/Subモデルの軽量なメッセージプロトコルで、IoTやM2Mでも利用されています。

[Beebotte](https://beebotte.com/)はMQTTブローカー(メッセージの配信を仲介するサーバー)のひとつで、API(URL)を叩くことでメッセージを流すこともできます。
1日あたりのメッセージ数が50000件までは無料で使えるので、無料枠でもかなり遊べるのが魅力的です。

[IFTTT](https://ifttt.com/)はWebhooksでAPI(URL)を叩くことはできますが、MQTTブローカーとしては機能しません。

そこで**IFTTTとBeebotteを組み合わせる**ことで、IFTTTにある任意のトリガー(今回はGoogle Assistant)でIoT機器へメッセージを配信することができます。今回はESP32をGoogle Homeから操作してみたいと思います。

![構成図.png](https://qiita-image-store.s3.amazonaws.com/0/137045/63042a5d-cef0-7a05-279f-32959b7ccfef.png)

この記事で紹介する内容では、最低限やっておきたいセキュリティ対策としてWiFiのパスフレーズのハッシュ化と MQTT over SSL/TLS による通信の暗号化を実施します。
(IFTTT -> Beebotte 間と Beebotte -> ESP32 間が**トークンを使った単純な認証**を用いているため、トークンを定期的に更新するとより良いです)

# 動作環境
* [MH-ET LIVE ESP32 MiniKit](https://macsbug.wordpress.com/2017/07/10/esp32-minikit/)などのESP-WROOM-32搭載ボード
  * 内蔵の青色LED(GPIO 2)をLチカで利用
  * [Installation instructions for Mac OS](https://github.com/espressif/arduino-esp32/blob/master/docs/arduino-ide/mac.md) または [Steps to install Arduino ESP32 support on Windows](https://github.com/espressif/arduino-esp32/blob/master/docs/arduino-ide/windows.md) に書かれている手順で[Arduino IDE](https://www.arduino.cc/en/Main/Software)と[arduino-esp32](https://github.com/espressif/arduino-esp32)をインストール

# Beebotteの設定
[Beebotte](https://beebotte.com/)にアクセスしてログインし、Control Panelを開き、Create New ボタンをクリックします:

<img width="640" alt="beebotte_01.png" src="https://qiita-image-store.s3.amazonaws.com/0/137045/47a5ade0-2f92-9892-bd35-832897866355.png">

Channel Nameには `beebotte_test`, Channel Descriptionには `google home -> ifttt -> beebotte -> esp32`(適当な説明), Resource nameには `led`, Resource Descriptionには `led on/off`(適当な説明)を入力し、Create Channelボタンをクリックします:

<img width="640" alt="beebotte_02.png" src="https://qiita-image-store.s3.amazonaws.com/0/137045/4189b979-a1d7-c4f6-efd8-53369d1e0b9c.png">

作成されたチャンネル名をクリックしてChannel Token(`token_xxxxxxxxxxxxxxxx` のような形式)を取得します:

<img width="640" alt="beebotte_03.png" src="https://qiita-image-store.s3.amazonaws.com/0/137045/f8d6c02a-684c-8bc5-6a0a-e8def8adb1b5.png">

# ESP32にスケッチを書き込む
## スケッチとツールのダウンロード
[mascii/esp32-beebottle](https://github.com/mascii/esp32-beebottle) から Clone or download -> Download ZIP でZIPファイルをダウンロードして解凍するか、リポジトリを `git clone` します

## 必要なライブラリのインストール
先ほどダウンロードしたスケッチで [knolleary/pubsubclient](https://github.com/knolleary/pubsubclient) と [bblanchon/ArduinoJson](https://github.com/bblanchon/ArduinoJson) 
(6.x系)が必要なので、以下のいずれかの方法でインストールします:

* Arduino IDE上の スケッチ->ライブラリをインクルード->ライブラリを管理 で、PubSubClient と ArduinoJson を検索してインストール
    * ArduinoJsonは6.x系をインストール
* [knolleary/pubsubclient](https://github.com/knolleary/pubsubclient) と [bblanchon/ArduinoJson](https://github.com/bblanchon/ArduinoJson) のリポジトリをZIPファイルとしてダウンロードし、Arduino IDE上の スケッチ->ライブラリをインクルード->.ZIP形式のライブラリをインストール でダウンロードした2つのZIPファイルを読みこむ

## CA証明書のダウンロード
[https://beebotte.com/certs/mqtt.beebotte.com.pem](https://beebotte.com/certs/mqtt.beebotte.com.pem) からCA証明書をダウンロードし、先ほどダウンロードしたスケッチと同じディレクトリに置きます

## CA証明書の変換
macOSなどBashがある方は `bash convcert.sh mqtt.beebotte.com.pem`, Node.jsが入っている方は `node convcert mqtt.beebotte.com.pem` を実行すると、`certificate.h`(Arduino スケッチが読み込める形式のCA証明書) が作成されます。

BashやNode.jsがない環境(Windowsなど)の場合は、メモ帳以外の改行コードLFに対応したエディタ(Atom, VSCode, TeraPad, サクラエディタなど)を用いて以下の手順で `certificate.h` を作成します:

* `mqtt.beebotte.com.pem` をテキストエディタで開き、内容をコピー
* `convcert.html` をブラウザで開いてコピーした内容を変換(JavaScriptの実行許可が必要)
* 変換された内容をコピーし、テキストエディタに貼り付けてスケッチと同じディレクトリ上に `certificate.h` として保存

<img width="640" alt="ie11.png" src="https://qiita-image-store.s3.amazonaws.com/0/137045/fb5bf85f-e082-3fe6-5f2f-33f750e54ad2.png">

## 設定ファイルの作成
`config_sample.h` をコピーして `config.h` を作成し、WiFiとBeebotteの設定を行います。

WiFiの `password` は平文のまま(そのまま入力)でも構いませんが、ハッシュ化した値を入力することを推奨します。
[ESP32のArduinoスケッチにWi-Fiのパスワードを平文で書くのはやめよう！](https://qiita.com/mascii/items/bbee7b7bff9cf5a2f833)


```C++:config.h
// Wi-FiアクセスポイントのSSIDとパスワード
const char *ssid = "SSID";
const char *password = "0000000000000000000000000000000000000000000000000000000000000000";

// クライアントID（任意）
const char *clientID = "ESP32";

// Beebotteのチャンネルトークン
const char* channelToken = "token_xxxxxxxxxxxxxxxx";

// トピック名（"channel/resource"の形式）
const char* topic = "beebotte_test/led";
```

## スケッチの書き込み
スケッチ(`esp32-beebottle.ino`)内の `#define LED_PIN 2` でLEDのピンを指定しているので、適宜変更してください。
このスケッチを書き込む前に、簡単なLチカのスケッチを試しておくと良いかもしれません。

LEDのピン指定を確認したら、Arduino IDE上の ツール -> ボード での設定が ESP32 Dev Module となっていることを確認して、スケッチをESP32に書き込みします。

<img width="400" alt="ArduinoIDE_01" src="https://qiita-image-store.s3.amazonaws.com/0/137045/47ebdd66-736c-24e5-da24-a8e17d89ec8b.png">

# ESP32とBeebotteの動作確認
Arduino IDEのシリアルモニタで、WiFiとMQTTの接続が確立していることを確認します:

<img width="640" alt="ArduinoIDE_02.png" src="https://qiita-image-store.s3.amazonaws.com/0/137045/1b4fe7e8-1559-60a7-20bf-92c6945fa0d3.png">

macOSなどcurlコマンドがある場合は、以下のコマンドでLEDを点灯させることができるはずです:

```
curl -d '{"data":"led_on"}' -H "Content-Type: application/json" -X POST \
 'https://api.beebotte.com/v1/data/publish/beebotte_test/led?token=token_xxxxxxxxxxxxxxxx'
```

curlコマンドがない場合は、Beebotteの Account Settings -> Access Management で Secret Key をコピーし、Console上 の Secret Key に貼り付けて、PublishのフォームにChannel: `beebotte_test`, Resource: `led`, Data: `led_on` を入力してPublish dataボタンを押すことで、LEDを点灯させることができるはずです:

<img width="640" alt="beebotte_04.png" src="https://qiita-image-store.s3.amazonaws.com/0/137045/61dce752-096a-8240-9442-39cc23ff2e31.png">

<img width="640" alt="beebotte_05.png" src="https://qiita-image-store.s3.amazonaws.com/0/137045/39997770-9003-9849-35d6-4ed5e00b334f.png">

# IFTTTの設定
[IFTTT](https://ifttt.com/)にアクセスしてログインし、以下のような内容でアプレットを作成します(LEDをオンにする例)。

## Step 1. Choose a service (this)
<img width="240" alt="Google Assistant.png" src="https://qiita-image-store.s3.amazonaws.com/0/137045/e97e6aba-2104-b7fd-d292-ac537e47321a.png">
Google Assistantを選択します

## Step 2. Choose trigger
<img width="300" alt="ifttt_step2.png" src="https://qiita-image-store.s3.amazonaws.com/0/137045/753c037e-47e8-6b41-8702-2ebc842f5c85.png">

"Say a simple phrase" を選択します

## Step 2. Complete trigger fields
| 設定項目                                 | 設定内容              |
|------------------------------------------|-----------------------|
| What do you want to say?                 | `電気つけて`   |
| What's another way to say it? (optional) | `電気をつけて` |
| And another way? (optional)              | `ライトをオン`     |
| What do you want the Assistant to say in response? | `点灯します` |
| Language                                 | Japanese            |
ここは、ご自身がGoogle Homeに話す癖や、好みを反映した方が良いです。

## Step 3. Choose action service (that)
<img width="240" alt="Webhooks.png" src="https://qiita-image-store.s3.amazonaws.com/0/137045/c3c5681a-6524-872e-8ae3-99d874f8a62d.png">
Webhooksを選択します

## Step 4. Choose action
<img width="301" alt="Make a web request.png" src="https://qiita-image-store.s3.amazonaws.com/0/137045/17e08d92-27a2-809f-196d-85c02529b0d2.png">
"Make a web request" を選択します

## Step 5. Complete action fields
| 設定項目     | 設定内容                                                                                                                                |
|--------------|-----------------------------------------------------------------------------------------------------------------------------------------|
| URL          | 例) `https://api.beebotte.com/v1/data/publish/beebotte_test/led?token=token_xxxxxxxxxxxxxxxx` |
| Method       | POST                                                                                                                                  |
| Content Type | application/json                                                                                                                            |
| Body         | `{"data":"led_on"}`  (オフの場合は`{"data":"led_off"}`) |

tokenは適切なものに置き換えてください

## Step 6. Review and finish
アプレットの名前を決定して Finish します。

# 動作確認(話かけてLEDを点灯させる)
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Google Home + IFTTT + Beebotte + ESP32 で LEDつけてみた <a href="https://t.co/Fs4LPABtr9">pic.twitter.com/Fs4LPABtr9</a></p>&mdash; mascii (@mascii_k) <a href="https://twitter.com/mascii_k/status/995215395261890561?ref_src=twsrc%5Etfw">2018年5月12日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

「OK Google, 電気つけて」で、LEDが点灯しました！

# 感想
この構成は多分できるんだろなと思っていましたが、いざちゃんとやろうとすると一筋縄ではいかなかったりしました(今回は証明書まわりなど)。
今回の記事も多くの人に試してもらえたらいいなと思い、少し面倒ですがWindowsとMac両方を考慮して記事やコードを書きました。
OS間の差異やTLSについてなど、自分自身の勉強にもなりました。

お手軽さを求めるのなら、Beebotteの代わりに[Blynk](https://www.blynk.cc/)(恐らくMQTTではなく独自プロトコルを用いている)を使った構成のほうが良さそうな感じでした。
通信経路が一部暗号化されていないですが、こちらをまず試してみるのもありだと思いました。
[Google Homeに話しかけてESP32でLチカしてみる](https://qiita.com/miso_develop/items/9c81753a69cb80e006a9)([@miso_develop](https://twitter.com/miso_develop)さんの記事)

# 参考文献
* [IFTTTのトリガーおよびアクションをESP8266で実行する](https://qiita.com/mayfair/items/e761c788a9d8787bc610)
* [IFTTT, Beebotte, Mosquitto, SSL/TLS を使って, なるべく安全に Google Home から Raspberry Pi や ESP8266 を操作する](https://qiita.com/Guwashi/items/e1ea9c61af4715198edc)