ArduinoMQTTClient - How To Reconnect

Hi, I have a Power Monitoring System running on an ESP32 which sends data to PVoutput and also MQTT (Mosquitto Broker) for use by HomeAssistant running on a Raspberry Pi 4. This all works fine except I have an issue when for whatever reason the MQTT Broker goes down / disconnects that it won't reconnect. I have tried various things I have found online including trying to disconnect Wifi and reconnect and then attempting to reconnect to the MQTT Broker but it doesn't seem to work.

I have attached a cut down version of my program where I have removed almost all the code that is not relevant to WiFi / MQTT connection and sending. Any assistance on how to get the MQTT to reconnect when it disconnects for whatever reason would be appreciated. I send data at 5 minute intervals to MQTT/PVoutput and would like to check it at the start of this routine and attempt a reconnect if necessary and then run through my code (regardless of if MQTT is up or not). If its down then it just doesn't get sent that cycle.

Hope that all makes sense.

// Connectivity Libraries (including MQTT)
#include <WiFi.h>             
#include <WiFiClient.h>
#include <ArduinoMqttClient.h>

// Set Static IP address
IPAddress local_IP(192, 168, 0, 81);
IPAddress gateway(192, 168, 0, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress primaryDNS(192, 168, 0, 1);
const char* ssid = "MySSID";
const char* wifipass = "MyWiFiPASS";
int WiFi_LoopCnt = 0;
long startTime;
long LastMillisMQTTPoll;

//MQTT Required. Need to have a 4 topics (ie. 1 for each sensor)
WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);
const char broker[] = "192.168.0.11";
int mqttport = 1883;
const char topic0[] = "PowerESP32/HouseUsage";
const char topic1[] = "PowerESP32/SolarGeneration";
double MQTTHouseUse;
double MQTTGenerate;

//Needed when using VSCode. All routines / functions need to be declared except Setup and Loop
void WiFiCheck_Func();
void WiFiConnect_Func();
void DataOutput();

void setup()
{
  Serial.begin(115200); 
  if (!WiFi.config(local_IP, gateway, subnet, primaryDNS)) 
  {
    Serial.println("STA Failed to configure");
  }
  WiFiConnect_Func();   //Calling direct as no need to check if WiFi is up
}

void loop()
{
  if ((millis() - LastMillisMQTTPoll) > 30000)  //if MQTT hasn't been polled for 30 seconds do it
  {
    LastMillisMQTTPoll = millis();    
    if (!mqttClient.connected())    //Added this routine section as if MQTT connection is dropped it doesn't attempt to re-establish
    {
      WiFiConnect_Func();   //Disconnect and Reconnect WiFi. See if this resolve current issue
      //The Following didn't work but read that ut appears that the WiFi Stack may need to reset in order to reattempt connect
      /*
      if (!mqttClient.connect(broker, mqttport)) 
      {
        Serial.print("MQTT reconnection error ");
        Serial.println(mqttClient.connectError());
      }
      Serial.println("You're connected to the MQTT broker!");
      */
    }
    mqttClient.poll();
  }

  if ((millis() - LastMillisPVoutput) > PVoutputTimer )
  {
    DataOutput();   //This Routine sends data to PVOutput, HomeAssistant (MQTT)
  }
}

void DataOutput()
{
    LastMillisPVoutput = LastMillisPVoutput + PVoutputTimer;   
    WiFiCheck_Func();   //Checks WiFi and if down calls for reconnect

    MQTTHouseUse = AValueThatHasBeenCalculated(CodeRemoved);
    MQTTGenerate = AValueThatHasBeenCalculated(CodeRemoved);

    mqttClient.beginMessage(topic0);
    mqttClient.print(String(MQTTHouseUse));
    mqttClient.endMessage();
    //THEN HAVE CODE TO SEND DATA TO PVOUTPUT. THIS ALL FUNCTIONS FINE (INCLUDING WIFI/INTERNET DOWN). REMOVED FROM THIS EXAMPLE
}

void WiFiCheck_Func()
{
  if (WiFi.status() != WL_CONNECTED)
  {
    WiFiConnect_Func();   //As WiFi is not connected run WiFi connect code. Will loop multiple times if fails and then restart ESP
  }
}

void WiFiConnect_Func()
{
  WiFi.disconnect();  //When this is called WiFi is likely already disconnected or hasn't yet been connected
  delay (1000); //Added to ensure WiFi Disconnect has fully completed (As sometimes this had failed prior to adding)
  WiFi.begin(ssid, wifipass);   //When reconnecting could use WiFi.reconnect() instead
  startTime = millis();
  while (WiFi.status() != WL_CONNECTED && (millis() - startTime) <= 10000) // try for 10 seconds
  {
    delay(500);
  }
  if (WiFi.status() == WL_CONNECTED)
  {
    //Serial.print("\nWiFi Connected\n");
    WiFi_LoopCnt = 0;   //As want it reset to 0 if it got higher
  } else
  {
    WiFi_LoopCnt ++;
    Serial.print("WiFi Fail. Loop = "); Serial.println(WiFi_LoopCnt);
    if (WiFi_LoopCnt > 10)
    {
      Serial.print("About to reboot as WiFi failed to connect more than 10 times");
      ESP.restart();
    }  
    delay(30000);
    WiFiCheck_Func();   //As want to recheck connection. If this is run its likely down so therefore this routine will then get called again immediately.
  }

  //MQTT  
  mqttClient.setId("PowerESP32");
  mqttClient.setUsernamePassword("MQTT", "MQTTH0me");
  //Serial.print("Attempting to connect to the MQTT broker: ");
  //Serial.println(broker);
  if (!mqttClient.connect(broker, mqttport)) {
    //Serial.print("MQTT connection failed! Error code = ");
    //Serial.println(mqttClient.connectError());
    while (1);
  }
  //Serial.println("You're connected to the MQTT broker!");
}

I may have found a solution to this (however just the early stages so could still be false hope).

I have based it off this https://github.com/arduino-libraries/ArduinoMqttClient/pull/15/files#diff-9530c0a956ea730563bf983afb932f39cbcb4173842d4aaee06d4396f5d3b7dc

I also read elsewhere that the MQTT ID identifier needed to be unique so I also incorporated with the above a incrementing integer on the end of my MQTT ID reconnect routine as follows in case the issue was perhaps that the broker hadn't detected the previous instance had disconnected when the new instance reconnected and therefore was perhaps sensing a conflict and refusing based on this.

int attemptReconnect()
{
  mqttconnectcounter++;  
  mqttID = "PowerESP32-" + String(mqttconnectcounter);
  mqttClient.setId(mqttID);
  if (!mqttClient.connect(broker, mqttport)) 
  {
    Serial.print("MQTT connection failed! Error code = ");
    Serial.println(mqttClient.connectError());
  }
  return mqttClient.connectError(); // return status
}

Like I said it is early days but have intentionally done a update to the MQTT broker software and also shut it down and restarted about 8 minutes later and both times it has reconnected without issue. Also not entirely sure which of the above two changes has made a difference but just thankful it appears to be working.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.