knolleary / pubsubclient

A client library for the Arduino Ethernet Shield that provides support for MQTT.
http://pubsubclient.knolleary.net/
MIT License
3.81k stars 1.47k forks source link

not able to reconnect to mosquitto once disconnected - timeout #552

Open gnkarn opened 5 years ago

gnkarn commented 5 years ago

im using this code to reconnect, but reconnection never happens successfully after the first disconnect, error code is timeout , on both ends , on broker , and on the esp client .

`void reconnect() { // Loop until we're reconnected WiFi.printDiag(Serial);// debug // Create a random client ID Serial.print("cl_state "); Serial.println(client.state());

    while (!client.connected()) {
            String clientId = SENSORNAME;
            clientId += String(random(0xffff), HEX);
            Serial.print("Attempting MQTT connection...");

            // Attempt to connect
            //  boolean connect (clientID, username, password, willTopic, willQoS, willRetain, willMessage, cleanSession)
            //  if (client.connect(clientId.c_str())) {
            if (client.connect(clientId.c_str())) {
                    Serial.println("connected");
                    sendState();
                    client.subscribe(light_set_topic);
                    sendState();
                    delay(100);
                    WiFi.printDiag(Serial); // debug
                    //setColor(0, 0, 0);

            } else {
                    Serial.print("failed, rc=");
                    Serial.print(client.state());
                    Serial.println(clientId.c_str());
                    // Wait 5 seconds before retrying
                    delay(5000);
                    yield();

            }
    }

}`

GithubMystic commented 5 years ago

After a few attempts to reconnect MQTT unsuccesfully, try and reconnect to wIfI and then try to reconnect to MQTT again That works for me. It seems that sometimes the WiFi is not working properly but it does not seem to report the issue to your sketch as being disconnected, so your sketch does not know that there is an issue. Hopefully that workaround will work for you as well

Markusenz commented 5 years ago

I have similar problems here. Several ESP8266 are used as MQTT clients, and all of them from time to time stop sending MQTT data, however they still respond to PING so wifi should not be a problem. The code for reconnection is

  if (!client.connected()) {  // ####### MQTT reconnect
    long now = millis();
    if (now - lastReconnectAttempt > 5000) {
      lastReconnectAttempt = now;                         
      if (reconnect()) {       // Attempt to reconnect
        lastReconnectAttempt = 0;
      }
    }
  } else {
    client.loop();     // Client connected
  }

Is there a scenario where reconnect() does not work, what is the recommended way to 100% secure automatic reconnection?

GithubMystic commented 5 years ago

Hi guys. For what it is worth, I have given up on the whole ESP..... range of products for WiFi/MQTT I have spent far too much time trying to debug issues with WiFi/MQTT over time. I have now switched to Raspberry PIs. All my automation servers were already Raspberry Pi 3Bs As an experiment, I just swapped out one of the troublesome ESP32s WiFi/MQTT clients for a Raspberry Pi zero WiFi/MQTT client but made no other changes to my environment and have had this on soak for about a week with a test program that subscribes to a message being sent every second (Node-Red) and sends an MQTT message every second. This has proved to be rock solid and reliable, so clearly the issues lies with the ESP... / WiFi/ MQTT setup. As the Raspberry Pi 3B servers have also been rock solid, I now feel somewhat liberated and wonder why I did not switch over to using only Raspberry Pi devices ages ago. There are also loads of advantages to using RPIs for all your clients. One of these is that you can just SSH to them remotely from anywhere and make changes to the processing script logic (Python scripts in my case) on the fly without. I can even do this from my mobile phone. Yes you can get near to that with the ESP... OTA setup but not easily from an android phone. Overall I am now very pleased with this all RPI based setup. Writing in C and managing conversion between data types,I have always found this a bit of a pain. So much easier doing this in python (ESP... do have teh option for MicroPython, but again, this is limited) For scenarios where I need the performance of a tight loop and processor dedication and the RPI is unable to handle this ( It is a full blown multitasking linux OS), I will use an ESP... as a slave device communicating to the RPI via I2C. So far I have not had an issue as there are so many I2C devices out there that handle all this for me anyway (Example . Light dimmer. Rather than coding this in an ESP... I just use an I2C light dimmer and communicate with it directly fom the RPI client. If anyone has any questions regarding the above, give me a shout and I will try to help. I am just happy to have put all this unreliability behind me (hopefully for good) I hope this will be useful to some of you who are as frustrated as I have been in the past with all this

Markusenz commented 5 years ago

I think many people still need microcontrollers like the ESP's for small sensor applications, maybe even on battery, where a Raspi is not suitable. There are sometimes workarounds needed to get the ESPs stable and self-restarting in case of wifi or power or other failures. (However, what I would like to know is, what is your strategy for a reliable OS/data storage on the Raspi. In the world of home automation where 10's or even 100 devices are working in a home, devices have to run for many years without maintenance, otherwise one had to service failed devices every few days or weeks. I experienced many problems with corrupted SD cards on Raspis, mainly on power failures. Small USB SSDs may be better, but I cannot yet confirm. Any ideas?)

