MQTT disconnects - Tried keepalive but no go. ESP8266 Board

Hi guys.
I have the same connection problem, identical to you. What changes is that I use the Arduino Mega with an ENC28j60 ethernet board. I actually use two Arduino Mega boards each with the ENC28j60 ethernet. The two have practically the same Scheduler, carrying one of them after a few touches on the switches or using the HA for some command disconnects, the other card is stable and working perfectly. I have already changed the plates, I have rewritten the codes, I have left only one connection on the network, I have done the cabling inspection, replaced the number of IPs and there is no way to be revolved. Follow my schedule, if anyone can help me. And I use a different name for each board.

#include <PubSubClient.h>
#include <UIPEthernet.h>

byte mac[] = {0x80, 0x7D, 0x3A, 0x69, 0x20, 0xC8 }; //physical mac address
byte ip[] = {192, 168, 0, 202 }; // ip in lan

int botao[] =                    {      11,              12,                10,                 9,              8,                7,            6,                 5,             4,              3,              27,               14,              17,              16,              15,             18,           22,              21,                20,            19,             23,               26,               25,           24        };//PORTAS DOS INTERRUPTORES
int rele[] =                     {      A11,             A10,               A12,               A13,            A14,              A15,           A6,               A5,             A4,             A3,             49,               48,              45,              46,              47,             44,           40,              41,                42,            43,             39,               36,               37,           38        }; //PORTAS DOS RELES
const char* TOPIC_PUBLISH [] =   {"ha/v_principal","ha/v_cabeceira",  "ha/v_acessoria", "ha/c_principal", "ha/c_acessoria", "ha/c_parede", "ha/q_principal", "ha/q_parede", "ha/q_entrada", "ha/q_esquerda", "ha/q_direita", "ha/q_arandela", "ha/m_principal", "ha/m_acessoria", "ha/m_parede", "ha/m_sacada", "ha/lustre", "ha/jantar_indireta", "ha/s_indireta", "ha/mezanino", "ha/v_sacada", "ha/porta_arandela", "ha/calcada", "ha/j_frente"  };
String strTopic []=              {"ha/v_principal","ha/v_cabeceira",  "ha/v_acessoria", "ha/c_principal", "ha/c_acessoria", "ha/c_parede", "ha/q_principal", "ha/q_parede", "ha/q_entrada", "ha/q_esquerda", "ha/q_direita", "ha/q_arandela", "ha/m_principal", "ha/m_acessoria", "ha/m_parede", "ha/m_sacada", "ha/lustre", "ha/jantar_indireta", "ha/s_indireta", "ha/mezanino", "ha/v_sacada", "ha/porta_arandela", "ha/calcada", "ha/j_frente"  };
String Switch[] =                {  "v_principal" ,  "v_cabeceira" ,   "v_acessoria"  ,  "c_principal"  ,   "c_acessoria" ,   "c_parede" ,  "q_principal"  ,  "q_parede"  ,   "q_entrada" ,   "q_esquerda" ,  "q_direita"  ,   "q_arandela" ,   "m_principal" ,   "m_acessoria" ,   "m_parede" ,   "m_sacada" ,   "lustre" ,   "j_indireta"      ,   "s_indireta" ,   "mezanino" ,  "v_sacada"  ,   "porta_arandela" ,  "calcada"  ,   "j_frente"   };
boolean statusrele[] =           {        1,              2,                3,                  4,              5,                 6,            7,                8,             9,              10,             11,                12,              13,              14,             15,              16,          17,              18,                 19,            20,             21,              22,               23,           24,       };
static unsigned long debounceInterruptor[]={1,            2,                3,                  4,              5,                 6,            7,                8,             9,              10,             11,                12,              13,              14,             15,              16,          17,              18,                 19,            20,             21,              22,               23,           24,       };
  
int relecont = 24; // NR DE PORTAS USADAS RELES OU INTERRUPETORES PARA O INDICE (i)
int i;

