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

# はじめに
AWS Summitで始めてみたalexaさんに心奪われAIスピーカに興味を持ち、気が付いたらGoogleHomeが家に置いてありました。

家族の無茶な命令で謝ってばかりのGoogleHomeの地位を向上させるべく、今回のプロジェクトを始めました。
まだスマホを持っていない子供との遠隔コミュニケーションが取れるようになれば、売れっ子間違いなしです。

※このプロジェクトを実現するにあたり、以下の記事が非常に参考になりました！ありがとうございました！
https://qiita.com/miso_develop/items/be562d8a823ad2639d94

絵が非常にわかりやすかったため、インスパイアされて~~パクって~~作ってみました。

# 実現イメージ
### 子供がGoogleHomeでLINEメッセージを送信
![googlehome1.png](https://qiita-image-store.s3.amazonaws.com/0/211866/2af3eb37-d14a-81f1-6cb6-75576a9699da.png)
### 親がLINEメッセージをGoogleHomeへ送信
![googlehome2.png](https://qiita-image-store.s3.amazonaws.com/0/211866/ad4f9e1c-57fd-83d9-ca7b-df8ffb6721a9.png)
### 子供がGoogleHomeから未読のLINEメッセージを聞く
![googlehome3.png](https://qiita-image-store.s3.amazonaws.com/0/211866/85bc14a9-8eea-726a-5588-f196a976a465.png)

ポイントは子供が使うので、GoogleHomeとのやり取りはシンプルな言葉でできること。

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

# 実現手段
本当なら自宅サーバーのラズパイとLINEBOTサービスだけで完結させたかったけど、一刻も早く地位を向上させる必要があるため、いろいろ情報を調べて以下のサービスを活用することでまずは実現させることを優先とします。
### 実現に必要なサービス
- LINE Messaging API
- IFTTT
- Dialogflow
- Cloud Functions
- Firebase

LINE Messaging APIはなければ今回のLINEで云々プロジェクトが始まりません。
IFTTTはGoogleHomeとFirebase(webhook)との連携で必要となります。
その他は、自宅サーバーが外部公開できていればwebhookで発火できますが、めんどくさくてしていません・・・。ngrokを使うことも考えましたが、常にトンネリングするのと、ネットワークが切れたら再接続でURLが変わるため、試作段階で却下です。

# 準備
## 各サービスへ登録しよう
### LINE Messaging API
LINE BOTはpushサービスを使うので、「Developer Trial」で登録します。
Channel基本設定で、以下のように設定します。

- Webhook送信 → 利用する
- Botのグループトーク参加 → 利用する
- 自動応答メッセージ → 利用しない

WebhookのURLはFirebaseを登録してからなので後で設定。

### Dialogflow
Googleアカウントでサクッと登録してみます。
自分のプロジェクトを作成するので、他のブログを参考にして作ってみてください。
とりあえず、LANGUAGEは「Japanese — ja」で。TIME ZONEも忘れずに。
では「Intents」を作っていきましょう。
その前に、「Integrations」で**LINE**にチェックを入れるのと、「Fulfillment」で**Inline Editor**をENABLEDにしましょう。
Fulfillmentは最終的には**Inline Editor**ではなく**Webhook**になりますが、最初を**Inline Editor**にすることで自動的に**Cloud Functions**に関数が作られます。
その関数を使っていく過程で、**Webhook**に強制的に移行されます。

#### LINEの設定
以下の設定はLINE Messaging APIの管理画面から持ってきましょう。

- Channel ID
- Channel Secret
- Channel Access Token

「Webhook URL」はURLをコピーして LINE Messaging APIの「Webhook URL」に設定してください。

#### Intentsの作成
ここでの役割は親のLINEメッセージをLINEBOTがそのまま横流しするのが役目となります。
要するに、メッセージに対して何もアクションを起こさず、全てFallbackとしてLINEのPayloadをFulfillmentにそのまま渡してあげるということです。
「CREATE INTENTS」の右にある3点をクリックして「Create Fallback Intents」を選択します。
![intents_fallback.png](https://qiita-image-store.s3.amazonaws.com/0/211866/78803638-f710-5099-03bf-2e7e78d34988.png)

Actionに「input.linetext」を入力するのと、FulfillmentのUse Webhookをチェック入れるだけです。
![intents_fallback_edit.png](https://qiita-image-store.s3.amazonaws.com/0/211866/787184b2-f290-17a5-6bc5-12e59da1ba47.png)

Actionの「input.linetext」はこの文字列でなくても大丈夫です。Fulfillmentの実装時にルーティングで使用するので、そこと整合が取れればOKです。
では次はFulfillmentを実装していきます。

#### Fulfillmentの実装
ここまで、駆け足で書いてきましたが、どうも何か忘れているような気がする・・・。
・・・あ、Firebaseの登録ですね。うん。忘れました。
どこかの流れで、登録した気がするのですが・・・。
とりあえず、登録してある前提で話を進めます。

今回は、Inline Editorで作成されたCloud Founctionsを改修する形で実装します。
まずは、右側にあるダウンロードをクリックしてローカル環境に落としましょう。
![inlineeditor.png](https://qiita-image-store.s3.amazonaws.com/0/211866/999cbed6-b901-dc60-13f3-4f462f7dae0a.png)

ローカルでの開発＆デプロイは以下を参照してください。
https://firebase.google.com/docs/functions/get-started?hl=ja
https://firebase.google.com/docs/hosting/deploying?hl=ja

##### 改修内容
index.jsの先頭付近に以下2行を追加します。

```js
const firebase = require('firebase-admin');
firebase.initializeApp(functions.config().firebase);
```

こんな感じになるはずです。

```js
'use strict';

const functions = require('firebase-functions'); // Cloud Functions for Firebase library
const DialogflowApp = require('actions-on-google').DialogflowApp; // Google Assistant helper library
const firebase = require('firebase-admin');
firebase.initializeApp(functions.config().firebase);
```

'input.unknow'と'default'の間に'input.linetext'を追加します。
はい。これだけです。

```js
// The default fallback intent has been matched, try to recover (https://dialogflow.com/docs/intents#fallback_intents)
'input.unknown': () => {
  // Use the Actions on Google lib to respond to Google requests; for other requests use JSON
  if (requestSource === googleAssistantRequest) {
    sendGoogleResponse('I\'m having trouble, can you try that again?'); // Send simple response to user
  } else {
    sendResponse('I\'m having trouble, can you try that again?'); // Send simple response to user
  }
},
'input.linetext': () => {
  if (requestSource !== "line") {
    sendResponse('LINEからじゃないよ');
    return;
  }
  if( !(requestData.type === "message" && requestData.message.type === "text") ){
    sendResponse('テキストメッセージしか送れないよ');
    return;
  }

  let update = {
    '/linebot/receive':requestData
  };

  Promise.resolve().then( () =>{
    return firebase.database().ref().update(update);
  }).catch((err)=>{
    sendResponse("送信に失敗したよ:"+ err );
    return
  }).then(()=>{
    let msg = requestData.message.text + " を送ったよ";
    sendResponse(msg);
  });

},
// Default handler for unknown or undefined actions
'default': () => {
```

どこかで、`$ firebase init`みたいなことをしたりしましたが、何とかなるので乗り切ってください。
最後に、`$ firebase deploy`をすれば終了です。

もう一度、Fulfillmentの画面に戻ると、Inline Editorではエラーとなるはずです。
Webhookに切り替えましょう。

### FirebaseのDatabase
Firebaseは非常にシンプルですね。jsonの階層がそのままURLの階層で扱えます。
始めて使いましたが、このようなスキーマとなります。
基本的な使い方としては、googlehomeは通知用のみ。linebotはreceiveにlineのpayload、sendにbotに話させる言葉を格納します。

![firebase.png](https://qiita-image-store.s3.amazonaws.com/0/211866/65ca1e18-8eff-c01c-48b2-b442160eae1b.png)

## ラズパイにNodejsとサービスを入れましょう。
### ラズパイとNodeのセッティング
これは、そこらじゅうに転がっているので、そちらを見てください。
ちなみに、自分はラズパイ3とケースをAmazonで買いました。

### サービスのインストール
ソースをGitHubに上げたのでそちらを参照してください。
今回、QiitaもGitHubも初です。
https://github.com/nk-tamago/googlehome-linebot

これで、LINEに投稿した内容がサービス内のDBの蓄えられて、未読メッセージとして聞けるようになります。

次はIFTTTと連携して、未読メッセージを聞いてみましょう。
今日は遅くなったので、これまで。明日更新します。

----------------------------
2017年11月10日更新
[GoogleHomeとiftttとDialogflowとfirebaseとLINEBOTとラズパイを使って子供と音声によるLINE交換をしてみる（後編）](https://qiita.com/nk-tamago/items/31ee5b70c6003fb97ee4)