GithubMystic commented 5 years ago

Yes, totally agree that there is a place for ESP... devices, especially for low power battery fed devices, and as I indicated, in circumstances where tight timing is critical and cannot be guaranteed in a full blown time slicing O/S In my automated world, I take a view that wherever I need to site a device, I will probably need power around somewhere near it for other things anyway so no issue there Where I am likely not to have power availabe, like up in my woods where I plan to install a few devices, I have to accept that a lower power device will probably not be suitable anyway for me as it would have to be able to transmit with a fair amount power and if it does, it would have to do so infrequently to conserve battery power, and would also have to get involved with sleep mode, etc... All things that I chose not to have to complicate my life with. In these situations I will install a small solar rechargeable battery that will feed my RPI zero W. I certainly do not want to have to go and replace batteries in all my devices from time to time even if it is once a year (if it even would last that long doing any useful work) Self restarting is not an issue with RPIs. I do this all the time with mine. They boot up at power up and automatically start running the automation scripts needed. RPIs with an OS like Rasbian are far more robust/reliable in software terms. For example you don't even have to consider WiFi and recovery. It is all done for you by the software and is rock solid. One less thing to worry about and not to have to code around. I have spent quite a lot of time around the issue of SD corruption For my RPI servers (ie automation hubs, etc...) I run the OS on a USB HDD drive (No SD card even present). in my case a 1TB drive and I also have it as File server, which means I can log data direct to it from my clients as and when I chose to do so. As these servers are typically more busy that client devices, the USB HDD being so much faster than SD cards help with the speed and throughput of the work going on there. For my clients which could literally be as small as a temperature/light/movement sensor, a USB HDD drive would be an overkill. I experimented with various memory only O/S images available (ie load up in RAM from SD and then run totally in RAM) and though they sort of work, you have support issues as they come, supported by one or two people and then become unsupported. I have chosen to stay with the well supported RASPBIAN route, namely the full one for my servers and the lite one for my clients (again One OS for all my devices making my life easier. I used the lite one as a base for my client images and did a lot of research on this and moved everything that needs to write frequently to run in RAM and turn off anything that writes back to the SD card.This will take care of +/- 99 % of write activity to the SD card, I use 16Gb SD cards and limit the root filesystem to 10Gb or so of which probably only about 2Gb is used, so with the small amount of write activity left on the SD card, the spare 8Gb in the root filestem and assuming that wear leveling is working as it should, it should last probably from 10 to 30 years, by which time I will probably have wanted to upgrade devices with newer more efficient / powerful ones anyway, especially at the rate that technology improvements are progressing (The RPI was introduced in 2012 - just under 7 years, and seehow far it has already come) What I like most of all is that I can just sit at my PC in my nice cosy home office and remote access every single device as if I was sitting in front of it. No need to ever visit the actual device unless I have to do anything with the physiacl implementation of it So far the above setup seems to be working very well, and I have been quite brutal in that I usually forget to shutdown the OS before powering it off, So far I have had no corruptions ... I hope the above helps you Let me know if you would like more information

