3
6

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.

【Raspberry Pi Zero W】おしゃべりGoogleHome

Last updated at Posted at 2018-04-06

##概要
ラズベリーパイにgoogle-home-notifierを導入してGoogleHomeをしゃべらせたいと思います。

##前提条件
Raspberry Pi

  • モデル : Raspberry Pi Zero W
  • OS : Raspbian Stretch Lite
$ uname -a
Linux raspberry 4.14.32+ #1106 Wed Apr 4 17:54:59 BST 2018 armv6l GNU/Linux

GoogleHome

  • GoogleHomeMini

##事前準備
お約束作業です。

$ sudo apt-get update
$ sudo apt-get upgrade

##Node.jsとnpmをインストール
google-home-notifierはNode.jsとnpmを使用するため、事前にインストールします。

参考サイト:
https://qiita.com/mascii/items/77c685df65c4cbca9315

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

$ node -v # バージョン確認
v9.10.1
$ npm -v # バージョン確認
5.6.0

##google-home-notifierをインストール
google-home-notifierをインストールします。

参考サイト:
https://qiita.com/ktetsuo/items/8c9cd5714e231aa6ae09

$ mkdir googlehome
$ cd googlehome
$ sudo apt-get install libavahi-compat-libdnssd-dev
$ npm init # すべてデフォルト
$ npm install google-home-notifier
$ cat package.json # 何となく確認
{
  "name": "googlehome",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "google-home-notifier": "^1.2.0"
  }
}

##動作確認
テスト用プログラムを作成します。
”xxx.xxx.xxx.xxx”はGoogle-HomeのIPアドレスです。アプリの設定画面等で確認できます。できれば固定しておきたいですね。

$ vi test.js
test.js
const googlehome = require('google-home-notifier');
const language = 'ja';
googlehome.device("Google-Home", language);
googlehome.ip("xxx.xxx.xxx.xxx");
googlehome.notify('こんにちは。私はグーグルホームです。', function(res) {
  console.log(res);
});

実行して(WARNINGは出るけど・・・)GoogleHomeがしゃべりだせば成功です!!

$ node test.js

##動作確認その2
コマンドで実行できたりすると可能性が広がりますよね。ほぼ参考サイトそのままです。

参考サイト:
https://qiita.com/azipinsyan/items/db4606aaa51426ac8dac

$ vi web.js
web.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 = 'xxx.xxx.xxx.xxx'; // default IP      //ここに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'; // default language code   //ここに「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'; // default language code     //ここに「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');
  });
})

実行すると(今回もWARNINGは出るけど・・・)POSTする際の例文が表示されます。

$ node web.js

もう1セッション接続して、以下のコマンドを実行してGoogleHomeがしゃべりだせば成功です!!

$ curl -X POST -d "text=こんにちは。私はグーグルホームです。" http://localhost:8091/google-home-notifier

動作確認ができたら、CTRL+Cで終了します。

##foreverをインストール
foreverを導入すると、nodeをバックグランドで起動することができるので便利です。

$ sudo npm install -g forever
$ forever start web.js
$ curl -X POST -d "text=こんにちは。私はグーグルホームです。" http://localhost:8091/google-home-notifier

ちなみにforever stop web.jsで終了できます。

##systemd登録
再起動しても自動で起動するように、systemdに登録します。

参考サイト:
https://qiita.com/you21979@github/items/588bddb59378ce7303a2
https://qiita.com/udon11/items/fef44cec7b243f93151b

$ sudo vi /etc/systemd/system/googlehomenotifier.service
googlehomenotifier.service
[Unit]
Description=google-home-notifier Server
After=syslog.target network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/forever start /home/pi/googlehome/web.js
WorkingDirectory=/home/pi/googlehome
KillMode=process
Restart=no
User=pi

[Install]
WantedBy = multi-user.target
$ sudo systemctl list-unit-files --type=service | grep googlehomenotifier
$ sudo systemctl enable googlehomenotifier
$ sudo systemctl status googlehomenotifier
$ sudo systemctl start googlehomenotifier

最後に、再起動して自動起動していることを確認してください。

##使用例
GoogleHomeでClovaを操作する。

radiko_1242.sh
curl -X POST -d "text=クローバ。。。ラジコでニッポン放送をつけて。" http://localhost:8091/google-home-notifier
radiko_off.sh
curl -X POST -d "text=クローバ。。。ラジコをとめて。" http://localhost:8091/google-home-notifier
$ crontab -l
00 22 * * 0 radiko_1242.sh # 毎週日曜日22:00にラジコをつける
30 22 * * 0 radiko_off.sh # 毎週日曜日22:30にラジコをとめる

なんか、すごい遠回りしてるような。。。

##2018/11/22更新
しゃべらなくなった?

下記参考サイトの「「Error: get key failed from google」エラー」参照
google-home-notifier関連のエラー対処方法

【原因】
google翻訳(https://translate.google.com)の返すキーが、「TKK = ‘405291.1334555331’」から「TKK=’12345678.90123’」になり、それをチェックする「node_modules/google-tts-api/lib/key.js」でエラーになっている
【解決方法】
Githubに対応ソースがあがっていたので、その内容で
「node_modules/google-tts-api/lib/key.js」を修正する
以下の内容に書き換える

var fetch = require('isomorphic-fetch');
var host = 'https://translate.google.com';
 
/**
 * Get Key from https://translate.google.com
 *
 * @param   {Number!} timeout  default is 10000ms
 * @return  Promise(key: String)
 */
module.exports = function (timeout) {
  return fetch(host, {
    timeout: timeout || 10 * 1000
  })
  .then(function (res) {
    if (res.status !== 200) {
      throw new Error('request to ' + host + ' failed, status code = ' + res.status + ' (' + res.statusText + ')');
    }
    return res.text();
  })
  .then(function (html) {
    var match = html.match("TKK='(\\d+.\\d+)';");
 
    if (!match) throw new Error('get key failed from google');
 
    return match[1];
  });
};
3
6
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
3
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?