でうまくいかなかったので放置していたけど、再挑戦した。 基本的には
を参考にしてるので、そっち見ながらこの記事も読んでください。
Raspberry Piからgoolgle-home-notifierを使えるようにする
まずはnodejsの実行環境をつくることにした。 適当に調べて以下の記事を参考にした。
Raspberry Pi への Node.js インストールとnvmでのバージョン管理 - Qiita
インストール可能バージョン一覧を見たときにLTSってなんじゃいとなったので適当に調べた(nodejsを避けて生きてきたので……)。
雰囲気的にはLTSってなってる最新のバージョンを使えば良さそうということで、 v10.15.0
を採用した。
次にgoogle-home-notifierをインストールする。
Raspberry Piセクションがあるのでその通りにしましょう。 そしてサンプルスクリプトを実行するとエラーが出たので、以下の通りに修正したところ動きました。
google-home-notifierってメンテナンス止まってるんですかね、かといって他に代替手段も無い気がするし不安。
これでひとまずRaspberry Piからgoogle-home-notifierを利用できるようになりました。 ハード的にもソフト的にも古いRaspberry Piだったので手間をかけずに動くか不安だったんですが、今の所大丈夫そうです。
HTTP GETしたJSONをパースして喋らせる
request
モジュールは普通にインストールできたんですが node-jq
は
などを参照しつつもうまくいかなくて諦めて、 request
の機能を使うことにしました。
webClient.get({ url: "http://example.com", json: true, }, function(error, response, json){
みたいな感じ。
ngrokとかもインストールして結局こうなった(nodejs知らないのとRaspberry Pi上のviで適当に書いていたので汚いのは勘弁)。
const googlehome = require('../google-home-notifier'); const webClient = require('request'); const ngrok = require('ngrok'); const express = require('express'); const config = require('config'); // ngrok設定 var app = express(); var port = 8091; // ライブラリ初期化 googlehome.device(config.googlehome.deviceName, config.googlehome.language); googlehome.ip(config.googlehome.ipAddress, config.googlehome.language); // GETリクエスト受信時の処理 app.get('/', function(req, res) { // 室温を取得 webClient.get({ url: config.apiUrl, json: true, }, function(error, response, settings){ var temp = Math.round(parseFloat(settings.temperature) * 10) / 10; var humd = Math.round(parseFloat(settings.humidity) * 10) / 10; var di = Math.round(parseFloat(settings.discomfort_index) * 10) / 10; var notifyText = '現在の部屋の温度は' + temp + '度、湿度は' + humd + '%、不快指数は' + di + 'です 。'; googlehome.notify(notifyText, function(notifyRes) { console.log(notifyRes); res.json({success: true, res: notifyRes}); }); }); }); // ngrok起動 app.listen(port, async function() { const url = await ngrok.connect(port); console.log('Endpoint: ' + url); });
とりあえず雑にnohupでバックグラウンド実行しましょう。
nohup node notify-temp.js &
これで最低限動くようにはなりました。
今後の課題
今日はもう疲れてきたのでやめときますが、以下の課題が残っています。
- 当該のスクリプトが自動実行されないので、Raspberry Piの電源が落ちるたびにいちいち手動で実行する必要がある
- daemon化などすれば自動実行できそう
- ngrokのエンドポイントが実行毎に変わってしまい、IFTTTの設定を手動で変更する必要がある
- お金を払えば固定できるらしい?けどこのためだけにお金を払う気も起きないので、強い気持ちでダイナミックDNSとかを使いつつグローバルに公開するとかしないとダメそう。だけど雑にやると危なさそう
この2つが組み合わさって結構だるそうですね。
追記
昨日つくったGoogle Homeが温湿度教えてくれるやつは、朝起きたらRaspberry Piがフリーズしていて見事にダメになっていた。厳しい
— shimobayashi (@shimobayashi) 2019年1月7日
古いRaspberry Piにnodejs+expressみたいないかにも重そうなプロセス常駐させるのはさすがに厳しいのかも、対策を考えなければ……。 cronで外部のジョブキューを読みに行って、そこにあるテキストを単に読み上げるとかだと大丈夫かな……?
追記
とりあえずめんどいのでcronで定期実行して通知したほうが良さそうな雰囲気だったら喋らせるということにした(自分用の仕組みのコードなのであまり参考にならないかも)。 1分待つ感じだとだるすぎるのですげー雑にsetTimeoutで複数回実行するようにした、ひどい。
const googlehome = require('../google-home-notifier'); const webClient = require('request'); const config = require('config'); // ライブラリ初期化 googlehome.device(config.googlehome.deviceName, config.googlehome.language); googlehome.ip(config.googlehome.ipAddress, config.googlehome.language); // 室温を取得 var run = function() { console.log('run'); webClient.get({ url: config.apiUrl, json: true, }, function(error, response, settings){ if (settings.notify_temp_scheduled == '1') { var temp = Math.round(parseFloat(settings.temperature) * 10) / 10; var humd = Math.round(parseFloat(settings.humidity) * 10) / 10; var di = Math.round(parseFloat(settings.discomfort_index) * 10) / 10; var notifyText = '現在の部屋の温度は' + temp + '度、湿度は' + humd + '%、不快指数は' + di + 'です 。'; googlehome.notify(notifyText, function(notifyRes) { console.log(notifyRes); }); webClient.get({ url: config.apiUrl + '?notify_temp_scheduled=0', json: true, }, function(error, response, settings){ console.log('notify_temp_scheduled is updated'); }); }; }); }; for (var i = 0; i < 5; i++) { setTimeout(run, i * 10 * 1000); }