Node-REDを使ってLINEとGoogleHomeを連携させた話【GoogleHome LINE Node-RED】

# 事の始まり
僕はご飯が大好きな文系新卒君です。
ありがたいことに、家に帰るとご飯が毎日用意されています。
しかし学生時代のように出来立てのホカホカご飯を食べれる機会は減ってしまいました。
そう...社会人は学生とは違い帰る時間がバラバラ。
帰る時間を連絡しても、1日中ケータイを触ってるわけじゃないのでご飯の完成にラグが起きてしまう。

.....だったら帰宅時間を教えることのできる通知機能を作ればいいじゃないか！！

## 全体図
どうすれば帰宅時間を知らせることができるか考えた結果、
**「物理的」**に知らせるのが一番じゃないかと考えました。
![100.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469819/93452af2-a96c-4513-4276-248d6403e395.png)

こんな感じで実装すれば、ラインメッセージと自宅へ音声送信両方が実現ができるはず！


## 実装
それでは実装していきますよ！！
事前準備は4つ

- Node-REDのインストール
- LINE Developersのアカウント
- Google App Script
- Node-REDと同じLANに接続されたGoogleHome

今回LINEとGoogleHomeを繋げる目的で利用する`Node-RED`ですが
何かと何かを繋ぐ際にGUI上で実行できるWebアプリケーションと思って下さい。

