#include "MQTT.h" WebServer MQTT::server = WebServer(80); bool MQTT::saveConfigFlag=false; WiFiManagerParameter custom_hostname("hostname", "Hostname", "", 40); WiFiManagerParameter custom_mqtt_server("server", "mqtt server", "", 40); WiFiManagerParameter custom_mqtt_port("port", "mqtt port", "",6); WiFiManagerParameter custom_mqtt_topic("topic", "topic", "", 40); WiFiManagerParameter custom_deftemp("deftemp", "Default Temperature", "", 6); WiFiManagerParameter custom_enbuff("enBuff", "Enable heatBuffer", "", 6); MQTT::MQTT(){ } void MQTT::serveOverride(void){ String sending; sending = "{"; if(server.args() == 1 && glblData.enBuff){ if(server.argName(0)=="SW" || server.argName(0)=="sw"){ if(server.arg(0) == "ON"){ glblData.override = OVR_ALWAYSON; sending = "{\"Status\": \"Success\", "; }else if(server.arg(0) == "OFF"){ glblData.override = OVR_ALWAYSOFF; sending = "{\"Status\": \"Success\", "; }else{ glblData.override = OVR_NONE; sending = "{\"Status\": \"Success\", "; } } }else if(!glblData.enBuff){ sending = "{\"Status\": \"Not Enabled\", "; glblData.override = OVR_NONE; } switch(glblData.override){ case OVR_ALWAYSOFF: sending += "\"Override\": \"Always OFF\"}"; break; case OVR_ALWAYSON: sending += "\"Override\": \"Always ON\"}"; break; case OVR_NONE: sending += "\"Override\": \"NONE\"}"; break; } server.send(404, "text/plain", sending); } void MQTT::serveData(void){ String sending; sending = "{\"Temp[degC]\": "; sending += glblData.temp; sending += ", \"pressure[hPa]\": "; sending += glblData.seaLevelPress; sending += ", \"rHum[%]\": "; sending += glblData.hum; sending += ", \"Heating\": "; sending += glblData.heating; sending += ", \"Set Temp[degC]\": "; sending += glblData.settemp; sending += " }"; Serial.println("Sending website..."); server.send(200, FPSTR(HTTP_HEAD_JSON), sending); Serial.println("Sent website..."); /* request->send(404, "text/plain", sending);*/ } void MQTT::sendStatus(void){ char buffer[10]; snprintf(buffer, sizeof buffer, "%0.1f", glblData.temp); publish_sub("Temp[degC]",buffer); snprintf(buffer, sizeof buffer, "%0.0f", glblData.seaLevelPress); publish_sub("pressure[hPa]",buffer); snprintf(buffer, sizeof buffer, "%0.0f", glblData.hum); publish_sub("rHum[%]",buffer); snprintf(buffer, sizeof buffer, "%s", digitalRead(PIN_REL)?"true":"false"); publish_sub("Heating",buffer); snprintf(buffer, sizeof buffer, "%0.1f", glblData.settemp); publish_sub("Set Temp[degC]",buffer); } void MQTT::begin(){ saveConfigFlag = false; prefs.begin("settings"); prefs.getString("HOST",hostname,40); prefs.getString("MQTT_SERVER",mqtt_server,40); mqtt_port = prefs.getInt("MQTT_PORT",mqtt_port); prefs.getString("MQTT_TOPIC",mqtt_topic,40); defTemp = prefs.getFloat("DEF_TMP",defTemp); enBuff = prefs.getBool("EN_OVR",enBuff); glblData.enBuff = enBuff; ui_settemp(defTemp); prefs.end(); wm.setSaveConfigCallback(MQTT::saveConfigCallback); custom_hostname.setValue(hostname,40); custom_mqtt_server.setValue(mqtt_server,40); custom_mqtt_port.setValue(String(mqtt_port).c_str(),6); custom_mqtt_topic.setValue(mqtt_topic,40); custom_deftemp.setValue(String(defTemp).c_str(),6); custom_enbuff.setValue(String(enBuff).c_str(),6); wm.addParameter(&custom_hostname); wm.addParameter(&custom_mqtt_server); wm.addParameter(&custom_mqtt_port); wm.addParameter(&custom_mqtt_topic); wm.addParameter(&custom_deftemp); wm.addParameter(&custom_enbuff); psclient.setClient(client); psclient.setServer(mqtt_server,mqtt_port); WiFi.setHostname(custom_hostname.getValue()); //define hostname wm.setConfigPortalBlocking(false); if(wm.autoConnect("AutoConnectAP")){ //if you get here you have connected to the WiFi Serial.println("connected...yeey :)"); strcpy(myIP,WiFi.localIP().toString().c_str()); wm.setHttpPort(8080); wm.startWebPortal(); wifiConnected = true; } else { wm.startWebPortal(); Serial.println("non blocking config portal running on Port 80"); } if(wifiConnected){ ArduinoOTA.setHostname(hostname); ArduinoOTA .onStart([]() { String type; if (ArduinoOTA.getCommand() == U_FLASH) type = "sketch"; else // U_SPIFFS type = "filesystem"; // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end() Serial.println("Start updating " + type); }) .onEnd([]() { Serial.println("\nEnd"); }) .onProgress([](unsigned int progress, unsigned int total) { Serial.printf("Progress: %u%%\r", (progress / (total / 100))); }) .onError([](ota_error_t error) { Serial.printf("Error[%u]: ", error); if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed"); else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed"); else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed"); else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed"); else if (error == OTA_END_ERROR) Serial.println("End Failed"); }); ArduinoOTA.begin(); // This is not the safest way to reset the webserver, it can cause crashes on callbacks initilized before this and since its a shared pointer... // @todo add a new callback maybe, after webserver started, callback cannot override handlers, but can grab them first /* Setup httpd callbacks, web pages: root, wifi config pages, SO captive portal detectors and not found. */ // G macro workaround for Uri() bug https://github.com/esp8266/Arduino/issues/7102 server.on("/", MQTT::serveData); server.on("/override", MQTT::serveOverride); server.on("/data", MQTT::serveData); server.begin(); reconnect(); } } void MQTT::saveConfigCallback(void){ Serial.println("SAVE"); saveConfigFlag = true; } void MQTT::saveConfigToFlash(void){ strcpy(mqtt_server,custom_mqtt_server.getValue()); mqtt_port = atoi(custom_mqtt_port.getValue()); strcpy(hostname,custom_hostname.getValue()); strcpy(mqtt_topic,custom_mqtt_topic.getValue()); defTemp = atof(custom_deftemp.getValue()); if(custom_enbuff.getValue() != "0"){ enBuff = true; } glblData.enBuff = enBuff; prefs.begin("settings"); prefs.putString("HOST",hostname); prefs.putString("MQTT_SERVER",mqtt_server); prefs.putInt("MQTT_PORT",mqtt_port); prefs.putString("MQTT_TOPIC",mqtt_topic); prefs.putFloat("DEF_TMP",defTemp); prefs.putBool("EN_OVR",enBuff); prefs.end(); } void MQTT::reconnect(void) { // Loop until we're reconnected Serial.print("Attempting MQTT connection..."); // Attempt to connect if (psclient.connect(hostname)) { Serial.println("connected"); // Subscribe if(strlen(mqtt_topic)>1) psclient.subscribe(mqtt_topic); } else { Serial.print("failed, rc="); Serial.print(psclient.state()); } } void MQTT::loop(void){ unsigned long now = millis(); if(now-lastStatusUpdate > 15000){ //update wifi status every 15secs. lastStatusUpdate = now; if(WiFi.isConnected()){ int32_t rssi = WiFi.RSSI(); if(rssi > -55){ update_wifi_strength(WIFI_STRENGTH_HIGH); }else if(rssi > -75){ update_wifi_strength(WIFI_STRENGTH_MED); }else if(rssi > -90){ update_wifi_strength(WIFI_STRENGTH_LOW); }else{ update_wifi_strength(WIFI_STRENGTH_OFF); } if(!psclient.connected()){ update_wifi_strength(WIFI_STRENGTH_ERROR); if(now-lastReconnectTry > 60000){ lastReconnectTry = now; reconnect(); } } }else{ update_wifi_strength(WIFI_STRENGTH_OFF); } } server.handleClient(); psclient.loop(); ArduinoOTA.handle(); wm.process(); if(saveConfigFlag){ Serial.println("Save Settings"); saveConfigFlag = false; saveConfigToFlash(); Serial.println("disconnect mqtt to activate new settings"); psclient.disconnect(); } } char* MQTT::getMqttServer(void){ return mqtt_server; } uint16_t MQTT::getMqttPort(void){ return mqtt_port; } char* MQTT::getHostname(void){ return hostname; } char* MQTT::getMqttTopic(void){ return mqtt_topic; } char* MQTT::getMyIP(void){ return myIP; } void MQTT::publish(const char* msg){ psclient.publish(mqtt_topic,msg); } void MQTT::publish(const char* msg, unsigned int len){ psclient.publish(mqtt_topic,msg,len); } void MQTT::publish(const char* msg, bool retained){ psclient.publish(mqtt_topic,msg,retained); } void MQTT::publish_sub(const char* subtopic, const char* msg){ char newtopic[60]; strcpy(newtopic,mqtt_topic); strcat(newtopic,"/"); strcat(newtopic,subtopic); psclient.publish(newtopic,msg); }