#include <FS.h> //this needs to be first, e folosit de salvarea credentialelor pe FS
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <WiFiManager.h> //https://github.com/tzapu/WiFiManager
#include <ArduinoJson.h> //https://github.com/bblanchon/ArduinoJson pentru salvarea credentialelor in eprom
#include <WiFiClient.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <ESP8266HTTPClient.h>
#include <ESP8266httpUpdate.h>
char mqtt_user[9]; //le va lua din FS
char mqtt_devid[5]; //le va lua din FS
char mqttPassword[15]; //urmatoarele le va genera cu functia gen
char mqttSUB[22];
char espName[13];
char mqttESP[22];
char mqttTEMP[23];
char mqttLWT[22];
const String model = "NodeMCU Dallas";
const String ver = "v2.0.1";
const char* mqttServer = "mqtt.clickhome.ro";
const int mqttPort = 1883;
long loopTimer = 900000; // miliseconds - by default trimite la 15 minute
long lastMsg = 0;
float loopTemp = 0;
int inPin = 5;
String mqttMessage;
// senzor de temperatura DALLAS
#define ONE_WIRE_BUS D4 // pinul de date (la mine am pus senzor pe D4)
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
//*********************************************************************
WiFiClient espClient;
PubSubClient client(espClient);
void generate_vars(){
strcpy (mqttPassword, "8219CH");
strcat (mqttPassword, mqtt_user);
strcpy (espName, mqtt_user);
strcat (espName, "-");
strcat (espName, mqtt_devid);
strcpy (mqttSUB, "cmnd/");
strcat (mqttSUB, espName);
strcat (mqttSUB, "/ESP");
strcpy (mqttESP, "stat/");
strcat (mqttESP, espName);
strcat (mqttESP, "/ESP");
strcpy (mqttTEMP, "stat/");
strcat (mqttTEMP, espName);
strcat (mqttTEMP, "/TEMP");
strcpy (mqttLWT, "tele/");
strcat (mqttLWT, espName);
strcat (mqttLWT, "/LWT");
}
String ipToString(IPAddress ip){
String s="";
for (int i=0; i<4; i++)
s += i ? "." + String(ip[i]) : String(ip[i]);
return s;
}
String getMacAddress() {
byte mac[6];
WiFi.macAddress(mac);
String cMac = "";
for (int i = 0; i < 6; ++i) {
cMac += String(mac[i],HEX);
if(i<5)
cMac += "-";
}
cMac.toUpperCase();
return cMac;
}
void reconectez() {
while (String(mqtt_user)==""){
Serial.println("Invalid user!");
delay(99999999);
}
// ma conectez la mqtt server
while (!client.connected()) {
client.setServer(mqttServer, mqttPort);
Serial.print("AtloopTempting MQTT connection...");
// Incerc sa ma reconectez cu LWT din 5 in 5 secunde
if (client.connect(espName, mqtt_user, mqttPassword, mqttLWT, 1, 1, "Offline")) {
Serial.println("connected");
client.publish(mqttLWT,"Online",TRUE);
// trimit informatii utile cand ma conectez
String esp_info = "{\"ESPMac\":\"";
esp_info += getMacAddress();
esp_info += "\", \"IPAddress\":\"";
esp_info += ipToString(WiFi.localIP());
esp_info += "\"}";
String netinfo = "{\"Module\":\"";
netinfo += String (model);
netinfo += "\", \"Version\":\"";
netinfo += String (ver);
netinfo += "\"}";
client.publish(mqttESP, netinfo.c_str(),TRUE);
Serial.println(netinfo);
client.publish(mqttESP, esp_info.c_str(),TRUE);
Serial.println(esp_info);
client.publish(mqttESP, "15 minute",TRUE); // trimit intervalul default
client.subscribe(mqttSUB);
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 60 seconds");
// Wait 60 seconds before retrying
delay(60000);
}
}
}
void setup()
{
Serial.begin(115200);
//generez variabilele
readFS();
// The extra parameters to be configured (can be either global or just in the setup)
// After connecting, parameter.getValue() will get you the configured value
// id/name placeholder/prompt default length
WiFiManagerParameter custom_mqtt_user("user", "mqtt user", mqtt_user, 9);
WiFiManagerParameter custom_mqtt_devid("devid", "mqtt devid", mqtt_devid, 5);
// ma conectez la AP via wifi
WiFiManager wifi;
wifi.setConfigPortalTimeout(120); // a timeout so the ESP doesn't hang waiting to be configured, for instance after a power failure
wifi.setTimeout(180); // sta AP 3 minute apoi se reseteaza din nou
if (!wifi.autoConnect("ClickHome")) {
Serial.println("timeout - going to sleep");
}
delay(200);
strcpy(mqtt_user, custom_mqtt_user.getValue()); //citesc datele salvate anterior pe FS
strcpy(mqtt_devid, custom_mqtt_devid.getValue());
generate_vars(); //genereaza topicurile de mqtt in baza mqtt_user si mqtt_devid
reconectez();
client.setCallback(getMessage); //setez functia care parseaza mesajele venite prin mqtt
pinMode(inPin, INPUT);
sensors.begin();
}
void getMessage(char* topic, byte* payload, unsigned int length) {
float t = 0;
mqttMessage="";
Serial.print("Message arrived in topic: ");
Serial.println(topic);
Serial.print("Message:");
for (int i = 0; i < length; i++) {
mqttMessage += (char)payload[i];
}
Serial.println(mqttMessage);
// daca a primit sendTemp trimite temperatura
if (mqttMessage == "temp")
{
Serial.println("Trimit temperatura");
sensors.setResolution(12);
sensors.requestTemperatures(); // Send the command to get Temperatures
t = sensors.getTempCByIndex(0);
String json = "{\"Temp\":";
json += String (t);
json += "}";
client.publish(mqttTEMP, json.c_str(),TRUE);
Serial.println(json);
}
// reset la ESP
if (mqttMessage == "reset")
{
String lastwords="Am fost resetat ...";
client.publish(mqttESP, lastwords.c_str(), TRUE);
delay (3000);
ESP.reset();
delay (5000);
}
// procedura de software update via WEB
if (mqttMessage == "update")
{
String msg="Software update: ";
t_httpUpdate_return ret;
//ESPhttpUpdate.rebootOnUpdate(false);
ret = ESPhttpUpdate.update("http://update.clickhome.ro/senzor/dallas/arduino.bin");
//ret = ESPhttpUpdate.update("update.clickhome.ro", 80, "/senzor/dallas/arduino.bin");
switch(ret) {
case HTTP_UPDATE_FAILED:
msg.concat(" eroare:");
msg.concat(ESPhttpUpdate.getLastError());
msg.concat(" motiv:");
msg.concat(ESPhttpUpdate.getLastErrorString().c_str());
break;
case HTTP_UPDATE_NO_UPDATES:
msg.concat(" no update.");
break;
case HTTP_UPDATE_OK:
msg.concat(" success.");
break;
}
Serial.println(msg);
}
// daca a primit valoarea in minute seteaza loopTimer si-l trimite in DB
if (mqttMessage == "debug")
{
loopTimer=30000; // setez sa trimita valori la 30 de secunde ca sa fac debug
client.publish(mqttESP, "{\"LoopInterval\":\"30 secunde\"}",TRUE);
}
if (mqttMessage == "10")
{
loopTimer=600000; // setez sa trimita valori la 10 minute
client.publish(mqttESP, "{\"LoopInterval\":\"10 minute\"}",TRUE);
}
if (mqttMessage == "15")
{
loopTimer=900000; // setez sa trimita valori la 15 minute
client.publish(mqttESP, "{\"LoopInterval\":\"15 minute\"}",TRUE);
}
if (mqttMessage == "30")
{
loopTimer=1800000; // setez sa trimita valori la 30 de minute
client.publish(mqttESP, "{\"LoopInterval\":\"30 de minute\"}",TRUE);
}
if (mqttMessage == "60")
{
loopTimer=3600000; // setez sa trimita valori la o ora
client.publish(mqttESP, "{\"LoopInterval\":\"o ora\"}",TRUE);
}
if (mqttMessage == "stop")
{
loopTimer=3600000000; // setez sa nu trimita valori
client.publish(mqttESP, "{\"LoopInterval\":\"oprit\"}",TRUE);
}
}
void readFS(){
//read configuration from FS json
//Serial.println("mounting FS...");
if (SPIFFS.begin()) {
//Serial.println("mounted file system");
if (SPIFFS.exists("/config.json")) {
//file exists, reading and loading
//Serial.println("reading config file");
File configFile = SPIFFS.open("/config.json", "r");
if (configFile) {
//Serial.println("opened config file");
size_t size = configFile.size();
// Allocate a buffer to store contents of the file.
std::unique_ptr<char[]> buf(new char[size]);
configFile.readBytes(buf.get(), size);
DynamicJsonBuffer jsonBuffer;
JsonObject& json = jsonBuffer.parseObject(buf.get());
//json.printTo(Serial);
if (json.success()) {
//Serial.println("\nparsed json");
strcpy(mqtt_user, json["mqtt_user"]);
strcpy(mqtt_devid, json["mqtt_devid"]);
} else {
//Serial.println("failed to load json config");
}
}
}
} else {
//Serial.println("failed to mount FS");
}
//end read
}
void loop()
{
if (!client.connected()) {
reconectez();
}
client.loop();
long now = millis();
if (now - lastMsg > loopTimer) {
lastMsg = now;
sensors.setResolution(12);
sensors.requestTemperatures(); // Send the command to get loopTemperatures
loopTemp = sensors.getTempCByIndex(0);
Serial.println(loopTemp);
if((loopTemp > -20) && (loopTemp <60))
{
String val = "{\"Temp\":";
val += String (loopTemp);
val += "}";
client.publish(mqttESP, val.c_str(),TRUE);
}
}
}