Attempting MQTT connection...Connected! in loop

Hi all,
I have this code to publish by mqtt and it worked great for month.

#include <EthernetENC.h> //più leggera rispetto UIPEthernet
#include <PubSubClient.h>   

unsigned long mytime = 0;

byte mac[] = {0x80, 0x7D, 0x3A, 0x69, 0x20, 0x99 }; //physical mac address
byte mqtt_ip[] = {mqtt ip}; // ip in lan
const char* mqttUser = "usr";
const char* mqttPassword = "pass";

int updateInterval = 10000; // Interval in milliseconds

EthernetClient espClient;
PubSubClient client(espClient);

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");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void sensors() {    Serial.println("TEST");}
 
void setup()
{
  Serial.begin(115200);
  delay(100);
  Ethernet.begin(mac,{nano ip },{dns },{gw }); //Ethernet.begin(mac, ip, dns, gateway);
  client.setServer(mqtt_ip, 1883);
}
 
void loop()
{
  if (!client.connected()) {    reconnect();  }
  client.loop();
  if (millis()-mytime>updateInterval)
      { mytime=millis(); 
        sensors();
      }
}

The ardware is an arduino nano with enc28j60. I use this to read some sensors connected to the nano and sending the values by mqtt,
Today I resumed this code to add another arduino nano+ enc28j60 but the code remains in loop with this output:
image

I tried with new nano board, new enc28j60 board but doen't work.... the code is always the same, should be an hardware problem?

Do you have another ESP with the same code on your local network?

The code looks like it connects to the MQTT broker okay but you don't seem to be publishing anything to it.

You know the if (client.connect("arduinoClientSuperior",mqttUser, mqttPassword)) will not happen because your while loop will have exited if this condition is true?

yes, but different ip and mac

I know, it's a test

mmm it should be like this:

void reconnect() {
    Serial.print("Attempting MQTT connection...");    // Attempt to connect
    if (client.connect("arduinoClientSuperior",mqttUser, mqttPassword)) {
      Serial.println("connected");
      delay(500);
    }
    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);
  delay(100);
  Ethernet.begin(mac,{192, 168, 0, 17 },{192, 168, 0, 1 },{192, 168, 0, 1 }); //Ethernet.begin(mac, ip, dns, gateway);
  client.setServer(mqtt_ip, 1883);
}
 
void loop()
{
  if (!client.connected()) {    reconnect();  }
  client.loop();
  delay(50);

}

is right?
I also added some delays but the problem ramains....

Here is my code to connect to WiFi

void connectToWiFi()
{
  int TryCount = 0;
  while ( WiFi.status() != WL_CONNECTED )
  {
    TryCount++;
    WiFi.disconnect();
    WiFi.begin( SSID, PASSWORD );
    vTaskDelay( 2500 );
    if ( TryCount == 10 )
    {
      ESP.restart();
    }
  }
  WiFi.onEvent( WiFiEvent );
}

Here is my code to connect to MQTT

void connectToMQTT()
{
  byte mac[5]; // create client ID from mac address
  WiFi.macAddress(mac); // get mac address
  String clientID = String(mac[0]) + String(mac[4]) ; // use mac address to create clientID
  while ( !MQTTclient.connected() )
  {
    MQTTclient.connect( clientID.c_str(), mqtt_username, mqtt_password );
    vTaskDelay( 250 );
  }
  MQTTclient.setCallback( mqttCallback );
  MQTTclient.subscribe( topicOK );
  MQTTclient.subscribe( topicGrpA );
  MQTTclient.subscribe( topicGrpB );
  MQTTclient.subscribe( topicGrpC );
  MQTTclient.subscribe( topicGrpD );
  MQTTclient.subscribe( topicGrpE );
  MQTTclient.subscribe( topicFlash );
} //void connectToMQTT()

Here is my code to maintain a constant WiFi and MQTT connection:

void MQTTkeepalive( void *pvParameters )
{
  sema_MQTT_KeepAlive   = xSemaphoreCreateBinary();
  xSemaphoreGive( sema_MQTT_KeepAlive ); // found keep alive can mess with a publish, stop keep alive during publish
  MQTTclient.setKeepAlive( 90 ); // setting keep alive to 90 seconds makes for a very reliable connection, must be set before the 1st connection is made.
  TickType_t xLastWakeTime = xTaskGetTickCount();
  const TickType_t xFrequency = 250; //delay for ms
  for (;;)
  {
    //check for a is-connected and if the WiFi 'thinks' its connected, found checking on both is more realible than just a single check
    if ( (wifiClient.connected()) && (WiFi.status() == WL_CONNECTED) )
    {
      xSemaphoreTake( sema_MQTT_KeepAlive, portMAX_DELAY ); // !!!!!whiles MQTTlient.loop() is running no other mqtt operations should be in process!!!!!
      MQTTclient.loop();
      xSemaphoreGive( sema_MQTT_KeepAlive );
    }
    else {
      if ( !(wifiClient.connected()) || !(WiFi.status() == WL_CONNECTED) )
      {
        connectToWiFi();
      }
      connectToMQTT();
    }
    xLastWakeTime = xTaskGetTickCount();
    vTaskDelayUntil( &xLastWakeTime, xFrequency );
  }
  vTaskDelete ( NULL );
}
////

Perhaps there are a few things in that code you can use to get your thing do working.

thanks for sharing....
I use ethernet, do I need to check the lan and mqtt connection or only the mqtt?

If the LAN connection has failed then the MQTT connection has failed. If the program is trying to reconnect to the MQTT Broker with a failed LAN connection then how will the Broker connection be re-established?

with this simple sketch I have the same problem:

void reconnect() {
Serial.print("Attempting MQTT connection...");
while ( !client.connected() )
  {
    client.connect("arduinoClientSuperior",mqttUser, mqttPassword);
    delay( 250 );
  }
Serial.println("connected");
}
 
void setup()
{
  Serial.begin(115200);
  delay(100);
  Ethernet.begin(mac,{192, 168, 0, 17 },{192, 168, 0, 1 },{192, 168, 0, 1 }); //Ethernet.begin(mac, ip, dns, gateway);
  client.setServer(mqtt_ip, 1883);
  }
 
void loop()
{
  if (!client.connected()) {    reconnect();  }
  client.loop();
  delay(50);
}

looks like it connects, so exits from while, but it disconnects and the loop call the reconnect() function...

image

If the LAN is disconnected how will this make a MQTT connection when the MQTT connection is DEPENDENT upon the LAN connection?

See that code?

See how there is a check for a WiFi/LAN connection BEFORE client.loop() is ran?

understood....
I'll try to convert the wifi part in ethernet....
Do you know what is the equivalent of this:
(wifiClient.connected()) && (WiFi.status() == WL_CONNECTED)?

No.

There's your problem.

if (client.connect("arduinoClientSuperior",mqttUser, mqttPassword)) {

The client name must be unique on each node on your network. As soon as one connects, it knocks the other offline.

2 Likes

Oi! Missed that. You need unique client names. I use the digits of the mac address to make client id's.

void connectToMQTT()
{
  MQTTclient.setKeepAlive( 90 ); // needs be made before connecting
  byte mac[5];
  WiFi.macAddress(mac);
  String clientID = String(mac[0]) + String(mac[4]) ; // use mac address to create clientID
  while ( !MQTTclient.connected() )
  {
    // boolean connect(const char* id, const char* user, const char* pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage);
    MQTTclient.connect( clientID.c_str(), mqtt_username, mqtt_password, NULL , 1, true, NULL );
    vTaskDelay( 250 );
  }
  MQTTclient.setCallback( mqttCallback );
  MQTTclient.subscribe( topicOK );
} // void connectToMQTT()

Many thanks to all...
The problem was the UNIQUE client name!