const char* mqtt_server = "192.168.xxx.xxx";
const char* mqttUser = "amkoxxxxxx";
const char* mqttPassword = "xxxxxxxxx";

EthernetClient espClient;
PubSubClient client(espClient);

String strTopic1;
String strPayload;



void interruptor(int i)  // FUNCAO PARA LIGAR/DESLIGAR LAMPADAS
{
   for (int i = 0; i < relecont; i++){
   if (  (millis() - debounceInterruptor[i]) > 30 ) {
    if((digitalRead(botao[i]) == HIGH))
    {
      while(digitalRead(botao[i]) == HIGH){};
        digitalWrite(rele[i],!statusrele[i]);
        statusrele[i] = !statusrele[i];
        if (statusrele[i]==false){
        client.publish(TOPIC_PUBLISH[i], "OFF");}
         if (statusrele[i]==true){
        client.publish(TOPIC_PUBLISH[i], "ON");}
       delay(350);
    }
   }
   }
   
   }


void setup_inicio() {

 
 Serial.begin(115200);
  delay(100);
 
   Ethernet.begin(mac,ip);
}

void callback(char* topic, byte* payload, unsigned int length) {
  payload[length] = '\0';
  strTopic1 = String((char*)topic);

  for (int i = 0; i < relecont; i++) 
{
  if(strTopic1 == strTopic[i])
    {
    Switch[i] = String((char*)payload);
    if(Switch[i] == "ON")
      {statusrele[i] = true;
        Serial.println("ON");
        digitalWrite(rele[i], HIGH);
        delay(350);
      }
    else
      {statusrele[i] = false;
        Serial.println("OFF");
        digitalWrite(rele[i], LOW);
        delay(350);
      }
    }
}
}
 
void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect("arduinoClientSuperior",mqttUser, mqttPassword)) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      client.subscribe("ha/#");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      
      delay(5000);
    }
    
  }
  
}
 
void setup()
{
Serial.begin(115200);
for (int i = 0; i < relecont; i++) 
{
  pinMode(rele[i],OUTPUT); //DEFINI PORTAS RELE COMO PORTA DE SAIDA
  pinMode(botao[i],INPUT); //DEFINE PORTAS DE INTERRUPTORES COMO PORTA DE ENTRADA
  digitalWrite(rele[i],HIGH); // DEFINIE ESTADO HIGH PARA PORTAS DE RELE
  statusrele[i] = true; // DEFINE O STATUS RELE COMO TRUE  
 }



 
  setup_inicio(); 
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
  


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


      
}

Suggest you to make your own thread @amkochaki as my thread was years ago.

1 Like

Hi @amkochaki,

which keepalive did you configure in PubSubClient?
I used it a while ago in ESP8266 and could mitigate this issue by switching to ArduinoMQTT but I think your problem is a more basic one.

Here is a list of findings regarding the posted code:

  1. You call Serial.begin() twice
  2. You use a global variable i that is not initialized.
  3. You use local scope variable i in for loops which is not a good practice.
  4. You pass global i into interruptor but for uses a local scoped i
  5. What is the purpose of the delay in interruptor?
  6. I’d avoid using delay() in the MQTT callback since it blocks MQTT loop. Also I do not see the use case for that.

Assumption:
Depending on the number of MQTT callbacks I assume that your keep alive expires.
interruptor delay() alone sums up to 8.4 seconds every loop. (relecont = 24 x 350 ms)

Recommendation:
In a first step I’d just add some timestamps to measure the time between the client.loop calls to see if this is the issues.
In a second step I’d change the code to strictly avoid the usage of delay().

P.S. I read this on my mobile so I might have missed something in the code due to the small screen.

Hi @eXtatic
Thanks for your return

I removed all the delays and left a delay (100) in the loop for, because without this the switch on the Arduino doesn’t work properly. Programming in this way worked better. I accessed the PuSubClient.h library and can see the following: #define MQTT_KEEPALIVE 15 and #define MQTT_SOCKET_TIMEOUT 15 the two items were 15 seconds old KEEPALIVE I changed to 60 and MQTT_SOCKET_TIMEOUT I put 80 for the purposes of these, it took a breather when disconnecting, I can switch on and off my lamps, but after 80 seconds the disconnection happens. What I don’t understand is that I have the same programming in another square that works perfectly, I have already tested it only with a connected board but even then disconnections occur.

