Edited at

ラズパイ+3GPi+イプシムを使って外から家のGoogle Homeを喋らせる

More than 1 year has passed since last update.

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

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)の使い方で参照したサイトと接続手段


どうやって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


セットアップ


  1. ラズパイ+3GPi+イプシム

    anyPi(ラズパイ+3GPi)で固定IPアドレスSIMイプシムを使うと、ラズパイ+3GPiをufw/hostapd/dnsmasqでモバイルWi-Fiルータにして格安SIMで使うに従って設定します。



  2. 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』は利用可能です。




  3. google-home-notifier

    Raspberry PiにNode.jsとnpmの最新版をインストールするを参考に進めます。

    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が動作しませんでした。完了後、バージョンを確認します。


    node

    $ node -v
    
    v8.9.0


    npm

    $ npm -v
    
    5.5.1

    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
    


    node_modules/mdns/lib/browser.js(修正前)

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


    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
    


    example.js

    //var deviceName = 'Google Home';
    
    var deviceName = '(Google Homeセットアップ時の名前)';

    vi google-home-notifier.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
    



  2. localhost上と同一LAN上から投げてみる


    RPi

    $ curl -X POST -d "text=ローカルホストからのメッセージ" http://localhost:8080/google-home-notifier
    
    Google Home will say: ローカルホストからのメッセージ


    無線LAN上の別PC

    $ curl -X POST -d "text=同一ネットワークからのメッセージ、漢字や句読点もOK" http://192.168.168.1:8080/google-home-notifier
    
    Google Home will say: 同一ネットワークからのメッセージ、漢字や句読点もOK




  3. 外から投げてみる

    事前に、ufwで「接続元のIPアドレスから、イプシムの固定IPアドレス:ポート8080への接続」を許可してください。

    sudo ufw allow from [会社のIPアドレス] to [イプシムのIPアドレス] port 8080 proto tcp
    


    会社のPC(任意ポートへのPOSTが許可されている方に限ります)

    $ curl -X POST -d "text=仕事が終わったので帰ります" http://イプシムの固定IPアドレス:8080/google-home-notifier
    
    Google Home will say: 仕事が終わったので帰ります

    簡単!

    iPhoneのiCurlHTTP3でもOKです。

    iCurlHTTP1.JPG

    iCurlHTTP2.JPG




今後の展開


  • ちゃんとしたWeb UI/APIを作る。

  • Web UI/API経由でgoogle-home-notifierを直接呼び出す。(フロントがあればリスナーは不要)

  • 認証を設ける。

  • ボイスメッセージを投げて、そのままGoogle Homeに再生させる。





  1. NAPTタイマ切れによる切断やグローバルIP変更時の再接続など、確実に接続できる保証もありません。そもそも外界にトンネル張りっぱなしというのも少し不安です。 



  2. Google Homeを自宅LANに接続したくない、という別の理由もありますが…。 



  3. 設定画面で「Use HTTP2」のチェックを外してください。