Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

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

概要

超めんどくさがりなので、家のドアポストに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);
benridane
おそらく書いているのはみやまるです。 twitter: @super_miyamaru
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away