#やりたいこと
書き出すと単純
・LINEで文字を打つ → Google Homeが読み上げる
・Google Homeで話す → LINEに投稿される
何をしたいかって、家にいる子供からLINEにメッセージを送りそれに返事をしたい。
家で留守番中にゲームしてるのを見計らって(みまもりSwitchを作ってくれた任天堂に感謝)「宿題したか!?」とか送ってビビらせたい。
電話はあるけど仕事中でとれなかったりするし、まだスマホを持たせるには早い。
今時の子供はデジタルネイティブなので、気まぐれでリビングに設置したGoogle Homeも僕より使いこなしているから案外使えるのではないか。
#最初の挫折
まず最初に参考にしたのは
Google Home mini で双方向の音声でのLINE送受信を実現する
動画もあるように既に実現しているのをそのままなぞるのが一番簡単である。
が、herokuの環境を構築するところで、なんだかわからなくなって一度やる気をなくす。
もうちょっと真面目に取り組めよって感じではあるが。
構成図を見て、結局自宅PCにgoogle-home-notifierが必要ということで、なんかもうちょっとやりようがあるんじゃないかと思い始める。
#プロジェクト(?)再起動
ポイントは、google-home-notifierで、サンプルのソース見てるとexpressでpost受けてgoogle homeに渡してるだけ。そのpostはngrokを通してグローバルで待ち受けている。
おお、ngrok、なんて素晴らしいサービス。
いや、その前にGoogle AssistantがPush用のAPIを公開してくれれば簡単なわけだが、うっかり脆弱性とか突かれたら面倒くさいからやらないんだろう。
ともかく、家庭内に必ずサーバーを立てる必要があることと、ngrokによってそこにアクセスできるというところで光明が見えた。
#構成
ざっとこんな感じ。
自前でLAN内にサーバーを立てることで、利用する外部サービスはIFTTTとngrokだけとシンプルに。
というか、この形でいろんなデバイス・サービスと連携することが簡単にできそう。
#セキュリティ的な話
ngrokの入り口が弱点になるので、IFTTTのwebhookにtokenつけるとか、LINEのgroupIdやuserIdで区別すれば良さそうだけど、今回はやらない。
そもそもかけたコストに見合った見返りのない事に人は労力をかけないものだ、と信じる。
#準備すること
- LINEのDeveloperアカウントをとる
- IFTTTのアカウントをとる
- 家庭内サーバー(Raspberry Pi3)をセットアップする
詳細はそれぞれググってね
#サーバーで動かすプログラム(node.js)
var express = require('express');
var googlehome = require('./google-home-notifier');
var ngrok = require('ngrok');
var bodyParser = require('body-parser');
var request = require('request');
var app = express();
var urlencodedParser = bodyParser.urlencoded({ extended: false });
app.use(urlencodedParser);
app.use(bodyParser.json());
app.post('/linetohome', function (req, res) {
if (!req.body) return res.sendStatus(400)
//ここでreqの中身を表示することで、ユーザーIDやグループIDが見れるので
// 控えておいて下の'/hometoline'で宛先に記載する
if(req.body.events[0].message.type == 'text'){ //メッセージのみでスタンプとか除外
var text = req.body.events[0].message.text;
//var userid = req.body.events[0].source.userId; //ユーザーで選別したり
googlehome.ip('192.168.11.19', 'ja'); //Google HomeのIP
googlehome.device('Google Home', 'ja');
if (text){
try {
googlehome.notify(text, function(notifyRes) {
console.log(notifyRes);
});
} catch(err) {
console.log(err);
res.sendStatus(500);
res.send(err);
}
}
}
res.send('ok');
})
app.post('/hometoline', function (req, res) {
if (!req.body) return res.sendStatus(400)
var text = req.body.text;
var options = {
uri: "https://api.line.me/v2/bot/message/push",
headers: {
"Content-type": "application/json",
"Authorization": "xxxxxxxxxxxxxxxxxxx", //LINEのアクセストークン
},
json: {
"to": "Cxxxxxxxxxxxxxxxxxxxx", //メッセージを送るグループのgroup id
"messages": [
{ "type" : "text",
"text" : text
}
]
}
};
request.post(options, function(error, response, body){});
res.send('ok');
})
app.listen(8091, function () {
ngrok.connect(8091, function (err, url) {
console.log('LINE webhook : ' + url + '/linetohome');
console.log('IFTTT webhook : ' + url + '/hometoline');
});
})
node hoge.js
と実行すれば、LINEとIFTTTに喰わせるwebhookのURLを表示するので控えておく。
このURL、実行する度に変化します。
なので、サーバーの設定で自動実行するようにするなら、URLを自分のLINEに送るような処理にしておくと出先でもIFTTTとLINEの設定更新できるかもね。
いやいや、毎回変化するとかダルすぎやろ固定化できないのかと、そういう場合はngrokに毎月なんぼか払えば固定のURLをゲットできる模様。
もっと活用できるようになったら挑戦してみたい。
#IFTTTの設定
My AppletsからNew Applet
「if this then that」の「this」と「that」を決めていく。
まずthisで、Google Assistantを選択
上のように書いてCreate trigger
次にthat
webhookを選ぶ
URLに例のURL、他上のように。
Bodyは
var text = req.body.text;
で取り出してLINEに渡してる。
#LINE側の設定
Developerコンソールでプロバイダー、チャネル作成していろいろ設定しておく。
(グループ参加可、自動応答なし、友達追加時あいさつなし、etc)
アクセストークンはさっきのコードAuthorizationのところへ
Webhook URLに例のURL。
このbotを画面の下の方にあるQRコードで追加して、必要ならグループに入れてメッセージ送る。ログで出力して確認できるグループIDをhometolineのtoのところへ。
これで、LINEとGoogle Homeの双方向のやりとり完成。