Skip to content
Takatoshi Kondo edited this page Feb 17, 2021 · 8 revisions

First step to create mqtt client

Include the header file for client.

#include <mqtt_client_cpp.hpp>

Define io_context.

int main() {
    boost::asio::io_context ioc;

Create client.

    auto c = mqtt::make_sync_client(ioc, "test.mosquitto.org", 1883);

Do client settings.

    c->set_client_id("cid1");
    c->set_clean_session(true);

Set handlers.

    c->set_connack_handler(
        [](bool sp, mqtt::connect_return_code connack_return_code){
            return true;
        }
    );
    c->set_close_handler(
        [] {
        }
    );
    c->set_error_handler(
        []
        (boost::system::error_code const& ec) {
        }
    );
    c->set_puback_handler(
        [](std::uint16_t packet_id) {
            return true;
        }
    );
    c->set_pubrec_handler(
        [](std::uint16_t packet_id) {
            return true;
        }
    );
    c->set_pubcomp_handler(
        [](std::uint16_t packet_id) {
            return true;
        }
    );
    c->set_suback_handler(
        [](std::uint16_t packet_id, std::vector<mqtt::suback_return_code> results){
            return true;
        }
    );
    c->set_publish_handler(
        []
        (mqtt::optional<std::uint16_t> packet_id,
         mqtt::publish_options pubopts,
         mqtt::buffer topic_name,
         mqtt::buffer contents) {
            return true;
        }
    );

Register connect command.

    c->connect();

Run io_context.

    ioc.run();
}

Actual connection is executed from ioc.run().

Implement the contents of connack_handler. Any mqtt operation need to wait establishing the connection. So connack_handler is the start point of the mqtt operation. In this tutorial, subscribe mqtt_cpp_topic1.

    c->set_connack_handler(
        [&c](bool sp, mqtt::connect_return_code connack_return_code){
            std::cout << "Connack handler called" << std::endl;
            std::cout << "Session Present: " << std::boolalpha << sp << std::endl;
            std::cout << "Connack Return Code: " << connack_return_code << std::endl;
            if (connack_return_code == mqtt::connect_return_code::accepted) {
                c->subscribe("mqtt_cpp_topic1", mqtt::qos::at_most_once);
            }
            return true;
        }
    );

Implement the contents of suback_handler. In this tutorial, publish a message test1 to mqtt_cpp_topic1.

    c->set_suback_handler(
        [&c](std::uint16_t packet_id, std::vector<mqtt::suback_return_code> results){
            std::cout << "suback received. packet_id: " << packet_id << std::endl;
            for (auto const& e : results) {
                std::cout << "subscribe result: " << e << std::endl;
            }
            c->publish("mqtt_cpp_topic1", "test1", mqtt::qos::at_most_once);
            return true;
        }
    );

Implement the publish_handler. The handler name is little bit confusing. This is a kind of receive message handler.

See the following diagram:

       publish (send)           publish (deliver)
client1 ---------------> broker ------------------> client2

MQTT spec calls both sending client1 to broker and delivering broker to client2 as publish.

mqtt_cpp respects MQTT specification. publish_handler means receiving published message handler.

In this tutorial, print published message and disconnect.

Now, we finished.

Let's compile it.

clang++ -std=c++14 -I path_to_mqtt_cpp tutorial.cpp -lboost_system -lpthread

Execute the program.

./a.out

Here is my result:

Connack handler called
Session Present: false
Connack Return Code: accepted
suback received. packet_id: 1
subscribe result: success_maximum_qos_0
publish received. dup: no qos: at_most_once retain: no
topic_name: mqtt_cpp_topic1
contents: test1

test.mosquitto.org is public test server. topic1 might has retained data.

In the above result,

publish received. dup: no qos: at_most_once retain: no
topic_name: mqtt_cpp_topic1
contents: test1

is retained data.

If you choose an unique topic name, retained data is not appeared.

Here is whole code:

#include <iostream>
#include <mqtt_client_cpp.hpp>

int main() {
    boost::asio::io_context ioc;
    auto c = mqtt::make_sync_client(ioc, "test.mosquitto.org", 1883);

    c->set_client_id("cid1");
    c->set_clean_session(true);

    c->set_connack_handler(
        [&c](bool sp, mqtt::connect_return_code connack_return_code){
            std::cout << "Connack handler called" << std::endl;
            std::cout << "Session Present: " << std::boolalpha << sp << std::endl;
            std::cout << "Connack Return Code: " << connack_return_code << std::endl;
            if (connack_return_code == mqtt::connect_return_code::accepted) {
                c->subscribe("mqtt_cpp_topic1", mqtt::qos::at_most_once);
            }
            return true;
        }
    );
    c->set_close_handler(
        [] {
        }
    );
    c->set_error_handler(
        []
        (boost::system::error_code const& ec) {
        }
    );
    c->set_puback_handler(
        [](std::uint16_t packet_id) {
            return true;
        }
    );
    c->set_pubrec_handler(
        [](std::uint16_t packet_id) {
            return true;
        }
    );
    c->set_pubcomp_handler(
        [](std::uint16_t packet_id) {
            return true;
        }
    );
    c->set_suback_handler(
        [&c](std::uint16_t packet_id, std::vector<mqtt::suback_return_code> results){
            std::cout << "suback received. packet_id: " << packet_id << std::endl;
            for (auto const& e : results) {
                std::cout << "subscribe result: " << e << std::endl;
            }
            c->publish("mqtt_cpp_topic1", "test1", mqtt::qos::at_most_once);
            return true;
        }
    );
    c->set_publish_handler(
        [&c]
        (mqtt::optional<std::uint16_t> packet_id,
         mqtt::publish_options pubopts,
         mqtt::buffer topic_name,
         mqtt::buffer contents) {
            std::cout << "publish received."
                      << " dup: "    << pubopts.get_dup()
                      << " qos: "    << pubopts.get_qos()
                      << " retain: " << pubopts.get_retain() << std::endl;
            if (packet_id)
                std::cout << "packet_id: " << *packet_id << std::endl;
            std::cout << "topic_name: " << topic_name << std::endl;
            std::cout << "contents: " << contents << std::endl;
            c->disconnect();
            return true;
        }
    );

    c->connect();

    ioc.run();
}