レッツラズパイ！〜Google Homeに室温を教えてもらおう編〜

## レッツラズパイ！・プロジェクト
1. [レッツラズパイ！〜Raspberry3にOSをインストールしよう〜](https://qiita.com/westvirginia/items/edc3b56da7be58419d70)  
[【番外編】レッツラズパイ！〜"ディスプレイなしで"RaspberryPiにOSをインストールしよう編〜](https://qiita.com/westvirginia/items/0d3b7d7dd19116cc14bf)
2. [レッツラズパイ！〜Lチカ＆Lピカをマスターしよう編〜](https://qiita.com/westvirginia/items/e339dbaf3286ea966483)
3. [レッツラズパイ！〜Webカメラで監視しちゃうゾ編〜](https://qiita.com/westvirginia/items/ba79f7549b43da116467)
4. [レッツラズパイ！〜温度センサーとmailgunで検知メールを送ろう編〜](https://qiita.com/westvirginia/items/c06887fd464e3718082d)
5. [レッツラズパイ！〜Google HomeでLピカさせよう編〜](https://qiita.com/westvirginia/items/47437d547485cd2784ef)
6. レッツラズパイ！〜Google Homeに室温を教えてもらおう編〜(これ)
7. [レッツラズパイ！〜Lチカボタン編〜](https://qiita.com/westvirginia/private/7b33d27ce50d30895e13)

RaspberryPiを始めて触る＆IT初心者向けのドキュメントです。私の所属する会社で使う、IT初心者の方のインターンシップ向けのドキュメントとして書きはじめたので、かなり丁寧に書いていますがご了承下さい。

## 参考記事
 - [IFTTTとBeebotteを使ってGoogleHomeからRaspberryPiを操作する](https://qiita.com/msquare33/items/9f0312585bb4707c686b)
 - [Google AssistantとRaspberry Piで自宅の家電を操作する](https://qiita.com/104ki/items/9dcfe03246099d03d4dd)
 - [google-home-notifierが「Error: get key failed from google」を吐いたので対策してみた](https://qiita.com/ezmscrap/items/24b3a9a8548da0ab9ff5)

この3つの記事を参考にさせていただきました！
ありがとうございます！

## Google Homeに室温を教えてもらう

### 用意するもの
- Raspberry Pi 3 Model B
- Google Home （今回はminiを使用）
- [レッツラズパイ！〜温度センサーとmailgunで検知メールを送ろう編〜](https://qiita.com/westvirginia/items/c06887fd464e3718082d)で使用したモノ（LEDを除く）

### 簡単な構成図
 - IFTTT,Beebotte,google-home-notifierを使用。
 - Google Homeが使用する人の発言を拾い、IFTTTをトリガーさせる。
 - IFTTTのwebhook（外部のウェブサーバに対してウェブリクエストを送信する機能）を利用してBeebotteに情報をPOSTする。
 - BeebotteからMQTTを利用してその情報をRaspberry Piへ通知する。
 - Raspberry Piが情報を取得するのを契機に、google-home-notifierを使用してGoogle Homeから室温を通知する。

![レッツラズパイ_GoogleHome&温度センサー.002.jpeg](https://qiita-image-store.s3.amazonaws.com/0/164786/9afec6c5-08bb-f312-0642-72f07d68b6c7.jpeg)



### Raspberry Piのセットアップ
#### 既存Node.jsのアンインストール
- Node.jsのバージョンを上げるために既存のNode.jsをアンインストールします。

1.下記コマンドを実行してください。
「続行しますか? [Y/n]」と表示されたら「Y」を入力してください。
※デフォルトでインストールされているNode-REDも消えてしまいます。

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

#### nvmのインストール
- nvmとはnode.jsのバージョン管理ツールです。今回はnvmを使用してnode.jsをセットアップします。

1. 格納ディレクトリ作成、権限変更を実施します。

```
$ sudo mkdir ~/.nvm
$ sudo chmod 777 ~/.nvm
```
　　
2. 作成したディレクトリを確認します。

```
$ ls -la ~/.
```

実行結果が「drwxrwxrwx  8 pi   pi    4096  6月 14 10:39 .nvm」のように表示されていればOKです。
　　
3. OSの時刻を確認します。
※時刻がずれていた場合はインストールが出来ないため、時刻設定のコマンドを実行します。

```
時刻確認コマンド
$ date

※時刻がずれていた場合(例)
$ sudo date -s "06/18 13:00 2018"
```
　　
4. nvmリポジトリをgitからクローン作成します。(インストール)

```
$ git clone https://github.com/creationix/nvm.git ~/.nvm
```
　　
5. nvmコマンドの実行環境を設定します。

```
$ source ~/.nvm/nvm.sh
```
　　
6. バージョン確認をしてnvmコマンドの実行確認をします。
バージョン情報が表示されればインストール完了です。

```
$ nvm --version
```
  
#### Node.jsのインストール、設定
1. Node.jsのインストールするバージョンを確認します。
※Node.jsをインストールすることにより、google-home-notifierを実行することができるようになります。

```
$ nvm ls-remote
※2018/6/18時点でLTSはv8.11.3
```
　　
2. 手順1.で確認したバージョンをインストールします。
本記事では2018/6/18時点でのLTS最新のv8.11.3をインストールする手順となっています。

```
$ nvm install v8.11.3
```
　　
3. インストール完了後、下記コマンドでインストールしたバージョンを確認します。

```
$ node -v
$ npm -v
```

※Node.jsはインストール時に指定したバージョンが入っていればOKです。npmはバージョン情報が表示されればOKです。
　　
4. ログイン時のnvm,npm起動設定をします。

```
$ sudo vim /etc/profile.d/nvm.sh
```

```shell:nvm.sh
source ~/.nvm/nvm.sh
```
　　
5. デフォルトで使用するNode.jsのバージョンを指定します。

```
$ nvm alias default v8.11.3
```  

#### google-home-notifierのインストール
- google-home-notifierとはコマンドベースでGoogle Homeを喋らすことができるプログラムです。

1. 作業ディレクトリを作成し、移動します。

```
$ mkdir ~/googlehome
$ cd ~/googlehome
```
　　
2. 現在のディレクトリを確認します。作成したディレクトリが表示されていればOKです。

```
$ pwd
```
　　
3. ライブラリのインストールを実施します。

```
$ sudo apt-get install git-core libnss-mdns libavahi-compat-libdnssd-dev
```
　　
4. Githubからgoogle-home-notifierのリポジトリのクローンを作成します。

```
$ git clone https://github.com/noelportugal/google-home-notifier
```
　　
5. クーロンの作成が完了したら、google-home-notifierディレクトリ配下のpackage.jsonを編集する。
※編集該当箇所のみ抜粋して記載しています。

```
$ cd ~/googlehome/google-home-notifier
$ vim package.json
```

<<変更前>>

```json:package.json
  ],
  "license": "MIT",
  "dependencies": {
    "body-parser": "^1.15.2",
    "castv2-client": "^1.1.2",
```

<<変更後>>　「"repository"〜」以下の3行を追記

```json:package.json
 ],
  "license": "MIT",
  "repository": {
    "type": "git"
  },
  "dependencies": {
    "body-parser": "^1.15.2",
    "castv2-client": "^1.1.2",
```
　　
6. google-home-notifierをインストールします。

```
$ npm install
```

### google-home-notifierの動作確認
#### test.jsを作成して動作確認
1. test.jsを作成します。【google homeのデバイス名】と【google homeのIPアドレス】はスマートフォンのアプリを開き、[デバイス]-[設定]から確認できます。

```
vim /home/pi/googlehome/google-home-notifier/test.js
```

```js:test.js
const googlehome = require('./google-home-notifier')
const language = 'ja';

googlehome.device('【google homeのデバイス名】', language);
googlehome.ip("【google homeのIPアドレス】"); //ここにgoogle homeのip追記．

googlehome.notify('こんにちは。私はグーグルホームです。', function(res) {
  console.log(res);
});
```
　　
2. Google Homeを日本語で発音できるように設定するため、google-home-notifier.jsを編集します。

```
vim /home/pi/googlehome/google-home-notifier/google-home-notifier.js
```

```js:google-home-notifier.js
var Client = require('castv2-client').Client;
var DefaultMediaReceiver = require('castv2-client').DefaultMediaReceiver;
var mdns = require('mdns');
var browser = mdns.createBrowser(mdns.tcp('googlecast'));
var deviceAddress;
var language;

var device = function(name, lang = 'ja') {   // ここを「ja」に書き換える
    device = name;
    language = lang;
    return this;
};

var ip = function(ip, lang = 'ja') {    // ここを「ja」に書き換える
  deviceAddress = ip;
  language = lang;
  return this;
}

deviceAddress = '【Google HomeのIPアドレス】';    // Google HomeのIPアドレスを書き加える

var googletts = require('google-tts-api');
var googlettsaccent = 'ja';    // ここを「ja」に書き換える
var accent = function(accent) {
  googlettsaccent = accent;
  return this;
}

// ############ 以下省略 #############

```
　　
3. key.jsを編集します。

```
vim /home/pi/googlehome/google-home-notifier/node_modules/google-tts-api/lib/key.js
```

<<変更前>>

```js:key.js
eval(html.match(/TKK=eval\(\'\(.*\)\'\);/g)[0]);
```

<<変更後>>

```js:key.js
eval(html.match(/TKK='[0-9]+.[0-9]+'/g)[0]);
```
　　
4. 作成した、test.jsを実行します。

```
node /home/pi/googlehome/google-home-notifier/test.js
```
  
***” Google homeが話し始めましたか？？ ”***
  
### Beebotteの設定

作成手順は[レッツラズパイ！〜Google HomeでLピカさせよう編〜 Beebotteのセットアップ](https://qiita.com/westvirginia/items/47437d547485cd2784ef#beebotte%E3%82%BB%E3%83%83%E3%83%88%E3%82%A2%E3%83%83%E3%83%97)を参考にしてください。

### IFTTTの設定
作成手順は[レッツラズパイ！〜Google HomeでLピカさせよう編〜 IFTTTのセットアップ](https://qiita.com/westvirginia/items/47437d547485cd2784ef#ifttt%E3%82%BB%E3%83%83%E3%83%88%E3%82%A2%E3%83%83%E3%83%97)を参考に、下記の設定値でAppletを作成してください。
Applet作成後は、次項の動作確認まで実施してください。

「this:Google Assistant」(トリガー)の設定値


|設定項目|設定値|
|:---|:---|
|What do you want to say?|会議室の $ を教えて|
|What do you want the Assistant to say in response?|少々おまちください|
|Language|Japanese|

「that:Webhook」(アクション)の設定値

|設定項目|設定値|
|:---|:---|
|URL|https://api.beebotte.com/v1/data/publish/[bebotteのChannel名]/voice?token=[Beebotteのトークン]|
|Method|POST|
|Content Type|application/json|
|Body|{"data":[{"room":"office","device":"{{TextField}}","action":"on"}]}|

### IFTTT+Beebotteの動作確認

Beebotteの「Console」画面を開き、Google Homeに「会議室の室温を教えて！」と聞いてみてください！
画面上に、"室温"を含む白文字列が表示されればIFTTT+Beebotteの動作確認は完了です。


### 温度センサーの設定
* Raspberry Piに温度センサーを接続して室温を計測し、計測結果をcsvファイルに出力する仕組みを作成します。
1. 温度センサーの設定については下記の記事を参考に、crontabの設定作業までを実施します。
※temperature.phpに関しては今回のコンテンツ向けに修正しているため、下記の内容で作成してください。
[レッツラズパイ！〜温度センサーとmailgunで検知メールを送ろう編〜](https://qiita.com/westvirginia/items/c06887fd464e3718082d#%E6%B8%A9%E5%BA%A6%E3%82%BB%E3%83%B3%E3%82%B5%E3%83%BC%E3%81%A7%E5%AE%A4%E6%B8%A9%E3%82%92%E3%83%A2%E3%83%8B%E3%82%BF%E3%83%AA%E3%83%B3%E3%82%B0%E3%81%99%E3%82%8B)

```php:temperature.php
<?php
//deviceIdは、先ほど確認したデバイスIDの値を入力
$deviceId = '【デバイスID】';
$today = date("Ymd");
$time = date("H:i");
$sensor_path = '/sys/bus/w1/devices/'.$deviceId.'/w1_slave';
$csv_dir = '/var/www/temperature/';
$csv_file = $today.'.csv';
$t = null;
//温度取得
exec("cat ".$sensor_path, $w1_slave);
if(isset($w1_slave[1])){
$tmp = explode('t=', $w1_slave[1]);

if(isset($tmp[1])) $t = $tmp[1] / 1000;
if(isset($t)) $t2 = explode('.', $t);
}
//CSV書き込み
if(!file_exists($csv_dir)){
mkdir($csv_dir);
}
if( $handle = fopen( $csv_dir.$csv_file , 'w' ) ){
fputcsv( $handle, Array("現在、".$t2[0]."度です") );
fclose($handle);
}
return;
```

2. 室温の計測結果がcsvファイルに出力されていることを確認します。1分間隔で計測しているため、コマンド実行後にファイルが更新されることを確認してください。

```
tail -F /var/www/temperature/YYYYMMDD.csv
※YYYYMMDD.csvは作業日と同じ日付のファイルを指定してください。
```

### Google Homeに発話させる設定
- Beebotteからの通知を受け取り、それを契機に温度センサーで計測した結果をGoogle Homeから音声として出力する仕組みを作成します。

#### smarthome.pyの作成
- Beebotteからの通知を待ち受けるsmarthome.pyを作成します。
1. smarthome.pyを作成します。

```
vim /home/pi/googlehome/google-home-notifier/smarthome.py
```

```python:smarthome.py
import paho.mqtt.client as mqtt
import json
import subprocess

TOKEN = "【Beebotteで取得したトークン】"
HOSTNAME = "mqtt.beebotte.com"
PORT = 8883
TOPIC = "【Beebotteのチャンネル名】/voice"
CACERT = "mqtt.beebotte.com.pem"

# 名詞の変換表
noun_conv = {
            "気温": "temperature",
            "室温": "temperature",
            "温度": "temperature",
            }

# 接続中の処理を記載→subscribeする
def on_connect(client, userdata, flags, respons_code):
        print('status {0}'.format(respons_code))
        client.subscribe(TOPIC)


def on_message(client, userdata, msg):
    print(msg.topic + " " + str(msg.payload))
    data = json.loads(msg.payload.decode("utf-8"))["data"][0]
    # Google Assistantの側でTextFiledの前後に半角スペースが入ることがあるのでstripして削除
    data = {key:value.strip(' ') for key, value in data.items()}
    # 「〜は」と言ってしまった際に「は」が入ってTextFieldに入ってくることがあるので削除
    if data["device"].endswith("は"):
        data["device"] = data["device"][:-1]
    print(data)

    # 日本語の表記ゆれに併せて、IFTTTのTextFieldをtemperatureに修正
    if not data["device"] in set(noun_conv.values()):
        try:
            data["device"] = noun_conv[data["device"]]
        except:
            print("unkown device")
            return
        print(data)
    subprocess.call(['node', '/home/pi/googlehome/google-home-notifier/googlehome.js'])


client = mqtt.Client()
client.username_pw_set("token:%s"%TOKEN)
client.on_connect = on_connect
client.on_message = on_message
client.tls_set(CACERT)
client.connect(HOSTNAME, port=PORT, keepalive=60)
client.loop_forever()
```


#### googlehome.jsの作成
- Google Homeが発話するためのgooglrhome.jsを作成します。
1. googlehome.jsを作成する。

```
vim /home/pi/googlehome/google-home-notifier/googlehome.js
```

```js:googlehome.js
const googlehome = require('./google-home-notifier')
const language = 'ja';

const execSync = require('child_process').execSync;
const result =  execSync('cat /var/www/temperature/`date "+%Y%m%d"`.csv').toString();


googlehome.device('【Google Homeのデバイス名】', language);
googlehome.ip("【Google HomeのIPアドレス】"); //ここにgoogle homeのip追記．

googlehome.notify(result, function(res) {
  console.log(res);
});
```

### Google Homeに室温を聞いてみよう！
1. MQTTのライブラリをRaspberry Piにインストールします。

```
$ sudo pip3 install paho-mqtt
```
　
2. Raspberry PiとBeebotteが接続するためにサーバ証明書をダウンロードします。

```
$ wget https://beebotte.com/certs/mqtt.beebotte.com.pem -P /home/pi/googlehome/google-home-notifier
```
　
3. smarthome.pyを実行します。

```
python3 /home/pi/googlehome/google-home-notifier/smarthome.py
```
　　
4. ターミナルの画面で「status 0」が表示されたら、Google Homeに話しかけてみてください。
  
  
  
***室温を教えてくれましたか？***

Google Homeから現在の室温の返答が返ってきたら完了となります！


Google Homeに室温を教えてもらおう編は以上です。お疲れ様でした♪