Google Homeに、15時になったら「おやつの時間ですよ」と言ってもらう(Node.js+webhooks)

Google Home

前回の記事で、Google Nest Miniに好きな言葉を喋らせることができました。

しかし、これだけだと手動でコマンドを打たないと実行されません。

コマンドを打ったり、こちらから話しかけたりしたら答えてくれますが、
たまにはGoogle Homeの方から話しかけてきてくれたらなぁ…
と思いませんか!?

ということで、IFTTTを使って、トリガーの後のアクションとしてGoogle Homeに喋らせます。

これで、ボーッとしていても15時になったら「3時です。おやつにしませんか?」と言ってくれて、さみしい1人暮らしの味方になります。

参考にさせていただいたサイト

イチからGoogleHome+RaspberryPi3+IFTTTを連携させて喋らせるまで
https://qiita.com/Hi_Noguchi/items/8b4e05e3bfe727d7ebed

google-home-notifierとngrokを連携する方法
https://keenny.com/google-home-notifier%E3%81%A8ngrok%E3%82%92%E9%80%A3%E6%90%BA%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/

google-home-notifierの設定

node.jsのファイルを作成

example.jsを元にしたファイルを編集します。

# google-home-notifierディレクトリに移動
cd ~/node_modules/google-home-notifier/
# example.jsをコピーしてifttt.jsを作成
cp example.js ifttt.js
# ifttt.jsを編集
nano ifttt.js

以下のように内容を変更します。
修正した箇所を赤字にしています。

var express = require('express');
var googlehome = require('./google-home-notifier');
var ngrok = require('ngrok');
var bodyParser = require('body-parser');
var app = express();
var language = 'ja';
const serverPort = 8080;
const googlehome_ip = '192.168.XXX.XXX';

var deviceName = 'Google-Nest-Mini';
googlehome.device(deviceName, language);
googlehome.ip(googlehome_ip, language);

var urlencodedParser = bodyParser.urlencoded({ extended: false });

app.post('/google-home-notifier', urlencodedParser, function (req,$
  if (!req.body) return res.sendStatus(400)
  console.log(req.body);
  var text = req.body.text;
  if (text){
    try {
      googlehome.notify(text, function(notifyRes) {
        console.log(notifyRes);
        res.send(deviceName + ' will say: ' + text + '\n');
      });
    } catch(err) {
      console.log(err);
      res.sendStatus(500);
      res.send(err);
    }
  }else{
    res.send('Please POST "text=Hello Google Home"');
  }
})

