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

MQTT v5

mqtt_cpp supports MQTT v5 since version 4.0.0.

Client

When you create a client, pass the protocol_version argument. If you want to use MQTT v5, then you create the client as follows:

    auto c = mqtt::make_sync_client(ios, "localhost", port, mqtt::protocol_version::v5);

The default protocol_version is v3_1_1. So the following two code is the same meaning:

    auto c = mqtt::make_sync_client(ios, "localhost", port, mqtt::protocol_version::v3_1_1);
    auto c = mqtt::make_sync_client(ios, "localhost", port);

Server

When you create a server, the server accepts all versions of MQTT protocol that mqtt_cpp supported. They are v3.1.1 and v5 currently.

    auto s = mqtt::server<>(
        boost::asio::ip::tcp::endpoint(
            boost::asio::ip::tcp::v4(),
            boost::lexical_cast<std::uint16_t>(argv[1])
        ),
        ios
    );

If you want to limit accepting connection, then call set_protocol_version() with the accepting version.

    s.set_protocol_version(mqtt::protocol_version::v5);

Sending message

When you send a message e.g.) connect(), publish(), subscribe(), etc..., you can call the same name function both MQTT v5 and MQTT v3.1.1. Some of functions have additional parameter and additional overloads. You can send newly introduced reason_code and property on MQTT v5.

Receiving message

When you want to receive MQTT v5 message, you need to set v5 handlers. A name of setter function is set_ with handler type. For example, connect_handler setter is set_connect_handler(), v5_connect_handler setter is set_v5_connect_handler().

Handler type v3.1.1 v5 client server(broker)
connect_handler x - - x
connack_handler x - x -
publish_handler x - x x
puback_handler x - x x
pubrec_handler x - x x
pubrel_handler x - x x
pubcomp_handler x - x x
subscribe_handler x - - x
suback_handler x - x x
unsubscribe_handler x - - x
unsuback_handler x - x x
disconnect_handler x - - x
v5_connect_handler - x - x
v5_connack_handler - x x -
v5_publish_handler - x x x
v5_puback_handler - x x x
v5_pubrec_handler - x x x
v5_pubrel_handler - x x x
v5_pubcomp_handler - x x x
v5_subscribe_handler - x - x
v5_suback_handler - x x -
v5_unsubscribe_handler - x - x
v5_unsuback_handler - x x -
v5_disconnect_handler - x - x
v5_auth_handler - x x x
pingreq_handler x x - x
pingresp_handler x x x -

Property

Property is newly introduced feature since MQTT v5. They are defined in the namespace mqtt::v5::property.

property type has_ref
payload_format_indicator 1byte -
message_expiry_interval 4bytes -
content_type string x
response_topic string x
correlation_data string x
subscription_identifier 1-4bytes -
session_expiry_interval 4bytes -
assigned_client_identifier string x
server_keep_alive 2bytes -
authentication_method string x
authentication_data binary x
request_problem_information 1byte -
will_delay_interval 4bytes -
request_response_information 1byte -
response_information string x
server_reference string x
reason_string string x
receive_maximum 2bytes -
topic_alias_maximum 2bytes -
topic_alias 2bytes -
maximum_qos 1byte -
retain_available 1byte -
user_property a pair of string (key,val) x
maximum_packet_size 4bytes -
wildcard_subscription_available 1byte -
subscription_identifier_available 1byte -
shared_subscription_available 1byte -

string and binary type properties has corresponding reference types. For example. content_type has corresponding reference type content_type_ref. The reference type holds only pointer and size of the string.

Sending

    auto c = mqtt::make_sync_client(ios, "localhost", port, mqtt::protocol_version::v5);

    // ...

    // prepare connect properties
    std::vector<mqtt::v5::property_variant> con_ps {
        mqtt::v5::property::topic_alias_maximum(0x1234U),
        mqtt::v5::property::user_property("key1", "val1"),
        mqtt::v5::property::user_property("key2", "val2")
    };

    // Connect with properties
    c->connect(std::move(con_ps));

