はじめに
Raspberry PiからGoogle Homeを喋らせる - Qiita で、GoogleHomeを自由に発話させることができるようになった。
いつも家に帰るときは妻に「帰るよ」というLINEを送っているが、それと同時に家のGoogleHomeが喋ったら面白いと思い、作ってみることにした。
ちょうど、参加中のOPEN BETA LABのメンバーの中でLINEbotが流行っており、調べてみるとLINEmessageingAPIというのがあり、LINEのメッセージを受信したり送信したりできることを知ったので、使ってみる。
2018/02/03 追記
なんでも喋らせられるようになりました!→LINEから家のGoogleHomeに好きな言葉を喋らせる
成果物
システム構成
- LINEのbotアカウントにメッセージを送ると、botはメッセージ受信をトリガーにIFTTTにwebhookを送る
- IFTTTがwebhookを受信すると、webhookでbeebotteのREST APIを叩いてメッセージをPublish(配信)する
- beebotteは、届いたメッセージを貯める
- 家のRaspberry Piは、beebotteにMQTTでメッセージをSubscribe(購読)しておく
- RaspberryPiにbeebotteからメッセージが届いたら、google-home-notifierを使ってGoogleHomeを喋らせる
機能
- LINEbotに何か送ると、GoogleHomeが固定の文章を喋る
- LINEで送ったメッセージによって文章を変えることはできていない
構成の検討
この構成になるまでは紆余曲折あった。
RaspberryPiを外から制御する方法
まず参考にしたのは、下記の記事。
GoogleHomeスピーカーに外部からプッシュして自発的に話してもらいます - Qiita
RaspberryPiをサーバーにして、HTTPリクエストを投げることによってトリガーにしている模様。しかし、自宅に置いてあるRaspberryPiに家の外からアクセスするためには、RaspberryPiをインターネットに公開する必要があり、セキュリティなどの心配があるため不採用とした。
RaspberryPiをサーバーにするのは敷居が高いので、RaspberryPiはクライアントとしてWeb上のどこかを定期監視してもらい、変化があったら喋らせるようなことがしたい。そんなものを探していたところ、見つかったのが下記の記事。
IFTTTのトリガーおよびアクションをESP8266で実行する - Qiita
IFTTTというのは「If Then This Then That」の通り、「こういうトリガーがあったらこういうアクションをする」というアプリ(アプレット)を簡単に作れるサービス。TwitterやDropboxといった様々なサービスが連携できるパーツが提供されており、入力(トリガー)と出力(アクション)の組み合わせで簡単にアプレットを作ることがきる。
この記事では、IFTTTのアクションとしてbeebotteというMQTTブローカー(IoTのデータを貯めておいたりするサービス)にwebhookを使ってデータを送信し、ESP8266(Wi-Fiマイコン)でbeebotteからデータを取得することでアクションを実現している。
この記事のESP8266の部分をRaspberryPiに置き換えればできるので、RaspberryPiを外から喋らせるのはこの方法を採用することにした。
LINEからIFTTTにメッセージを届ける方法
IFTTTは様々なサービスと連携できるので、LINEのメッセージをトリガーにすることくらいできるだろうと思っていたが、IFTTTのトリガーに設定可能なサービス一覧にLINEがなかった。(アクションなら、LINEで通知する、というのが設定可能だった。)
LINEのAPIについて調べていると、LINE Developersというのを発見した。LINE Developersに登録すると、LINEbotが作成でき、メッセージを受け取ったときにwebhookが送信できることがわかった。本来はLINEのbotを作るためによく使われるようだが、これを単なる通知として使うことにした。
IFTTT不要説
感の良い読者なら気づくかもしれないが、LINEbotからwebhookをIFTTTに送信し、IFTTTからwebhookでbeebotteに通知しているため、IFTTTは省略できそうである。しかし、LINEbotから送信されるwebhookのJSONと、beebotteが受信できるwebhookのJSONの形式が一致せず、IFTTTは省略できなかった。
作成の手順
LINEbotにIFTTTのアクセスキーが必要で、IFTTTにはbeebotteのアクセスキーが必要なので、逆にbeebotte→IFTTT→LINEbotの順番で設定をするのが良い。
beebotteチャンネルの作成
基本的にはIFTTTのトリガーおよびアクションをESP8266で実行する - Qiitaを参考にする。
beebotteにアクセスし、アカウント登録とチャンネル、リソースを作成する。
- チャンネル名: ifttt
- リソース: action
を作成した。
My Channelsから作成したチャンネルをクリックすると、チャンネルの詳細が出て来ます。「Channel Token: ...」と書いてあるのが、そのチャンネルにアクセスするトークン。IFTTTに入力するのでとっておく。
IFTTTアプレットの作成
ここも基本的にはIFTTTのトリガーおよびアクションをESP8266で実行する - Qiitaを参考にする。
IFTTTのアカウント登録を済ませ、IFTTT WebhooksをConnectしておく。
- トリガー: webhooks
- アクション: webhooks
のアプレットを作成する。
URLには先ほどbeebotteで取得したチャンネルのアクセストークンを入力する。
https://ifttt.com/maker_webhooks の右上の「Documentation」をクリックすると、「Your key is: ...」にIFTTTのwebhookにアクセスするキーが書いてあるので取っておく。
LINEbotの作成
LINE Developersのアカウントを作成し、Messaging APIを作成する。作ったbotアカウントの「Channel基本設定」の「メッセージ送受信設定」で、
- Webhook送信を有効に
- Webhook URLに、先ほどIFTTTで取得した アクセスキーを入力する。
Raspberry Pi プログラムの作成
Node.jsとgoogle-home-notifierの設定
Raspberry PiからGoogle Homeを喋らせる - Qiita を参考にして、設定する。
Node.js用MQTTライブラリMQTT.jsのインストール
Node.jsでMQTTが簡単に使えるようにするライブラリMQTT.jsをnpm(Node Package Manager)でインストールする。
上記リンク先のInstallationに記載の通り、作業ディレクトリで下記を実行するとインストールできる。
$ npm install mqtt --save
--saveとつけるのは、npmで生成されるpackages.jsonに「MQTT.jsが必要だよ」という情報を記録するためらしい。
Node.jsプログラムの作成
作成したソースコードは以下。前回作成したgoogle-home-notifierのソースと、MQTT.jsのサンプルソースを合体させた感じ。
const googlehome = require('google-home-notifier');
const mqtt = require('mqtt');
const language = 'ja';
googlehome.device("Google-Home", language);
googlehome.ip("192.168.xxx.xxx");
const client = mqtt.connect('mqtt://mqtt.beebotte.com',
{username: 'token:token_XXXXXXXXXXXXXX', password: ''} // XXX..の部分にはbeebotteのチャンネルのアクセストークンを入れる
);
client.on('connect', function() {
client.subscribe('ifttt/action');
});
client.on('message', function(topic, message) {
console.log(message.toString());
googlehome.notify('こんにちは世界。', function(res) {
console.log(res);
});
});
動作確認
これで、作成したLINEbotにメッセージを何か送信すると、GoogleHomeが喋るようになるはず。うまくいかない場合は、IFTTTやbeebotteでは動作履歴が記録されているのでデバッグ時の参考にできる。
↓動作中の動画
妻が留守番中に外からこれを実行したら、ただただビックリしていた模様。。LINEからGoogle Homeを喋らせることに成功!現状、何を送っても同じこと言いますがw
— テツオ (@ktetsuo) 2018年1月12日
LINE BotからIFTTTのwebhook経由でbeebotteにデータ貯めて、自宅のRaspberry Piでbeebotteからデータ取得、Node.jsのgoogle-home-notifierでGoogle Homeに発話させてます。 pic.twitter.com/YtJnEXmCLM
所感
LINE MessagingAPI, IFTTT, beebotteといった小さいサービスでも工夫次第で連携して好きなことができて楽しい。「ピタゴラスイッチ的」というのをどこかで見たが、まさにその通り。
今後
今回は固定の文章しか喋れなかったが、好きな文章を喋らせるようにしたい。
IFTTTのwebhook受信が、JSONの細かいステータスを読み込むことができなかったのが敗因なので、IFTTTをAWS LambdaやAzure Functionあたりに差し替えて、LINEからどんなメッセージが来たかを読み取ることで実現できるのではないかと構想中。