eclipse-paho / paho.mqtt.embedded-c

Paho MQTT C client library for embedded systems. Paho is an Eclipse IoT project (https://iot.eclipse.org/)
https://eclipse.org/paho
Other
1.37k stars 757 forks source link

Arduino keeps reconnecting in loop #221

Open dervur opened 3 years ago

dervur commented 3 years ago

Hello there,

I'm trying to use a modified version of the sample code for Arduino (I'm using an ESP01 with arduino's framework) however, in the main loop the function isconnected() always returns a false value instead of a true one, in fact the client is receiving and sending messages with no problem it is indeed connected, however for this function the client is somehow not connected. Do you have any idea of what is the issue here?

This is my code below (I only cleared my Wifi and personal broker fields for privacy reasons, but I have the problem both with my broker and with hiveMQ's public broker, so I left only hivemq's broker field):

#include <Arduino.h>

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <SPI.h>
#include "ESP8266WiFi.h"
#include <IPStack.h>
#include <Countdown.h>
#include <MQTTClient.h>

/******************* Wi-Fi connection options *******************/
//Enter SSID
#define ssid "" 
//Enter Password
#define wifipassword ""
/****************************************************************/

/******************* MQTT CONNECT options ***********************/
//HiveMQ open broker host and port
#define brokerhost "broker.hivemq.com"
#define brokerport 1883

//ClientID (must be unique for each device)
#define MQTTclientID "ESP01"
//Authentication
#define MQTTusername ""
#define MQTTpassword ""
//Persistent session = 0, Clean session = 1
#define MQTTsession 0
//MQTT 3.1.1 = 4, MQTT 3.0 = 3
#define MQTTver 3
//Time to keep alive the session defined in seconds
#define MQTTkeepAlive 120
//Last Will and Testament (LWT_flag = 1 to implement this)
#define LWT_flag 1
#define LWT_topic "EE579/ESP01/status"
#define LWT_payload "offline"
#define LWT_retained 1
#define LWT_qos 1
/****************************************************************/

void messageArrived(MQTT::MessageData& md)
{
  //Obtain MQTT message
  MQTT::Message &message_rec = md.message;
  //Obtain topic string
  MQTTLenString topic_rec = md.topicName.lenstring;

  char printbuf[100];
  //Print message data
  sprintf(printbuf, "Message arrived: qos %d, retained %d, dup %d, packetid %d, ", 
        message_rec.qos, message_rec.retained, message_rec.dup, message_rec.id);
  Serial.print(printbuf);
  //Print message topic
  sprintf(printbuf, "Topic: ");
  Serial.print(printbuf);
  snprintf(printbuf, topic_rec.len+1, "%s", topic_rec.data);
  Serial.println(printbuf);
  //Print payload
  sprintf(printbuf, "Payload: ");
  Serial.print(printbuf);
  snprintf(printbuf, message_rec.payloadlen+1, "%s", (char*)message_rec.payload);
  Serial.println(printbuf);
}

WiFiClient c;
IPStack ipstack(c);
MQTT::Client<IPStack, Countdown> client = MQTT::Client<IPStack, Countdown>(ipstack);

//Connect to WiFi
void connectWiFi()
{
  //Connect to WiFi
  WiFi.begin(ssid, wifipassword);
  while (WiFi.status() != WL_CONNECTED) 
  {
     delay(500);
     Serial.print("*");
  }

  Serial.println("");
  Serial.println("WiFi connection Successful");
  Serial.print("The IP Address of ESP8266 Module is: ");

  //Print the IP address
  Serial.print(WiFi.localIP());

  Serial.print("\n");
}

//Connect to MQTT broker
void connectMQTT()
{
  char printbuf[100];
  char hostname[] = brokerhost;
  int port = brokerport;
  sprintf(printbuf, "Connecting to %s:%d\n", hostname, port);
  Serial.print(printbuf);
  int rc = ipstack.connect(hostname, port);
  if (rc != 1)
  {
    printbuf[100];
    sprintf(printbuf, "rc from TCP connect is %d\n", rc);
    Serial.print(printbuf);
  }

  Serial.println("MQTT connecting");
  MQTTPacket_connectData data = MQTTPacket_connectData_initializer; 
  data.clientID.cstring = MQTTclientID;
  data.username.cstring = MQTTusername;
  data.password.cstring = MQTTpassword;
  data.cleansession = MQTTsession;
  data.willFlag = LWT_flag;      
  data.MQTTVersion = MQTTver;
  data.keepAliveInterval = MQTTkeepAlive;
  MQTTPacket_willOptions LWT = MQTTPacket_willOptions_initializer;
  LWT.topicName.cstring = LWT_topic;
  LWT.message.cstring = LWT_payload;
  LWT.retained = LWT_retained;
  LWT.qos = LWT_qos;
  data.will = LWT;

  rc = client.connect(data);
  if (rc != 0)
  {
    printbuf[100];
    sprintf(printbuf, "rc from MQTT connect is %d\n", rc);
    Serial.print(printbuf);
  }
  Serial.println("MQTT connected");

  const char* topic = "EE579/#";

  rc = client.subscribe(topic, MQTT::QOS2, messageArrived);   
  if (rc != 0)
  {
    printbuf[100];
    sprintf(printbuf, "rc from MQTT subscribe is %d\n", rc);
    Serial.print(printbuf);
  }
  Serial.println("MQTT subscribed");
}

//Publish first message "online"
void msg_online()
{
  MQTT::Message message_pub;
  //Topic
  const char* topic = "EE579/ESP01/status";
  //Payload
  const char* message = "online";
  char payload[100];
  snprintf(payload, strlen(message)+1, "%s", (char*)message);
  message_pub.payload = (void*)payload;
    message_pub.payloadlen = strlen(payload);
  //Settings
  message_pub.qos = MQTT::QOS1;
  message_pub.retained = true;
  message_pub.dup = false;
  //Publish message
  int rc = client.publish(topic, message_pub);
}

//Publish empty message to retain client online
void msg_empty()
{
  MQTT::Message message_pub;
  //Topic
  const char* topic = "e";
  //Payload
  const char* message = "";
  char payload[1];
  snprintf(payload, strlen(message)+1, "%s", (char*)message);
  message_pub.payload = (void*)payload;
    message_pub.payloadlen = strlen(payload);
  //Settings
  message_pub.qos = MQTT::QOS1;
  message_pub.retained = true;
  message_pub.dup = false;
  //Publish message
  int rc = client.publish(topic, message_pub);
}

void setup()
{
  Serial.begin(115200);

  //Connect to WiFi and then to MQTT broker
  connectWiFi();
  connectMQTT();

  //Communicate online status
  msg_online();

  delay(500);
}

void loop()
{
  //20 seconds delay
  delay(20000);

  //If client is not connected, connect it
  if (client.isConnected())
    connectMQTT();

  client.yield(1000);

  //Send empty message to keep client online
  msg_empty();

}

Kind regards, Vur

scaprile commented 3 years ago
  //If client is not connected, connect it
  if (client.isConnected())
    connectMQTT();

Your comment does not match your action, you are testing for true and connecting when it is connected.

dervur commented 3 years ago

I'm sorry I copied the wrong code, that was to test only if it was a problem of the isconnected() code, the fact is that with the code below it doesn't work.

if (!client.isConnected())
    connectMQTT();

In fact it continues to reconnect every 20 second. If I comment that section of the code and I try to publish something else in the topics the ESP01 has subscribed it continues receiving them, thence I think it is indeed still online (confirmed by the fact that the broker doesn't send the last will to other clients) screenshot

In the screenshot it is even possible to see that the client receives even its own last will (green square brackets) before subscribing to the topic which is very odd...