Node.js
ifttt
LINEmessagingAPI
GoogleAssistant
GoogleHome

Google Home mini で双方向の音声でのLINE送受信を実現する

More than 1 year has passed since last update.

Google Home Miniを買ったので、こんなものを作りました。

↓Youtubeです
Google Home miniでLINEする!

Google Homeを通して、グループへのLINE送信&グループに投稿されたメッセージを読み上げしてくれます。

やりたかったこと

彼女は僕より帰宅が早いです。
いつも家で料理を作って待っててくれるのですが、僕がいつ会社を出るのか、
最寄り駅に付くのはいつなのかによって、料理の行程が変わるという話を聞きました。
そんなときに、LINEで「いまどこ」「これから会社出る」などと連絡を取り合っているのですが、
料理中なので見れたり見れなかったり、手が汚れてて返信できなかったりと不便とのこと。
せっかくGoogle Home Miniを買ったので、テクノロジーで解決できないかと考えました。

筆者のレベル

HTML書いたことがあるくらい。
ProcessingとArduino勉強中。
プログラミングはほぼ未経験。
今回のプロジェクトで、node.js歴2日
完全に素人なので、間違っていることややっちゃいけないことがいっぱいある気がします。
先輩プログラマさんたちは優しく指摘してくれればうれしいです。

下記をめっちゃ参考(丸パクリ)させていただきました。

Google Homeで時報を知らせる
Node.js:JSONデータをPOSTする
node.js + expressでPOSTを受け取る & POSTパラメータをJSONで取得する

しくみ

スクリーンショット 2017-11-17 3.51.01.png

コード

たぶんこんな感じ、、、

linetogooglehome.js
const express = require('express');
const bodyParser = require('body-parser');
var request = require('request');

const app = express();

//line messaging API用
const line = require('@line/bot-sdk');
const client = new line.Client({
  channelAccessToken: 'MessagingAPIのchannelAccessTokenを入れる'
});
const groupId = 'BOTが入るグループIDを入れる';

// urlencodedとjsonは別々に初期化する
app.use(bodyParser.urlencoded({
    extended: true
}));
app.use(bodyParser.json());

//herokuなのでポート指定こんな感じらしい
app.listen(process.env.PORT, process.env.IP);
console.log('Server is online.');

//POSTきたらコレが動く多分。
app.post('/', function(req, res) {

//送受信両方載っけたかったので、よくわからないけどJSONの中身があるかないかで判別する
//こっちはメッセージを読み上げる用
  if(req.body.events){

    // リクエストボディを出力(確認用)
    console.log(req.body);
    // パラメータを出力(確認用)
    console.log(req.body.events[0].message);
    console.log(req.body.events[0].source.groupId);

    //JSONの中身を変数に入れてる。多分
    var user1 = req.body.events[0].source.userId;
    var textmain = req.body.events[0].message.text;
    var lineReplyToken = req.body.events[0].replyToken;

    //リプライトークンを出力(確認用)
    console.log(lineReplyToken);

        //メッセージ受信した時のJSONに入ってるUserIdを使ってユーザー名を取る
    client.getProfile(user1)
      .then((profile) => {

        //LINEの名前とかIDを出力(確認用)
        console.log(profile.displayName);
        console.log(profile.userId);

        var username = profile.displayName;
        res.end();

        //IFTTTにWebhook送信
        //POSTのなかみ
        var options = {
          uri: "IFTTTのWebhook先のURLを入れる",
          headers: {
            "Content-type": "application/json",
          },
          body: JSON.stringify({
            value1: username,
            value2: textmain
          })
        };
        //IFTTTにPOST
        request.post(options, function(error, response, body){

          //完了後、BOTからリプライする
          /*
          var message = {
            type: 'text',
            text: 'Google Home Done!'
          };

          client.replyMessage(lineReplyToken, message)
          .then(() => {
          })
          .catch((err) => {
            // error handling
          });
          */
        });
      })
      .catch((err) => {
        // error handling
                //多分なんかしなくちゃいけない
      });
    }else{

            //こっちはGoogleHomeに喋ったメッセージをLINEに投稿する方
      // リクエストボディを出力
      console.log(req.body);
      var texttoline = req.body.text;
      console.log(texttoline);
      res.write('ok');
      res.end();

      const message = {
        type: 'text',
        text: texttoline
      };

      client.pushMessage(groupId, message)
        .then(() => {
        })
        .catch((err) => {
          // error handling
                    //多分なんかしなくちゃいけない
        });
    }
})

あってるかすらわからないけど、とりあえず今のところ動いてるみたい

抱負

あとでもうちょい書く

----ここから追記----
調べたことやわかったこと、わからなかったことを書いていく。

やりたいことベースで何をすればいいか調べた

まずなにをしたいかを細かく分けて考えた。

Google Homeから音声入力でLINEに投稿

1:音声入力で話しかける
IFTTTを利用すれば、言葉をきっかけに他のサービスを動かせることがわかった。
→具体的には、アプレット(IFTTTで設定できる「これが来たらこう!」っていうプログラム)のThisにGoogle Assistantを設定する。

2:LINEで喋らせる
→簡単にやろうと思ったら、IFTTTのThatにLINEを設定できるのでこれでLINE連携はできる。
→が、次にやろうとしている「LINEからGoogle Homeを喋らせる」が実現できないので、LINE Messaging APIを使うことにする。(LINEのBOTを作れるサービス)