You can use both non reference types and reference types. If you use reference types, you need to manage the lifetime of string.

Receiving

When you want to receive property, you need to use mqtt::visit() as follows:

    auto c = mqtt::make_sync_client(ios, "localhost", port, mqtt::protocol_version::v5);

    // ...

    c->set_v5_connack_handler( // use v5 handler
        [&c]
        (bool sp, mqtt::v5::connect_reason_code reason_code, mqtt::v5::properties props){
            std::cout << "[client] Connack handler called" << std::endl;
            std::cout << "[client] Clean Session: " << std::boolalpha << sp << std::endl;
            std::cout << "[client] Connect Reason Code: "
                      << static_cast<int>(reason_code) << std::endl;

            for (auto const& p : props) {
                mqtt::visit(
                    mqtt::make_lambda_visitor<void>(
                        [&](mqtt::v5::property::session_expiry_interval const& t) {
                            std::cout << "[client] prop: session_expiry_interval: " << t.val() << std::endl;
                        },
                        [&](mqtt::v5::property::receive_maximum const& t) {
                            std::cout << "[client] prop: receive_maximum: " << t.val() << std::endl;
                        },
                        [&](mqtt::v5::property::maximum_qos const& t) {
                            std::cout << "[client] prop: maximum_qos: " << t.val() << std::endl;
                        },
                        [&](mqtt::v5::property::retain_available const& t) {
                            std::cout << "[client] prop: retain_available: " << t.val() << std::endl;
                        },
                        [&](mqtt::v5::property::maximum_packet_size const& t) {
                            std::cout << "[client] prop: maximum_packet_size: " << t.val() << std::endl;
                        },
                        [&](mqtt::v5::property::assigned_client_identifier const& t) {
                            std::cout << "[client] prop: assigned_client_identifier_ref: " << t.val() << std::endl;
                        },
                        [&](mqtt::v5::property::topic_alias_maximum const& t) {
                            std::cout << "[client] prop: topic_alias_maximum: " << t.val() << std::endl;
                        },
                        [&](mqtt::v5::property::reason_string const& t) {
                            std::cout << "[client] prop: reason_string_ref: " << t.val() << std::endl;
                        },
                        [&](mqtt::v5::property::user_property const& t) {
                            std::cout << "[client] prop: user_property_ref: " << t.key() << ":" << t.val() << std::endl;
                        },
                        [&](mqtt::v5::property::wildcard_subscription_available const& t) {
                            std::cout << "[client] prop: wildcard_subscription_available: " << t.val() << std::endl;
                        },
                        [&](mqtt::v5::property::subscription_identifier_available const& t) {
                            std::cout << "[client] prop: subscription_identifier_available: " << t.val() << std::endl;
                        },
                        [&](mqtt::v5::property::shared_subscription_available const& t) {
                            std::cout << "[client] prop: shared_subscription_available: " << t.val() << std::endl;
                        },
                        [&](mqtt::v5::property::server_keep_alive const& t) {
                            std::cout << "[client] prop: server_keep_alive: " << t.val() << std::endl;
                        },
                        [&](mqtt::v5::property::response_information const& t) {
                            std::cout << "[client] prop: response_information_ref: " << t.val() << std::endl;
                        },
                        [&](mqtt::v5::property::server_reference const& t) {
                            std::cout << "[client] prop: server_reference_ref: " << t.val() << std::endl;
                        },
                        [&](mqtt::v5::property::authentication_method const& t) {
                            std::cout << "[client] prop: authentication_method_ref: " << t.val() << std::endl;
                        },
                        [&](mqtt::v5::property::authentication_data const& t) {
                            std::cout << "[client] prop: authentication_data_ref: " << t.val() << std::endl;
                        },
                        [&](auto&& ...) {
                            BOOST_ASSERT(false);
                        }
                    ),
                    p
                );
            }


            c->disconnect();
            return true;
        });