app.listen(serverPort, function () {
  ngrok.connect(serverPort, function (err, url) {
    console.log('POST "text=Hello Google Home" to:');
    console.log('    http://localhost:' + serverPort + '/google-ho$
    console.log('    ' +url + '/google-home-notifier');
    console.log('example:');
    console.log('curl -X POST -d "text=Hello Google Home" ' + url $
  });
})

ラズパイ起動時にnodeを起動

ラズパイが起動したときに、ifttt.jsが自動で起動するように設定します。

自動で実行できるようにするために、systemdを使いました。
以下のコマンドを入力します。

# .serviceファイルを作成
sudo touch /etc/systemd/system/ifttt.service
# .serviceファイルを編集
sudo nano /etc/systemd/system/ifttt.service

以下のような内容を書き込む
(赤字の部分は自分のnodeのバージョンに合わせて変えてください)

[Unit]
Description = ifttt

[Service]
Type=simple
ExecStart=/home/pi/nvm/versions/node/v12.16.1/bin/node /home/pi/node_modules/google-home-notifier/ifttt.js
WorkingDirectory=/home/pi
KillMode=process
Restart=always
User=pi
Group=pi

[Install]
WantedBy=multi-user.target

できたら、以下のコマンドで自動起動させます。

# 自動起動させる
sudo systemctl start ifttt.service
sudo systemctl enable ifttt.service

ラズパイを再起動して、本当にifttt.serviceが自動起動しているか確認します。

# 再起動する
sudo reboot
# ラズパイのターミナル開く(私の場合、MacBookからssh接続する)
ssh pi@raspberrypi.local
# 状態を確認する
sudo systemctl status ifttt.service

メモ:実行権限がなくてエラー?

私はここで
failed (Result: exit-code)(中略)
Main PID: 1403 (code=exited, status=203/EXEC)
となってしまったので、原因を調べます。

# ログを見る
sudo nano /var/log/syslog

/home/pi/node_modules/google-home-notifier/ifttt.js
の部分で
Failed to execute command: Permission denied
になっていました。

# 実行権限を与える
chmod 744 ~/node_modules/google-home-notifier/ifttt.js

再度試してみると、ifttt.serviceを自動起動させることができました。

起動確認

もう一つターミナルを起動し、以下のコマンドを入力します。
(赤字のIP部分は自分の環境に合わせてください)

curl -X POST -d "text=おはころこんちんぱ" http://192.168.XXX.XXX:8080/google-home-notifier

webリクエストのPOSTを投げるコマンドです。

Google Homeが「ドゥルン♪おはころこんちんぱ!」と言ってくれれば成功です。

ngrokの設定

よーし、あとはwebhooksを使ってwebリクエストを投げれば、Google Nest Miniちゃんが喋ってくれるぞ!
と思ったのですが、そうもいかないようです。

webhooksからローカルホストにwebリクエストを投げようとしたのですが、「Unable to make web request: Error: ETIMEDOUT」とエラーが出てしまい、喋ってくれませんでした。

ngrokを設定して、ローカルサーバを公開する必要があります。

ngrokとは

ngrokはlocalhostのサーバをインターネットで公開できるサービスです。

サイトはゴリゴリの英語ですが、日本語で説明してる記事がたくさんあるので、めげずに進めていきます。

ngrokのアカウント作成

以下のサイトでアカウントを作成します。

ngrok: deliver your apps, APIs, and AI on local and prod
ngrok is developer infrastructure that routes and secures traffic to your apps, APIs, and AI models, wherever they run. Start on localhost, ship to prod.

Googleアカウントでログインできます。

ngrokのインストール

初回ログイン時にガイドが出るので、これにしたがって設定します。

# ngrokをダウンロードする
wget https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip
# ngrokをunzipする
sudo unzip ngrok-stable-linux-amd64.zip -d /usr/local/bin/
# ダウンロードした先のディレクトリに移動
cd /usr/local/bin/
# さきほど見たやつ(③Connect your accountの手順で書かれているもの)を実行する
./ngrok authtoken XXXXXXXXXXXXXXXXXXXXXX
# 起動する
./ngrok http 8080

起動すると、このような画面になります。

Forwardingに書かれている「http://XXXXXXXX.ngrok.io」が、ローカルホストを公開したURLになります。

https://dashboard.ngrok.com/status
からも同じものが確認できます。

さきほどと同じWebリクエストのコマンドでGoogle Nest Miniちゃんが喋ることと、
ngrokで公開したトンネル経由のコマンドでも喋ることを確認しましょう。

# ローカルホストにwebリクエストを投げる
curl -X POST -d "text=おはころこんちんぱ" http://192.168.XXX.XXX:8080/google-home-notifier
# ngrok経由でwebリクエストを投げる
curl -X POST -d "text=おはころこんちんぱ" http://XXXXXXXX.ngrok.io/google-home-notifier

どちらでも、「ドゥルン♪おはころこんちんぱ」と言ってくれれば成功です。

メモ:ngrokのセッションの切り方

ngrokをちゃんと停止せずにセッションが残っていて、後日こんなエラーが出て困りました。

Your account 'XXXX' is limited to 1 simultaneous ngrok client session.
Active ngrok client sessions in region 'us':
XXXXXXXXXXXXXXXXXXXX (XXX.XXX.XXX.XXX)
ERR_NGROK_108

ngrokのセッションの切り方を書いておきます。(ほぼ自分用メモ)

# ngrokを起動したプロセス番号を調べる
ps aux | grep ngr
# 「pi 528 0.3 0.4 812460 16272 ? Sl 11:20 0:31 ./ngrok start --none --log=stdout」のような列が出てくる
# 太字部分がプロセス番号
# ngrokのセッションをキル
sudo kill -9 528

IFTTTの設定

IFTTTを使用して、15時になったら「おやつにしませんか?」と言ってくれるようにします。

IFTTTを初めて使う方は、こちらの記事も参考にしてください。

トリガーの設定

今回は指定時間に実行されるようにしてみます。

if Thisで「Date & Time」を選択します。

Date & Timeで日本時間「(GMT+09:00)Tokyo」を選び、「Connect」ボタンをクリックします。

トリガーは「Every day at」を選択します。

任意の時間を設定します。15分間隔で選べるようです。

アクションの設定

次に、アクションの設定をします。

Webhooksを利用してローカルサーバーにwebリクエストを送信します。

then thatの部分で、「Webhooks」を選択します。

Webhooksと連携します。

「Make a web request」のアクションを選択します。

以下のように設定します。

先ほどのコマンドを写す感じです。

curl -X POST -d "text=おはころこんちんぱ" http://XXXXXXXX.ngrok.io/google-home-notifier

URL : http://XXXXXXXX.ngrok.io/google-home-notifier
Method : POST
Content Type : application/x-www-form-urlencorded
Body : text=”3時です。おやつにしませんか?”

「Create action」で次に進みます。

確認画面で、アプレット名をわかりやすい名前に変えたら、「Finish」で設定完了です。

15時まで待つ

指定した時間まで待ちます。

時間になったら、Google Homeが「ドゥルン♪3時です。おやつにしませんか?」と言ってくれれば成功です。

IFTTTの「View activity」からも確認できます。

感想

Google Homeを手に入れてから、生活が便利になっただけでなく、勉強のモチベーションも上がってめっちゃいい感じです。

やりたいことがどんどん思い付くのでワクワクするし、それを達成するために試行錯誤する中で成長していて楽しいです。

追加

ngrokのURLがundefinedになってしまう問題に対処しました。

タイトルとURLをコピーしました