diff --git a/samples/net/mqtt_publisher/README.rst b/samples/net/mqtt_publisher/README.rst index d94bb9708fbf..4f5f90bb821e 100644 --- a/samples/net/mqtt_publisher/README.rst +++ b/samples/net/mqtt_publisher/README.rst @@ -11,11 +11,15 @@ Overview publish/subscribe messaging protocol optimized for small sensors and mobile devices. -The Zephyr MQTT Publisher sample application is a MQTT v3.1.1 -client that sends MQTT PUBLISH messages to a MQTT broker. -See the `MQTT V3.1.1 spec`_ for more information. +The Zephyr MQTT Publisher sample application is a MQTT client that sends +MQTT PUBLISH messages to a MQTT broker. The sample supports MQTT client in +version v3.1.1 (default) and v5.0. -.. _MQTT V3.1.1 spec: http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/mqtt-v3.1.1.html +See the `MQTT v3.1.1 spec`_ and `MQTT v5.0 spec`_ for more information about +MQTT v3.1.1 and v5.0, respectively. + +.. _MQTT v3.1.1 spec: https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/mqtt-v3.1.1.html +.. _MQTT v5.0 spec: https://docs.oasis-open.org/mqtt/mqtt/v5.0/mqtt-v5.0.html The source code of this sample application can be found at: :zephyr_file:`samples/net/mqtt_publisher`. @@ -136,6 +140,23 @@ Open another terminal window and type: $ mosquitto_sub -t sensors +MQTT v5.0 support +================= + +The sample can be configured to use MQTT v5.0 instead of MQTT v3.1.1. To enable +MQTT v5.0 in the sample, build it with ``-DEXTRA_CONF_FILE=overlay-mqtt-5.conf`` +parameter. The sample should work with any broker supporting MQTT v5.0, however +it was specifically tested with mosquitto version 2.0.21. Server side +configuration in this particular case is the same as for MQTT v3.1.1. + +When the sample is configured in the MQTT v5.0 mode, it makes use of the topic +aliasing feature. i.e. if the broker reports it supports topic aliases, the +client will register a topic alias for the default ``sensors`` topic, and use it +for consecutive MQTT Publish messages. It can be observed (for example using +Wireshark) how the actual topic is only present in the first Publish message, and +all subsequent Publish messages are smaller, as they include topic alias +property only. + Connecting securely using TLS ============================= diff --git a/samples/net/mqtt_publisher/overlay-mqtt-5.conf b/samples/net/mqtt_publisher/overlay-mqtt-5.conf new file mode 100644 index 000000000000..c6f851780d61 --- /dev/null +++ b/samples/net/mqtt_publisher/overlay-mqtt-5.conf @@ -0,0 +1 @@ +CONFIG_MQTT_VERSION_5_0=y diff --git a/samples/net/mqtt_publisher/src/main.c b/samples/net/mqtt_publisher/src/main.c index 7ae967058e3c..2cf61ff6eadb 100644 --- a/samples/net/mqtt_publisher/src/main.c +++ b/samples/net/mqtt_publisher/src/main.c @@ -53,9 +53,14 @@ static APP_BMEM struct sockaddr socks5_proxy; static APP_BMEM struct pollfd fds[1]; static APP_BMEM int nfds; - static APP_BMEM bool connected; +/* Whether to include full topic in the publish message, or alias only (MQTT 5). */ +static APP_BMEM bool include_topic; +static APP_BMEM bool aliases_enabled; + +#define APP_TOPIC_ALIAS 1 + #if defined(CONFIG_MQTT_LIB_TLS) #include "test_certs.h" @@ -155,6 +160,18 @@ void mqtt_evt_handler(struct mqtt_client *const client, connected = true; LOG_INF("MQTT client connected!"); +#if defined(CONFIG_MQTT_VERSION_5_0) + if (evt->param.connack.prop.rx.has_topic_alias_maximum && + evt->param.connack.prop.topic_alias_maximum > 0) { + LOG_INF("Topic aliases allowed by the broker, max %u.", + evt->param.connack.prop.topic_alias_maximum); + + aliases_enabled = true; + } else { + LOG_INF("Topic aliases disallowed by the broker."); + } +#endif + break; case MQTT_EVT_DISCONNECT: @@ -242,12 +259,18 @@ static char *get_mqtt_topic(void) static int publish(struct mqtt_client *client, enum mqtt_qos qos) { - struct mqtt_publish_param param; + struct mqtt_publish_param param = { 0 }; + + /* Always true for MQTT 3.1.1. + * True only on first publish message for MQTT 5.0 if broker allows aliases. + */ + if (include_topic) { + param.message.topic.topic.utf8 = (uint8_t *)get_mqtt_topic(); + param.message.topic.topic.size = + strlen(param.message.topic.topic.utf8); + } param.message.topic.qos = qos; - param.message.topic.topic.utf8 = (uint8_t *)get_mqtt_topic(); - param.message.topic.topic.size = - strlen(param.message.topic.topic.utf8); param.message.payload.data = get_mqtt_payload(qos); param.message.payload.len = strlen(param.message.payload.data); @@ -255,6 +278,13 @@ static int publish(struct mqtt_client *client, enum mqtt_qos qos) param.dup_flag = 0U; param.retain_flag = 0U; +#if defined(CONFIG_MQTT_VERSION_5_0) + if (aliases_enabled) { + param.prop.topic_alias = APP_TOPIC_ALIAS; + include_topic = false; + } +#endif + return mqtt_publish(client, ¶m); } @@ -308,7 +338,11 @@ static void client_init(struct mqtt_client *client) client->client_id.size = strlen(MQTT_CLIENTID); client->password = NULL; client->user_name = NULL; +#if defined(CONFIG_MQTT_VERSION_5_0) + client->protocol_version = MQTT_VERSION_5_0; +#else client->protocol_version = MQTT_VERSION_3_1_1; +#endif /* MQTT buffers configuration */ client->rx_buf = rx_buffer; @@ -435,6 +469,9 @@ static int publisher(void) { int i, rc, r = 0; + include_topic = true; + aliases_enabled = false; + LOG_INF("attempting to connect: "); rc = try_to_connect(&client_ctx); PRINT_RESULT("try_to_connect", rc);