#include <ESP8266WebServer.h>
#include <DNSServer.h>
#include <WiFiManager.h>
#include <MQTT.h>
#include <PubSubClient.h>
//#include <PubSubClient_JSON.h>
#include <ESP8266WiFi.h>
#include <ArduinoJson.h>
#include <Arduino.h>
#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>
//#include "WemoSwitch.h"
//#include "WemoManager.h"
#include "CallbackFunction.h"
#define GATE 2
#define GATESTATE 12
#define DOOROPEN 0
#define DOORCLOSE 4
#define DOORSTATE 5
//on/off callbacks
/*void GarageOn();
void GarageOff();
void GatesOn();
void GatesOff();*/
/*
IoT Manager mqtt device client https://play.google.com/store/apps/details?id=ru.esp8266.iotmanager
Based on Basic MQTT example with Authentication
PubSubClient library v 1.91.1 https://github.com/Imroy/pubsubclient
- connects to an MQTT server, providing userdescr and password
- subscribes to the topic "/IoTmanager" (waiting "HELLO" messages from mobile device)
- publishes config to the topic "/IoTmanager/config/deviceID/"
Tested with Arduino IDE 1.6.7 + ESP8266 Community Edition v 2.1.0-rc2
PubSubClient library v 1.91.1 https://github.com/Imroy/pubsubclient
ArduinoJson library 5.0.7 https://github.com/bblanchon/ArduinoJson
sketch version : 1.0
IoT Manager : 1.4.7 and above
simple-btn widget demo, for details look at Widgets Guide on IoT Manager
<div class="class1" style="style1">
<div class="class2" style="style2">
descr
</div>
<button class="class3" style="style3">
title
</button>
</div>
*/
String prefix = "/IoTmanager"; // global prefix for all topics - must be some as mobile device
String deviceID="YardESP";
String PUBclientID;
String DOORPOS;
String wifistren;
long wifistr;
OneWire ds(14);
DallasTemperature sensors(&ds);
float temp;
static unsigned long lastupdate = millis();
WiFiClient wclient;
WiFiManager wifiManager;
/*WemoManager wemoManager;
WemoSwitch *Garage = NULL;
WemoSwitch *Gates = NULL;*/
// config for cloud mqtt broker by DNS hostname ( for example, cloudmqtt.com use: m20.cloudmqtt.com - EU )
String mqttServerName = "m21.cloudmqtt.com"; // for cloud broker - by hostname, from CloudMQTT account data
int mqttport = zzzzz; // default 1883, but CloudMQTT.com use other, for example: 13191, 23191 (SSL), 33191 (WebSockets) - use from CloudMQTT account data
String mqttuser = "xxxxxxx"; // from CloudMQTT account data
String mqttpass = "yyyyyyyyy"; // from CloudMQTT account data
PubSubClient client(wclient, mqttServerName, mqttport); // for cloud broker - by hostname
// config for local mqtt broker by IP address
//IPAddress server(192, 168, 1, 100); // for local broker - by address
//int mqttport = 9001; // default 1883, but WebSockets port needed
//String mqttuser = ""; // from broker config
//String mqttpass = ""; // from broker config
//PubSubClient client(wclient, server, mqttport); // for local broker - by address
int freeheap;
const int nWidgets = 15; // number of widgets
String sTopic [nWidgets];
String stat [nWidgets];
String thing_config[nWidgets];
DynamicJsonBuffer jsonBuffer;
JsonObject& json_status = jsonBuffer.createObject();
void FreeHEAP() {
if ( ESP.getFreeHeap() < freeheap ) {
if ( ( freeheap != 100000) ) {
Serial.print("Memory leak detected! old free heap = ");
Serial.print(freeheap);
Serial.print(", new value = ");
Serial.println(ESP.getFreeHeap());
}
freeheap = ESP.getFreeHeap();
}
}
String setStatus ( String s ) {
json_status["status"] = s;
String string_status;
json_status.printTo(string_status);
Serial.print("Status String is: ");
Serial.println(string_status);
return string_status;
}
String setStatus ( int s ) {
json_status["status"] = s;
String string_status;
json_status.printTo(string_status);
Serial.print("Status int is: ");
Serial.println(string_status);
return string_status;
}
void initVar() {
PUBclientID = String( ESP.getChipId() ) + "-" + String( ESP.getFlashChipId() ); // IoT thing device ID - unique device id in our project
// widget0
JsonObject& root = jsonBuffer.createObject();
sTopic[0] = prefix + "/" + deviceID + "/Garage_status0";
root["id"] = 0;
root["page"] = "Yard";
root["pageId"] = "10";
root["widget"] = "anydata";
root["class1"] = "no-border text-center col-xs-6"; // class for 1st div
root["style1"] = ""; // style for 1st div
root["descr"] = "Garage Position:"; // text for description
root["class2"] = "calm"; // class for description from Widgets Guide - Color classes
root["style2"] = "font-size:20px;float:top;padding-bottom:10px;font-weight:bold;"; // style for description
root["topic"] = sTopic[0];
root["class3"] = "button button-calm icon ion-model-s"; // class for button
root["style3"] = "float:left;"; // style for button
root.printTo(thing_config[0]);
// widget1
JsonObject& root1 = jsonBuffer.createObject();
sTopic[1] = prefix + "/" + deviceID + "/Wifi_RSSI1";
root1["id"] = 1;
root1["page"] = "Yard";
root1["pageId"] = "10";
root1["widget"] = "anydata";
root1["class1"] = "no-border text-center col-xs-6"; // class for 1st div
root1["style1"] = ""; // style for 1st div
root1["descr"] = "WiFi Strength:"; // text for description
root1["class2"] = "royal"; // class for description from Widgets Guide - Color classes
root1["style2"] = "font-size:20px;float:top;padding-bottom:10px;font-weight:bold;"; // style for description
root1["topic"] = sTopic[1];
root1["class3"] = "button button-royal icon ion-wifi"; // class for button
root1["style3"] = "float:right;"; // style for button
root1.printTo(thing_config[1]);
// widget2
JsonObject& root2 = jsonBuffer.createObject();
sTopic[2] = prefix + "/" + deviceID + "/Garage_open2";
root2["id"] = 2;
root2["page"] = "Yard";
root2["pageId"] = "10";
root2["widget"] = "simple-btn";
root2["class1"] = "item no-border"; // class for 1st div
root2["style1"] = ""; // style for 1st div
root2["descr"] = "Garage Door Open"; // text for description
root2["class2"] = "balanced"; // class for description from Widgets Guide - Color classes
root2["style2"] = "font-size:20px;float:left;padding-top:10px;font-weight:bold;"; // style for description
root2["topic"] = sTopic[2];
root2["class3"] = "button button-balanced icon ion-arrow-up-a"; // class for button
root2["style3"] = "float:right;"; // style for button
root2.printTo(thing_config[2]);
// widget3
JsonObject& root3 = jsonBuffer.createObject();
sTopic[3] = prefix + "/" + deviceID + "/Garage_close3";
root3["id"] = 3;
root3["page"] = "Yard";
root3["pageId"] = "10";
root3["widget"] = "simple-btn";
root3["class1"] = "item no-border"; // class for 1st div
root3["style1"] = ""; // style for 1st div
root3["descr"] = "Garage Door Close"; // text for description
root3["class2"] = "assertive"; // class for description from Widgets Guide - Color classes
root3["style2"] = "font-size:20px;float:left;padding-top:10px;font-weight:bold;"; // style for description
root3["topic"] = sTopic[3];
root3["class3"] = "button button-assertive icon ion-arrow-down-a"; // class for button
root3["style3"] = "float:right;"; // style for button
root3.printTo(thing_config[3]);
// widget4
JsonObject& root4 = jsonBuffer.createObject();
sTopic[4] = prefix + "/" + deviceID + "/Gate4";
stat [4] = setStatus (1); // LED off at startup
root4["id"] = 4;
root4["page"] = "Yard";
root4["pageId"] = "10";
root4["descr"] = "Gate"; // text for description
root4["descrStyle"] = "background-color:#5F9EA0;border:solid 2px #F00;font-size:20px;font-weight:bold;";
root4["widget"] = "toggle";
root4["iconClass"] = "ion-wifi";
root4["color"] = "black"; // black, blue, green, orange, red, white, yellow (off - grey)
root4["topic"] = sTopic[4];
root4.printTo(thing_config[4]);
// widget5
JsonObject& root5 = jsonBuffer.createObject();
JsonObject& cfg5 = jsonBuffer.createObject();
sTopic[5] = prefix + "/" + deviceID + "/5BMP180_temp5";
root5["id"] = 5;
root5["page"] = "Yard";
root5["pageId"] = "10";
root5["widget"] = "steel";
//root5["class1"] = "item no-border";
root5["descr"] = "Yard Temperature (°C)"; // text for description
root5["topic"] = sTopic[5];
cfg5["titleString"] = "Yard Temperature (°C)";
cfg5["unitString"] = "°C";
cfg5["width"] = "auto";
cfg5["BackgroundColor"] = "CARBON";
cfg5["gaugeType"] = "TYPE2";
cfg5["type"] = "Linear";
cfg5["lcdDecimals"] = "2";
cfg5["height"] = "140";
cfg5["FrameDesign"] = "GLOSSY_METAL";
cfg5["lcdVisable"] = true;
cfg5["ColorDef"] = "RAITH";
cfg5["LcdColor"] = "RED_DARKRED";
cfg5["LedColor"] = "MAGENTA_LED";
cfg5["threshold"] = 20;
root5["widgetConfig"] = cfg5;
root5.printTo(thing_config[5]);
// widget6
JsonObject& root6 = jsonBuffer.createObject();
sTopic[6] = prefix + "/" + deviceID + "/HLight";
stat [6] = setStatus (1); // LED off at startup
root6["id"] = 6;
root6["page"] = "House";
root6["pageId"] = "20";
root6["descr"] = "Hall Light"; // text for description
root6["descrStyle"] = "background-color:#5F9EA0;border:solid 2px #F00;font-size:20px;font-weight:bold;";
root6["widget"] = "toggle";
//root4["iconClass"] = "ion-wifi";
root6["color"] = "black"; // black, blue, green, orange, red, white, yellow (off - grey)
root6["topic"] = sTopic[6];
root6.printTo(thing_config[6]);
// widget7
JsonObject& root7 = jsonBuffer.createObject();
sTopic[7] = prefix + "/" + deviceID + "/Hlight_B";
stat [7] = setStatus (1); // LED off at startup
root7["id"] = 7;
root7["page"] = "House";
root7["pageId"] = "20";
//root7["descr"] = "Hall Light Brightness"; // text for description
//root7["descrStyle"] = "background-color:#5F9EA0;border:solid 2px #F00;font-size:20px;font-weight:bold;";
root7["widget"] = "range";
//root4["iconClass"] = "ion-wifi";
root7["color"] = "black"; // black, blue, green, orange, red, white, yellow (off - grey)
root7["topic"] = sTopic[7];
root7["debounce"] = 600;
root7.printTo(thing_config[7]);
// widget8
JsonObject& root8 = jsonBuffer.createObject();
sTopic[8] = prefix + "/" + deviceID + "/Light1";
stat [8] = setStatus (1); // LED off at startup
root8["id"] = 8;
root8["page"] = "House";
root8["pageId"] = "20";
root8["descr"] = "Liv Light 1"; // text for description
root8["descrStyle"] = "background-color:#5F9EA0;border:solid 2px #F00;font-size:20px;font-weight:bold;";
root8["widget"] = "toggle";
//root4["iconClass"] = "ion-wifi";
root8["color"] = "black"; // black, blue, green, orange, red, white, yellow (off - grey)
root8["topic"] = sTopic[8];
root8.printTo(thing_config[8]);
// widget9
JsonObject& root9 = jsonBuffer.createObject();
sTopic[9] = prefix + "/" + deviceID + "/light1_B";
stat [9] = setStatus (1); // LED off at startup
root9["id"] = 9;
root9["page"] = "House";
root9["pageId"] = "20";
//root9["descr"] = "Liv Light1 Brightness"; // text for description
//root9["descrStyle"] = "background-color:#5F9EA0;border:solid 2px #F00;font-size:20px;font-weight:bold;";
root9["widget"] = "range";
//root4["iconClass"] = "ion-wifi";
root9["color"] = "black"; // black, blue, green, orange, red, white, yellow (off - grey)
root9["topic"] = sTopic[9];
root9["debounce"] = 600;
root9.printTo(thing_config[9]);
// widget10
JsonObject& root10 = jsonBuffer.createObject();
sTopic[10] = prefix + "/" + deviceID + "/Light2";
stat [10] = setStatus (1); // LED off at startup
root10["id"] = 10;
root10["page"] = "House";
root10["pageId"] = "20";
root10["descr"] = "Liv Light 2"; // text for description
root10["descrStyle"] = "background-color:#5F9EA0;border:solid 2px #F00;font-size:20px;font-weight:bold;";
root10["widget"] = "toggle";
//root4["iconClass"] = "ion-wifi";
root10["color"] = "black"; // black, blue, green, orange, red, white, yellow (off - grey)
root10["topic"] = sTopic[10];
root10.printTo(thing_config[10]);
// widget11
JsonObject& root11 = jsonBuffer.createObject();
sTopic[11] = prefix + "/" + deviceID + "/light2_B";
stat [11] = setStatus (1); // LED off at startup
root11["id"] = 11;
root11["page"] = "House";
root11["pageId"] = "20";
//root11["descr"] = "Liv Light2 Brightness"; // text for description
//root11["descrStyle"] = "background-color:#5F9EA0;border:solid 2px #F00;font-size:20px;font-weight:bold;";
root11["widget"] = "range";
//root4["iconClass"] = "ion-wifi";
root11["color"] = "black"; // black, blue, green, orange, red, white, yellow (off - grey)
root11["topic"] = sTopic[11];
root11["debounce"] = 600;
root11.printTo(thing_config[11]);
// widget12
JsonObject& root12 = jsonBuffer.createObject();
sTopic[12] = prefix + "/" + deviceID + "/Light3";
stat [12] = setStatus (1); // LED off at startup
root12["id"] = 12;
root12["page"] = "House";
root12["pageId"] = "20";
root12["descr"] = "Liv Light 3"; // text for description
root12["descrStyle"] = "background-color:#5F9EA0;border:solid 2px #F00;font-size:20px;font-weight:bold;";
root12["widget"] = "toggle";
//root4["iconClass"] = "ion-wifi";
root12["color"] = "black"; // black, blue, green, orange, red, white, yellow (off - grey)
root12["topic"] = sTopic[12];
root12.printTo(thing_config[12]);
// widget13
JsonObject& root13 = jsonBuffer.createObject();
sTopic[13] = prefix + "/" + deviceID + "/light3_B";
stat [13] = setStatus (1); // LED off at startup
root13["id"] = 13;
root13["page"] = "House";
root13["pageId"] = "20";
//root13["descr"] = "Liv Light3 Brightness"; // text for description
//root13["descrStyle"] = "background-color:#5F9EA0;border:solid 2px #F00;font-size:20px;font-weight:bold;";
root13["widget"] = "range";
//root4["iconClass"] = "ion-wifi";
root13["color"] = "black"; // black, blue, green, orange, red, white, yellow (off - grey)
root13["topic"] = sTopic[13];
root13["debounce"] = 600;
root13.printTo(thing_config[13]);
// widget14
JsonObject& root14 = jsonBuffer.createObject();
sTopic[14] = prefix + "/" + deviceID + "/Heating";
stat [14] = setStatus (0); // LED off at startup
root14["id"] = 14;
root14["page"] = "House";
root14["pageId"] = "20";
root14["descr"] = "Heating"; // text for description
root14["descrStyle"] = "background-color:#5F9EA0;border:solid 2px #F00;font-size:20px;font-weight:bold;";
root14["widget"] = "toggle";
//root4["iconClass"] = "ion-wifi";
root14["color"] = "black"; // black, blue, green, orange, red, white, yellow (off - grey)
root14["topic"] = sTopic[14];
root14.printTo(thing_config[14]);
}
void pubStatus(String t, String payload) {
if (client.publish(t + "/status", payload)) {
Serial.println("Publish new status to " + t + "/status" + ", value: " + payload);
} else {
Serial.println("Publish new status to " + t + "/status" + " FAIL!");
client.disconnect();
}
yield();
FreeHEAP(); // check memory leak
}
void pubConfig() {
bool success;
bool success2;
success2 = client.publish(MQTT::Publish(prefix + "/" + deviceID + "/response", "{\"pages\":[{\"pageId\": 10, \"pageName\": \"Yard\"},{\"pageId\": 20, \"pageName\": \"House\"}]}").set_qos(1));
if (success2) {
Serial.println("Publish config: Success");
} else {
Serial.println("Publish config FAIL!");
delay(1000);
ESP.restart();
}
for (int i = 0; i < nWidgets; i = i + 1) {
success = client.publish(MQTT::Publish(prefix + "/" + deviceID + "/config", thing_config[i]).set_qos(1));
if (success) {
Serial.println("Publish config: Success (" + thing_config[i] + ")");
Serial.println(i);
} else {
Serial.println("Publish config FAIL! (" + thing_config[i] + ")");
delay(1000);
ESP.restart();
}
}
char buffer[16];
char bufferjson = '}';
char buffertot[16];
sprintf(buffer,"%s","{\"status\":");
dtostrf(temp, 2, 2, &buffer[strlen(buffer)]);
sprintf(buffertot, "%s%c", buffer, bufferjson);
stat[5] = buffertot;//setStatus( buffer );
Serial.println(stat[5]);
if(digitalRead(DOORSTATE)==HIGH) {
DOORPOS=" OPEN";
} else {
DOORPOS=" CLOSED";
}
pubStatus(sTopic[0], setStatus(DOORPOS)); // LED off at startup
pubStatus(sTopic[5], stat[5]);
}
void callback(const MQTT::Publish& sub) {
Serial.print("Get data from subscribed topic ");
Serial.print(sub.topic());
Serial.print(" => ");
Serial.println(sub.payload_string());
if ( sub.payload_string() == "HELLO" ) { // handshaking
pubConfig();
}
if (sub.topic() == sTopic[2] + "/control") { // control from toggle - widget id 0 - ON
// payload from button always 1, change status only for widget toggle - id 2
stat[2] = setStatus(1); // 1-on 2-off LED on phone
digitalWrite(DOOROPEN, HIGH); // 0-on 1-off LED on device
pubStatus(sTopic[2], stat[2]);
} else if (sub.topic() == sTopic[3] + "/control") { // control from simple-btn - widget id 1 - OFF
// payload from button always 1, change status only for widget toggle - id 2
stat[3] = setStatus(0); // 1-on 2-off LED on phone
digitalWrite(DOORCLOSE, HIGH); // 0-on 1-off LED on device
pubStatus(sTopic[3], stat[3]);
} else if (sub.topic() == sTopic[4] + "/control") { // control from simple-btn - widget id 2 - ON
lastupdate = millis();
if (sub.payload_string() == "0") {
stat[4] = setStatus(0);
digitalWrite(GATE, HIGH);
} else {
stat[4] = setStatus(1);
digitalWrite(GATE, HIGH);
}
pubStatus(sTopic[4], stat[4]);
}
}
void setup() {
Serial.begin(115200);
initVar();
wifiManager.autoConnect("XXXXXX", "YYYYYYYYYY");
delay(10);
Serial.println();
Serial.println();
Serial.println("MQTT client started.");
sensors.begin();
Serial.print("Requesting temperatures...");
sensors.requestTemperatures();
Serial.print("Temperature for Device 1 is: ");
Serial.println(sensors.getTempCByIndex(0));
temp = sensors.getTempCByIndex(0);
Serial.println(WiFi.RSSI());
Serial.println(ESP.getFreeHeap());
// GATE
pinMode(GATE, OUTPUT);
digitalWrite(GATE, HIGH);
// DOOROPEN
pinMode(DOOROPEN, OUTPUT);
digitalWrite(DOOROPEN, HIGH);
// DOORCLOSE
pinMode(DOORCLOSE, OUTPUT);
digitalWrite(DOORCLOSE, HIGH);
// DOORSTATE
pinMode(DOORSTATE, INPUT_PULLUP);
// GATESTATE
pinMode(GATESTATE, INPUT_PULLUP);
/*wemoManager.begin();
// Format: Alexa invocation name, local port no, on callback, off callback
Serial.println(ESP.getFreeHeap());
Garage = new WemoSwitch("Garage Door", 80, GarageOn, GarageOff);
Gates = new WemoSwitch("Gates", 81, GatesOn, GatesOff);
wemoManager.addDevice(*Garage);
wemoManager.addDevice(*Gates);*/
FreeHEAP();
freeheap = 100000;
}
void loop() {
if (WiFi.status() != WL_CONNECTED) {
ESP.restart();
}
if (WiFi.status() == WL_CONNECTED) {
if (!client.connected()) {
Serial.println("Connecting to MQTT server ...");
bool success;
if (mqttuser.length() > 0) {
success = client.connect( MQTT::Connect( PUBclientID ).set_auth(mqttuser, mqttpass) );
} else {
success = client.connect( PUBclientID );
}
if (success) {
client.set_callback(callback);
Serial.println("Connect to MQTT server: Success");
client.subscribe(prefix); // for receiving HELLO messages and handshaking
client.subscribe(prefix + "/" + deviceID + "/+/control"); // subscribe to all "control" messages for all widgets of this device
pubConfig();
} else {
Serial.println("Connect to MQTT server: FAIL");
delay(1000);
}
}
if (client.connected()) {
client.loop();
}
}
//yield();
//wemoManager.serverLoop();
yield();
static unsigned long last = millis();
if (millis() - last > 1000) {
last = millis();
digitalWrite(DOOROPEN, LOW);
digitalWrite(DOORCLOSE, LOW);
digitalWrite(GATE, LOW);
}
if (millis() - lastupdate > 7000) {
lastupdate = millis();
Serial.println(ESP.getFreeHeap());
Serial.println(lastupdate);
if(digitalRead(DOORSTATE)==HIGH) {
DOORPOS=" OPEN";
} else {
DOORPOS=" CLOSED";
}
stat[0]=setStatus(DOORPOS);
wifistr = WiFi.RSSI();
Serial.println(wifistr);
if(wifistr > -55) {
wifistren=" Excellent";
} else if (wifistr < -55 & wifistr > -65) {
wifistren=" Very Good";
} else if (wifistr < -65 & wifistr > -70) {
wifistren=" Okay";
} else if (wifistr < -70 & wifistr > -80) {
wifistren=" Not Good";
} else {
wifistren=" Unuseable";
}
Serial.println(DOORPOS);
Serial.println(wifistren);
stat[1]=setStatus(wifistren);
stat[4] = setStatus(digitalRead(GATESTATE));
Serial.println(stat[0]);
Serial.println(stat[1]);
char buffer[16];
char bufferjson = '}';
char buffertot[16];
sensors.requestTemperatures();
temp = sensors.getTempCByIndex(0);
sprintf(buffer,"%s","{\"status\":");
dtostrf(temp, 2, 2, &buffer[strlen(buffer)]);
sprintf(buffertot, "%s%c", buffer, bufferjson);
stat[5] = buffertot;//setStatus( buffer );
if(temp < 20){
thing_config[5].replace("ColorDef\":\"RED", "ColorDef\":\"RAITH");
client.publish(MQTT::Publish(prefix + "/" + deviceID + "/config", thing_config[5]).set_qos(1));
Serial.println(thing_config[5]);
} else {
thing_config[5].replace("ColorDef\":\"RAITH", "ColorDef\":\"RED");
client.publish(MQTT::Publish(prefix + "/" + deviceID + "/config", thing_config[5]).set_qos(1));
Serial.println(thing_config[5]);
}
for (int i = 0; i < 6; i = i + 1) {
pubStatus(sTopic[i], stat[i]);
}
}
}
/*void GarageOn() {
Serial.print("Garage Open Relay turn on ...");
digitalWrite(DOOROPEN, HIGH);
}
void GarageOff() {
Serial.print("Garage Close Relay turn on ...");
digitalWrite(DOORCLOSE, HIGH);
}
void GatesOn() {
Serial.print("Gate Reley turn on ...");
digitalWrite(GATE, HIGH);
}
void GatesOff() {
Serial.print("Gate Relay turn on ...");
digitalWrite(GATE, HIGH);
}*/
Thanks