GoogleHomeスピーカーに外部からプッシュして自発的に話してもらいますを参考に、ラズパイ+3GPiとイプシムだけで、外出先から自宅のGoogle Homeを喋らせてみます。IFTTT、Firebase、Twitter、Slackなどの外部サービスやngrokなどのトンネルサービスは使いません。
#何ができるの?
- どこでも『OK, Google』(固定回線不要・無線LAN不要)
- 外から家のGoogle Homeを喋らせる!
##準備するもの
- Raspberry Pi 3 Model B(またはRPi2とUSB無線LANドングルの組み合わせ+追加設定)
- 3GPi+同梱Raspbian(3gpi2-jessie-20170904)(またはUSBモデム+追加設定)
- 固定IPアドレスMVNO「イプシム」標準SIM
- Google Home または Google Home Mini
- 自由にHTTP POSTできる環境
##ネットワーク構成
Internet --(3G回線)-- <ppp0>[3GPi+イプシム]+[RPi]<wlan0> --(無線LAN)-- [Google Home]
#はじめに:Google Homeの利用方法3パターン
Input | 中間処理 | Output | 例 | |||
---|---|---|---|---|---|---|
(1)OK, Google | Google Home | → | → | Google Home | 「今日の天気は?」⇒『晴れです』 | |
(2)内から外 | Google Home | → | IFTTT | → | Twitter, Slack等 | 「~と呟いて」⇒"~"をtweet |
(3)外から内 | 何かのトリガと手段 | → | google-home-notifier | → | Google Home | "帰ります"をPOST⇒『カエリマス』 |
(1)は普通の使い方ですね。
(2)はIFTTTを使う例が多いようです。
(3)が今回やりたいことですが、google-home-notifierをラズパイなどで動作させることで、簡単に実現できるようです。なんと「Google Homeに喋らせたいメッセージ」を、google-home-notifierにPOSTで投げるだけで、Google Homeが喋ります。残る問題は、LAN以外からどうやってgoogle-home-notifierに投げるか、だけです。
##(3)の使い方で参照したサイトと接続手段
- GoogleHomeスピーカーに外部からプッシュして自発的に話してもらいます (LAN)
- Google Homeで時報を知らせる (LAN)
- 帰宅したらGoogleHomeから好きな音声で「おかえり」って言ってもらいます (LAN)
- Twitterの通知をGoogle Homeに教えてもらう (ngrok)
- Google Home、IFTTT、Googleスプレッドシートを使って独自音声コマンドでログをとる(ついでにNode.jsやngrokやらも使ってLINEやGoogle Homeに通知する) (ngrok)
- 新着メールを知らせてくれるGoogle Home (Firebase)
##どうやってgoogle-home-notifierに投げるか?
LANから投げるのであれば、
http://ラズパイのIPアドレス:8080/google-home-notifier
にPOSTすれば良いだけです。悩むことはありません。
また親切なことに(?)、google-home-notifierはデフォルトでngrokが使えるようになっていて、WAN(Internet側)から投げる場合も、起動時に表示されるURL
https://********.nrgok.io/google-home-notifier
にPOSTすれば、後はngrokのトンネル経由で到達できるようになっています。しかし、ngrokはgoogle-home-notifierを起動する度にURLが変わってしまいます。このためIFTTTのwebhookなどに設定するのには向きません。1
そうすると、FirebaseのリアルタイムDB更新とFirebase Listenerを組み合わせが、NAT+クラウド時代のまっとうな解決方法かもしれません。
…が、固定IPアドレスがあれば、そこに投げれば良いのでは? ということで
http://イプシムの固定IPアドレス:8080/google-home-notifier
に投げる、という安易な解が導き出されました。2
#セットアップ
-
ラズパイ+3GPi+イプシム
anyPi(ラズパイ+3GPi)で固定IPアドレスSIMイプシムを使うと、ラズパイ+3GPiをufw/hostapd/dnsmasqでモバイルWi-Fiルータにして格安SIMで使うに従って設定します。 -
Google Home
Google HomeのMACアドレスを調べて、ラズパイのDHCPサーバでGoogle Homeに恒久的にIPアドレスを割り当てます。/etc/dnsmasq.conf
dhcp-host=XX:XX:XX:XX:XX:XX, GoogleHome, 192.168.168.2, infinite
スマートフォンでGoogle Home側の設定を終わらせます。この時点ですでに『OK, Google』は利用可能です。
1. google-home-notifier
[Raspberry PiにNode.jsとnpmの最新版をインストールする](https://qiita.com/mascii/items/77c685df65c4cbca9315)を参考に進めます。
```
sudo apt-get install nodejs npm
sudo npm cache clean
sudo npm install npm n -g
sudo n lts
最後を`sudo n stable`とすると、v9.0.0がインストールされてしまい、google-home-notifierが動作しませんでした。完了後、バージョンを確認します。
```text:node
$ node -v
v8.9.0
```text:npm
$ npm -v
5.5.1
[google-home-notifier](https://github.com/noelportugal/google-home-notifier)のREADMEにある、Raspberry Piの記載を先に実行します。
```
curl -sL https://deb.nodesource.com/setup_7.x | sudo -E bash -
sudo apt-get install nodejs
sudo apt-get install git-core libnss-mdns libavahi-compat-libdnssd-dev
あとはgoogle-home-notifier本体です。
```
git clone https://github.com/noelportugal/google-home-notifier
cd google-home-notifier
npm install
npm install後、READMEに従ってファイルを修正します。
```
vi node_modules/mdns/lib/browser.js
```text:node_modules/mdns/lib/browser.js(修正前)
Browser.defaultResolverSequence = [
rst.DNSServiceResolve(), 'DNSServiceGetAddrInfo' in dns_sd ? rst.DNSServiceGetAddrInfo() : rst.getaddrinfo()
, rst.makeAddressesUnique()
];
```
```text:node_modules/mdns/lib/browser.js(修正後)
Browser.defaultResolverSequence = [
rst.DNSServiceResolve(), 'DNSServiceGetAddrInfo' in dns_sd ? rst.DNSServiceGetAddrInfo() : rst.getaddrinfo({families:[4]})
, rst.makeAddressesUnique()
];
```
設定ファイルを編集します。
```
vi example.js
```js:example.js
//var deviceName = 'Google Home';
var deviceName = '(Google Homeセットアップ時の名前)';
```
vi google-home-notifier.js
```js:google-home-notifier.js
//var deviceAddress;
var deviceAddress='192.168.168.2';
//var device = function(name, lang = 'en') {
var device = function(name, lang = 'ja') {
//var googlettsaccent = 'us';
var googlettsaccent = 'ja';
#動作確認
1. 起動
```
node example.js
-
localhost上と同一LAN上から投げてみる
RPi
$ curl -X POST -d "text=ローカルホストからのメッセージ" http://localhost:8080/google-home-notifier
Google Home will say: ローカルホストからのメッセージ
```bash:無線LAN上の別PC
$ curl -X POST -d "text=同一ネットワークからのメッセージ、漢字や句読点もOK" http://192.168.168.1:8080/google-home-notifier
Google Home will say: 同一ネットワークからのメッセージ、漢字や句読点もOK
-
外から投げてみる
事前に、ufwで「接続元のIPアドレスから、イプシムの固定IPアドレス:ポート8080への接続」を許可してください。
sudo ufw allow from [会社のIPアドレス] to [イプシムのIPアドレス] port 8080 proto tcp
```bash:会社のPC(任意ポートへのPOSTが許可されている方に限ります)
$ curl -X POST -d "text=仕事が終わったので帰ります" http://イプシムの固定IPアドレス:8080/google-home-notifier
Google Home will say: 仕事が終わったので帰ります
簡単!
iPhoneの[iCurlHTTP](https://itunes.apple.com/jp/app/icurlhttp/id611943891)[^3]でもOKです。
<img width="375" alt="iCurlHTTP1.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/211762/04dc4db2-a2ae-c25e-3982-c09c2c6edeee.jpeg">
<img width="375" alt="iCurlHTTP2.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/211762/912b071c-7813-c9fd-7b71-7ad27c2dad8f.jpeg">
#今後の展開
- ちゃんとしたWeb UI/APIを作る。
- Web UI/API経由でgoogle-home-notifierを直接呼び出す。(フロントがあればリスナーは不要)
- 認証を設ける。
- ボイスメッセージを投げて、そのままGoogle Homeに再生させる。