On Fri, Jan 25, 2019 at 6:43 PM Markusenz notifications@github.com wrote:

Thanks for all your work! I think many people still need microcontrollers like the ESP's for small sensor applications, maybe even on battery, where a Raspi is not suitable. There are sometimes workarounds needed to get the ESPs stable and self-restarting in case of wifi or power or other failures. (However, what I would like to know is, what is your strategy for a reliable OS/data storage on the Raspi. In the world of home automation where 10's or even 100 devices are working in a home, devices have to run for many years without maintenance, otherwise one had to service failed devices every few days or weeks. I experienced many problems with corrupted SD cards on Raspis, mainly on power failures. Small USB SSDs may be better, but I cannot yet confirm. Any ideas?)

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/knolleary/pubsubclient/issues/552#issuecomment-457678383, or mute the thread https://github.com/notifications/unsubscribe-auth/AsJ1f8JyvSUKnEqeodXcKWxB-n5oTcEEks5vG1BZgaJpZM4ZgfiG .

sprior commented 5 years ago

See if this helps you: https://github.com/knolleary/pubsubclient/issues/566 Here's the pull request: https://github.com/knolleary/pubsubclient/pull/567

I'm not sure of this, but it seems logical.

philbowles commented 5 years ago

@ GithubMystic "so clearly the issues lies with the ESP... / WiFi/ MQTT setup." That's a huge (and incorrect) assumption: there's an obvious alternative - and in my experience 99% of the time it's the real cause: a lot of people are unable to master the particular foibles of that combination. I have code that runs perfectly and is rock solid for days on end, chucking tons of stuff through mosquitto ...it automatically reconnects on failure of WiFi or restart of MQTT server....

But I also see a ton or really bad code "out there". In fact I'd say most of what I see isn't written properly for the ESP8266 / WiFI / MQTT scenario...mostly in that it has all the kind of problems described here...

"A bad workman blames his tools"

sebashb commented 4 years ago

@philbowles Could you please share your code? Right now I'm trying to put everything working with mosquitto, and I have actually managed to do it. But I can only publish to the topics once every 200 ms, since the publishing function (publishing to 5 topics) takes 200+ ms to run.

I'm using a Teensy 3.2 connected to an ESP8266 with PubSub Client library.

Thanks in advance.

tavdog commented 3 years ago

@philbowles Yes, it would great to see some code that can actually reconnect. None of my esps can ever reconnect and require a full restart to re-establish the mqtt connection to mosquitto even though WiFi is up during the reconnect process. This is what's happening to me on esp8266

Got new data
brightness: 1
in max show_data. . .night mode inactive
rx_callback
Message topic: [maui/wind] ENE 57 27g31 , 0.7f,5s,E85 - 2021-07-10T14:57:07+444444444544444455555444545555544443
done.
Attempting MQTT connection...client id : Tron-ECFABCC114CD
failed, rc=-2 waiting 5+ seconds
Attempting MQTT connection...client id : Tron-ECFABCC114CD
failed, rc=-2 waiting 5+ seconds
Attempting MQTT connection...client id : Tron-ECFABCC114CD
failed, rc=-2 waiting 5+ seconds
Attempting MQTT connection...client id : Tron-ECFABCC114CD
Trying WiFi.reconnect()wifi is connected
failed, rc=-2 waiting 5+ seconds
Attempting MQTT connection...client id : Tron-ECFABCC114CD
Trying WiFi.reconnect()wifi is connected
failed, rc=-2 waiting 5+ seconds
Attempting MQTT connection...client id : Tron-ECFABCC114CD
Trying WiFi.reconnect()wifi is connected
failed, rc=-2 waiting 5+ seconds
config url : http://gt.wildc.net:8080/api/v1/gt_ECFABCC114CD/attributes
http://gt.wildc.net:8080/api/v1/gt_ECFABCC114CD/telemetry
telem_code: 200

 ets Jan  8 2013,rst cause:2, boot mode:(3,6)

