Raspberry Piを使ってGoogle Homeを自発的に喋らせる

Google Homeは話しかけると喋ってくれますが、自発的に喋るのは苦手なようです。僕みたいですね。そこでRaspberry Piを使って、内気なGoogle Homeくんを自ら喋らせてみました。

# 使用したもの
- Google Home mini
- Raspberry Pi 3

# 使用した環境
```bash
$ lsb_release -a
No LSB modules are available.
Distributor ID:	Raspbian
Description:	Raspbian GNU/Linux 8.0 (jessie)
Release:	8.0
Codename:	jessie
$ node -v
v9.6.1
$ npm -v
5.6.0
```

# Google Homeを自発的に喋らせる方法
Google Homeに通知を送ることのできる`google-home-notifier`を使います。これをRaspberry Pi上で動作させ、Google Homeに通知を送ってやることで、Google Homeが喋ります。

以下コマンドで、Node.jsとnpmの最新版をインストールします。

```bash
sudo apt-get update
sudo apt-get install -y nodejs npm
sudo npm cache clean
sudo npm install npm n -g
sudo n stable
```

以下コマンドで、必要なパッケージをインストールします。

```bash
$ sudo apt-get install git-core libnss-mdns libavahi-compat-libdnssd-dev
```

以下コマンドで、`google-home-notifier`をダウンロードし、必要なパッケージをインストールします。

```bash
$ git clone https://github.com/noelportugal/google-home-notifier
$ cd google-home-notifier
$ npm install
```

以下コマンドで、設定ファイルを編集します。コメント行を適宜修正してください。

```bash
$ vi 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; // リスナーポートです。必要であれば変更してください。

var deviceName = 'Google Home';
var ip = '192.168.1.20'; // Google Homeの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 = 'ja'; // Google Homeに喋らせたい言語を設定します。今回は日本語なので「ja」を設定します。
  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 = 'ja'; // Google Homeに喋らせたい言語を設定します。今回は日本語なので「ja」を設定します。
  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');
  });
})
```

もうひとつ、設定ファイルを編集します。

```bash
$ vi node_modules/mdns/lib/browser.js

# before
Browser.defaultResolverSequence = [
  rst.DNSServiceResolve(), 'DNSServiceGetAddrInfo' in dns_sd ? rst.DNSServiceGetAddrInfo() : rst.getaddrinfo()
, rst.makeAddressesUnique()
];

#after
Browser.defaultResolverSequence = [
  rst.DNSServiceResolve(), 'DNSServiceGetAddrInfo' in dns_sd ? rst.DNSServiceGetAddrInfo() : rst.getaddrinfo({families:[4]})
, rst.makeAddressesUnique()
];
```

以下コマンドで、`google-home-notifier`を起動します。コマンドの後ろに`&`をつけるとバックグラウンド実行できます。

```bash
$ node example.js
or
// バックグラウンド実行
$ node example.js &
```

以下コマンドで、Google Homeに喋ってもらいます。

```bash
$ curl -X POST -d "text=はじめまして。" http://(RaspberryPiのIP):8091/google-home-notifier
```

<blockquote class="twitter-tweet" data-cards="hidden" data-lang="ja"><p lang="ja" dir="ltr">Raspberry Piを使ってGoogle Homeを喋らせました。 <a href="https://t.co/GaxlO2Bi4E">pic.twitter.com/GaxlO2Bi4E</a></p>&mdash; だいぱんまん@はてなブログ (@donchan922) <a href="https://twitter.com/donchan922/status/971007933013110791?ref_src=twsrc%5Etfw">2018年3月6日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# まとめ
あの内気なGoogle Homeくんが喋った！

# 参考リンク
- [GoogleHomeスピーカーに外部からプッシュして自発的に話してもらいます - Qiita](https://qiita.com/azipinsyan/items/db4606aaa51426ac8dac)
- [noelportugal/google-home-notifier: Send notifications to Google Home](https://github.com/noelportugal/google-home-notifier)