19
24

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

myThingsを使って雨が降りそうなときにGoogle Homeが自動的に教えてくれるようにする

Last updated at Posted at 2018-03-04

先日登壇した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は以下のようになっています。

google-home-notifier/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アプリを開き、左上のハンバーガーメニューから「デバイス」
ファイル名

次に右上のマークを押す
ファイル名

設定
ファイル名

一番下までスクロールするとIPアドレスが書いてあります。
ファイル名

このアドレスで書き換えます。

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リクエストをしてみましょう。

GETリクエスト
curl -i -X GET \
 'https://<生成されたサブドメイン>.ngrok.io/google-home-notifier?text=こんにちは'
POSTリクエスト(ヘッダーをつける必要あり)
curl -i -X POST \
   -H "Content-Type:application/x-www-form-urlencoded" \
   -d \
'text=こんにちは' \
 'https://<生成されたサブドメイン>.ngrok.io/google-home-notifier'

するとGoogle Homeが下の動画のように喋り出すはずです!
GoogleHome発話デモ1

myThings Developersからのリクエストを受け取れるようにする。

myThings Developersからのリクエストは以下のような形式で送られてきます。

リクエスト内容

・リクエストメソッド
POST
・Content-Type
application/json
・リクエストヘッダー
X-Secret : <シークレットの値>
・リクエストパラメーター
要素 説明
user_id 実行されたユーザーID
service_id 実行されたサービスID
mythings_id 実行された組み合わせID
values トリガーから渡された値
Yahoo!天気トリガーのサンプルボディー
{
    "user_id": "<実行されたユーザーのID>",
    "service_id": "<サービスID>",
    "mythings_id": "<myTingsID>",
    "values": [
        {
            "area": "<地域>",
            "datetime": "<降雨日時>",
            "time": "<降雨時刻>",
            "date": "<降雨日>",
            "rainfall": "<降水量>",
        }
    ]
}

これを受け取れるようにexample.jsに以下のような新たなエンドポイントを追加しましょう。

google-home-notifier/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'

するとこんな感じにGoogle Homeが喋り始めます。
GoogleHome発話デモ2

これで手順①は終了です。次に手順②のmyThings Developersのトリガーとアクションを設定をします。

myThings Developersのトリガーとアクションを設定する。

myThings Developersへ登録 or ログイン

右上のから新規登録 or ログインをしてください
ファイル名

ログイン後、開始を押してください。
ファイル名

サービス登録画面が出ますので、「名称」を適当に設定してください。
ファイル名

天気トリガーの設定

ファイル名 ①左下のトリガーのタブから「Yahoo!天気」を「トリガー」の丸いところまでドラッグ&ドロップ ②チャンネル設定 ・トリガー プルダウンの中にいくつか項目がありますが、ここでは「雨が降りそうなら」を選択 ・地域 好きな地域を選択 ・時間 何時間以内に雨が降りそうだったら教えて欲しいかを設定 ・降水量 降水量がいくつ以上だったら通知して欲しいかを設定 降水量の目安については[こちら](https://piropurin.com/event/kosuiryo)を参考にしてください。 ③設定を保存ボタンを押す

ここまで完了すると「組み合わせ設定」の画面になり
ファイル名
④組み合わせ設定
・組み合わせ名
好きな名前を入力
・曜日指定
この組み合わせを発火させたい曜日を選択
⑤設定を保存

Google Homeアクションの設定

次にアクションを設定します。
ファイル名
①左下のアクションのタブから「カスタムアクション」を「アクション」の丸いところまでドラッグ&ドロップ
②チャンネル設定
・アクション名
好きな名前を入力

・リクエストURL
ここに手順①で生成した、Google Homeが話すためのエンドポイントを入力します。
※ngrokのURLはサーバーを再起動するたびに変わります。サブドメインを固定させることもできますが、ngrokの有料プランとなります。なので、無料でやる場合は毎回サブドメインが変わるので、nodeサーバーを再起動させたらmyThings Developers上のリクエストURLも変更する必要があります。

③リクエスト内容
どのようなリクエストがくるか確認できます。valuesに入るkeyを好きに使ってGoogle Homeに喋らせてください。

④設定保存ボタンを押す

テスト実行

ここまできたらゴールは目前。
トリガーとアクションんのつなぎ込みのテストをしましょう。

テスト実行ボタンを押して
ファイル名

Yahoo!天気を認証して
ファイル名

テスト実行
ファイル名

するとGoogle Homeが喋り出すはずです!

GoogleHome発話デモ3
もし、失敗してしまったらリクエストURLが間違っていないかなどを確認してみてください。

定期実行をする

ファイル名

組み合わせを実行したい曜日を指定して実行
ファイル名

これで雨が降りそうな時にこの組み合わせが発動してGoogle Homeが教えてくれるようになりました!
ファイル名

他のトリガーを使っても様々なことができる

他にもトリガーとして

  • ヤフオク、Yahoo!ショッピングでと組み合わせて「あるキーワードを含む商品が出品されたとき」
  • Yahoo!防災速報と組み合わせて「地震情報が出たとき」「熱中症の危険度が高まったとき」
  • 期限切れの間近のTポイントがあったら

などなど様々なサービスと組み合わせることができます。もちろんIFTTTでも生成したエンドポイントは使えます。
Twitterの通知をGoogle Homeに教えてもらう
IFTTTを使った例はこちらが参考になります。

是非いろいろなサービスと組み合わせて日常をハックしてみてください!!

19
24
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
24

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?