I did some more tests regarding the disconnections by timeout, I put an Arduino mega Wifi and the disconnections remained the same, but I noticed some things, for example if I modify the state of the lamps in a slower way, that is, by spacing the time with each lamp that ascending the connection remains alive for longer, if I do it quickly the disconnection is instantaneous. The switches in position zero and position 17 of ARRAY [] never disconnect the board or if I can turn it off very quickly that the Arduino Mega remains connected with the broker. I tried to use the ArduinoMqtt Library but I confess that I didn’t understand them very well. I keep looking for a solution to my problem.

hello
merry Christmas
kindly asking, if you solve your problem please leave a comment on this post

hello,
have you find a solution to the problem ?
I am keep getting the following and it drives me mad.

1609092244: New client connected from 192.168.70.161 as plant-esp32 (p2, c1, k60, u'local-user').
1609092335: Client plant-esp32 has exceeded timeout, disconnecting.

Olá
Sim consegui resolver meu problema. Era a fonte de energia que alimentava. Os fios negativos da fonte do arduino deve estar ligados ao fio negativo da fonte de energia do raspberry. No meu caso isso resolveu o problema. Pelo que vi voce está usando um esp32 é wifi então nao sei comutar as fontes de energia resolveria o problema.

This really leads me to wonder how many people are here solely for plant and garden use. Im one of them! (Also have experienced a never ending headache with mqtt disconnects and reconnects lately, not sure how it went away, wish I could help.)

have you found a solution?

Yes. The solution was to call the client.loop() and to also send a message to keep the client active once every 60 seconds. Doesn’t matter what channel (doesn’t ahve to be your sensor data) just a /status channel

it took me a while to realize where my mistakes was.
And it took me a while to realize that I was looking at the wrong place.

My original problem was the following:

I thought that the problem was on HA or the MQTT server which is running at my HA instance.
I was so wrong.

The problem occurrs because I was running on a battery and to save energy I was using deep sleep mode.
So far so good.

I was sleeping too long :slight_smile:
This was the problem as I was using deep sleep for 3600s

This was the main problem and the client.loop() couldn’t run as the esp was in deep sleep mode.
I gave up battery scenario as my 18650 battery was running out too fast.
(even though I had optimize almost everything)

I would love to hear your experiences.
Is there someone out there who can tell us how to sleep for such a long time and keep the connection with MQTT open?

I think it is not possible.
But even if it is, I can’t figure out how to achieve it.

If you have a mqtt sketch and you are using long deep sleep mode I would love to hear how do you keep the connection open?

You can’t sleep AND maintain a connection to a server. When the device is asleep it cannot communicate, it is essentially off. When it wakes up it will reconnect.

so how to make a proper disconnect and then a new proper reconnect when it awakes ?

Call disconnect() before you go to sleep.

do you mean mqttclient.disconnect() ???

https://pubsubclient.knolleary.net/api

I found this video as a problem solver, This may help you. All MQTT Errors explained very well and Suggester Different troubleshooting techniques https://youtu.be/CbodTTk-D18

Hi ,
I am a new user to home assistant. I also have 2x mega and 2x Wiznet 5100 ethernet shields.
I want to use your code.
However, my main conclusion was that my coding knowledge was not very low. I want to use your code only as output. And if possible, I want to use all the allowed and stable pins of the Arduino.
I would be very happy if you could help me translate the code in this way in the home assistant. Thank you in advance for your valuable help :pray:

HA your Arduinos like me. My advice to friends who have difficulty integrating

If you have deficiencies in coding like me, you can get this done with a little help from chatGPT.

@dawidchyrzynski
Thank you again for your efforts. I easily integrated my system consisting of Arduino Mega + Ethernet Shield HA and it works very well.