イチからGoogleHome＋RaspberryPi3＋IFTTTを連携させて喋らせるまで

### 前置き
既存の記事は色々とあるものの、イチから喋らせるまでには、かなり情報が拡散しているため、つまみ食いしていくのが大変でしたので、備忘録兼ねて記事にしておきます。
本記事を書くにあたって諸々参考にさせていただいた各記事／ページは、本文中にも随時出していきつつ、末尾にまとめておきます。

……というのを、2018/03/26に下書きに突っ込んで3ヶ月以上放置して忘れていたので、少し内容が古くなってる箇所があるかもしれませんが、勿体ないので投稿します。


# GoogleHome
## 購入
GoogleHome についてはあまり語ることはないです。Google assistant 搭載のスマートスピーカーを用意しましょう。DIY で自作することもできるようですね。

ちなみに私は、 [JBL Link10](http://jbl.harman-japan.co.jp/product.php?id=link) を購入しました（2018/03購入）
設置場所は、なるべく部屋の高い位置が良いと思います。物理的に複数個あるスピーカーでなく、単一の 360 度スピーカーなので。高さ 1.8m くらいのワイヤーラックの最上段に設置した時と、3 段目あたり（高さ 1.0m くらい）に設置した時とで、音の拡がり・反響が全然違います。

### 余談：GoogleHome Mini も追加購入
ちなみに、その後、2018/06の半額セール時に、GoogleHome Mini も追加購入しました。GoogleHome の方が、当然、Google のお膝元ということで、ファームウェアの更新を頻繁にしてくれます。キャスト対応している Google Assistant 搭載のスピーカーをグルーピングしてくれるので、 JBL Link10 とグルーピングした上で、部屋の両端に設置することで、安価になかなか素晴らしいサラウンド環境が構築できます。

## IP アドレスの確認
初期設定してネットワークに接続されたら、IP アドレスを Google Home アプリから確認しておいてください。後で使います。



# RaspberryPi3
## 購入～組立
みんな大好き amazon で購入しました。
たぶん一番売れているのは、 [ケースつきのコレ](https://www.amazon.co.jp/dp/B01CSFZ4JG/) ですよね。これ選んでおけば無難だとは思います。

ちなみに私は、ケースを別途購入したかった（ファンつきのものにしたかったのと、もうちょっとカッコイイケースの方がよかった）ので、 [日本製と銘打っているこちら](https://www.amazon.co.jp/dp/B01NAHBSUD/) にしました。 [ケースはこちら](https://www.amazon.co.jp/dp/B075F7HC31/) 。
組立も全く大変じゃないです。一点だけ気をつけるべきこととしては、ファンの配線は、なるべく距離を取れるような向きでファンを上部蓋に固定すること（でないとケーブルが詰まる）。あと、廃熱性能を考えると、回転数の多くなる 5V の方に挿した方がいいかと思います。音は全然うるさくない。


## 初期設定
OS は色々と調べたのですが、大人しく Raspbian Lite にしておきました。GUI は重くなるから今回は要らんです。
初期設定にあたり、一番参考にさせていただいた記事が以下です。

* [Raspbianのインストールと最強の初期設定](https://jyn.jp/raspbian-setup/)


### OS の img ダウンロード ～ 解凍
以下のミラー FTP サイトから。日本サーバなので高速。最新版で良いでしょう。
http://ftp.jaist.ac.jp/pub/raspberrypi/raspbian_lite/images/
ダウンロードしてきたら解凍します。


### microSD カードの用意 ～ img の書き込み
どうやらラズパイさんは microSD カードの相性にうるさいようで……。Team と SanDisk はやめた方が無難とのこと。これから買おうという方は要注意。

* [Raspberry Pi 3で安定して使える相性の無い最適な microSDカードの種類のまとめ](http://www.neko.ne.jp/~freewing/raspberry_pi/raspberry_pi_3_microsd_card_stable/)

手元には TOSHIBA の SDXC 64GB があったので、それを使うことにしました。Windows 機なので、SD カードへの書き込みは以下ソフトを使用。

[DD for Windows](http://www.si-linux.co.jp/techinfo/index.php?DD%20for%20Windows#s74c46f6)

実行ファイル DDWin.exe は「管理者として実行」します。ディスクを選択し、imgファイルを選択し、「 << 書き込み << 」を実行。このソフトであれば同時にフォーマットもしてくれるようです。

なお、書き込み完了後に、SDカードで新しくパーティション分けされたところについて「フォーマットしますか？」などと訊かれますが、キャンセルしてください。

boot ドライブが SD カード内にできているはずなので、その直下に ssh という名前の空ファイルを作成してください。このファイルの有無で、SSH 接続が有効判定されます。


### ラズパイの起動 ～ SSH 接続
ラズパイには起動／終了の物理スイッチはありません。給電は microUSB ケーブルです。公式では、3B からは、5V 2.5A 以上が推奨されているようですが、GUI でよっぽどハードな使い方でもしなければ、別に 2.1A でも問題なさそうです。ということで、私は、2.1A で運用してみます。

microUSB ケーブルを差し込むと、早速給電が始まり、起動しました。ファンが静音ながらも頼もしく回ってくれます。

さて、ラズパイに直接 USB でキーボードを接続、HDMI でディスプレイを接続、としてもよいのですが、面倒なので、 SSH 接続で済ませます。ラズパイ本体は、有線 LAN で運用したいので、ルータの近くにひっそり設置。

ラズパイに SSH 接続するには、ラズパイに割り当てられた　IP アドレスが必要になります。自明の理。コマンドプロンプトで arp -a 実行して、同一ネットワーク内の IP の一覧を表示させます。よっぽど色々と DHCP で自動払い出ししているデバイスがある環境でもない限りは、すぐにこれがラズパイの IP アドレスかなーと分かると思います。

IP が分かったら、あとはターミナルから接続です。ユーザは pi で、パスワードは raspberry がデフォルト設定なので、それを入力すれば開けるはずです。


#### :persevere:ラズパイの IP が分からない！！　という場合……
……もし万が一、ここに表示されない、とか、フリーソフトで IP 検出してくれるものを試してもダメ、とかいう場合には、仕方ないので、ラズパイを直で操作しましょう。/etc/dhcpcd.conf を編集して、IP アドレスを静的に固定させてしまえばよいです。

``` /etc/dhcpcd.conf
interface eth0
  static ip_address=192.168.x.x
  static routers=192.168.x.1
  static domain_name_servers=192.168.x.1 8.8.8.8
```

### 変更されるべき初期状態
#### IP アドレスを静的に固定する
SSH 接続が問題なくうまくいった場合も、上記の通り、IP アドレスは静的に固定してしまいましょう。

#### apt で諸々アップデート
```
sudo apt-get update && sudo apt-get -y dist-upgrade && sudo apt-get -y autoremove && sudo apt-get autoclean
```

#### raspi-config
諸々の初期設定を司るファイルです。

```
sudo raspi-config
```

* Change User Password → 任意のものへ
* Hostname → ラズパイを複数台運用する可能性があるなら個体識別させる必要があるので分かりやすい名付けを
* Localisation Options > Change Locale → ja_JP.UTF-8
* Localisation Options > Change Timezone → Asia Tokyo
* Localisation Options > Change Wi-fi Country → 一応 JP へ
* Advanced Options > Memory Split → GUI 使わないので 16 に

以上おこなった上で、 Finish すると、勝手に再起動かかります。パスワードを変える場合、入れなくなるという過ちを犯さないようご注意を。

#### その他、鍵設定など
ufw を用いたファイアウォールの設定だとか、SSH 接続における鍵の設定だとかは、他 Linux システムの運用と同じなので流石にここでは割愛します。


## Node.js のインストール
さて、ようやく初期設定が終わりました。が、まだまだこれからです。徐々にヘヴィになってきます。Node.js をインストールしましょう。

* [Raspberry Pi 3 Model BにnvmでNode.jsをインストールする](http://sirasu55.hatenablog.com/entry/2017/10/11/235223)

まず準備段階として、git をインストールしておきます。

```
sudo apt-get install git
```

最初に、古い Node.js をアンインストール。

```
sudo apt-get autoremove nodejs
```

続いて、nvm インストール用フォルダ用意して、そこに nvm リポジトリのクローンを作成。

```
sudo mkdir ~/.nvm
sudo chmod 777 ~/.nvm
git clone https://github.com/creationix/nvm.git ~/.nvm
```

nvm を使えるように sh 実行させ、無事に成功したかどうか確認のため ver. チェック。

```
source ~/.nvm/nvm.sh
nvm --version
```

nvm が使えるようになったので、LTS 最新の ver. をチェック。2018/03/25 時点での最新は、 v.6.13.1 でしたので、それをインストール。無事に成功したかどうか確認のため ver. チェックまで。

```
nvm ls-remote
nvm install v6.13.1
node -v
npm -v
```

サーバ起動時に node が動くように、/etc/profile.d/nvm.sh を作成します。

``` /etc/profile.d/nvm.sh
source ~/.nvm/nvm.sh
```


## ngrok の設定
さて、自宅にグローバル IP アドレスを設置している人でもなければ、外部からラズパイ宛てに cUrl で POST することなんぞできませんね。そこで、活用されるのが、 [ngrok](https://ngrok.com/) というサービスです。

* [LINE Messaging APIをngrok経由でRaspberry Pi 3で使ってみる（サンプルbot編）](https://hakengineer.xyz/2017/10/10/post-425/#ngrok)

[ngrok](https://ngrok.com/) に登録 → ログインしてから、 Install your authtoken に表示されている authtoken を保管しておいてください。

```
./ngrok authtoken XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
```

次に、ターミナルに戻ってきて、適当な場所に zip ファイルをダウンロードしてきます。それを /usr/local/bin/ に展開します。

```
wget https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-arm.zip
sudo unzip ngrok-stable-linux-arm.zip -d /usr/local/bin/
```

で、 authtoken を入力するために以下の通りコマンドを叩いてください。

```
ngrok authtoken XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
```

これでラズパイにエンドポイントを設定できるようになります。


## google-home-notifier
このあたりから参考記事が増えてきますね……。

* [Google Home開発入門 / google-home-notifier解説](https://qiita.com/SatoTakumi/items/c9de7ff27e5b70508066)
* [Raspberry PiからGoogle Homeを喋らせる](https://qiita.com/ktetsuo/items/8c9cd5714e231aa6ae09)
* [GoogleHomeスピーカーに外部からプッシュして自発的に話してもらいます](https://qiita.com/azipinsyan/items/db4606aaa51426ac8dac)
* [google-home-notifier周りをほぼ自動化した](https://qiita.com/k_keisuke/items/3e67aa25a24f07656f47)

### google-home-notifier のインストール
package.json を作ってからインストール。

```
npm init
npm install google-home-notifier
```

### とりあえず喋らせてみる
/home/pi 直下に main.js を設置。IP アドレスは Home アプリで確認したものを拾ってきましょう。

``` main.js
※入れる
```

なお、喋らせるだけでなく音声ファイルを流すこともできます。
以下の箇所を、

```
googlehome.notify('こんにちは。私はグーグルホームですよ。', function(res) {
  console.log(res);
});
```

以下のようにします。

```
googlehome.play('mp3ファイルへのリンク', function(res) {
  console.log(res);
});
```

さて、今回は、IFTTT と連携させて、IFTTT 側から渡されてきたものに応じて喋ってもらったり mp3 を再生してもらったりしたいので、example.js に手を入れます。

``` example.js
var express = require('express');
var googlehome = require('./google-home-notifier');
var ngrok = require('ngrok');
var bodyParser = require('body-parser');
var app = express();
var language = 'ja';
const serverPort = xxxx;
const googlehome_ip = '192.168.x.xx';

var deviceName = 'Google Home';
googlehome.device(deviceName,language);
googlehome.ip(googlehome_ip,language);

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 (text){
    try {
      if (text.match(/mp3/)) {
        googlehome.play(text, function(notifyRes) {
          console.log(notifyRes);
          res.send(deviceName + ' will play: ' + text + '\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 POST "text=Hello Google Home"');
  }
})

// 後略
```

port はお好みで。googlehome_ip は前述通りに。

下の方で設定することになる IFTTT から渡ってくる body.text 内に、mp3 という文字列を含んでいたら、mp3 再生にする、という、単純な分岐条件にしています。とりあえず。



### google-home-notifier のバックグランド実行
本当であれば、上記の example.js (仮名) は、ラズパイの起動時に自動で起動させたいところですが、ひとまず、forever でバックグラウンド実行してもらうに留めておきます。

* [foreverコマンドでNodeJSアプリを起動したままにする](https://qiita.com/h1y0r1n/items/a2cf8f2e8d3d31ccba49)

まずは forever のインストール。

```
npm install -g forever
```

そして、バックグラウンド実行の開始。

```
forever start /home/pi/node_modules/google-home-notifier/example.js
```

すると、/home/pi/.forever/ にログファイルができますので、それを開くと、ngrok のURLが分かりますから、これを控えておきましょう。

なお、私は手をつけられていませんが、自動化については以下あたりが参考になるかと。

* [google-home-notifier周りをほぼ自動化した](https://qiita.com/k_keisuke/items/3e67aa25a24f07656f47)
* [[Node.js] PM2を用いて本番環境でNodeJSアプリを動かす](https://www.yoheim.net/blog.php?q=20170706)

ちなみに forever も pm2 も、nvm を /.nvm にインストールしてしまうと取り扱いづらくなってしまうことに今さら気づきました。ので、面倒になってしまって……。


# IFTTT
みんな大好き [IFTTT](https://ifttt.com/) 。アカウントは簡単に作成できます。


## THEN
トリガなので何でも良いと思います。ひとまず実験しやすいもので。Gmail の新着メール受信とか。

実際に使うとなると、時報的に、毎時 00 分になると指定した mp3 が再生される、とか面白いですよ。機械仕掛けの時計みたいな。Date & Time です。

他にも、Weather Underground で、外気温の変動や、晴れ ⇔ 曇り ⇔ 雨の変動を知らせてもらうとか。Weather Underground は、デフォルトでちゃんと日本の設定にはなってますが、ロケーションを自分で設定／変更したい場合は、以下記事を参照。

* [IFTTTのWeather Undergroundで取得する地域を設定する方法](https://qiita.com/yukkin4649/items/b52781928742b7eeaa74)


## THAT
Webhook を選んでください。詳細な設定は以下の通りに。URL は、先ほど forever のログファイルから拾ってきたものです。ngrok のフリープランだと再起動毎に変わるので要注意。

* Make a web request
    * URL → https://xxxxxxxx.ngrok.io/google-home-notifier
    * Method → POST
    * Content Type → application/x-www-form-urlencoded
    * Body (テキストスピーチの場合) → text="ほげほげふがふが"
    * Body (mp3 再生の場合) → text=http://hogehoge.fugafuga/hogefuga.mp3

言うまでもなく mp3 ファイルはあらかじめ任意のものを任意の場所に置いておいてください。


# 参考にさせていただいた各記事／ページ
* [Raspbianのインストールと最強の初期設定](https://jyn.jp/raspbian-setup/)
* [Raspberry Pi 3で安定して使える相性の無い最適な microSDカードの種類のまとめ](http://www.neko.ne.jp/~freewing/raspberry_pi/raspberry_pi_3_microsd_card_stable/)
* [Raspberry Pi 3 Model BにnvmでNode.jsをインストールする](http://sirasu55.hatenablog.com/entry/2017/10/11/235223)
* [LINE Messaging APIをngrok経由でRaspberry Pi 3で使ってみる（サンプルbot編）](https://hakengineer.xyz/2017/10/10/post-425/#ngrok)
* [Google Home開発入門 / google-home-notifier解説](https://qiita.com/SatoTakumi/items/c9de7ff27e5b70508066)
* [Raspberry PiからGoogle Homeを喋らせる](https://qiita.com/ktetsuo/items/8c9cd5714e231aa6ae09)
* [GoogleHomeスピーカーに外部からプッシュして自発的に話してもらいます](https://qiita.com/azipinsyan/items/db4606aaa51426ac8dac)
* [foreverコマンドでNodeJSアプリを起動したままにする](https://qiita.com/h1y0r1n/items/a2cf8f2e8d3d31ccba49)
* [google-home-notifier周りをほぼ自動化した](https://qiita.com/k_keisuke/items/3e67aa25a24f07656f47)
* [[Node.js] PM2を用いて本番環境でNodeJSアプリを動かす](https://www.yoheim.net/blog.php?q=20170706)
* [IFTTTのWeather Undergroundで取得する地域を設定する方法](https://qiita.com/yukkin4649/items/b52781928742b7eeaa74)