MQTT connection is not STABLE! Any suggestion?

I found a code online to control a LED using ESP8266 so I modified that code to control two LEDs and that’s it. The purpose of this project was to test the connection stability and so far the system is not stable at all, so before we go further let me describe the system components first:

  • HA (installed in a VM) to control the LEDs.

  • I’m using a TPLINK mesh router, so the esps and the HA are connected to that router.

  • ESP8266 - D1 - mini.

On the HA side, the configuration.yaml file as following:

# Light
light:
  - platform: mqtt
    name: 'Office lamp'
    state_topic: 'home/office/light1/status'
    command_topic: 'home/office/light1/switch'
    optimistic: false
    qos: 1
    retain: true
    
  - platform: mqtt
    name: 'Office main'
    state_topic: 'home/office/light2/status'
    command_topic: 'home/office/light2/switch'
    optimistic: false
    qos: 1
    retain: true

Since the connection wasn’t stable, I tried to change the QoS and the problem still there. At the beginning I did a couple of tests to test the stability, and one of these tests was:
“press the reset button on the esp to reboot and while you pressing change the led state by clicking on it once”.
Sometime the esp after reboot is not reachable (from the dashboard I mean, if you tried to change the led state it’s not responding). At the beginning I thought my shitty code was the problem so I decided to test the previous code again (the online code) and I got the same results.

The next thing came to me was “BECAUSE OF THE ROUTER” so I decided to build a local network and it was not the problem.
“Maybe because of the library” so I tried to use a different library and it gave me the same result. When you check the MQTT logs you will see the esp is connected, so why I can’t control it?
Suddenly I decided to open wireshark to see what is going on, for some reason you will see that the HA tried to ‘re transmit’ the packet again and again (something related to the SYN) and you will see also the HA (or the broker) ping the esp and the esp send the response back, hah??


#include <ESP8266WiFi.h>
#include <PubSubClient.h>

#define MQTT_VERSION MQTT_VERSION_3_1_1

const PROGMEM uint8_t LED_PIN = D1;
const PROGMEM uint8_t LED2_PIN = D2;

// Wifi: SSID and password
const char* WIFI_SSID = "xxxxxxxx";
const char* WIFI_PASSWORD = "xxxxxxxx";

// MQTT: ID, server IP, port, username and password
const PROGMEM char* MQTT_CLIENT_ID = "office_light1";
const PROGMEM char* MQTT_CLIENT2_ID = "office_light2";
const PROGMEM char* MQTT_SERVER_IP = "192.168.68.143";
const PROGMEM uint16_t MQTT_SERVER_PORT = 1883;


// MQTT: topics
const char* MQTT_LIGHT_STATE_TOPIC = "office/light1/status";
const char* MQTT_LIGHT_COMMAND_TOPIC = "office/light1/switch";

const char* MQTT_LIGHT2_STATE_TOPIC = "office/light2/status";
const char* MQTT_LIGHT2_COMMAND_TOPIC = "office/light2/switch";

// payloads by default (on/off)
const char* LIGHT_ON = "ON";
const char* LIGHT_OFF = "OFF";


boolean m_light_state = false; // light is turned off by default
boolean m_light2_state = false; // light is turned off by default

WiFiClient wifiClient;
PubSubClient client(wifiClient);

//Function to publish Office light state
void    publishLightState(uint8_t TopicCase) {
    switch(TopicCase) {
        case    1:
            if(m_light_state)
                client.publish(MQTT_LIGHT_STATE_TOPIC, LIGHT_ON, true); 
            else
                client.publish(MQTT_LIGHT_STATE_TOPIC, LIGHT_OFF, true);
        break;

        case    2:
            if(m_light2_state)
                client.publish(MQTT_LIGHT2_STATE_TOPIC, LIGHT_ON, true); 
            else
                client.publish(MQTT_LIGHT2_STATE_TOPIC, LIGHT_OFF, true);
        break;

        default:
        break;
    }
}

