3 years, 1 month ago.

MQTT connection get lost, using it with Thread reading Serial Data

Hi Guys, I'm facing a problem with MQTT connection with Mosquito Broker. The program flow is as:

  • Opening Serial for Debug msgs
  • Opening a thread reading serial data from Enocean sensor
  • Starting the Ethernet and MQTT connections
  • In the while(1) loop, I'm just checking if the connection is still alive, I'm publishing Serial Data Packet to MQTT broker.

Everything works fine, if i keep sending data from my Enocean sensor and buttons, But the problem arises when there is no sensor/button sending data through MQTT.

  • The connection get lost from MQTT broker.
  • I have tried to reconnect again, but in the main loop the method client.isConnected() always return true even if it has lost connection with MQTT broker.
  • I have also tried using client.yield() in the while(1) loop, but it get everything stuck. No thing works at all by adding yield.

Please guide.

include the mbed library with this snippet

#include "mbed.h"
#include "rtos.h"

// change this to 0 to output messages to serial instead of LCD
#define USE_LCD 0

#define MQTTCLIENT_QOS2 1

#include "easy-connect.h"
#include "MQTTNetwork.h"
#include "MQTTmbed.h"
#include "MQTTClient.h"

Serial pc(USBTX, USBRX);    // Serial port for Debug messages
Serial enocean(p28, p27);   // tx, rx --> Serial Communication with EnOcean Transiver
DigitalOut led1(LED1); // Connection information LED
DigitalOut led2(LED2);
DigitalOut led3(LED3);

Thread thread_ENOCEAN;

char c[30];
char buf[30];
volatile int i = 0;

// Network and MQTT
const char* hostname = "192.168.10.5";
int port = 1883;
char* topic = "hellomqtt/topic";
int rc;
// generate a unique random Client-ID
char str[20] ="mbed-clientID-0001";

// Interupt Routine to read in data from serial port
void Rx_intt() {
    c[i++] = LPC_UART2->RBR;
    led2 = !led2;
    return;
}

void enocean_thread() {
    enocean.baud(57600);
    enocean.attach(&Rx_intt, Serial::RxIrq);
    i = 0;    
}

int main(int argc, char* argv[])
{
    pc.baud(9600);
    NetworkInterface* network = easy_connect(false);
    MQTTNetwork mqttNetwork(network);
    MQTT::Client<MQTTNetwork, Countdown> client(mqttNetwork);
    rc = mqttNetwork.connect(hostname, port);
    MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
    data.MQTTVersion = 3;    
    str[18] = 0;
    data.clientID.cstring = str;
    rc = client.connect(data);
    led1 = 1;
    MQTT::Message message;
    // Opening thread for Enocean Serial Data
    thread_ENOCEAN.start(enocean_thread);
    
    
    while(1)
    {
        if(!client.isConnected())
        {
            led1 = 0;
            rc = client.disconnect();
            mqttNetwork.disconnect();
            
            network = easy_connect(false);
            MQTTNetwork mqttNetwork(network);
            MQTT::Client<MQTTNetwork, Countdown> client(mqttNetwork);
            rc = mqttNetwork.connect(hostname, port);
            MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
            data.MQTTVersion = 3;    
            str[18] = 0;
            data.clientID.cstring = str;
            rc = client.connect(data);
        }
        
        if(i > 20 && client.isConnected())
        {
            rc = client.connect(data);
            led1 = 1;
            led2 = 0;
            
            memcpy(buf, c, i);
            
            message.qos = MQTT::QOS0;
            message.retained = false;
            message.dup = false;
            message.payload = (void*)buf;
            message.payloadlen = 21;//strlen(buf)+1;
            
            rc = client.publish(topic, message);
            //pc.printf("Length: %i\n",sizeof(buf));
            for(int j=0; j<21;j++)
            {
                pc.putc(buf[j]);
            }
            i = 0;
        }
        //client.yield(100);
    }
}

Hi Peter,

I have also checked by removing the line of code. There was no difference.

Actual problem i'm facing is unexpected behavior of client.isConnected() method. It's is always returning me true whether the client is connected with MQTT server or not.

posted by sohaib qamar 16 Aug 2018

Hi, Which board are you using?

-Peter

posted by Peter Nguyen 16 Aug 2018

I'm using LPC1768 board.

Sohaib.

posted by sohaib qamar 16 Aug 2018

1 Answer

3 years, 1 month ago.

Hello sohaib,

Did you try to add a null character (0) at the end of your message? This will tell the Broker that this is the end of your message and stop listening. Otherwise, it will wait because it thinks that there is more message to be sent.

Please let me know if you have any questions!

-Peter, team Mbed

If this solved your question, please make sure to click the "Thanks" link below!

Hey Peter, Thanks for the quick reply. I have used the following to add null character (0)

if(i > 20 && client.isConnected())
        {
            rc = client.connect(data);
            led1 = 1;
            led2 = 0;
            
            memcpy(buf, c, i);
            buf[21] = 0x00;
            message.qos = MQTT::QOS0;
            message.retained = false;
            message.dup = false;
            message.payload = (void*)buf;
            message.payloadlen = 22;//strlen(buf)+1;
            
            rc = client.publish(topic, message);
            //pc.printf("Length: %i\n",sizeof(buf));
            for(int j=0; j<21;j++)
            {
                pc.putc(buf[j]);
            }
            i = 0;
        }

As I know the Enocean msg contain 21 bytes packet so i appended 0x00 at Byte 22. But the problem has not been resolved yet. Again, i'm losing the connection with MQTT broker. Please advise.

posted by sohaib qamar 03 Aug 2018

Hi,

If the problem only occurs when there is no sensor/button data, can you just put an if statement to check for that and only publish when you have data?

Peter

posted by Peter Nguyen 03 Aug 2018

Hi Peter, I'm already doing that, I'm receiving the Enocean Sensor/button data in a separate thread. And in the while(1) loop, when i receive the whole packet, only then i publish the msg to MQTT.

Waiting for your kind response.

posted by sohaib qamar 03 Aug 2018

Hello, why are you calling client.connect() everytime before you publishing your data?

-Peter

posted by Peter Nguyen 14 Aug 2018

Hi Peter,

I need to make sure if the connection is intact before sending the message to MQTT server.

posted by sohaib qamar 15 Aug 2018

Hi, Isn't that what client.isConnect() doing? Reading the MQTTClient library, the connect function is trying to create a connection between your board and the MQTT Broker. So it seems that you are creating new connection everytime you publish, which can be an issue.

-Peter

posted by Peter Nguyen 15 Aug 2018

Hi Peter,

I have also checked by removing the line of code. There was no difference.

Actual problem i'm facing is unexpected behavior of client.isConnected() method. It's is always returning me true whether the client is connected with MQTT server or not.

posted by sohaib qamar 16 Aug 2018

Hi Sohaib, What microcontroller are you using? I can't seem to be able to recreate your problem. It might be target specific.

-Peter

posted by Peter Nguyen 21 Aug 2018