load 0x4010f000, len 3584, room 16 
tail 0
chksum 0xb0
sprior commented 3 years ago

I've spent a lot of time developing some IOT code that works on both ESP8266 and ESP32 and is very modular, It takes nothing but ifdefs to compile the same Arduino project to be a sensor which reports temp/humidity to a "display" server which controls Neopixels or an LCD or OLED. And individual features like MQTT, web interface, OTA can all be enabled/disabled with an ifdef. So while I won't share all of that I will share the MQTT and Wifi part. There will be references to other pieces you'll have to work around. I'm not saying that any of this is perfect, but it's been stable for weeks/months on devices.

mqtt_control.h

`#pragma once

include "Settings.h"

if defined(ENABLE_MQTT)

include "FS.h"

include

struct MQTTConfig { String mqtt_server; int mqtt_port; String mqtt_sub_topic; String mqtt_log_topic; String mqtt_notify_start_topic;

if defined(ENABLE_SENSORS)

     String mqtt_pub_topic;
     String top_of_mqtt_path;
  #endif

}; extern MQTTConfig mqtt_config;

void parseMQTTConfigLine(String line); void writeMQTTSettings(File &f); void setupMQTTTopic(); void setupPubSubServer(); void handleMQTT(bool inSetup); void reconnect(bool inSetup); void possiblyUpdateSubscription(String oldTopic, String newTopic); void publishSubscription(bool inSetup); bool fillInMQTTJSONConfig(JsonDocument &obj);

if defined(USE_SCREEN) || defined(USE_NEOPIXEL)

void publishImageLoadComplete();

endif

void publishMQTTMessage(const char topic, const char message); void publishMQTTMessage(String topic, String message);

endif

`

mqtt_control.cpp