void    setLightState(uint8_t SwitchCase) {
    switch(SwitchCase) {
        case    1:
            if(m_light_state) {
                digitalWrite(LED_PIN, HIGH);
                Serial.println("INFO: Desk light is ......... ON"); }
            else {
                digitalWrite(LED_PIN, LOW);
                Serial.println("INFO: Desk light is ......... OFF"); }
        break;

        case    2:
            if(m_light2_state) {
                digitalWrite(LED2_PIN, HIGH);
                Serial.println("INFO: Main light is ......... ON"); }
            else {
                digitalWrite(LED2_PIN, LOW);
                Serial.println("INFO: Main light is ......... OFF"); }
        break;

        default:
        break;
    }
}

// function called when a MQTT message arrived
void callback(char* p_topic, byte* p_payload, unsigned int p_length) {
  // concat the payload into a string
  String payload;
  for (uint8_t i = 0; i < p_length; i++) {
    payload.concat((char)p_payload[i]);
  }
  //Serial.print("CallBack function: payload is ............. ");
  //Serial.println(payload);

  // handle message topic
  if (String(MQTT_LIGHT_COMMAND_TOPIC).equals(p_topic)) {
    // test if the payload is equal to "ON" or "OFF"
    if (payload.equals(String(LIGHT_ON))) {
      if (m_light_state != true) {
        m_light_state = true;
        setLightState(1);
        publishLightState(1);
      }
    } else if (payload.equals(String(LIGHT_OFF))) {
      if (m_light_state != false) {
        m_light_state = false;
        setLightState(1);
        publishLightState(1);
      }
    }
  }

  else if (String(MQTT_LIGHT2_COMMAND_TOPIC).equals(p_topic)) {
    // test if the payload is equal to "ON" or "OFF"
    if (payload.equals(String(LIGHT_ON))) {
      if (m_light2_state != true) {
        m_light2_state = true;
        setLightState(2);
        publishLightState(2);
      }
    } else if (payload.equals(String(LIGHT_OFF))) {
      if (m_light2_state != false) {
        m_light2_state = false;
        setLightState(2);
        publishLightState(2);
      }
    }
  }
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.println("INFO: Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect(MQTT_CLIENT_ID)) {
      Serial.println("INFO: connected");
      // Once connected, publish an announcement...
      publishLightState(1);
      // ... and resubscribe
      client.subscribe(MQTT_LIGHT_COMMAND_TOPIC, 1);
    } else {
      Serial.print("ERROR: failed, rc=");
      Serial.print(client.state());
      Serial.println("DEBUG: try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }

    if (client.connect(MQTT_CLIENT2_ID)) {
      Serial.println("INFO: connected");
      // Once connected, publish an announcement...
      publishLightState(2);
      // ... and resubscribe
      client.subscribe(MQTT_LIGHT2_COMMAND_TOPIC, 1);
    } else {
      Serial.print("ERROR: failed, rc=");
      Serial.print(client.state());
      Serial.println("DEBUG: try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void setup() {
  // init the serial
  Serial.begin(115200);

  // init the led
  pinMode(LED_PIN, OUTPUT);
  pinMode(LED2_PIN, OUTPUT);
  analogWriteRange(255);
  setLightState(1);
  setLightState(2);

  // init the WiFi connection
  Serial.println();
  Serial.println();
  Serial.print("INFO: Connecting to ");
  WiFi.mode(WIFI_STA);
  Serial.println(WIFI_SSID);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("INFO: WiFi connected");
  Serial.print("INFO: IP address: ");
  Serial.println(WiFi.localIP());

  // init the MQTT connection
  client.setServer(MQTT_SERVER_IP, MQTT_SERVER_PORT);
  client.setCallback(callback);
}

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
}

This is the code for the esp and below you will find a snapshot for the wireshark. As you can see (packet #8188) after many trails I was able to control the LEDs, and below you will see (packet #8758, the selected) the publish message (the esp respond), unfortunately it’s not possible to upload the PCAP file here.

Appreciate your help guys.


I couldn’t upload the first picture before since I’m new user and I’m not allowed to upload so here you go.

I think you chose the wrong category for your topic. “Share your Projects” is for sharing something you have created, not for resolving problems. I suggest you change the category to Configuration.

It’s my fault sorry for that

Rather than use some code that you found, why not use esphome? It can be setup for mqtt and it’s known to work without problems. You will also have additional logs and sensor options to monitor the connection at the esp.

@Mikefila thanks for suggestion, actually there is a reason behind that there are some things that are impossible to implement in ESPHome, I know a lot of great things there but like I said it is not possible to achieve what I want to achieve using ESPHome.