参考資料
[Node-RED日本ユーザ会](https://nodered.jp/)
[Windowsで実行する : Node-RED日本ユーザ会](https://nodered.jp/docs/getting-started/windows)
[LINEのBot開発 超入門（前編） ゼロから応答ができるまで](https://qiita.com/nkjm/items/38808bbc97d6927837cd)
[Google Homeの初期設定をする手順](https://dekiru.net/article/17530/)



### １．Node-REDとGoogleHomeを繋げる

まず初めにNode-REDのページを開き、パレットの管理から`node-red-contrib-cast`を追加します。
これがGoogleHomeへ送ったメッセージを読み上げさせるノードになります。
インストールが完了したら、下図のフローを作成してください。
![無題1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469819/ac6fbf54-221b-52d5-3306-1a9f6718e93c.png)

次に**Castノード**の設定を行います。

|項目  |入力内容  |
|---|---|---|
|IP  |GooglHomeのIPアドレス  |
|language  |ja  |
|Volume|0~100(好みの音量サイズ)  |

設定後に**injectノード**を実行し、設定した言葉がGoogleHomeから聞こえたらOKです！


### ２．Node-REDをネットワークに公開
このままではNode-REDはローカル外からのアクセスができません。
なので簡単にローカル環境を外部から接続させることのできる`ngrok`を使いたいと思います。
ngrokをインストールしてNode-REDで設定されているポートをパスワード付きで公開してください。

```
EXAMPLES:
    ngrok http 80                    # secure public URL for port 80 web server
ngrok by @inconshreveable                                                                                                                                           (Ctrl+C to quit)

Session Status                online
Version                       2.2.4
Region                        United States (us)
Web Interface                 http://127.0.0.1:1880
Forwarding                    http://xxxxxxxx.ngrok.io -> localhost:1880
Forwarding                    https://xxxxxxxx.ngrok.io -> localhost:1880

Connections                   ttl     opn     rt1     rt5     p50     p90
                              6       0       0.05    0.02    23.33   25.98
```

`Forwading`に書かれているURL(https)にアクセスができたらOKです！

[ngrokの使い方（windows, mac）](https://qiita.com/Esfahan/items/74e71edfe17d9935d47e)
[少しでも安全にngrokを使用する(Basic認証)](https://qiita.com/da-sugi/items/77f5b9bbbd32d8a79bf3)


### ３．LINEとNode-REDを繋げる
最後にLINEとNode-REDを繋げたいと思います。
まずはGoogle App Script(GAS)で以下のコードを張り付けて下さい。
※アクセス先の情報は自身で入力してください。

```
function doPost(e) {
  // アクセス先の情報
  var url = "ngrokで作成したHTTPSのURL" + "/line";
  var userid = "任意のID";
  var password = "任意のパスワード";
    
    // POSTメソッドの投稿データ
  var event = JSON.parse(e.postData.contents).events[0];
  var replyToken = event.replyToken
  var msg = event.message.text;
  var msgType = event.message.type;
  
  var payload = {"replyToken":  replyToken, "message":msg, "type":msgType};
    
    // POSTメソッドのオプション
    var options = {
      "method" : "POST",
      "headers" : {"Authorization" : " Basic " + Utilities.base64Encode(userid + ":" + password)},
      "payload" : payload,
      "muteHttpExceptions" : true
    }
    
    try{
      // POSTメソッドのリクエスト
      var response = UrlFetchApp.fetch(url, options);
      var content = response.getContentText("UTF-8");
    }catch(e){
      Logger.log(e.message);
    }
}
```
その後**Webアプリケーションとして導入**を行うことでWebhook用のURLが表示されるので、
それを忘れないようコピーして置いてください。(`Current web app URL`のところです)
![無題2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469819/4484c7ab-4861-2fdb-ae56-31f79ec0d8f1.png)

**LINE Developers**へアクセスしてWebhook先へ先ほどのURLを貼り付けます。

![無題3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469819/7cb44262-daaa-f579-8542-b114c32eff30.png)

ついでに**チャンネルアクセストークン**を使うのでメモしておきましょう。
![100.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469819/ad2b6859-8c8f-cc80-a4ab-7bd7130b3ef8.png)

あとはNode-RED上でLINE+GASからのメッセージとGoogleHomeを繋げてあげれば完了です！

### ４．LINEのメッセージとGoogleHomeを繋げる
いよいよ最終工程。完成状態はこんな感じになります！
![無題4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469819/14bb4c02-0691-97f5-ebaa-b5b867211474.png)
最後に下に記載したJSONデータを読み込ませて、以下の項目を行えば終了です！！

- `googlehomeノード`を最初に設定したgooglehomeノードに変更。
- `Line Reply API用設定`の**Bearer "your_channel_access_token"**の`""中身を`先程メモしたチャンネルアクセストークンに変更。

※Line Reply API用設定でLINE Developersから**チャンネルアクセストークンは**確認できます。


**作成したLINE botにメッセージを送信すれば、Googleホームが読み上げてくれます！！！**

```
[{"id":"314b7d3f.2adc62","type":"tab","label":"フロー 1","disabled":false,"info":""},{"id":"72e325a4.cdbacc","type":"comment","z":"314b7d3f.2adc62","name":"line reply msg","info":"","x":310,"y":160,"wires":[]},{"id":"65a3144c.b1371c","type":"http in","z":"314b7d3f.2adc62","name":"","url":"/line","method":"post","upload":false,"swaggerDoc":"","x":170,"y":220,"wires":[["246b9d27.a33942","4ff3caa3.50ed94"]]},{"id":"accdaf77.6e5c9","type":"http response","z":"314b7d3f.2adc62","name":"","statusCode":"","headers":{},"x":850,"y":220,"wires":[]},{"id":"1bc5bba6.3b0244","type":"http request","z":"314b7d3f.2adc62","name":"Line Reply API","method":"POST","ret":"txt","paytoqs":false,"url":"https://api.line.me/v2/bot/message/reply","tls":"","persist":false,"proxy":"","authType":"","x":660,"y":220,"wires":[["accdaf77.6e5c9"]]},{"id":"246b9d27.a33942","type":"change","z":"314b7d3f.2adc62","name":"Line Reply API 用設定","rules":[{"t":"set","p":"headers.Content-Type","pt":"msg","to":"application/json","tot":"str"},{"t":"set","p":"headers.Authorization","pt":"msg","to":"Bearer \"your_channel_access_token\"","tot":"str"},{"t":"set","p":"payload.replyToken","pt":"msg","to":"payload.replyToken","tot":"msg"},{"t":"set","p":"payload.messages[0].type","pt":"msg","to":"text","tot":"str"},{"t":"set","p":"payload.messages[0].text","pt":"msg","to":"送信完了","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":420,"y":220,"wires":[["1bc5bba6.3b0244"]]},{"id":"894d56ce.436268","type":"cast-to-client","z":"314b7d3f.2adc62","name":"google home","url":"","contentType":"","message":"","language":"ja","ip":"","port":"","volume":"50","x":770,"y":380,"wires":[[]]},{"id":"97eee3ab.2f10f","type":"comment","z":"314b7d3f.2adc62","name":"googlehome","info":"","x":350,"y":340,"wires":[]},{"id":"4ff3caa3.50ed94","type":"change","z":"314b7d3f.2adc62","name":"受信したJSONからメッセージのみ取得","rules":[{"t":"set","p":"message","pt":"msg","to":"payload.message","tot":"msg"},{"t":"delete","p":"payload","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":500,"y":380,"wires":[["894d56ce.436268"]]}]
```

文系新卒君の挑戦は続く...