#include // librarie folosita de salvarea credentialelor pe FS #include #include #include // librarie folosita pentru salvarea credentialelor WIFI in eprom #include // librarie folosita pentru salvarea credentialelor MQTT in eprom #include #include #include #include #include // variabilele user si devid sunt incarcate din eprom folosind FS char mqtt_user[9]; char mqtt_devid[5]; // variabile generate cu functia generate_vars, folosind user si devid char mqttPassword[15]; 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.2"; const char* mqttServer = "mqtt.clickhome.ro"; const int mqttPort = 1883; long loopTimer = 900000; // by default trimite temperatura la 15 minute long lastMsg = 0; float loopTemp = 0; int inPin = 5; String mqttMessage; #define ONE_WIRE_BUS D1 // pinul de date folosit la nodeMCU este D1 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() { // daca nu am credentialele MQTT, nu fac nimic, delay 1000 de ore while (String(mqtt_user)=="") { Serial.println("User MQTT invalid!"); delay(3600000000); } // 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("Incerc din nou in 60 de secunde"); delay(60000); } } } void setup() { Serial.begin(115200); //generez variabilele readFS(); 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; // ESP-ul asteapta ca sa fie configurat 2 minute wifi.setConfigPortalTimeout(120); // sta AP 3 minute apoi se reseteaza din nou wifi.setTimeout(180); if (!wifi.autoConnect("ClickHome")) { Serial.println("timeout - going to sleep"); // EU aici nu am inteles ce se intampla ... poate ii punem un delay!! } delay(200); //citesc datele salvate anterior pe FS strcpy(mqtt_user, custom_mqtt_user.getValue()); strcpy(mqtt_devid, custom_mqtt_devid.getValue()); //genereaza topicurile de mqtt in baza mqtt_user si mqtt_devid generate_vars(); reconectez(); //setez functia care parseaza mesajele venite prin mqtt client.setCallback(getMessage); pinMode(inPin, INPUT); sensors.begin(); } void getMessage(char* topic, byte* payload, unsigned int length) { float t = 0; mqttMessage=""; Serial.print("Mesaj primit pe topicul: "); Serial.println(topic); Serial.print("Mesaj:"); for (int i = 0; i < length; i++) { mqttMessage += (char)payload[i]; } Serial.println(mqttMessage); // daca primeste 'temp' pe mqtt, 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); } // daca primeste 'reset' pe mqtt, isi da reset if (mqttMessage == "reset") { String lastwords="Am fost resetat ..."; client.publish(mqttESP, lastwords.c_str(), TRUE); delay (3000); ESP.reset(); delay (5000); } // daca primeste 'update' isi face 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 primeste valoarea in minute seteaza loopTimer si-l trimite in DB if (mqttMessage == "debug") { loopTimer=30000; client.publish(mqttESP, " {\"LoopInterval\":\"30 secunde\"}",TRUE); } if (mqttMessage == "10") { loopTimer=600000; client.publish(mqttESP, " {\"LoopInterval\":\"10 minute\"}",TRUE); } if (mqttMessage == "15") { loopTimer=900000; client.publish(mqttESP, " {\"LoopInterval\":\"15 minute\"}",TRUE); } if (mqttMessage == "30") { loopTimer=1800000; client.publish(mqttESP, " {\"LoopInterval\":\"30 de minute\"}",TRUE); } if (mqttMessage == "60") { loopTimer=3600000; client.publish(mqttESP, " {\"LoopInterval\":\"o ora\"}",TRUE); } if (mqttMessage == "stop") { loopTimer=3600000000; // setez sa nu trimita valori, 1000 de ore client.publish(mqttESP, " {\"LoopInterval\":\"oprit\"}",TRUE); } } void readFS() { 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 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"); } } void loop() { if (!client.connected()) { reconectez(); } client.loop(); long now = millis(); if (now - lastMsg > loopTimer) { lastMsg = now; sensors.setResolution(12); sensors.requestTemperatures(); 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); } } }