インターホンが鳴ったら別部屋のGoogleHomeに来客を知らせてもらう

# 背景
我が家は２階建で２階にリビングがあるのだが、インターホンの親機？がそこにしかなく、１階にいると全く音が聞こえない
家にいるにも関わらず宅急便の再配達をお願いすること数知れずで、とても申し訳ない思いをしていたため、インターホンがなったら１階にいても気づく仕組みを検討した

# 全体構想
1. 来客者によってインターホンが押される
2. リビングのインターホン親機が「ピンポン」と鳴る
3. インターホン親機付近に音センサーを仕込んで「ピンポン」を検知
4. 音センサーに繋いでいるRaspberryPiが1階のGoogleHomeに通知
5. GoogleHomeが「インターホンがなりました」と発声

# 構成
* [Maruduino（ArduinoUno互換ボード）](https://www.marutsu.co.jp/pc/i/605620/)
* [高感度マイクアンプキット](http://akizukidenshi.com/catalog/g/gK-05757/)
* ジャンパワイヤ（オス-メス × ３本）
* RaspberryPi（無線LANにつながる状態）
* GoogleHome mini（設定が終わってる状態）

# 作り方
今回、音センサーは秋月電子の[高感度マイクアンプキット](http://akizukidenshi.com/catalog/g/gK-05757/)を使用した
注意点として、このキットは基盤へのハンダ付けを自分でやる必要があるため、面倒な場合は別の音センサーを使った方がいい（[これとか](https://www.amazon.co.jp/HiLetgo%C2%AE-5%E5%80%8B%E3%82%BB%E3%83%83%E3%83%88-%E3%82%B5%E3%82%A6%E3%83%B3%E3%83%89%E3%82%BB%E3%83%B3%E3%82%B5%E3%83%BC%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB%E5%A3%B0%E6%A4%9C%E5%87%BA%E5%A3%B0%E3%82%B3%E3%83%B3%E3%83%88%E3%83%AD%E3%83%BC%E3%83%AB%E3%82%B9%E3%82%A4%E3%83%83%E3%83%81-%E4%B8%A6%E8%A1%8C%E8%BC%B8%E5%85%A5%E5%93%81/dp/B0116IZ3AQ/ref=sr_1_7?ie=UTF8&qid=1538800410&sr=8-7&keywords=%E9%9F%B3+%E3%82%BB%E3%83%B3%E3%82%B5%E3%83%BC)）
以下のページを参考（ほぼそのまま）にした
[[Arduino と 音センサー 使ってみた]](http://dd647.blogspot.com/2016/01/580-arduino-170.html)

## 1.音センサーをMaruduinoに接続
ジャンパワイヤを使って、音センサーとMaruduinoを接続する
接続先は以下の表と上記参考ページの図を参照

|音センサー|Maruduino|
|:---:|:---:|
|VCC|5V|
|GND|GND|
|OUT|A0|

## 2.Maruduinoにスケッチを入れる
ArduinoIDEを使って以下スケッチを作成し、Maruduinoに入れる

```C
void setup() {
  Serial.begin(9600); 
}

void loop() {
  if(analogRead(0) == 0){
    Serial.println(0);
    delay(20000);
  }
  delay(200);
}
```

## 3.ArduinoIDEのシリアルモニタで動作確認
私の環境では、なぜだかわからないけど、一定以上の音を拾うと"0"が帰ってくるため、このコードで動作させた場合、大きな音がした時だけモニタに"0"が表示される
センサーの種類や設定によっては調整する必要があると思うので、その辺りは適宜対応
この確認の際、実際にインターホン親機にマイクをセットし、ピンポンが鳴った時に"0"が表示されることを確認することが重要！！

## 4.RaspberryPiの設定
RaspberryPiの役割は、Maruduinoからのシリアル出力を監視し、"0"がきたらGoogleHomeに通知すること

### GoogleHomeへの通知
GoogleHomeへの通知には「google-home-notifier」というnpmのパッケージを使う
こういった便利ツールを作って公開してくれる偉大な先人たちへの感謝を胸に、以下参考ページの手順通りに環境設定を進める
[[Raspberry PiからGoogle Homeを喋らせる]](https://qiita.com/ktetsuo/items/8c9cd5714e231aa6ae09)

ただし、最近Google側で仕様変更が入ったようで、上記手順のみでは動作しない模様
google-home-notifier側が対応すれば問題ないように思うが、エラーがでる場合には以下参考ページの内容を実行すると問題なく動作する
[[google-home-notifierがエラーになっちゃった！]](https://aeka-books.com/get-key-failed-from-google/)

ソースについては、複数のアプリからおしゃべりしてもらう言葉を変えつつ使いたかったので、少しいじって以下のようにした

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

var sayText = 'いえーー';

if(process.argv.length == 3){
  sayText = process.argv[2];
}

googlehome.device('Google-Home', '192.168.1.xxx', language); 

googlehome.notify(sayText, function(res) {
  console.log(res);
});
```
ソースのIPアドレス箇所（'192.168.1.xxx'）には、自分のGoogleHomeのIPアドレスを入れる
IPの調べ方は以下ページ参照
[[Google HomeのIPアドレスを確認する方法]](https://qiita.com/shun91/items/aba1a554d829126945f6)

上記ソースファイルを適当なフォルダに設置し、以下コマンドを実行するとおしゃべりしてくれるはず

```shell
node say.js こんにちわ
```

### Maruduinoとの通信
上で設定したMaruduinoは、音センサーが反応したらシリアル通信で文字列"0"が送られてくる
なので、RaspberryPiとMaruduinoを繋いでシリアルを監視する
これにはPythonでPySerialを使う
[[Pythonでシリアル通信]](https://qiita.com/kosystem/items/0023cfee941fdf099087)

Maruduinoから通知がきたら上で作ったGoogleHomeにおしゃべりさせるやつを呼び出すようにする
ソースは以下のようになった

```py:sensor.py
#! /usr/bin/python
# coding: utf-8

import serial
import time
import commands

s = serial.Serial('/dev/ttyACM0', 9600)
time.sleep(2)

while True:
    outVal = s.readline().rstrip()
    if outVal == '0':
        commands.getoutput('/usr/local/bin/node /home/pi/googlehome/say.js インターホンが鳴りました。確認してください。')
        time.sleep(20)
        s.close()
        time.sleep(1)
        s.open()
        time.sleep(2)
```
ピンポン音が鳴っている間に何回も反応してしまうので適当にスリープをいれた
一度シリアルを切っているのは、何か理由があったはずだが忘れてしまった

あとは、RaspberryPiを移動するたびにSSHしてPythonを実行したくないので、自動起動するようcrontabに設定する
実行権限をつけていないと以下はエラーになるのでchmodするのを忘れずに

```shall
@reboot /home/pi/sensor/sensor.py > /home/pi/sensor/cronlog.log 2>&1
```

# 所感
実際に運用してみたが、リビングに住んでいる犬たち（パピヨンメス９歳、パピヨンメス７歳）が構って欲しさでワンワンすると、センサーが反応してしまうことがわかった
リビングで大きな音が出ない家なら今回の仕組みはとても有用だが、我が家では機能しない
音センサー以外の何かを検討しようと思います