先日登壇したSIerIoTLTでmyThingsを使ったヤフーサービスとGoogle Homeの連携について多くの方に興味を持っていただいたので、連携の仕方についてご紹介します。myThings Developersを使うと様々なヤフーサービスとGoogle Homeを連携させることができます。
この記事のゴール
今回は具体例としてmyThings Developersを使ってYahoo!天気とGoole Homeを組み合わせて雨が降りそうなときにGoogle Homeが自動的に教えてくれるようにする、というのをゴールに説明していきます。
必要なもの
- Google Home
- Yahoo! JAPAN ID(myThings Developersを利用するため)
- nodeがインストールされているPC(Raspberry Piでやった方が実用的なのですが、持ってない人もいると思うので今回はMacの使用を前提として説明します。)
手順
手順は大きく二つのパートがあります。
①発話テキストをPOSTするとGoogle Homeが話し始めるエンドポイントを作る。(1時間)
②myThings Developersのトリガーとアクションを設定する。(30分)
スムーズにいけば2時間もかからないでできる思いますので、是非やってみてください!
Google Homeが話し始めるエンドポイントを作る
以下Macのターミナルでのコマンドになります。
Google Homeを喋られせるためのライブラリgoogle-home-notifierの準備
まず、Google Homeを喋らせるようにするためのnode.jsのライブラリ、google-home-notifierを準備します。
PCのターミナルを起動し、以下のコマンドを打ちます。
$ git clone https://github.com/noelportugal/google-home-notifier
$ cd google-home-notifier
$ npm install
ここでnpm install
をすると以下のようなエラーが出た場合は文字通りpythonのバージョンがv2.5.0 から 3.0.0の間でないとダメと怒られているので、
gyp ERR! configure error
gyp ERR! stack Error: Python executable "/Users/tsubasa_oshima/.pyenv/shims/python" is v3.6.4, which is not supported by gyp.
gyp ERR! stack You can pass the --python switch to point to Python >= v2.5.0 & < 3.0.0.
gyp ERR! stack at PythonFinder.failPythonVersion (/usr/local/lib/node_modules/npm/node_modules/node-gyp/lib/configure.js:463:19)
python 2.7.10あたりを適当にインストールして
$ pyenv install 2.7.10
pythonのバージョンの切り替え(globalとすると全体に、localにするとそのカレントディレクトリに指定したバージョンが反映されます。)
$ pyenv local 2.7.10
ちゃんと切り替わったかを確認する。 2.7.10になっていればOK
$ python --version
Python 2.7.10
気を取り直して 再度npm install
をすると先ほどのエラーが出なくなり、無事node_modules
のインストールが完了するはずです。
コードを書き換える
cloneしてくるとexample.jsは以下のようになっています。
var express = require('express');
var googlehome = require('./google-home-notifier');
var ngrok = require('ngrok');
var bodyParser = require('body-parser');
var app = express();
const serverPort = 8091; // default port
var deviceName = 'Google Home';
var ip = '192.168.1.20'; // default IP
var urlencodedParser = bodyParser.urlencoded({ extended: false });
app.post('/google-home-notifier', urlencodedParser, function (req, res) {
if (!req.body) return res.sendStatus(400)
console.log(req.body);
var text = req.body.text;
if (req.query.ip) {
ip = req.query.ip;
}
var language = 'pl'; // default language code
if (req.query.language) {
language;
}
googlehome.ip(ip, language);
googlehome.device(deviceName,language);
if (text){
try {
if (text.startsWith('http')){
var mp3_url = text;
googlehome.play(mp3_url, function(notifyRes) {
console.log(notifyRes);
res.send(deviceName + ' will play sound from url: ' + mp3_url + '\n');
});
} else {
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 GET "text=Hello Google Home"');
}
})
app.get('/google-home-notifier', function (req, res) {
console.log(req.query);
var text = req.query.text;
if (req.query.ip) {
ip = req.query.ip;
}
var language = 'pl'; // default language code
if (req.query.language) {
language;
}
googlehome.ip(ip, language);
googlehome.device(deviceName,language);
if (text) {
try {
if (text.startsWith('http')){
var mp3_url = text;
googlehome.play(mp3_url, function(notifyRes) {
console.log(notifyRes);
res.send(deviceName + ' will play sound from url: ' + mp3_url + '\n');
});
} else {
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 GET "text=Hello+Google+Home"');
}
})
app.listen(serverPort, function () {
ngrok.connect(serverPort, function (err, url) {
console.log('Endpoints:');
console.log(' http://' + ip + ':' + serverPort + '/google-home-notifier');
console.log(' ' + url + '/google-home-notifier');
console.log('GET example:');
console.log('curl -X GET ' + url + '/google-home-notifier?text=Hello+Google+Home');
console.log('POST example:');
console.log('curl -X POST -d "text=Hello Google Home" ' + url + '/google-home-notifier');
});
})
この中の言語(var language
)とGoogle HomeのIPアドレス(var ip
)を書き換えます。
language
は以下のようにja
としてください。
var language = 'ja';
変更箇所がGETリクエストとPOSTリクエストの中の2箇所あるので注意してください。
(それぞれで宣言する必要もないと思うので、変数宣言を括弧の外に出してしまってもよいです。)
次にIPアドレスを自分のGoogle Homeのアドレスに書き換えます。
ipアドレスの確認の仕方はGoogle Homeアプリを開き、左上のハンバーガーメニューから「デバイス」
このアドレスで書き換えます。
var ip = <自分のGoogle HomeのIPアドレス>;
実際にリクエストを送ってGoogle Homeを喋らせてみる。
ここまできたらあとはサーバーを起動してリクエストを送るとGoogle Homeが話し始めます。
サーバーを起動
node example.js
すると
Endpoints:
http://192.168.xxxx.XXX:8091/google-home-notifier
https://<生成されたサブドメイン>.ngrok.io/google-home-notifier
GET example:
curl -X GET https://<生成されたサブドメイン>.ngrok.io/google-home-notifier?text=Hello+Google+Home
POST example:
curl -X POST -d "text=Hello Google Home" https://<生成されたサブドメイン>.ngrok.io/google-home-notifier
のようにエンドポイントが生成されます。ngrok.io
という文字列が入ったエンドポイントも同時に生成されます。
ngrokはローカル環境を簡単に外部に公開することができるツールです。詳しくはngrok.comやこちらをみてください。
生成されたエンドポイントに対して、GETやPOSTリクエストをしてみましょう。
curl -i -X GET \
'https://<生成されたサブドメイン>.ngrok.io/google-home-notifier?text=こんにちは'
curl -i -X POST \
-H "Content-Type:application/x-www-form-urlencoded" \
-d \
'text=こんにちは' \
'https://<生成されたサブドメイン>.ngrok.io/google-home-notifier'
するとGoogle Homeが下の動画のように喋り出すはずです!
myThings Developersからのリクエストを受け取れるようにする。
myThings Developersからのリクエストは以下のような形式で送られてきます。
リクエスト内容
- ・リクエストメソッド
- POST
- ・Content-Type
- application/json
- ・リクエストヘッダー
- X-Secret : <シークレットの値>
- ・リクエストパラメーター
要素 | 説明 |
---|---|
user_id | 実行されたユーザーID |
service_id | 実行されたサービスID |
mythings_id | 実行された組み合わせID |
values | トリガーから渡された値 |
{
"user_id": "<実行されたユーザーのID>",
"service_id": "<サービスID>",
"mythings_id": "<myTingsID>",
"values": [
{
"area": "<地域>",
"datetime": "<降雨日時>",
"time": "<降雨時刻>",
"date": "<降雨日>",
"rainfall": "<降水量>",
}
]
}
これを受け取れるようにexample.js
に以下のような新たなエンドポイントを追加しましょう。
var jsonParser = bodyParser.json();
app.post('/mythings/weather', jsonParser, function (req, res) {
if (!req.body) return res.sendStatus(400)
console.log(req.body);
var values = req.body.values[0];
var area = values.area;
var time = values.time;
var rainfall = values.rainfall;
var text = area + "に" + time + "に1時間あたり" + rainfall + "ミリの雨がふりそうです。" ;
if (req.query.ip) {
ip = req.query.ip;
}
var language = 'ja';
if (req.query.language) {
language;
}
googlehome.ip(ip, language);
if (text){
try {
if (text.startsWith('http')){
var mp3_url = text;
googlehome.play(mp3_url, function(notifyRes) {
console.log(notifyRes);
res.send(deviceName + ' will play sound from url: ' + mp3_url + '\n');
});
} else {
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('textが空です');
}
})
このエンドポイントにサンプルリクエストを送ってみましょう。
curl -i -X POST \
-H "Content-Type:application/json" \
-d \
'{
"mythings_id": "XXXXXXXXXX",
"service_id": "YYYYYYYYYYYYYYY",
"user_id": "ZZZZZZZZZZZZ",
"values": [
{
"area": "千代田区",
"time": "10:30",
"rainfall": "10"
}
]
}' \
'https://<生成されたサブドメイン>.ngrok.io/mythings/weather'
これで手順①は終了です。次に手順②のmyThings Developersのトリガーとアクションを設定をします。
myThings Developersのトリガーとアクションを設定する。
myThings Developersへ登録 or ログイン
サービス登録画面が出ますので、「名称」を適当に設定してください。
天気トリガーの設定
①左下のトリガーのタブから「Yahoo!天気」を「トリガー」の丸いところまでドラッグ&ドロップ ②チャンネル設定 ・トリガー プルダウンの中にいくつか項目がありますが、ここでは「雨が降りそうなら」を選択 ・地域 好きな地域を選択 ・時間 何時間以内に雨が降りそうだったら教えて欲しいかを設定 ・降水量 降水量がいくつ以上だったら通知して欲しいかを設定 降水量の目安については[こちら](https://piropurin.com/event/kosuiryo)を参考にしてください。 ③設定を保存ボタンを押すここまで完了すると「組み合わせ設定」の画面になり
④組み合わせ設定
・組み合わせ名
好きな名前を入力
・曜日指定
この組み合わせを発火させたい曜日を選択
⑤設定を保存
Google Homeアクションの設定
次にアクションを設定します。
①左下のアクションのタブから「カスタムアクション」を「アクション」の丸いところまでドラッグ&ドロップ
②チャンネル設定
・アクション名
好きな名前を入力
・リクエストURL
ここに手順①で生成した、Google Homeが話すためのエンドポイントを入力します。
※ngrokのURLはサーバーを再起動するたびに変わります。サブドメインを固定させることもできますが、ngrokの有料プランとなります。なので、無料でやる場合は毎回サブドメインが変わるので、nodeサーバーを再起動させたらmyThings Developers上のリクエストURLも変更する必要があります。
③リクエスト内容
どのようなリクエストがくるか確認できます。values
に入るkeyを好きに使ってGoogle Homeに喋らせてください。
④設定保存ボタンを押す
テスト実行
ここまできたらゴールは目前。
トリガーとアクションんのつなぎ込みのテストをしましょう。
するとGoogle Homeが喋り出すはずです!
もし、失敗してしまったらリクエストURLが間違っていないかなどを確認してみてください。
定期実行をする
これで雨が降りそうな時にこの組み合わせが発動してGoogle Homeが教えてくれるようになりました!
他のトリガーを使っても様々なことができる
他にもトリガーとして
- ヤフオク、Yahoo!ショッピングでと組み合わせて「あるキーワードを含む商品が出品されたとき」
- Yahoo!防災速報と組み合わせて「地震情報が出たとき」「熱中症の危険度が高まったとき」
- 期限切れの間近のTポイントがあったら
などなど様々なサービスと組み合わせることができます。もちろんIFTTTでも生成したエンドポイントは使えます。
Twitterの通知をGoogle Homeに教えてもらう
IFTTTを使った例はこちらが参考になります。
是非いろいろなサービスと組み合わせて日常をハックしてみてください!!