287 lines
9.4 KiB
C++

#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);
}