LINEで投稿した内容をGoogle Homeに喋らせる

1:LINEで投稿した内容を認識する
→LINE Messaging APIを使ってbotを作る。

2:投稿した内容を処理
Messaging APIの設定で受信したメッセージをwebhookできるので、
Heroku上に立ち上げたnode.jsにメッセージのJSONをPOSTする。

3:Google HomeにPushする
→IFTTTを再度通して、Thisにwebhookでnode.jsからメッセージをPOSTしてもらい、thatにもwebhookでサーバー上に起動したGoogle-Home-Notifierに送る
→Google-Home-NotifierがGoogle Homeを喋らせる。

環境をつくる

node.jsを使うことになって、まずインストールの仕方からわからない。
使えるようになるまでに何をすればいいかわからなかったので、下記の本をKindleで買って読んだ。
Node.jsビギナーズガイド: サーバーサイドJavaScriptをマスターせよ!

Herokuの設定方法やコードアップロードの仕方も書いてあってとても役立った。

(最初はAWS Lambdaを使おうと思ったが、IAMロール?とかAPI GATEWAYとかよくわからなすぎて結局コンソールログを出すことができずに挫折した。)

1:音声入力で話しかける

LINE Messaging APIの設定

LINE Developersとかにいくと、デベロッパー登録ができる。
適当に登録しておく。

スクリーンショット 2017-11-18 18.43.04.png
Messaging APIを始めるを押して、プロバイダの設定へ進む。

スクリーンショット 2017-11-18 18.45.24.png
新規作成で適当な名前のプロバイダを作る。

スクリーンショット 2017-11-18 18.45.57.png
Messaging APIをおすとチャンネルの作成画面にいく。

screencapture-developers-line-me-console-register-messaging-api-channel-1510998371989.png
アイコンとか名前とか色々適当に入力する。
プランはDeveloper Trialにした。
(確か友達登録上限が50人とか制限がある。今回は2人でつかうだけなので問題なし。)

そうするとチャンネルの基本設定みたいな画面に行く。
スクリーンショット 2017-11-18 18.54.36.png
スクリーンショット 2017-11-18 18.54.51.png
この辺あとで使うので後ほど戻ってこよう。

Herokuにコードを上げる

最初はAWS Lambdaを使おうと思った。
が、用語がわからずに挫折。
Herokuを使うことにした。
Node.jsビギナーズガイド: サーバーサイドJavaScriptをマスターせよ!
この本にHerokuが使えるようにする方法が書いてあったので、そのとおりに。
terminal自体ほぼ初心者だったが、慣れたらなんかできるようになった。

上で書いてあるコードに、LINE Messaging APIで取った、AccessTokenとか突っ込んでHerokuに上げた。
コードの解説は後ほど

IFTTTの設定

IFTTTでアカウントを作ったら、
MyApplets>New Appletsで新しいAppletを作成する。
スクリーンショット 2017-11-18 18.24.20.png
まず"this"を選んで、

スクリーンショット 2017-11-18 18.24.46.png
繋ぐサービスを選ぶ画面で、Google Assistantと入力すると、"Google Assistant"が出て来る。
これを選択して、Google Homeで設定したのと同じGoogleアカウントでアカウントを繋ぐ。
そうすると使えるようになる。

スクリーンショット 2017-11-18 18.26.40.png
アカウントがつなげると、こんなかんじでトリガーを選ぶことができる。
今回は任意の言葉をLINEに投稿するのが目的なので、"Say a phrase with a text ingredient"を選択する。
意訳すると「変数込みのフレーズをトリガーにする」って感じかしら。

スクリーンショット 2017-11-18 18.29.50.png
そうするとこんな入力画面が出てくる。
"What do you want to say?"にトリガーにする言葉を入力する。
今回は「LINE \$」と入れた。
→\$というのは、この部分が変数で、任意の言葉に置き換わる。
例えば「LINE いまから帰るよ」というと、「いまから帰るよ」部分が変数として、他で使えるようになる。

"What do you want the Assistant to say in response?"には、上記のトリガーが来たときに、Google Homeがなんて返すかを指定できる。
今回は「\$ とラインします。」と設定した。
→ここの$には、トリガーで話した\$の内容と同じものが入る。

LanguageはJapaneseに設定する。

スクリーンショット 2017-11-18 18.35.42.png
こんな感じで設定できたら、Create triggerする。

次はthatを設定する。
スクリーンショット 2017-11-18 18.35.32.png

スクリーンショット 2017-11-18 18.36.43.png
先ほどと同様に、サービスと繋ぐ画面で、今度はwebhookと入れる。

スクリーンショット 2017-11-19 14.53.38.png
Make a web requestを選択

スクリーンショット 2017-11-19 14.53.46.png
また設定入力画面が出てくるので、

  • URL→
    • HerokuにあげたURLを設定。
  • Method
    • POST
  • Content Type
    • LINE Messaging APIにはJSONで内容を渡してあげる必要がある。"application/json"にしておく。
  • BODY
    • 今回は{"text": "喋らせたい内容"}という形でMessaging APIに投げてあげればBOTが喋ってくれる。 なので、今回は変数を使って{"text": "{{TextField}}"}とする。

あとはCreate Actionして、Finishすれば、IFTTTの設定は終わり。

これで、Google Homeに向かって「OK Google, LINE いまから帰るよ」と発言すると、LINEに「いまから帰るよ」とBOTが投稿してくれる。

疲れたので続きは次回。