はじめに
AWS Summitで始めてみたalexaさんに心奪われAIスピーカに興味を持ち、気が付いたらGoogleHomeが家に置いてありました。
家族の無茶な命令で謝ってばかりのGoogleHomeの地位を向上させるべく、今回のプロジェクトを始めました。
まだスマホを持っていない子供との遠隔コミュニケーションが取れるようになれば、売れっ子間違いなしです。
※このプロジェクトを実現するにあたり、以下の記事が非常に参考になりました!ありがとうございました!
https://qiita.com/miso_develop/items/be562d8a823ad2639d94
絵が非常にわかりやすかったため、インスパイアされてパクって作ってみました。
実現イメージ
子供がGoogleHomeでLINEメッセージを送信
親がLINEメッセージをGoogleHomeへ送信
子供がGoogleHomeから未読のLINEメッセージを聞く
ポイントは子供が使うので、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」を選択します。
Actionに「input.linetext」を入力するのと、FulfillmentのUse Webhookをチェック入れるだけです。
Actionの「input.linetext」はこの文字列でなくても大丈夫です。Fulfillmentの実装時にルーティングで使用するので、そこと整合が取れればOKです。
では次はFulfillmentを実装していきます。
Fulfillmentの実装
ここまで、駆け足で書いてきましたが、どうも何か忘れているような気がする・・・。
・・・あ、Firebaseの登録ですね。うん。忘れました。
どこかの流れで、登録した気がするのですが・・・。
とりあえず、登録してある前提で話を進めます。
今回は、Inline Editorで作成されたCloud Founctionsを改修する形で実装します。
まずは、右側にあるダウンロードをクリックしてローカル環境に落としましょう。
ローカルでの開発&デプロイは以下を参照してください。
https://firebase.google.com/docs/functions/get-started?hl=ja
https://firebase.google.com/docs/hosting/deploying?hl=ja
改修内容
index.jsの先頭付近に以下2行を追加します。
const firebase = require('firebase-admin');
firebase.initializeApp(functions.config().firebase);
こんな感じになるはずです。
'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'を追加します。
はい。これだけです。
// 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に話させる言葉を格納します。
ラズパイに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交換をしてみる(後編)