From e121e1b34b9dfab7eec7b8014576d8672e8f0e31 Mon Sep 17 00:00:00 2001 From: Euripedes Rocha Filho Date: Fri, 24 Apr 2026 13:55:21 +0200 Subject: [PATCH] feat(mqtt5): Exposes server properties in connect event ESP_MQTT_EVENT_CONNECTED exposes the server properties Closes: #325 --- include/mqtt5_client.h | 22 ++++++- mqtt5_client.c | 14 ++++- test/apps/mqtt5/main/test_mqtt5.c | 1 + .../mqtt5/main/test_mqtt5_client_broker.c | 58 ++++++++++++++++++- .../mqtt5/main/test_mqtt5_client_broker.h | 8 ++- 5 files changed, 99 insertions(+), 4 deletions(-) diff --git a/include/mqtt5_client.h b/include/mqtt5_client.h index 0353a7e..26f19db 100644 --- a/include/mqtt5_client.h +++ b/include/mqtt5_client.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -142,6 +142,25 @@ typedef struct { user_property; /*!< The handle for user property, call function esp_mqtt5_client_set_user_property to set it */ } esp_mqtt5_disconnect_property_config_t; +/** + * MQTT5 server response properties from CONNACK (section 3.2.2.3) + * + * These properties indicate the server's capabilities and limits. + * Available in MQTT_EVENT_CONNECTED via event->property->server. + */ +typedef struct { + uint32_t maximum_packet_size; /*!< Maximum packet size the server will accept (0 = no limit imposed) */ + uint16_t receive_maximum; /*!< Maximum number of QoS 1/2 messages the server will process concurrently */ + uint16_t topic_alias_maximum; /*!< Maximum topic alias value the client may use (0 = topic aliases not supported) */ + uint8_t max_qos; /*!< Maximum QoS level the server supports (0, 1, or 2) */ + bool retain_available; /*!< true if the server supports retained messages */ + bool wildcard_subscribe_available; /*!< true if the server supports wildcard subscriptions */ + bool subscribe_identifiers_available; /*!< true if the server supports subscription identifiers */ + bool shared_subscribe_available; /*!< true if the server supports shared subscriptions */ + const char *response_info; /*!< Response information string for request/response (NULL if not provided) */ + int response_info_len; /*!< Length of response_info */ +} esp_mqtt5_server_resp_property_t; + /** * MQTT5 protocol for event properties */ @@ -156,6 +175,7 @@ typedef struct { uint16_t subscribe_id; /*!< Subscription identifier of the message */ mqtt5_user_property_handle_t user_property; /*!< The handle for user property, call function esp_mqtt5_client_delete_user_property to free the memory */ + esp_mqtt5_server_resp_property_t server; /*!< Server response properties from CONNACK (valid only in MQTT_EVENT_CONNECTED) */ } esp_mqtt5_event_property_t; /** diff --git a/mqtt5_client.c b/mqtt5_client.c index 8cc7e32..8267d3e 100644 --- a/mqtt5_client.c +++ b/mqtt5_client.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -111,6 +111,18 @@ esp_err_t esp_mqtt5_parse_connack(esp_mqtt5_client_handle_t client, int *connect if (*connect_rsp_code == MQTT_CONNECTION_ACCEPTED) { ESP_LOGD(TAG, "Connected"); client->event.session_present = ack_flag & 0x01; + esp_mqtt5_connection_server_resp_property_t *src = &client->mqtt5_config->server_resp_property_info; + esp_mqtt5_server_resp_property_t *dst = &client->event.property->server; + dst->maximum_packet_size = src->maximum_packet_size; + dst->receive_maximum = src->receive_maximum; + dst->topic_alias_maximum = src->topic_alias_maximum; + dst->max_qos = src->max_qos; + dst->retain_available = src->retain_available; + dst->wildcard_subscribe_available = src->wildcard_subscribe_available; + dst->subscribe_identifiers_available = src->subscribe_identifiers_available; + dst->shared_subscribe_available = src->shared_subscribe_available; + dst->response_info = src->response_info; + dst->response_info_len = src->response_info ? strlen(src->response_info) : 0; return ESP_OK; } diff --git a/test/apps/mqtt5/main/test_mqtt5.c b/test/apps/mqtt5/main/test_mqtt5.c index bdb5eb3..5ed79a7 100644 --- a/test/apps/mqtt5/main/test_mqtt5.c +++ b/test/apps/mqtt5/main/test_mqtt5.c @@ -145,6 +145,7 @@ TEST(mqtt5, broker_tests) RUN_MQTT5_BROKER_TEST(mqtt5_subscribe_publish); RUN_MQTT5_BROKER_TEST(mqtt5_lwt_clean_disconnect); RUN_MQTT5_BROKER_TEST(mqtt5_subscribe_payload); + RUN_MQTT5_BROKER_TEST(mqtt5_server_properties); connect_test_fixture_teardown(); } #endif // SOC_EMAC_SUPPORTED diff --git a/test/apps/mqtt5/main/test_mqtt5_client_broker.c b/test/apps/mqtt5/main/test_mqtt5_client_broker.c index d2e8963..8536118 100644 --- a/test/apps/mqtt5/main/test_mqtt5_client_broker.c +++ b/test/apps/mqtt5/main/test_mqtt5_client_broker.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,6 +7,7 @@ #include "freertos/FreeRTOS.h" #include "freertos/event_groups.h" #include "mqtt_client.h" +#include "mqtt5_client.h" #include "esp_log.h" #include "esp_mac.h" @@ -285,3 +286,58 @@ bool mqtt5_subscribe_payload(void) free(topic); return true; } + +static esp_mqtt5_server_resp_property_t s_server_props; +static bool s_server_props_received = false; + +static void mqtt5_event_handler_server_props(void *handler_args, esp_event_base_t base, + int32_t event_id, void *event_data) +{ + esp_mqtt_event_handle_t event = event_data; + + switch ((esp_mqtt_event_id_t)event_id) { + case MQTT_EVENT_CONNECTED: + s_server_props = event->property->server; + s_server_props_received = true; + xEventGroupSetBits(s_event_group, CONNECT_BIT); + break; + + case MQTT_EVENT_DISCONNECTED: + xEventGroupSetBits(s_event_group, DISCONNECT_BIT); + break; + + default: + break; + } +} + +bool mqtt5_server_properties(void) +{ + s_server_props_received = false; + memset(&s_server_props, 0, sizeof(s_server_props)); + const esp_mqtt_client_config_t mqtt5_cfg = { + .broker.address.uri = CONFIG_MQTT5_TEST_BROKER_URI, + .network.disable_auto_reconnect = true, + .session.protocol_ver = MQTT_PROTOCOL_V_5, + }; + s_event_group = xEventGroupCreate(); + esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt5_cfg); + TEST_ASSERT_TRUE(NULL != client); + esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt5_event_handler_server_props, NULL); + TEST_ASSERT_TRUE(ESP_OK == esp_mqtt_client_start(client)); + WAIT_FOR_EVENT(CONNECT_BIT); + TEST_ASSERT_TRUE(s_server_props_received); + ESP_LOGI("mqtt5-server-props", "topic_alias_maximum: %d", s_server_props.topic_alias_maximum); + ESP_LOGI("mqtt5-server-props", "receive_maximum: %d", s_server_props.receive_maximum); + ESP_LOGI("mqtt5-server-props", "maximum_packet_size: %lu", (unsigned long)s_server_props.maximum_packet_size); + ESP_LOGI("mqtt5-server-props", "max_qos: %d", s_server_props.max_qos); + ESP_LOGI("mqtt5-server-props", "retain_available: %d", s_server_props.retain_available); + ESP_LOGI("mqtt5-server-props", "wildcard_subscribe_available: %d", s_server_props.wildcard_subscribe_available); + ESP_LOGI("mqtt5-server-props", "subscribe_identifiers_available: %d", s_server_props.subscribe_identifiers_available); + ESP_LOGI("mqtt5-server-props", "shared_subscribe_available: %d", s_server_props.shared_subscribe_available); + TEST_ASSERT_TRUE(s_server_props.max_qos <= 2); + TEST_ASSERT_TRUE(s_server_props.receive_maximum > 0); + esp_mqtt_client_destroy(client); + vEventGroupDelete(s_event_group); + return true; +} diff --git a/test/apps/mqtt5/main/test_mqtt5_client_broker.h b/test/apps/mqtt5/main/test_mqtt5_client_broker.h index 429e860..066dcd8 100644 --- a/test/apps/mqtt5/main/test_mqtt5_client_broker.h +++ b/test/apps/mqtt5/main/test_mqtt5_client_broker.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -48,3 +48,9 @@ bool mqtt5_lwt_clean_disconnect(void); * and verifies the qos in SUBACK message from the broker. */ bool mqtt5_subscribe_payload(void); + +/** + * @brief The client connects and verifies that server response + * properties from CONNACK are available in the CONNECTED event. + */ +bool mqtt5_server_properties(void);