`#include

include "Settings.h"

if defined(ENABLE_MQTT)

include "Status.h"

include

if defined(ESP8266)

include

elif defined(ESP32)

include

endif

if defined(ENABLE_DISPLAY)

include "DisplayConfig.h"

include

endif

if defined(ENABLE_SENSORS)

include "SensorConfig.h"

endif

if defined(ENABLE_REDIS)

include "redis_control.h"

endif

if defined(ENABLE_SYSLOG)

include "syslog_client.h"

endif

include "mqtt_control.h"

include "json_cmd.h"

MQTTConfig mqtt_config = { DEFAULT_MQTT_BROKER, DEFAULT_MQTT_PORT, DEFAULT_MQTT_SUBSCRIBE_TOPIC, DEFAULT_MQTT_LOG_TOPIC, ""

if defined (ENABLE_SENSORS)

  ,
  "",
  ""

endif

};

void callback(char topic, byte payload, unsigned int length); void possiblyUpdateSubscription(String oldTopic, String newTopic); void publishSubscription(bool inSetup);

static WiFiClient espClient; static PubSubClient pubSubClient(espClient);

void parseMQTTConfigLine(String line){ if (line.indexOf("mqtt_server=") >= 0) { mqtt_config.mqtt_server = line.substring(line.lastIndexOf("mqtt_server=") + 12); mqtt_config.mqtt_server.trim(); Serial.println("mqtt_server=" + mqtt_config.mqtt_server); } if (line.indexOf("mqtt_port=") >= 0) { String temp = line.substring(line.lastIndexOf("mqtt_port=") + 10); temp.trim(); mqtt_config.mqtt_port = temp.toInt(); Serial.println("mqtt_port=" + String(mqtt_config.mqtt_port)); } if (line.indexOf("mqtt_sub_topic=") >= 0) { mqtt_config.mqtt_sub_topic = line.substring(line.lastIndexOf("mqtt_sub_topic=") + 15); mqtt_config.mqtt_sub_topic.trim(); Serial.println("mqtt_sub_topic=" + mqtt_config.mqtt_sub_topic); } if (line.indexOf("mqtt_log_topic=") >= 0) { mqtt_config.mqtt_log_topic = line.substring(line.lastIndexOf("mqtt_log_topic=") + 15); mqtt_config.mqtt_log_topic.trim(); Serial.println("mqtt_log_topic=" + mqtt_config.mqtt_log_topic); }

if defined(ENABLE_SENSORS)

  if (line.indexOf("mqtt_pub_topic=") >= 0) {
     mqtt_config.mqtt_pub_topic = line.substring(line.lastIndexOf("mqtt_pub_topic=") + 15);
     mqtt_config.mqtt_pub_topic.trim();
     Serial.println("mqtt_pub_topic=" + mqtt_config.mqtt_pub_topic);
  }

endif

}

void writeMQTTSettings(File &f){ f.println("mqtt_server=" + mqtt_config.mqtt_server); f.println("mqtt_port=" + String(mqtt_config.mqtt_port)); f.println("mqtt_sub_topic=" + mqtt_config.mqtt_sub_topic); f.println("mqtt_log_topic=" + mqtt_config.mqtt_log_topic);

if defined(ENABLE_SENSORS)

  f.println("mqtt_pub_topic=" + mqtt_config.mqtt_pub_topic);

endif

}

void handleMQTT(bool inSetup){ if (!pubSubClient.connected()) { reconnect(inSetup); } pubSubClient.loop(); }

void setupPubSubServer(){ Serial.println("setting MQTT buffer size to 2048"); pubSubClient.setBufferSize(2048); Serial.println("setting MQTT server: " + mqtt_config.mqtt_server + " port: " + mqtt_config.mqtt_port); pubSubClient.setServer(mqtt_config.mqtt_server.c_str(), mqtt_config.mqtt_port); pubSubClient.setCallback(callback); }

void callback(char topic, byte payload, unsigned int length) { char buffer = (char) malloc (length+1); memcpy( buffer, payload, length ); buffer[length] = '\0'; / null character manually added /

Serial.print("Message arrived ["); Serial.print(topic); Serial.print("] "); Serial.println(buffer);

if defined(ENABLE_DISPLAY)

  jsonCmd(buffer, length);

else

  // Switch on the LED if an 1 was received as first character
  if ((char)payload[0] == '1') {
     locatorLEDOn();
  } else {
     locatorLEDOff();
  }

endif

free(buffer); }

void reconnect(bool inSetup) { // Loop until we're reconnected while (!pubSubClient.connected()) {

if defined(ENABLE_SYSLOG)

     {
        String message = "MQTT not connected, attempting connection: ";
        message += pubSubClient.state();

        uint16_t pri = inSetup ? SyslogConfig::P_DEBUG : SyslogConfig::P_ERR;
        syslog_log(pri, message);
     }
  #elif defined(ENABLE_REDIS)
     {
        String key = "log:";
        key += physical_config.hostname;
        String message = "MQTT not connected, attempting connection: ";
        message += pubSubClient.state();
        redis_lpush(key.c_str() , message.c_str());
     }      
  #endif

  Serial.print("Attempting MQTT connection...");
  String clientId = physical_config.mac_addr;
  // Attempt to connect
  if (pubSubClient.connect(clientId.c_str())) {
     Serial.println("connected.");
     #if defined(ENABLE_SYSLOG)
        {
           String message = "MQTT connected: ";
           message += pubSubClient.state();
           syslog_log(SyslogConfig::P_DEBUG, message);
        }
     #elif defined(ENABLE_REDIS)
        {
           String key = "log:";
           key += physical_config.hostname;
           String message = "MQTT connected: ";
           message += pubSubClient.state();
           redis_lpush(key.c_str() , message.c_str());
        }
     #endif

     possiblyUpdateSubscription("", mqtt_config.mqtt_sub_topic);
     publishSubscription(inSetup);
  } else {
     #if defined(ENABLE_SYSLOG)
        {
           String message = "MQTT connect failed: ";
           message += pubSubClient.state();
           syslog_log(SyslogConfig::P_ERR, message);
        }
     #elif defined(ENABLE_REDIS)
        {
           String key = "log:";
           key += physical_config.hostname;
           String message = "MQTT connect failed: ";
           message += pubSubClient.state();
           redis_lpush(key.c_str() , message.c_str());
        }
     #endif
     Serial.print("failed, rc=");
     Serial.print(pubSubClient.state());
     Serial.println(" try again in 5 seconds");
     // Wait 5 seconds before retrying
     delay(5000);
  }

} }

void possiblyUpdateSubscription(String oldTopic, String newTopic){ if (newTopic.equals(oldTopic)){ return; } if (!oldTopic.equals("")){ pubSubClient.unsubscribe(oldTopic.c_str()); Serial.print("unsubscribed topic: "); Serial.println(oldTopic); } if (!newTopic.equals("")){ pubSubClient.subscribe(newTopic.c_str()); Serial.print("subscribed topic: "); Serial.println(newTopic); } }

void publishMQTTMessage(const char topic, const char message){ pubSubClient.publish(topic, message); }

void publishMQTTMessage(String topic, String message){ publishMQTTMessage(topic.c_str(), message.c_str()); }

void publishSubscription(bool inSetup){ String logmessage = physical_config.device_category;

if (inSetup){ logmessage += " boot connect: "; } else { logmessage += " reconnect: "; } logmessage += mqtt_config.mqtt_sub_topic; logmessage += " IP addr: "; logmessage += WiFi.localIP().toString(); logmessage += " Location: "; logmessage += physical_config.device_location;

if defined(ENABLE_SYSLOG)

  {
     uint16_t pri = inSetup ? SyslogConfig::P_INFO : SyslogConfig::P_WARNING;
     syslog_log(pri, logmessage);
  }

else

  publishMQTTMessage(mqtt_config.mqtt_log_topic, logmessage);

endif

// publish notify start message publishMQTTMessage(mqtt_config.mqtt_notify_start_topic, getConfigAsJSONString()); }

if defined(USE_SCREEN) || defined(USE_NEOPIXEL)

void publishImageLoadComplete(){ String notifyTopic = "Smarthome/Notify/display/image/load/complete/"; notifyTopic += physical_config.mac_addr; publishMQTTMessage(notifyTopic, "image load complete"); }

endif

void setupMQTTTopic(){

/*

bool fillInMQTTJSONConfig(JsonDocument &mqttJSON){ //JsonObject mqttJSON = obj.createNestedObject("mqtt"); mqttJSON["mqtt_server"] = mqtt_config.mqtt_server; mqttJSON["mqtt_port"] = mqtt_config.mqtt_port; mqttJSON["mqtt_sub_topic"] = mqtt_config.mqtt_sub_topic; mqttJSON["mqtt_log_topic"] = mqtt_config.mqtt_log_topic;

if defined(ENABLE_SENSORS)

  mqttJSON["mqtt_pub_topic"] = mqtt_config.mqtt_pub_topic;

endif

return true; }

endif

`

