GoogleHomeとiftttとDialogflowとfirebaseとLINEBOTとラズパイを使って子供と音声によるLINE交換をしてみる（後編）

# 前回のおさらい

[GoogleHomeとiftttとDialogflowとfirebaseとLINEBOTとラズパイを使って子供と音声によるLINE交換をしてみる（前編）](https://qiita.com/nk-tamago/items/b4039195ca4fc24a7f86)

以下の外部サービス設定とラズパイに自作サービスを登録して、LINEから自作サービスにメッセージを蓄えてGooleHomeに通知を送るところまで書きました。

- 外部サービス
    - LINE Messaging API
    - Dialogflow
    - Cloud Functions
    - Firebase
- 自作サービス
    - ラズパイ3
    - https://github.com/nk-tamago/googlehome-linebot

出来たのはここまですね。
![googlehome2.png](https://qiita-image-store.s3.amazonaws.com/0/211866/ad4f9e1c-57fd-83d9-ca7b-df8ffb6721a9.png)

今回はGoogleHomeとIFTTTを連携して、GoogleHomeにメッセージを読んでもらいます。

# その前に・・・
前回の記事では、自作サービスについての情報が少なかったので補足します。
自作サービスの責務としては以下となります。

- LINE BOTとの連携
    - LINE BOTから送られてきたメッセージをFirebaseかWebhookが受ける
    - 受け取ったメッセージを内部DBに格納する
    - GoogleHomeへLINEが届いた通知メッセージを送る
- GoogleHomeとの連携
    - イベントタイプ毎に以下の処理に振り分ける
        - メッセージ送信
            - LINE BOTへメッセージ送信
        - 未読メッセージの読み上げ
            - 内部DBから未読のメッセージを読み上げて既読にする
        - 既読メッセージの読み上げ
            - 内部DBから既読になってから数分前までのメッセージを読み上げる

これらを実装します。

## 自作サービス
Node.jsで作成し、自宅サーバーとしてラズパイにデプロイします。
GoogleHomeとLANで繋がっている必要があるので自宅サーバーとしていますが、VPNでAWSなどのクラウドと繋がっているのであれば、クラウドにデプロイするのもいいと思います。
以下のモジュールをインストールする必要があります。

- google-home-notifier
- line-bot-sdk-nodejs
- firebase-admin

とくに問題なくインストールできると思いますが、開発用のwindows環境で一部トラブルがありましので、情報共有しておきます。

- google-home-notifier
    - **Apple Bonjour**というサービスを入れないとInstallが失敗しました。
    - iTunesなどApple製のソフトが入っている方は問題ないと思いますが、使っていない方はエラーが出たらBonjour疑ってみたら如何でしょうか？

Node.jsとECMAScript2015をちゃんと弄ったのは初めてですが、非常に便利ですね。
ただ、書きっぷりにかなり不安を覚えたのも確かです。これから勉強ですね。

#### Promiseの多用
今回、非同期個所がどうしても多くなるので、Promiseパターンで実装したのですが、正直こんなPromiseだらけでいいのかと不安になりました。
もっといい書き方があれば教えてください。

#### 試作段階のゴミ
あと、試作段階のロジック（ngrokなど）も残ってたりしますが、目をつぶりましょう。
Databaseとして、**NeDBb**というのを使ってみました。
最初の大きな構想では、メッセージを全て格納する想定でしたので、最終的には専用DBへ移行することを想定して、MongoDBのapiと互換性のあるNeDBを採用しました。
・・・ですが、そもそも音声インターフェースで過去のメッセージを聞くことは意味がないことを悟り、結果的に1日でデータをパージする実装にしています。
そうなると、mapで実装しても全然よかったですね。
モジュール分割も勉強不足で出来ていないですが、時間があればリファクタリングして綺麗にしたいですね。

# IFTTT連携
なかなか本題に入りませんでしたが、やっと本題に入ります。
ここで次回に持ち越したら、やるやる詐欺になってしまいますしね。

GoogleHomeとIFTTTの連携では以下を実現します。

- LINEで"ただいま" → "ただいま"メッセージをLINEへ送る
- 新しいLINE → 未読のメッセージを読み上げて既読にする
- さっきのLINE → 既読になってから数分前までのメッセージを読み上げる

この左の言葉を解釈して各機能へ連携させるのがIFTTTの役目です。

IFTTTの設定は以下のようになります。

## 未読のメッセージを読み上げる
### this
#### Google Assistant
![ifttt_googlehome_unread_this.png](https://qiita-image-store.s3.amazonaws.com/0/211866/dbcc59a0-415c-7563-1e29-929da645afcc.png)
いろいろ登録しましたが、「新しいLINE」が一番認識率が高そうです。

### that
#### Webhook
![ifttt_googlehome_unread_that.png](https://qiita-image-store.s3.amazonaws.com/0/211866/73a5861b-67e6-da56-88d5-98a03a645a10.png)
Firebaseの場合はURLにFirebaseのDatabaseURLを指定します。
未読を読み上げるので、「/googolehome/unread/」へ現在のタイムスタンプを更新するようにします。
Bodyに**{".sv":"timestamp"}**を設定すると、[Firebase](https://firebase.google.com/docs/database/rest/save-data?hl=ja)が自動でタイムスタンプを設定しれくれます。

自作サービス側が「/googolehome/unread/」を監視していますので、タイムスタンプに変更があれば内部DBから未読を読み上げる機能が発火する仕組みです。
ついでに未読から既読にしますので、もう一回「新しいLINE」と呼んでも、もう読み上げられることはありません。
ただし、もう一度聞きたいというニーズもありますので、「さっきのLINE」という機能も作っています。この後で紹介します。

##### FirebaseのRESTによる認証
FirebaseをRESTでアクセスする場合、認証情報が必要となります。最新の公式では**Google OAuth2**を渡せとあったので、試したのですが有効期限がすぐ切れてしまうため、IFTTTのように固定して使うのには向いていないと思いました。※使い方が間違っているかもしれないので、もし違えていればご指摘ください。
そこで現在は非推奨となっているFirebaseの認証キーを使います。
![firebase_auth.png](https://qiita-image-store.s3.amazonaws.com/0/211866/38a36a34-60a4-de59-18bf-990bc5ba82ab.png)
データベースのシークレットをコピーして、URLの最後にauth=●●●●を追加します。
ちなみにFirebaseを使わずに、自作サービスに直接Webhookする場合は、そのURLを設定します。
Content Typeを「application/x-www-form-urlencoded」に変更し、Bodyには「events='[{"type":"unread"}]'」を設定してください。多分いけます・・・。

## さっき読んだメッセージを読み上げる
### this
#### Google Assistant
![ifttt_googlehome_before_this.png](https://qiita-image-store.s3.amazonaws.com/0/211866/3bc9a543-a07e-e33e-b0bf-df9d931dadd9.png)

### that
#### Webhook
![ifttt_googlehome_before_that.png](https://qiita-image-store.s3.amazonaws.com/0/211866/5dee0e59-761b-3a0b-19a5-405c59feb99b.png)
少し前の読み上げるので、「/googolehome/before/」へ現在のタイムスタンプを更新するようにします。
この機能は「新しいLINE」を聞き漏らしたりしてもう一度読み上げたい場合に使います。
現在の仕様は、未読が既読になったら時点から5分間であれば何回でも聞ける機能となっています。
IFTTTの設定はURL以外は変わっていませんので割愛しますね。
Webhookで呼び出したい場合は、Bodyに「events='[{"type":"before"}]'」を設定してください。

## GoogleHomeからLINEにメッセージを飛ばす
### this
#### Google Assistant
![ifttt_line_send_this.png](https://qiita-image-store.s3.amazonaws.com/0/211866/be77a84e-dbd5-d583-34e0-9f575261418e.png)

### that
#### Webhook
![ifttt_line_send_that.png](https://qiita-image-store.s3.amazonaws.com/0/211866/0f91152d-9aa4-d999-e65f-098c1f10325c.png)
thisが先ほどと比べると少し複雑になっています。
「LINEで $」が一番認識率が高いですね。
thatもほとんど変わっていませんが、URLとBodyが変わっています。途中の階層も「googlehome」から「linebot」に変えていますので注意してください。
Bodyは、読み取った「$」部分を送信したいので、**"{{TextField}}"**を設定します。
Webhookで呼び出したい場合は、Bodyに「events='[{"type":"send","text":"{{TextField}}"}]'」を設定してください。

## IFTT連携後のイメージ

### 子供がGoogleHomeでLINEメッセージを送信
![googlehome1.png](https://qiita-image-store.s3.amazonaws.com/0/211866/2af3eb37-d14a-81f1-6cb6-75576a9699da.png)
### 子供がGoogleHomeから未読、少し前のLINEメッセージを聞く
![googlehome3.png](https://qiita-image-store.s3.amazonaws.com/0/211866/85bc14a9-8eea-726a-5588-f196a976a465.png)

# さいごに
今回、GoogleHomeの地位を向上すべく始まったプロジェクトですが、はたして結果はどうなったか・・・

子供は大喜びです。大成功です。
夜な夜な寝る時間を削ってやった甲斐があったというもんです。

ただ嫁がボソッと、「安いスマホ買えば済むよね」という身も蓋もないことを言ったことは伏せておきます。

次は、王道で行くとリモコン制御ですかね。
せっかくラズパイも買ったのですから満喫しないと。

2回に渡り長文でしたが最後まで読んでいただき、ありがとうございました！