##概要
ラズベリーパイに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
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
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
[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を操作する。
curl -X POST -d "text=クローバ。。。ラジコでニッポン放送をつけて。" http://localhost:8091/google-home-notifier
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];
});
};