wifimgr.h

#pragma once void setupWifiMgr(String hostname); String getCurrentSSID();

wifimgr.cpp

`#include

include "Settings.h"

include "SettingsFile.h"

include "Status.h"

if defined(ENABLE_MQTT)

include "mqtt_control.h"

endif

if defined(ENABLE_REDIS)

include "redis_control.h"

endif

if defined(ENABLE_SYSLOG)

include "syslog_client.h"

endif

include

//flag for saving data static bool shouldSaveConfig = false;

void flashLED(int number, int delayTime) { for (int inx = 0; inx < number; inx++) { delay(delayTime); locatorLEDOn(); delay(delayTime); locatorLEDOff(); delay(delayTime); } }

void configModeCallback (WiFiManager *myWiFiManager) { Serial.println("Entered config mode"); Serial.println(WiFi.softAPIP());

Serial.println("Wifi Manager"); Serial.println("Please connect to AP"); Serial.println(myWiFiManager->getConfigPortalSSID()); Serial.println("To setup Wifi Configuration"); flashLED(20, 50); }

//callback notifying us of the need to save config void saveConfigCallback () { Serial.println("Should save config"); shouldSaveConfig = true; }

void setupWifiMgr(String hostname) { WiFi.mode(WIFI_STA); // explicitly set mode, esp defaults to STA+AP

if defined(ENABLE_MQTT)

  WiFiManagerParameter custom_mqtt_server("server", "mqtt server", mqtt_config.mqtt_server.c_str(), 40);
  String mqtt_port_str = String(mqtt_config.mqtt_port);
  WiFiManagerParameter custom_mqtt_port("port", "mqtt port", mqtt_port_str.c_str(), 5);

endif

if defined(ENABLE_REDIS)

  WiFiManagerParameter custom_redis_server("redisserver", "redis server", redis_config.redis_server.c_str(), 40);
  String redis_port_str = String(redis_config.redis_port);
  WiFiManagerParameter custom_redis_port("redisport", "redis port", redis_port_str.c_str(), 5);

endif

if defined(ENABLE_SYSLOG)

  WiFiManagerParameter custom_syslog_server("syslogserver", "syslog server", syslog_config.syslog_server.c_str(), 40);
  String syslog_port_str = String(syslog_config.syslog_port);
  WiFiManagerParameter custom_syslog_port("syslogport", "syslog port", syslog_port_str.c_str(), 5);

endif

WiFiManagerParameter custom_device_location("device_location", "device location", physical_config.device_location.c_str(), 40);

//WiFiManager //Local intialization. Once its business is done, there is no need to keep it around WiFiManager wifiManager;

//set config save notify callback wifiManager.setSaveConfigCallback(saveConfigCallback);

if defined(ENABLE_MQTT)

  wifiManager.addParameter(&custom_mqtt_server);
  wifiManager.addParameter(&custom_mqtt_port);

endif

if defined(ENABLE_REDIS)

  wifiManager.addParameter(&custom_redis_server);
  wifiManager.addParameter(&custom_redis_port);

endif

if defined(ENABLE_SYSLOG)

  wifiManager.addParameter(&custom_syslog_server);
  wifiManager.addParameter(&custom_syslog_port);

endif

wifiManager.addParameter(&custom_device_location);

// Uncomment for testing wifi manager //wifiManager.resetSettings(); wifiManager.setAPCallback(configModeCallback);

//sets timeout in seconds for which to attempt connecting //wifiManager.setConnectTimeout(30);

//sets timeout until configuration portal gets turned off //useful to make it all retry or go to sleep //in seconds // I am adding this so the device will periodically retry in case the ESP came up before the access point after a power failure wifiManager.setConfigPortalTimeout(300);

if (!wifiManager.autoConnect((const char *)hostname.c_str())) {// new addition delay(3000); //WiFi.disconnect(true); ESP.restart(); delay(5000); }

physical_config.device_location = (String)custom_device_location.getValue(); if (shouldSaveConfig) { writeSettingsFile(); } }

String getCurrentSSID(){ WiFiManager wifiManager; return wifiManager.getWiFiSSID(); } `

