3

I'm trying to create a simple MQTT client for my home application and I'm using libmosquittopp (which is C++ version of libmosquitto).
There is not much of a documentation for this library, but I found 2 examples (here and here) that helped me to create a code for my "MQTTWrapper" class.

Here's my code:

MQTTWrapper.h :

#pragma once

#include <mosquittopp.h>
#include <string>

class MQTTWrapper : public mosqpp::mosquittopp
{
public:
    MQTTWrapper(const char* id, const char* host_, int port_);
    virtual ~MQTTWrapper();

    void myPublish(std::string topic, std::string value);
private:
    void on_connect(int rc);
    void on_publish(int mid);

    std::string host;
    int port;
};

MQTTWrapper.cpp

#include "MQTTWrapper.h"

#include <iostream>

MQTTWrapper::MQTTWrapper(const char* id, const char* host_, int port_) :
    mosquittopp(id), host(host_), port(port_)
{
    mosqpp::lib_init();

    int keepalive = 10;
    if (username_pw_set("sampleuser", "samplepass") != MOSQ_ERR_SUCCESS) {
        std::cout << "setting passwd failed" << std::endl;
    }
    connect_async(host.c_str(), port, keepalive);
    if (loop_start() != MOSQ_ERR_SUCCESS) {
        std::cout << "loop_start failed" << std::endl;
    }
}

MQTTWrapper::~MQTTWrapper()
{
    std::cout << "1" << std::endl;
    if (loop_stop() != MOSQ_ERR_SUCCESS) {
        std::cout << "loop_stop failed" << std::endl;
    }
    std::cout << "2" << std::endl;
    mosqpp::lib_cleanup();
    std::cout << "3" << std::endl;
}

void MQTTWrapper::on_connect(int rc)
{
    std::cout << "Connected with code " << rc << "." << std::endl;
}

void MQTTWrapper::myPublish(std::string topic, std::string value) {
    int ret = publish(NULL, topic.c_str(), value.size(), value.c_str(), 1, false);
    if (ret != MOSQ_ERR_SUCCESS) {
        std::cout << "Sending failed." << std::endl;
    }
}

void MQTTWrapper::on_publish(int mid) {
    std::cout << "Published message with id: " << mid << std::endl;
}

and my main():

#include <iostream>
#include <string>
#include "MQTTWrapper.h"

int main(int argc, char *argv[])
{
    MQTTWrapper* mqtt;
    mqtt = new MQTTWrapper("Lewiatan IoT", "my.cloudmqtt.host", 12345);

    std::string value("Test123");
    mqtt->myPublish("sensors/temp", value);

    std::cout << "about to delete mqtt" << std::endl;
    delete mqtt;
    std::cout << "mqtt deleted" << std::endl;
    return 0;
}

Sorry for so much code.

My problem is that when I compile it and execute - my application hangs infinitely (I only waited 9 minutes) in MQTTWrapper destructor on loop_stop() method.
Tested with libmosquittopp 1.4.8 (debian package) and then after removing it- with version 1.4.9 from github.

loop_start() and loop_stop(bool force=false) should start/stop a separate thread that handles messaging.

I have tested it with forced stop (loop_stop(true)) but this way my application stops and does not publish any data. loop_stop() on the other hand publishes the data but then halts.

console output (make && ./executable):

g++ -c MQTTWrapper.cpp
g++ -c main.cpp
g++ -o executable main.o MQTTWrapper.o -lmosquittopp
about to delete mqtt
1
Connected with code 0.
Published message with id: 1
(here it hangs infinitely...)

My question:
Why this loop_stop() hangs and how to fix it?

(any documentation/tutorial/example appreciated)

lewiatan
  • 1,126
  • 2
  • 21
  • 37

1 Answers1

2

Try call disconnect() before loop_stop(). You should also bear in mind that you're effectively doing this:

connect_async();
loop_start();
loop_stop();

The client may not even have had chance to connect, nor the thread actually be started before you tell it to stop.

It's worth considering running actions in the callbacks:

on_connect -> call publish
on_publish -> call disconnect
ralight
  • 11,033
  • 3
  • 49
  • 59
  • It worked when I added `disconnect()` to `on_publish()`. Thank you. Can you please write some more about this "way of working" using callback? I mean - do you suggest that every time I want to publish some data- I should reconnect? There should be a better place to call disconnect() than in on_publish ... – lewiatan Jun 22 '16 at 21:44
  • In your code as presented you seem to want to connect, publish, once the message has been published then disconnect. I was addressing that use case. If you want to publish continuously, then you're right that disconnecting in on_publish would be a bad idea. – ralight Jun 23 '16 at 13:09
  • @lewiatan I feel this doesn't really answer your query. It is only a stop gap example. All mosquitto library c/c++ examples, expect user to disconnect() after a publish which isn't fair as you already replied. Could have left it open. – kiranpradeep Sep 24 '16 at 18:22