レッツラズパイ！〜Google HomeでLピカさせよう編〜

## レッツラズパイ！・プロジェクト
1. [レッツラズパイ！〜Raspberry3にOSをインストールしよう〜](https://qiita.com/westvirginia/items/edc3b56da7be58419d70)  
[【番外編】レッツラズパイ！〜"ディスプレイなしで"RaspberryPiにOSをインストールしよう編〜](https://qiita.com/westvirginia/items/0d3b7d7dd19116cc14bf)
2. [レッツラズパイ！〜Lチカ＆Lピカをマスターしよう編〜](https://qiita.com/westvirginia/items/e339dbaf3286ea966483)
3. [レッツラズパイ！〜Webカメラで監視しちゃうゾ編〜](https://qiita.com/westvirginia/items/ba79f7549b43da116467)
4. [レッツラズパイ！〜温度センサーとmailgunで検知メールを送ろう編〜](https://qiita.com/westvirginia/items/c06887fd464e3718082d)
5. レッツラズパイ！〜Google HomeでLピカさせよう編〜(これ)
6. [レッツラズパイ！〜Google Homeに室温を教えてもらおう編〜](https://qiita.com/westvirginia/private/f0842c034695665a78a6)
7. [レッツラズパイ！〜Lチカボタン編〜](https://qiita.com/westvirginia/private/7b33d27ce50d30895e13)


RaspberryPiを始めて触る＆IT初心者向けのドキュメントです。私の所属する会社で使う、IT初心者の方のインターンシップ向けのドキュメントとして書きはじめたので、かなり丁寧に書いていますがご了承下さい。

## 参考記事
 - [IFTTTとBeebotteを使ってGoogleHomeからRaspberryPiを操作する](https://qiita.com/msquare33/items/9f0312585bb4707c686b)
 - [Google AssistantとRaspberry Piで自宅の家電を操作する](https://qiita.com/104ki/items/9dcfe03246099d03d4dd)
 - [Amazon EchoとRaspberry Piで部屋の照明を制御する #おうちハック](http://denpa-shinbun.com/entry/amazonecho-raspberrypi)
 - [IFTTTの使い方](https://ifttt-japan.club/knowledge#IFTTT)

この4つの記事を参考にさせていただきました。

## Google HomeでLピカさせよう

### 用意するもの
- Raspberry Pi 3 Model B　※[OS設定](https://qiita.com/westvirginia/items/edc3b56da7be58419d70)済みのもの
- Google Home （今回はminiを使用）
- [レッツラズパイ！〜Lチカ＆Lピカをマスターしよう編〜](https://qiita.com/westvirginia/items/e339dbaf3286ea966483)で使用したモノ

### 簡単な構成図
 - Google HomeとRaspberry Pi、作業用のクライアント端末は同一ネットワーク上のWi-Fiに接続させます。
 - 今回はRaspberry PiとGoogle Homeを連携させるためにIFTTT,Beebotteを使用します。
 - Google Assistantが使用する人の発言を拾い、IFTTTをトリガー（this）させます。
 - IFTTTのwebhook（外部のウェブサーバに対してウェブリクエストを送信する機能）を利用してBeebotteに情報をPOSTして、その情報をRaspberry Piが取得しLEDランプを点灯させます。

図にすると以下の通りです。

![【修正済み】Google Home×Lピカ構成図.jpg](https://qiita-image-store.s3.amazonaws.com/0/164786/5d7199af-4068-ca94-6715-99dc7a5ceb78.jpeg)




### Google Homeの準備
#### スマートフォンにてアプリをインストールからの設定
まずは、使用するGoogle Homeのデバイス設定を行うため、スマートフォンからGoogle Homeのアプリケーションをインストールします。

こちらは、公式手順を参照して下さい。

- Androidは[こちら](https://support-content-staging.sandbox.google.com/googlehome/answer/7029485?co=GENIE.Platform%3DAndroid&hl=ja)
- iPhone・iPadは[こちら](https://support-content-staging.sandbox.google.com/googlehome/answer/7029485?co=GENIE.Platform%3DiOS&hl=ja)

### Beebotteセットアップ

[Beebotte](https://beebotte.com/)は、IoT向けのクラウドサービス。REST API や MQTTをサポートして、接続された機器にリアルタイムでメッセージを通知することができます。

今回の通信のイメージとしては、以下のようになります。

Google Home → IFTTT → Beebotte（ここ） ⇔　Raspberry Pi → LEDランプ

ではさっそく、Bebotteの設定を始めていきましょう！

#### Channel作成
1. 「Home」より[Create New]をクリックして新規Channelを作成する。

![Beebotte_1.png](https://qiita-image-store.s3.amazonaws.com/0/164786/56fcb954-eb21-7ae9-4a85-7501d3f2f8c7.png)  
2. 各項目を下記の通りに設定し、[Create Channel]をクリックします。下記以外の項目はデフォルト値のままでOKです。

| 設定項目 | 設定値 |
|:-:|:-:|
|Channel Name|MySmartHome|
|Channel Description|MySmartHome|
|Resource Name|voice|
|Resource Description|voice|
![Beebotte_2.png](https://qiita-image-store.s3.amazonaws.com/0/164786/91be5f21-0fad-dcda-cbe6-e46cdde7f097.png)  


#### アクセストークンの取得
1. 前手順で作成した「MySmartHome」をクリックします。

![Beebotte_3.png](https://qiita-image-store.s3.amazonaws.com/0/164786/7e69c833-e5bd-774c-8d9c-b252354f6782.png)  
2. 赤丸で囲まれた部分に赤文字でトークンが表示されているので、それをメモしておきます。
![Beebotte_4.png](https://qiita-image-store.s3.amazonaws.com/0/164786/65aafc6c-4645-1139-412e-33f68d14d612.png)  
#### Beebotteの動作確認
1. Account SettingsメニューのAccess Managementタブをクリックして、「Seacret Key」をメモしておきます。
![Beebotte_5.png](https://qiita-image-store.s3.amazonaws.com/0/164786/edcd7085-c98b-abf0-bcb5-bed446c20505.png)  
2. Consoleメニューをクリックして、各項目を下記の通りに設定し、[Subscribe]をクリックします。下記以外の項目はデフォルト値のままでOKです。

|設定項目|設定値|
|:-:|:-:|
|Seacret Key|手順1.でメモした内容を記載|

以下、設定値は「Subscribe」についての設定になります。

|設定項目|設定値|
|:-:|:-:|
|Channel Description|MySmartHome|
|Resource Name|voice|

![Beebotte_6.png](https://qiita-image-store.s3.amazonaws.com/0/164786/2caca445-b3e9-9d99-ddc4-ac0acb36abd8.png)  
3. 「Messages」に青い文字が表示されていることが確認できたら、Macを使用している場合はターミナルから、Windowsを使用している場合は、Raspberry Piから下記コマンドを実行します。

```
curl -i -H "Content-Type: application/json" -X POST -d '{"data":"Hello World"}' http://api.beebotte.com/v1/data/publish/MySmartHome/voice?token=[Channelのトークン]
```

「Messages」に先程作成したチャンネル名やリソース名、"Hello World"等を含む文字列が表示されればBeebotteの動作確認は完了です！


### IFTTTセットアップ

[IFTTT](https://ifttt.com/)は簡単に言うとWebサービス同士を自動的に連携できるサービスです。

今回は、Google AssistantとIFTTTのwebhookを連携させ、Beebotteに情報をPOSTします。
今回の通信のイメージとしては、以下のようになります。

Google Home → IFTTT（ここ） → Beebotte ⇔　Raspberry Pi → LEDランプ

ではさっそく、IFTTTの設定を始めていきましょう！

#### 『this』トリガーの作成

GoogleHomeからの音声を受けてBeebotteにPOSTするためのIFTTTを作成します。
1. IFTTTにサインアップ＆サインインします。
  
![002_IFTTT.png](https://qiita-image-store.s3.amazonaws.com/0/164786/e3dcb70d-31ce-0ceb-7c35-d3c34e0d723b.png)    
2. サインインが成功したら、画面上にある［My Applets］をクリックします。

![003_IFTTT.png](https://qiita-image-store.s3.amazonaws.com/0/164786/87404a8e-6130-d617-be01-5bfa6ffe97e9.png)　　
3. 「My Appletsページ」が表示されたら、［New Applet］をクリックします。

![004_IFTTT.png](https://qiita-image-store.s3.amazonaws.com/0/164786/371fb9a1-4c0f-a4f2-1a25-bd262b810909.png)　　
4. これからAppletを作成していきます。

IFTTTの基本的な考え方は「If this then that」です。「もし〜ならば〜する」といった具合ですね。


**`【考え方】`**
**`・this → どのプラットフォームの何をトリガーにするか`**
**`・that → どのプラットフォームの何を実行するか（アクション）`**


それでは、「もし〜ならば」から作成していきますので、［this］をクリックします。
今回でいうと「もし"Google Assistantからあるフレーズを認識した"ならば」となりますね。

![005_IFTTT.png](https://qiita-image-store.s3.amazonaws.com/0/164786/54941f47-96a5-dbc2-cac7-983a9a1011a5.png)  
5. 検索フォームより［Google Assistant］を検索し、クリックします。

![006_IFTTT.png](https://qiita-image-store.s3.amazonaws.com/0/164786/be7c076c-e047-44ce-421d-805b026bb184.png)  
6. 今回は、キーワード付きのフレーズを認識できる機能を使いますので、［Say a phrase with a text ingredient］をクリックします。

![007_IFTTT.png](https://qiita-image-store.s3.amazonaws.com/0/164786/17c666ad-13b1-d2f4-4f9a-3a723c653ada.png)  
7. 動作を設定します。設定項目は以下の通りです。

|項目|値|
|:---|:---|
|What do you want to say?|部屋の $ をつけて|
|What do you want the Assistant to say in response?|ちょっとまっててー|
|Language|Japanese|


![008_IFTTT.png](https://qiita-image-store.s3.amazonaws.com/0/164786/1202f843-25c9-e419-9aaf-1783f77d0bf8.png)

他に入力する箇所もありますが、空欄でOKです。
入力が完了したら［Create trigger］をクリックします。

これで「もし〜ならば」の［this］の作成は完了です！

#### 『that』アクションの作成

1. 続いて、「ならば〜する」を作成していきますので、［that］をクリックします。

![009_IFTTT.png](https://qiita-image-store.s3.amazonaws.com/0/164786/03e9fd5a-03df-36c3-e63c-95a3b6cbd2c7.png)  
2. 検索フォームより［webhooks］を検索し、クリックします。

![010_IFTTT.png](https://qiita-image-store.s3.amazonaws.com/0/164786/a59cb963-291b-0415-62c7-d0aed50c2a8a.png)


webhooksは、FTTT上でWEBリクエストによる『トリガー』や『アクション』が利用できるものです。  
3. ［Make a web request］をクリックします。

![011_IFTTT.png](https://qiita-image-store.s3.amazonaws.com/0/164786/b13380a6-3968-ceab-9be2-d5b36042c233.png)  
4. webhooks(アクション)の設定をします。設定項目は以下の通りです。

|項目|値|
|:---|:---|
|URL|https://api.beebotte.com/v1/data/publish/[bebotteのChannel名]/voice?token=[Beebotteのトークン]|
|Method|POST|
|Content Type|application/json|
|Body|{"data":[{"room":"office","device":"{{TextField}}","action":"on"}]}|

※URLの内容はBebotteで作成したChannelとトークンにしましょう！

![【修正済み】012_IFTTT.png](https://qiita-image-store.s3.amazonaws.com/0/164786/d298c03e-858d-1e0d-4034-833bde7b1a32.png)



入力が完了したら［Create action］をクリックします。  
5. 確認が入るので、問題なければ［Finish］をクリックします。

![013_IFTTT.png](https://qiita-image-store.s3.amazonaws.com/0/164786/43fc0b1d-6dc5-d1a9-e968-2f9c65bd52d1.png)  
6. この画面が表示されたら、IFTTTの完成です！！！

![014_IFTTT.png](https://qiita-image-store.s3.amazonaws.com/0/164786/f9b45616-2513-fb63-d839-39d2ed98b43c.png)


#### 「部屋の◯◯を消して」も作ろう

やっぱり、電気はつけたら消したいですよね。
なのでさっそく「消して」ver.も作成しましょう！

手順は簡単です。

『this』と『that』の設定を少し変えるだけ！
作り方は同じです。

今回は、設定値だけ載せておきますので、手順は「つけて」の手順を参考にしましょう。

* 『Google Assistant』の設定値

|項目|値|
|:---|:---|
|What do you want to say?|部屋の $ を消して|
|What do you want the Assistant to say in response?|ちょっとまっててー|
|Language|Japanese|

* 『webhooks』の設定値

|項目|値|
|:---|:---|
|URL|https://api.beebotte.com/v1/data/publish/[bebotteのChannel名]/voice?token=[Beebotteのトークン]|
|Method|POST|
|Content Type|application/json|
|Body|{"data":[{"room":"office","device":"{{TextField}}","action":"off"}]}|

### 動作確認

BeebotteとIFTTTの設定が完了したので、実際にGoogleHomeに「部屋のライトをつけて」と言ってみましょう！

そうすると・・・・！？

![015_IFTTT.png](https://qiita-image-store.s3.amazonaws.com/0/164786/5aae3272-4c32-a26d-7b7e-59de11d35db9.png)


成功すれば、メッセージに表示されます！
これで、BeebotteとIFTTTが連携されていることが確認できましたね。

### Raspberry Piセットアップ
Python3を使ってRaspberry PiからBeebotteのトリガーを検知させます。
前提として、ラズパイにSSH接続をしましょう！


#### Beebotte連携テスト
これからRaspberry PiにPythonのコードを作成していきます。
#### MQTTライブラリのインストール
1. Beebotteを監視するためのライブラリをインストールします

````
$ sudo pip3 install paho-mqtt
````

#### Beebotte連携テスト
1. 事前にサーバにアクセスするための証明書をダウンロードします。

```
$ wget https://beebotte.com/certs/mqtt.beebotte.com.pem -P ~/work
```

ダウンロード先は、[LチカLピカ編](https://qiita.com/westvirginia/items/e339dbaf3286ea966483)で作成したディレクトリです。これから作成するPythonファイルの同じディレクトリで作成します。ディレクトリがない場合は、新規で作成してください。
　　


2. 先ほどダウンロードした証明書のディレクトリに移動します。

```
$ cd ~/work
```  

　　
3. 連携テスト用のプログラムを作成します。

````
$ vim smarthome.py
````  

　　
4. 下記プログラムをコピペして作成して下さい。

````Python:smarthome.py
import paho.mqtt.client as mqtt
import json

TOKEN = "[Beebotteのトークン]" # 変更箇所
HOSTNAME = "mqtt.beebotte.com"
PORT = 8883
TOPIC = "[BeebotteのChannel名]/voice" # 変更箇所
CACERT = "mqtt.beebotte.com.pem"

def on_connect(client, userdata, flags, respons_code):
    print('status {0}'.format(respons_code))
    client.subscribe(TOPIC)

def on_message(client, userdata, msg):
    print(msg.topic + " " + str(msg.payload))
    data = json.loads(msg.payload.decode("utf-8"))["data"][0]
    data = {key:value.strip() for key, value in data.items()}
    if "room" in data.keys():
        print(data)

client = mqtt.Client()
client.username_pw_set("token:%s"%TOKEN)
client.on_connect = on_connect
client.on_message = on_message
client.tls_set(CACERT)
client.connect(HOSTNAME, port=PORT, keepalive=60)
client.loop_forever()
````

　　
一部、BeebotteのトークンとChannel名に変更する箇所があるので注意してください。
編集後は、［ESC］キーを押下して［:wq］で保存しましょう。
　　
5. それではさっそくプログラムを実行してみましょう。

`````
$ python3 smarthome.py
`````

↓　実行後・・・

`````
status 0
`````

上記のように表示されたことを確認します。  
6. 「OK Google！部屋のライトをつけて！」と言ってみましょう。

`````
MySmartHome/voice b'{"data":[{"room":"office","device":"\xe9\x9b\xbb\xe6\xb0\x97","action":"on"}],"ispublic":true,"ts":1529208677835}'
{'device': 'ライト', 'room': 'office', 'action': 'on'}
`````

連携が成功していると、上記のように認識します！
以上で、Beebotteとの連携テストは終了です。

#### Raspberry Pi配線作業

基本的には[レッツラズパイ！〜Lチカ＆Lピカをマスターしよう編〜](https://qiita.com/westvirginia/items/e339dbaf3286ea966483)の配線を参考にしてください。

ただし今回は、16番ピンから制御するため、LEDのプラス側のジャンパーワイヤーを16番ピンに差し替えてください。

配線図は以下の通りです。

![016_配線図.jpeg](https://qiita-image-store.s3.amazonaws.com/0/164786/3f2743bd-4dfd-a339-4763-754f44a5a16a.jpeg)


#### Google Homeから操作してLEDピカさせる

1. ラズパイのGPIOを利用できるようにするためプログラムを編集します。また、さきほど作ったプログラムは「部屋の〇〇をつけて！」の「◯◯」は何が来ても反応してしまいます。よって、プログラムに「電気」と「ライト」だけ反応するように編集します。。

`````Python:smarthome.py
import paho.mqtt.client as mqtt
import json
import time
import RPi.GPIO as GPIO

TOKEN = "[Beebotteのトークン]" # 変更箇所
HOSTNAME = "mqtt.beebotte.com"
PORT = 8883
TOPIC = "[BeebotteのChannel名]/voice" # 変更箇所
OUTPUT_PIN = 16
CACERT = "mqtt.beebotte.com.pem"
GPIO.setmode(GPIO.BOARD)
GPIO.setup(OUTPUT_PIN, GPIO.OUT)

# 名詞の変換表
noun_conv = {
            "電気": "light",
            "ライト": "light",
            }

# 接続中の処理を記載→subscribeする
def on_connect(client, userdata, flags, respons_code):
    print('status {0}'.format(respons_code))
    client.subscribe(TOPIC)

def on_message(client, userdata, msg):
    print(msg.topic + " " + str(msg.payload))
    data = json.loads(msg.payload.decode("utf-8"))["data"][0]
    # Google Assistantの側でTextFiledの前後に半角スペースが入ることがあるのでstripして削除
    data = {key:value.strip() for key, value in data.items()}
    # 「〜を」と言ってしまった際に「を」が入ってTextFieldに入ってくることがあるので削除
    if data["device"].endswith("を"):
        data["device"] = data["device"][:-1]
    print(data)

    # 日本語の表記ゆれに併せて、IFTTTのTextFieldをlightに修正
    if not data["device"] in set(noun_conv.values()):
        try:
            data["device"] = noun_conv[data["device"]]
            print(data)
        except:
            print(data)
            print("unkown device")
            return

    # 部屋の電気（ライト）をつけて
    if data['action'] == 'on':
        GPIO.output(OUTPUT_PIN, True)

    # 部屋の電気（ライト）を消して
    if data['action'] == 'off':
        GPIO.output(OUTPUT_PIN, False)

client = mqtt.Client()
client.username_pw_set("token:%s"%TOKEN)
client.on_connect = on_connect
client.on_message = on_message
client.tls_set(CACERT)
client.connect(HOSTNAME, port=PORT, keepalive=60)
client.loop_forever()
`````

一部、BeebotteのトークンとChannel名に変更する箇所があるので注意してください。
編集後は、［ESC］キーを押下して［:wq］で保存しましょう。  
2. それではもう一度プログラムを実行して「OK Google！部屋のライトをつけて！」と言ってみましょう！

`````
$ python3 smarthome.py
`````

↓　実行後・・・

`````
MySmartHome/voice b'{"data":[{"room":"office","device":"\xe3\x83\xa9\xe3\x82\xa4\xe3\x83\x88","action":"on"}],"ispublic":true,"ts":1529991711851}'
{'room': 'office', 'device': 'ライト', 'action': 'on'}
{'room': 'office', 'device': 'light', 'action': 'on'}
`````

正常に動作をしたら、続けて「OK Google！部屋のライトを消して！」と言ってみましょう！

`````
$ python3 smarthome.py
`````

↓　実行後・・・

`````
MySmartHome/voice b'{"data":[{"room":"office","device":"\xe3\x83\xa9\xe3\x82\xa4\xe3\x83\x88","action":"off"}],"ispublic":true,"ts":1529991798747}'
{'room': 'office', 'device': 'ライト', 'action': 'off'}
{'room': 'office', 'device': 'light', 'action': 'off'}
`````

どうですか？LEDライトは消えましたか？

Google HomeでLピカさせよう編は以上です。お疲れ様でした♪