※記事が間に合いませんでした。端折りましたことをご了承ください。
#概要
超めんどくさがりなので、家のドアポストに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ちゃん
流れは、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のセンサー部分はメインではないので、記事の最後にソースを載せておきます。
#簡易サーバです。
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と電池ボックスです。
cdsと10k抵抗を繋げてESP8266に繋げて、バッテリーと共に、箱に詰めた様子。
#結果とこれから
あまり暗すぎることがなければ、そこそこ動いてくれました。誤動作はほぼありませんでした。
現在は4日ほどで電池が切れます。DeepSleepを繋げるともっといけそうな。
外部経由を考えると、IFTTTになると思いますが、そうなるとgoogle homeに通知する手段が無いんですね。家のネットワークを解放したくないので、外部経由させるときは、MQTTサーバを外部においてアクセスされば、家のネットワークを解放せずにすみそうです。Wifi外のポストとか。
あと、センサー側にも工夫がしてあるので(ソースが乱れてますが)、説明したいですが、別記事になるかもしれません。
#ESP8266のスケッチを載せます。
#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);