ドアポストに投函されたら、google homeでお知らせする。

※記事が間に合いませんでした。端折りましたことをご了承ください。

#概要
超めんどくさがりなので、家のドアポストにCDSセンサーを取り付け、変化があれば、MQTTであるmosquittoサーバを中継させて、google homeにアクションさせたいと思います。
ローカル環境で実行する分には、MQTTは大げさな気がしますが、いづれ外部ネットワーク経由で通知させたくなるのと、push/subscribe実行がしやすいので、IFTTTを使わない構成としました。

#用意するもの
ESP8266とCDSセンサー: 動きを検知して通知します。
raspberry pi：簡易サーバとmosquittoサーバとgoogle homeに通知します。
google-home-notifier：google homeに喋らせるソフト
mosquitto：メッセージングサーバ
google home：google homeちゃん


<img src="https://qiita-image-store.s3.amazonaws.com/0/104300/43c8f56c-7a63-ec4e-e198-8169e961b0d7.jpeg" width=90%>

流れは、Wifi付きのESP8266でセンサーを読み取り、raspberrypiの簡易サーバで受けとり、MQTTに通知します。それをbashでMQTTでsubscribeしておき、通知がきたらgoogle-home-notifierでgoogle homeで喋らせます。

google-home-notifierをラズパイにインストールしておきます。
https://qiita.com/SatoTakumi/items/c9de7ff27e5b70508066

MQTTサーバインストールをラズパイにインストールしておきます。
https://qiita.com/s_edward/items/c044f3d3e4d4a05d2dee

ESPのセンサー部分はメインではないので、記事の最後にソースを載せておきます。

#簡易サーバです。

```ruby
require 'sinatra'
require 'mqtt'

get '/iot' do
  client = MQTT::Client.connect(host: "localhost",port: "1883", username: "user",password: "token")
  client.publish("iot",params["token"])
end
```
ここで、ESPから受け取ったデータをMQTTサーバに流します。頑張れば、ESPから直接MQTTプロトコルが使えたかもしれないです。

#受け取りプログラムです。

```
#!/bin/bash

while read msg; do
if [ $(echo $msg | grep "XXXXXXXXXXXXXXXバス") ] ; then
  node main.js "次のバスは$(./bus.sh) です。";
fi
if [ $(echo $msg | grep "XXXXXXXXXXXXXXX") ] ; then
  node main.js "何か荷物が届いていますよ。";
fi
done < <(mosquitto_sub -t iot -h localhost -u user -P password -q 1)
```
mosquitto_subでsubscribeしています。


#センサーとESP8266と電池ボックスです。
<img src="https://qiita-image-store.s3.amazonaws.com/0/104300/5a9d9fb9-21ad-ef81-8233-ff7c7266be76.jpeg" width=50%>
cdsと10k抵抗を繋げてESP8266に繋げて、バッテリーと共に、箱に詰めた様子。

#結果とこれから

あまり暗すぎることがなければ、そこそこ動いてくれました。誤動作はほぼありませんでした。
現在は４日ほどで電池が切れます。DeepSleepを繋げるともっといけそうな。
外部経由を考えると、IFTTTになると思いますが、そうなるとgoogle homeに通知する手段が無いんですね。家のネットワークを解放したくないので、外部経由させるときは、MQTTサーバを外部においてアクセスされば、家のネットワークを解放せずにすみそうです。Wifi外のポストとか。
あと、センサー側にも工夫がしてあるので(ソースが乱れてますが)、説明したいですが、別記事になるかもしれません。

#ESP8266のスケッチを載せます。

```sketch
#include <ESP8266WiFi.h>
#include <WiFiClient.h> 
#include <ESP8266WebServer.h>
#include <ESP8266HTTPClient.h>
 
/* Set these to your desired credentials. */
const char *ssid = "XXXXXX";  //ENTER YOUR WIFI SETTINGS
const char *password = "XXXXXXX";
 
//Web/Server address to read/write from 
const char *host = "";   

const int btn = 12;
const int btn2 = 14;
double avgdR = 0.0;
int initCount = 20;

///=======================================================================
//                    Power on setup
//=======================================================================
 
void setup() {
  delay(1000);
  Serial.begin(115200);
  WiFi.mode(WIFI_OFF);        //Prevents reconnection issue (taking too long to connect)
  delay(1000);
  WiFi.mode(WIFI_STA);        //This line hides the viewing of ESP as wifi hotspot
  
  WiFi.begin(ssid, password);     //Connect to your WiFi router
  Serial.println("");
 
  Serial.print("Connecting");
  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
 
  //If connection successful show IP address in serial monitor
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());  //IP address assigned to your ESP
}

void sendLetter()
{
   //start 
  HTTPClient http;    //Declare object of class HTTPClient 
  //GET Data
  String Link,getData;
  getData = "?token=XXXXXXXXXX";  //Note "?" added at front
  Link = "http://localhost:7070" + getData;
  
  http.begin(Link);     //Specify request destination
    Serial.println("button pushed");
    int httpCode = http.GET();            //Send the request
    String payload = http.getString();    //Get the response payload 
    Serial.println(httpCode);   //Print HTTP return code
    Serial.println(payload);    //Print request response payload
 
  http.end();  //Close connection
 //end
}
 
//=======================================================================
//                    Main Program Loop
//=======================================================================
void loop() {

 int iValue = analogRead( A0 );
  double dV = iValue * 3.3 / 1023;
  double dis = 0.0;
  double dR = 0.0;
  
  if( 0.005 < (3.3 - dV) )
  {
    dR = 10 * 1000 * dV / (3.3 - dV);
  }
  if( 0.0 == dR )
  {
    Serial.println("Infinity");
  }
  else
  {
    if(initCount > 0)
    {
    dis = dR - avgdR;
    avgdR = ( ( dR + avgdR + avgdR) / 3 ) ; 
    initCount = initCount - 1;
    return ; 
    }
    dis = dR - avgdR;
    avgdR = ( ( dR + avgdR + avgdR) / 3 ) ; //新規の輝度を取り込んで適応させる。
    Serial.print("dR:");
    Serial.println(dR);
    Serial.print("avgdR:");
    Serial.println(avgdR);
    Serial.print("dis:");
    Serial.println(dis);
  }
  if(dis > 2000 || dis < -2000){ //平均から外れると何か横切ったと判定する。
    Serial.println("ON!!!!!!");
    sendLetter();
  }else{
    Serial.println("off");
  }

  delay(1000);
```