smarthome_iot.ino

` /**

include "Settings.h"

if defined(ENABLE_DISPLAY)

include "DisplayConfig.h"

if defined(USE_LCD)

  #include "lcd.h"

elif defined(USE_OLED)

  #include "oled.h"

elif defined(USE_NEOPIXEL)

  #include "neopixel.h"

endif

endif

if defined(ENABLE_SENSORS)

include "SensorConfig.h"

include "periodic_publish.h"

endif

include "Status.h"

if defined(ENABLE_MQTT)

include "mqtt_control.h"

endif

if defined(ENABLE_REDIS)

include "redis_control.h"

endif

if defined(ENABLE_SYSLOG)

include "syslog_client.h"

endif

if defined(ENABLE_OTA)

include "ota.h"

endif

if defined(ENABLE_WEBSERVER)

include "webinterface.h"

if defined(ENABLE_MDNS)

  #if defined(ESP8266)
     #include <ESP8266mDNS.h>
  #endif
  #if defined(ESP32)
     #include <ESPmDNS.h>
  #endif

endif

endif

include "wifimgr.h"

include "FS.h"

ifdef ESP32

include

endif

include "SettingsFile.h"

void setup() { Serial.begin(115200); while(!Serial) {} // Wait

//New Line to clear from start garbage Serial.println();

setupMACAddr();

if defined(ENABLE_MQTT)

  setupMQTTTopic();

endif

SPIFFS.begin(); delay(10);

setupLocatorLED();

readSettingsFile(); setupWifiMgr(physical_config.hostname);

// print the received signal strength: Serial.print("Signal Strength (RSSI): "); Serial.print(getWifiQuality()); Serial.println("%");

if defined(ENABLE_REDIS)

  setupRedis();
  String key = "log:";
  key += physical_config.hostname;
  redis_lpush(key.c_str() , "booted");

endif

if defined(ENABLE_OTA)

  setupOTA(physical_config.hostname);

endif

if defined(USE_LCD)

  setupLCD();

elif defined(USE_OLED)

  setupOLED();

elif defined(USE_NEOPIXEL)

  setupNeoPixel(); 

endif

if defined(ENABLE_SENSORS)

 setupSensors();

endif

if defined(ENABLE_WEBSERVER)

  #if defined(ENABLE_MDNS)
     #if !defined(ENABLE_OTA)
        // Set up mDNS responder:
        // - first argument is the domain name, in this example
        //   the fully-qualified domain name is "esp8266.local"
        // - second argument is the IP address to advertise
        //   we send our IP address on the WiFi network
        if (!MDNS.begin(hostname.c_str())) {
           Serial.println("Error setting up MDNS responder!");
           while (1) {
              delay(1000);
           }
        }
        Serial.println("MDNS started.");
     #else
        Serial.println("MDNS should already be started by OTA code.");
     #endif
     Serial.print("mDNS url http://");
     Serial.print(physical_config.hostname);
     Serial.println(".local");
  #else
     Serial.println("mDNS not enabled");
  #endif

  initializeWebServer();
  #if defined(ENABLE_MDNS)
     // Add service to MDNS-SD
     MDNS.addService("http", "tcp", webserver_config.webserver_port);
  #endif

else

 Serial.println("Web Interface is Disabled");

endif

if defined(ENABLE_SYSLOG)

  setupSyslog();

endif

if defined(ENABLE_MQTT)

  setupPubSubServer();

  #if defined(USE_SCREEN)
     displayText("ready for mqtt message");
  #endif
  #if defined(ENABLE_SENSORS)
     setup_periodic_publish();
  #endif
  handleMQTT(true);

endif

}

//**** // Main Looop //**** void loop() {

if defined(ENABLE_WEBSERVER)

  handleWebClient();
  #if defined(ENABLE_MDNS)
     #if defined(ESP8266)
        MDNS.update();
     #endif
  #endif

endif

if defined(ENABLE_OTA)

  handleOTA();

endif

if defined(ENABLE_MQTT)

  handleMQTT(false);

endif

if defined(USE_NEOPIXEL)

  serviceNeoPixel();

endif

if defined(USE_SCREEN) || defined(USE_NEOPIXEL)

  checkForBlankTime();

endif

if defined(ENABLE_SENSORS)

 serviceSensors();
 #if !defined(USE_BUTTONS)  // buttons are an edge triggered sensor, not a state sensor
    service_periodic_publish();
 #endif

endif

} `