こんにちは。
前回の記事の予告通りgoogle homeさんに歌ってもらいました。
歌は心と情報量
いきなりですが結果からです。
IoTシステムを構築して歌ってもらいました。
www.youtube.com
google homeさんは200文字程度が読み上げ限界なので
概要のみの読み上げになりますが、
これで気になったおさるさんはいつでも調べてもらえますね!
技術解説
システム概要
概要図です。
前回のpythonプログラムを使ってシステムを構成しました。
本当はインターネットにデータを出したくなかったのですが
google homeからローカルで直接情報を引っ張ってくる手段がなかったので
こんな冗長に見える構成になっています。
後段ではsocket.IOという双方向通信プロトコルのライブラリを使い、
RaspberryPiをクライアントとして接続させています。
これはローカルのRaspberryPiをwebサーバーとして公開する事を避けるためです。
webサーバーを公開するとなるとセキュリティやポートの設定などが必要になってきますからね・・・
(そもそも私の住処は集合住宅なので・・・)
以下、要素技術を解説していきます。
IFTTT
まず、IFはgoogle assistantを指定して以下のように設定しました。
thenについてはweb hooksで
AzureサーバーにPOSTするようにしています。
"TextField"部分にアイアイなどのキーワードが入り、送信されます。
また送信情報には"token"を追加し、
Azureサーバーはこのtokenを持ったリクエストのみ受け付けるようにしています。
(画像のtokenは変更済みですので今はもう使えません)
なお、tokenはこちらのハッシュ生成サービスを利用して生成しました。入力は適当です。
tool-taro.com
webサーバー
AzureのApp serviceからnode.jsの実行環境を利用しています。 ここではコード全文を記載します。
var app = require('express')(); var http = require('http').Server(app); var io = require('socket.io')(http); var bodyParser = require('body-parser'); // this programs receive IFTTT message and send it to raspberry pi // setting body pearser app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.json()); var client; //AzureにアップロードするときはPORTを環境変数で決めるため、必ず下記が必要になる。 var port = process.env.PORT || 8080; //認証用トークン。IFTTTから同じトークンが送られて来た場合のみ本プログラムは動作する const token = "9C3C4A2D197074C63221EA9FC98FF8323F40F543FF6E48CF1E4BCE9A83373957" app.post(`/`, (req, res) => { console.log('IFTTT posted!' + req); //check token (authenticated User) if (req.body.token == token) { req.body.name = req.body.name.trim(); var check = req.body.name; var sendName; // verify word from IFTTT(google home) if (check == "II" || check == "ii" || check == "I愛" || check == "I 愛" || check == "i愛") { sendName = "アイアイ"; } else { sendName = req.body.name; } // send to raspberry pi client.emit('ifttt', sendName); } }); io.sockets.on('connection', (socket) => { client = socket; console.log('ras-pi connected'); }); //start server http.listen(port, function () { console.log('listening on *:' + port); });
「アイアイ」がその文字のまま解釈してくれない事があるので、修正コードが入っていますw
「オランウータン」は一発なので、google assistantに認識されやすい固有名詞と
そうでないものがあるという事ですね。
セキュリティ的にはトークンでガードしています。
ローカルのraspberryPi
node.jsからpython(前回の記事のコードを少し変更したもの)プログラムを読んで、wikipediaの情報を得ています。
そしてgoogle-home-notifierというライブラリでgoogle homeに喋らせたい内容を送ります。
あとはgoogle homeが読み上げてくれます。
//google home settings var googlehome = require('google-home-notifier'); var language = 'ja'; googlehome.ip('192.168.123.456'); googlehome.device('Google Home', language); //// socket IOを接続先(Azureサーバー)指定で読み込む var socket = require('socket.io-client')('https://iotwebappraiot.azurewebsites.net/'); socket.on('connect', function(){ console.log('connected!'); }); socket.on('ifttt', function (name) { // サーバから受け取った動物の名前をwikipediaパーサーへ送り、 var spawn = require('child_process').spawn; py = spawn('python3', ['WikiExForHome.py', name]); // wikipediaから抽出した内容をパーサーから受け取る。 var say; py.stdout.on('data', function (data) { say = data.toString(); console.log(say); //wikiの内容をgoogle homeへ送信する。(話させる) try { googlehome.notify(say, function (res) { console.log(res); }); //error } catch (err) { console.log(err); } }); });
まとめ
まとめます。
- 情報量を増したアイアイを歌ってもらうIoTシステムを作った。
- IFTTTのWebhooksは、自前のwebサーバーが作れればある意味なんでも出来るのでとても使い勝手が良い。
- ひと昔前と比べると格段に個人で(POCレベルの)IoTシステムを作る事は楽になっているけど、
「初めての人でも簡単です」とはまだまだ言えない感じ。
参考資料
Google AssistantとRaspberry Piで自宅の家電を操作する
Raspberry Pi で google-home-notifier を利用してGoogleHomeをしゃべらす方法
おまけ
google home + IFTTT の構成だけでもこのようにgoogle homeと歌うことができます。 youtu.be
IFTTTの「IF」に次のように設定、返事を登録できます。
なお、後段の「THEN」は使わないのでなんでも良いです。
それでは!