NODE_MQTT_PIR_TEMP.ino
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <BlynkSimpleEsp8266.h>
#define BLYNK_PRINT Serial // Comment this out to disable prints and save space
#include "Settings.h"
#include "mqtt_publish.h"
#include "timer.h"
#include "mqtt_subscribe.h"
#include "wifi_credentials.h"
/*-------------------------------- Setup -------------------------------------*/
void setup() {
WiFi.mode(WIFI_STA);
Serial.begin(115200); // See the connection status in Serial Monitor
Serial.println(F("\n Setup STARTING"));
WiFi.begin(WIFI_SSID, WIFI_PASS);
if(WiFi.status() == 6) Serial.println("\tWiFi not connected yet.");
//----------------------------------Blynk------------------------------------
#ifdef LOCAL_SERVER
Blynk.config(AUTH, LOCAL_SERVER ,8080);
#else
Blynk.config(AUTH, Geo_DNS_SERVER);
#endif
while (Blynk.connect() == false) { // Wait until connected
if ((millis() - last_UP_change) > 30000) { // 30s before reset
Serial.println(F("resetting"));
ESP.restart();
}
}
client.setServer(MQTT_SERVER, 1883);
client.setCallback(callback);
//-----------------------------------OTA--------------------------------------
ArduinoOTA.setHostname(OTA_HOSTNAME);
// ArduinoOTA.setPassword(OTA_PASSWORD); //If you need a Password uncomment this line
ArduinoOTA.begin();
Serial.println(F(" Entering loop"));
timer.setInterval(4000L, Heartbeat); // Heartbeat 4000L
CountdownTimer = timer.setInterval(1000, CountdownTimerFunction);
timer.disable(CountdownTimer); // disable it on boot
Blynk.syncVirtual(vPIN_ON_OFF_1);
Blynk.syncVirtual(vPIN_ON_OFF_2);
Blynk.syncVirtual(vPIN_AUTO_MOTION);
Blynk.syncVirtual(vPIN_NUMERIC_TIMER);
Blynk.virtualWrite(vPIN_COUNTDOWN, " 0:00:00" );
Blynk.setProperty(vPIN_ON_OFF_1, "label", String("T1 = ") + "0:00:00" + String(" S") );
Blynk.setProperty(vPIN_PIR_LED, "label", String ("PIR <---- ") + memory1 + String(" S") );
Blynk.setProperty(vPIN_HEARTBEAT, "label", String("\xF0\x9F\x92\x93") + " HEARTBEAT");
}
/*----------------------------------Loop--------------------------------------*/
void loop() {
Blynk.run();
if(!Blynk.connected()) {
Serial.println(F("Resetting in loop"));
ESP.restart();
}
timer.run();
if (!client.connected()) {
reconnect();
}
client.loop();
ArduinoOTA.handle();
}
/*=============================================================================*/
Settings.h
/*****************************************************************************
*
* Settings.h
*
*****************************************************************************/
/*---------------------------Blynk Auth Code----------------------------------*/
#define AUTH "*******************************************" // NodeMCU
/*-------------------------Over The Air Hostname------------------------------*/
#define OTA_HOSTNAME "N-MQTT_Bridge" // put here your host name
#define OTA_PASSWORD "blynk" // your password for OTA if needed
/*----------------------------Hardware Pins-----------------------------------*/
/*-NodeMCU#*/
/*-------------------------------Virtual Pins---------------------------------*/
#define vPIN_HEARTBEAT V0
#define vPIN_DS18B20_1_TEMP V1
#define vPIN_DS18B20_2_TEMP V2
#define vPIN_DS18B20_3_TEMP V3
#define vPIN_DS18B20_4_TEMP V4
#define vPIN_AM2301_TEMP V5
#define vPIN_AM2301_HUM V6
#define vPIN_SR04_DIST V7
#define vPIN_PIR_LED V8
#define vPIN_TEMP_UNIT V9
#define vPIN_HUM V10
#define vPIN_ALL_TEMP V11
#define vPIN_ON_OFF_1 V21 // ON/OFF POWER 1 Activated by Motion (Tasmota Rule1 & Rule2)
#define vPIN_AUTO_MOTION V22 // when motion is detected Relay1 turns on for timer sec & repeats
#define vPIN_NUMERIC_TIMER V23 // up to 32767 ~9hrs
#define vPIN_COUNTDOWN V24 // triggered by motion countdown for timer sec and restart with each PIR trigger
#define vPIN_AUTO_SR04 V25 // Activate/Desactivate Rule3
#define vPIN_ON_OFF_2 V31 // ON/OFF POWER 2 Activated by Sun
/*-----------------------------variables-------------------------------------*/
bool memory2 ;
int memory1 ;
int counter = 0;
int CountdownTimer;
int CountdownRemain;
long int last_UP_change = millis();
int rssi;
float Vcc;
float Distance;
mqtt_publish.h
/******************************************************************************
*
* mqtt_publish.h
*
*****************************************************************************/
WiFiClient espClient;
PubSubClient client(espClient);
BlynkTimer timer;
//----------------------------------------------℃/℉-----------------------------------------------------------
BLYNK_WRITE(vPIN_TEMP_UNIT) { // Change Temp. Unit from Celsius ℃ to Fahrenheit
if (param.asInt()) {
client.publish("stairs/cmnd/setoption8","1"); // Fahrenheit ℉
Blynk.setProperty(vPIN_TEMP_UNIT, "label",String("\xf0\x9f\x8c\xa1") + "Fahrenheit ℉");
} else {
client.publish("stairs/cmnd/setoption8","0"); // Celcius ℃
Blynk.setProperty(vPIN_TEMP_UNIT, "label",String("\xf0\x9f\x8c\xa1") + " Celsius ℃");
}
}
//---------------------------------------------POWER1----(Motion)-------------------------------------------
BLYNK_WRITE(vPIN_ON_OFF_1) { // ON/OFF switch
if (param.asInt()) {
client.publish("stairs/cmnd/POWER1","1");
} else {
client.publish("stairs/cmnd/POWER1","0");
}
}
BLYNK_WRITE(vPIN_AUTO_MOTION) { // AUTO/Manual
if (param.asInt()) {
client.publish("stairs/cmnd/mem2","1");
Blynk.setProperty(vPIN_AUTO_MOTION, "label",String("\xF0\x9F\x92\xAB") + " AUTO PIR");
memory2 = 1;
} else {
client.publish("stairs/cmnd/mem2","0");
Blynk.setProperty (vPIN_AUTO_MOTION, "label",String("\xE2\x9C\x8B") + " MANUAL PIR");
memory2 = 0;
CountdownRemain = 1;
}
}
BLYNK_WRITE(vPIN_NUMERIC_TIMER) { // TIMER 0-300 Sec up to 32767sec [9hr:06min:07sec]
int VALUE = param.asInt();
char value[4];
dtostrf(VALUE, 3, 0, value);
client.publish("stairs/cmnd/Mem1", value);
Blynk.setProperty(vPIN_PIR_LED, "label", String("PIR <---- ") + value + String(" S") );
if (memory2 == 1) {
client.publish("stairs/cmnd/POWER1", "ON");
} else {
CountdownRemain = 1;
}
}
//-----------------------------------------------SR04---------------------------------------------------
BLYNK_WRITE(vPIN_AUTO_SR04) { // AUTO/Manual
if (param.asInt()) {
client.publish("stairs/cmnd/Rule3","1");
Blynk.setProperty(vPIN_AUTO_SR04, "label",String("\xF0\x9F\x92\xAB") + " AUTO SR04");
} else {
client.publish("stairs/cmnd/Rule3","0");
Blynk.setProperty (vPIN_AUTO_SR04, "label",String("\xE2\x9C\x8B") + " MANUAL SR04");
}
}
//---------------------------------------------POWER2----(Sun)-------------------------------------------
BLYNK_WRITE(vPIN_ON_OFF_2) { // ON/OFF switch
if (param.asInt()) {
client.publish("stairs/cmnd/POWER2","1");
} else {
client.publish("stairs/cmnd/POWER2","0");
}
}
/*--------------------------------Heartbeat--------------------------------*/
void Heartbeat() {
Blynk.virtualWrite(vPIN_HEARTBEAT," \xF0\x9F\x92\x96"); //
timer.setTimeout(2000L,[](){Blynk.virtualWrite(vPIN_HEARTBEAT," \xF0\x9F\x92\x97");});
}
/*--------------------------------------------------------------------------*/
mqtt_subscribe.h
/*******************************************************************************
*
* mqtt_subscribe.h
*
******************************************************************************/
#define MQTT_SERVER IPAddress(192,168,xxx,xxx) // Your MQTT Broker IP address
#define MQTT_USERNAME "xxxx" // put here your MQTT username
#define MQTT_PASSWORD "xxxx" // put here your MQTT password
#define InTOPIC_0 "stairs/tele/STATE"
#define InTOPIC_1 "stairs/tele/SENSOR"
#define InTOPIC_2 "stairs/PIR_stairs/state"
#define InTOPIC_3 "stairs/stat/POWER1"
#define InTOPIC_4 "stairs/stat/POWER2"
#define InTOPIC_5 "stairs/Distance"
#define InTOPIC_6 "stairs/stat/RESULT"
void reconnect() { // Loop until we're reconnected
while (!client.connected()) {
Serial.print(" Attempting MQTT connection..."); // Attempt to connect
if (client.connect("DVES",MQTT_USERNAME,MQTT_PASSWORD)) {
Serial.println("connected");
counter = 0; // ... and resubscribe
client.subscribe(InTOPIC_0);
client.subscribe(InTOPIC_1);
client.subscribe(InTOPIC_2);
client.subscribe(InTOPIC_3);
client.subscribe(InTOPIC_4);
client.subscribe(InTOPIC_5);
client.subscribe(InTOPIC_6);
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 0.3 second");
++counter;
if (counter > 180) ESP.reset(); // Wait .3 seconds before retrying
delay(300);
}
}
}
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
Serial.println();
//-------------------------------------------STATE------------------------------------------------
// MQT: stairs/tele/STATE =
// {"Time":"2019-03-18T17:56:18","Uptime":"0T18:23:11","Vcc":3.002,"SleepMode":"Dynamic",
// "Sleep":50,"LoadAvg":19,"POWER1":"ON","POWER2":"OFF","Wifi":{"AP":1,"SSId":"BLYNK",
// "BSSId":"48:F8:B3:84:AB:22","Channel":10,"RSSI":84,"LinkCount":6,"Downtime":"0T00:00:21"}}
if (String(topic) == InTOPIC_0) { // stairs/tele/STATE
StaticJsonBuffer<450> jsonBuffer;
JsonObject& root = jsonBuffer.parseObject((char*)payload);
Vcc = root["Vcc"]; // 3.002
rssi = root["Wifi"]["RSSI"]; // 84
// const char* Time = root["Time"]; // 2019-03-18T17:56:18
// const char* Uptime = root["Uptime"]; // 0T18:23:11
// const char* SleepMode = root["SleepMode"];// Dynamic
// int Sleep = root["Sleep"]; // 50
// int LoadAvg = root["LoadAvg"]; // 19
// const char* POWER1 = root["POWER1"]; // ON
// const char* POWER2 = root["POWER2"]; // OFF
// int AP = root["Wifi"]["AP"]; // 1
// const char* SSId = root["Wifi"]["SSId"]; // BLYNK
// const char* BSSId = root["Wifi"]["BSSId"];// 48:F8:B3:84:AB:22
// int Chl = root["Wifi"]["Channel"];// 10
// int LC= root["Wifi"]["LinkCount"];// 6
// const char* DT = root["Wifi"]["Downtime"];// 0T00:00:21
//-------------------------------------------SENSOR-----------------------------------------------
//MQT: stairs/tele/SENSOR =
//{"Time":"2019-03-19T13:19:16","Switch1":"OFF","DS18B20-1":{"Id":"000006F242B1","Temperature":21.9},
//"DS18B20-2":{"Id":"000006F2B80A","Temperature":22.0},"DS18B20-3":{"Id":"00000789E508","Temperature":21.9},
//"DS18B20-4":{"Id":"8000001F18D8","Temperature":22.6},"AM2301":{"Temperature":22.0,"Humidity":68.7},
//"ADS1115":[{"A0":-1,"A1":26033,"A2":4851,"A3":4809}],"SR04":{"Distance":40.509},"TempUnit":"C"}
}else if (String(topic) == InTOPIC_1) { // stairs/tele/SENSOR
StaticJsonBuffer<450> jsonBuffer;
JsonObject& root = jsonBuffer.parseObject((char*)payload);
const char* Time = root["Time"]; // 2019-03-19T13:19:16
float DS1_T = root["DS18B20-1"]["Temperature"]; // 21.9
float DS2_T = root["DS18B20-2"]["Temperature"]; // 22.0
float DS3_T = root["DS18B20-3"]["Temperature"]; // 21.9
float DS4_T = root["DS18B20-4"]["Temperature"]; // 22.6
float Temp = root["AM2301"]["Temperature"]; // 22.0
float Hum = root["AM2301"]["Humidity"]; // 68.7
float Dist = root["SR04"]["Distance"]; // 40.509
// const char* Switch1 = root["Switch1"]; // OFF
// const char* DS1_ID = root["DS18B20-1"]["Id"]; // 000006F242B1
// const char* DS2_ID = root["DS18B20-2"]["Id"]; // 000006F2B80A
// const char* DS3_ID = root["DS18B20-3"]["Id"]; // 00000789E508
// const char* DS4_ID = root["DS18B20-4"]["Id"]; // 8000001F18D8
// float ADS_A0 = root["ADS1115"]["A0"]; // -1
// float ADS_A1 = root["ADS1115"]["A1"]; // 26033
// float ADS_A2 = root["ADS1115"]["A2"]; // 4851
// float ADS_A3 = root["ADS1115"]["A3"]; // 4809
// const char* TU = root["TempUnit"];// "C"
// Blynk.virtualWrite(vPIN_DS18B20_1_TEMP,DS1_T);
// Blynk.virtualWrite(vPIN_DS18B20_2_TEMP,DS2_T);
// Blynk.virtualWrite(vPIN_DS18B20_3_TEMP,DS3_T);
// Blynk.virtualWrite(vPIN_DS18B20_4_TEMP,DS4_T);
// Blynk.virtualWrite(vPIN_AM2301_TEMP,Temp);
// Blynk.virtualWrite(vPIN_AM2301_HUM,Hum);
// Blynk.virtualWrite(vPIN_SR04_DIST,Dist);
Blynk.virtualWrite(vPIN_ALL_TEMP, (String (DS1_T,1)+" "+String (DS2_T,1)+" "+String (DS3_T,1)+" "+String (DS4_T,1)+" "+String (Temp,1)));
Blynk.setProperty (vPIN_ALL_TEMP, "label",String("\xf0\x9f\x8c\xa1") + "DS18B20-1 DS18B20-2 DS18B20-3 DSPROBE-4 "+String("\xf0\x9f\x8c\xa1")+"AM2302");
Blynk.virtualWrite(vPIN_HUM,String (Hum,1)+"%"+" "+String("\xF0\x9F\x93\xB6")+String (rssi)+"%"+" "+String(Vcc)+"V");
Blynk.setProperty (vPIN_HUM, "label",String("\xF0\x9F\x92\xA7")+"AM2302 Hum "+ String (Time)+" Vcc");
//--------------------------------------------PIR------------------------------------------------
}else if (String(topic) == InTOPIC_2) { // stairs/PIR_stairs/state = (1/0)
StaticJsonBuffer<450> jsonBuffer;
JsonObject& root = jsonBuffer.parseObject((char*)payload);
if ((char)payload[0] == '1') { // Switch1 on LED if 1 was received as first character
Blynk.virtualWrite(vPIN_PIR_LED,255);
Serial.println("PIR = ON");
Blynk.setProperty (vPIN_AUTO_MOTION, "label",String("\xF0\x9F\x9A\x85")+ "MOTION >>> detected");
}else{
Blynk.virtualWrite(vPIN_PIR_LED,0);
Serial.println("PIR = OFF");
if (memory2==1) {
Blynk.setProperty (vPIN_AUTO_MOTION, "label",String("\xF0\x9F\x92\xAB") + " AUTO PIR ");
} else {
Blynk.setProperty (vPIN_AUTO_MOTION, "label",String("\xE2\x9C\x8B") + " MANUAL PIR ");
}
}
//---------------------------------------------POWER1-----------------------------------------------
}else if (String(topic) == InTOPIC_3) { // stairs/stat/POWER1
StaticJsonBuffer<450> jsonBuffer;
JsonObject& root = jsonBuffer.parseObject((char*)payload);
if ((char)payload[1] == 'N') {
Blynk.virtualWrite(vPIN_ON_OFF_1,1);
Serial.println("POWER1 = ON");
}else{
Blynk.virtualWrite(vPIN_ON_OFF_1,0);
Serial.println("POWER1 = OFF");
}
//----------------------------------------------POWER2----------------------------------------------
}else if (String(topic) == InTOPIC_4) { // stairs/stat/POWER2
StaticJsonBuffer<450> jsonBuffer;
JsonObject& root = jsonBuffer.parseObject((char*)payload);
if ((char)payload[1] == 'N') {
Blynk.virtualWrite(vPIN_ON_OFF_2,1);
Serial.println("POWER2 = ON");
}else{
Blynk.virtualWrite(vPIN_ON_OFF_2,0);
Serial.println("POWER2 = OFF");
}
//--------------------------------------------------------------------------------------------
}else if (String(topic) == InTOPIC_5) { // stairs/Distance
StaticJsonBuffer<450> jsonBuffer;
JsonObject& root = jsonBuffer.parseObject((char*)payload);
Distance = root["Distance"];
Blynk.virtualWrite(vPIN_SR04_DIST,Distance);
Blynk.setProperty (vPIN_SR04_DIST, "label", "DISTANCE in Cm");
//--------------------------------------------------------------------------------------------
//09:59:13 MQT: stairs/stat/RESULT = {"T1":30,"T2":0,"T3":0,"T4":0,"T5":0,"T6":0,"T7":0,"T8":0}
//10:01:05 MQT: stairs/stat/RESULT = {"POWER1":"ON"}
//10:01:40 MQT: stairs/stat/RESULT = {"POWER1":"OFF"}
//10:04:11 MQT: stairs/stat/RESULT = {"Mem1":"20_"}
}else if (String(topic) == InTOPIC_6) { //stairs/stat/RESULT
StaticJsonBuffer<450> jsonBuffer;
JsonObject& root = jsonBuffer.parseObject((char*)payload);
int memory1 = root["Mem1"];
int T1 = root["T1"];
const char* POWER1 = root["POWER1"]; // "OFF"
if ( memory1 > 0) {
Blynk.setProperty(vPIN_PIR_LED, "label", String("PIR ") + memory1 + String(" S") );
CountdownRemain = memory1;
Serial.print("memory1 = "); Serial.print(memory1); Serial.println(" Sec");
Serial.println(CountdownRemain);
if (CountdownRemain) { // check if there is a time set or not
CountdownShowFormatted(CountdownRemain);
timer.enable(CountdownTimer);
}
}
if ( T1 > 0) {
Blynk.setProperty(vPIN_PIR_LED, "label", String("PIR ") + T1 + String(" S") );
CountdownRemain = T1;
if (CountdownRemain) { // check if there is a time set or not
CountdownShowFormatted(CountdownRemain);
timer.enable(CountdownTimer);
}
}
}
}
timer.h
/*******************************************************************************
*
* timer.h
*
*******************************************************************************/
void CountdownShowFormatted(int seconds) {
long hours = 0;
long mins = 0;
long secs = 0;
String secs_o = ":";
String mins_o = ":";
secs = seconds; // set the seconds remaining
mins = secs / 60; //convert seconds to minutes
hours = mins / 60; //convert minutes to hours
secs = secs - (mins * 60); //subtract the coverted seconds to minutes in order to display 59 secs max
mins = mins - (hours * 60); //subtract the coverted minutes to hours in order to display 59 minutes max
if (secs < 10) {
secs_o = ":0";
}
if (mins < 10) {
mins_o = ":0";
}
if (memory2 == 1){
Blynk.virtualWrite(vPIN_COUNTDOWN, String(" ")+ hours + mins_o + mins + secs_o + secs);
Blynk.setProperty(vPIN_ON_OFF_1, "label", String("\xE2\x8F\xB3") + String("T1 = ") + hours + mins_o + mins + secs_o + secs + String(" S"));
} else {
Blynk.virtualWrite(vPIN_COUNTDOWN, " 0:00:00");
Blynk.setProperty(vPIN_ON_OFF_1, "label", String("T1 = ") + "0:00:00" + String(" S") );
}
}
void CountdownTimerFunction() {
CountdownRemain--; // remove 1 every second
CountdownShowFormatted(CountdownRemain);
if (!CountdownRemain) { // check if CountdownRemain == 0/FALSE/LOW
timer.disable(CountdownTimer); // if 0 stop timer
if (memory2 == 1) {
Blynk.setProperty(vPIN_ON_OFF_1, "label", String("T1 = ") + "0:00:00" + String(" S") );
client.publish("stairs/cmnd/POWER1", "0");
}
}
}
wifi_credentials.h
/*******************************************************************************
*
* wifi_credentials.h
*
******************************************************************************/
/*******************************************************************************
Local Blynk Server Settings (uncomment to use local server and set address)
*******************************************************************************/
#define WIFI_SSID "xxxx" // ["xxxx" PW = "xxxx" ]
#define WIFI_PASS "xxxx" //Set pass to "" for open networks.
//#define LOCAL_SERVER IPAddress(192, 168,xxx, xxx) //your Local IP Server
#define Geo_DNS_SERVER IPAddress(xxx, xxx, xxx, xxx) //FRANKFURT
- Put all files in the same Folder