feat: Adds an event reporting PING related control messages

Fixes #334
This commit is contained in:
Euripedes Rocha Filho
2026-09-22 11:04:24 +02:00
committed by Euripedes Rocha
parent a26d2adc90
commit 7e52c2eba1
5 changed files with 40 additions and 0 deletions
+1
View File
@@ -334,6 +334,7 @@ The following events may be posted by the MQTT client:
* ``MQTT_EVENT_PUBLISHED``: The broker has acknowledged the client's publish message. This is only posted for QoS level 1 and 2, as level 0 does not use acknowledgements. The event data contains the message ID of the publish message.
* ``MQTT_EVENT_DATA``: The client has received a publish message. The event data contains: message ID, name of the topic it was published to, received data and its length. For data that exceeds the internal buffer, multiple ``MQTT_EVENT_DATA`` events are posted and :cpp:member:`current_data_offset <esp_mqtt_event_t::current_data_offset>` and :cpp:member:`total_data_len <esp_mqtt_event_t::total_data_len>` from event data updated to keep track of the fragmented message.
* ``MQTT_EVENT_ERROR``: The client has encountered an error. The field :cpp:type:`error_handle <esp_mqtt_error_codes_t>` in the event data contains :cpp:type:`error_type <esp_mqtt_error_type_t>` that can be used to identify the error. The type of error determines which parts of the :cpp:type:`error_handle <esp_mqtt_error_codes_t>` struct is filled.
* ``MQTT_EVENT_KEEPALIVE``: The client sent a keepalive ``PINGREQ`` or received a ``PINGRESP``. :cpp:member:`data <esp_mqtt_event_t::data>` points to one byte of type :cpp:type:`esp_mqtt_keepalive_kind_t` (``MQTT_KEEPALIVE_PINGREQ`` or ``MQTT_KEEPALIVE_PINGRESP``) and :cpp:member:`data_len <esp_mqtt_event_t::data_len>` is 1. Keepalive timeout and failure to send ``PINGREQ`` still produce ``MQTT_EVENT_DISCONNECTED`` (and ``MQTT_EVENT_ERROR`` when a transport write fails); they do not post this event.
Relation between errors and disconnections in MQTT client
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+1
View File
@@ -232,6 +232,7 @@ MQTT 客户端可能会发布以下事件:
* ``MQTT_EVENT_PUBLISHED``:服务器已确认客户端的发布消息。消息将仅针对 QoS 级别 1 和 2 发布,因为级别 0 不会进行确认。事件数据将包含发布消息的消息 ID。
* ``MQTT_EVENT_DATA``:客户端已收到发布消息。事件数据包含:消息 ID、发布消息所属主题名称、收到的数据及其长度。对于超出内部缓冲区的数据,将发布多个 ``MQTT_EVENT_DATA``,并更新事件数据的 :cpp:member:`current_data_offset <esp_mqtt_event_t::current_data_offset>` 和 :cpp:member:`total_data_len<esp_mqtt_event_t::total_data_len>` 以跟踪碎片化消息。
* ``MQTT_EVENT_ERROR``:客户端遇到错误。使用事件数据 :cpp:type:`error_handle <esp_mqtt_error_codes_t>` 字段中的 :cpp:type:`error_type <esp_mqtt_error_type_t>`,可以发现错误。错误类型决定 :cpp:type:`error_handle <esp_mqtt_error_codes_t>` 结构体的哪些部分会被填充。
* ``MQTT_EVENT_KEEPALIVE``:客户端已发送 keepalive ``PINGREQ`` 或已收到 ``PINGRESP``。:cpp:member:`data <esp_mqtt_event_t::data>` 指向一个 :cpp:type:`esp_mqtt_keepalive_kind_t` 字节(``MQTT_KEEPALIVE_PINGREQ`` 或 ``MQTT_KEEPALIVE_PINGRESP``),:cpp:member:`data_len <esp_mqtt_event_t::data_len>` 为 1。Keepalive 超时以及发送 ``PINGREQ`` 失败仍会发布 ``MQTT_EVENT_DISCONNECTED``(传输写入失败时还会发布 ``MQTT_EVENT_ERROR``),不会发布本事件。
API 参考
-------------
+15
View File
@@ -97,8 +97,23 @@ typedef enum esp_mqtt_event_id_t {
All fields from the esp_mqtt_event_t type could be used to pass
an additional context data to the handler.
*/
MQTT_EVENT_KEEPALIVE, /*!< Keepalive PINGREQ sent or PINGRESP received.
Additional context:
- data pointer to one byte, an :cpp:type:`esp_mqtt_keepalive_kind_t`
- data_len always 1
The pointer remains valid for the duration of the event handler.
*/
} esp_mqtt_event_id_t;
/**
* Kind of keepalive traffic reported in :cpp:enumerator:`MQTT_EVENT_KEEPALIVE`.
* Encoded as a single byte in :cpp:member:`esp_mqtt_event_t::data`.
*/
typedef enum {
MQTT_KEEPALIVE_PINGREQ = 0, /*!< Client sent a PINGREQ */
MQTT_KEEPALIVE_PINGRESP = 1, /*!< Client received a PINGRESP */
} esp_mqtt_keepalive_kind_t;
/**
* *MQTT* connection error codes propagated via ERROR event
*/
+12
View File
@@ -37,6 +37,7 @@ static const int DISCONNECT_BIT = (1 << 2);
static esp_err_t esp_mqtt_dispatch_event(esp_mqtt_client_handle_t client);
static esp_err_t esp_mqtt_dispatch_event_with_msgid(esp_mqtt_client_handle_t client);
static void esp_mqtt_dispatch_keepalive_event(esp_mqtt_client_handle_t client, esp_mqtt_keepalive_kind_t kind);
static esp_err_t esp_mqtt_connect(esp_mqtt_client_handle_t client, int timeout_ms);
static void esp_mqtt_abort_connection(esp_mqtt_client_handle_t client);
static esp_err_t esp_mqtt_client_ping(esp_mqtt_client_handle_t client);
@@ -818,6 +819,7 @@ static esp_err_t process_keepalive(esp_mqtt_client_handle_t client)
}
client->wait_for_ping_resp = true;
esp_mqtt_dispatch_keepalive_event(client, MQTT_KEEPALIVE_PINGREQ);
return ESP_OK;
}
}
@@ -1275,6 +1277,15 @@ esp_err_t esp_mqtt_dispatch_custom_event(esp_mqtt_client_handle_t client, esp_mq
return ret;
}
static void esp_mqtt_dispatch_keepalive_event(esp_mqtt_client_handle_t client, esp_mqtt_keepalive_kind_t kind)
{
char data = (char)kind;
client->event.event_id = MQTT_EVENT_KEEPALIVE;
client->event.data_len = 1;
client->event.data = &data;
esp_mqtt_dispatch_event(client);
}
static esp_err_t esp_mqtt_dispatch_event(esp_mqtt_client_handle_t client)
{
client->event.client = client;
@@ -1830,6 +1841,7 @@ static esp_err_t mqtt_process_receive(esp_mqtt_client_handle_t client)
* [MQTT-3.1.2-23]
*/
client->keepalive_tick = platform_tick_get_ms();
esp_mqtt_dispatch_keepalive_event(client, MQTT_KEEPALIVE_PINGRESP);
break;
case MQTT_MSG_TYPE_DISCONNECT:
@@ -193,6 +193,17 @@ void conformance_mqtt_event_handler(void *, esp_event_base_t, int32_t event_id,
break;
case MQTT_EVENT_KEEPALIVE:
if (event->data && event->data_len == 1) {
const auto kind = static_cast<esp_mqtt_keepalive_kind_t>(
static_cast<uint8_t>(event->data[0]));
ESP_LOGI(TAG, "MQTT_EVENT_KEEPALIVE kind=%d", static_cast<int>(kind));
} else {
ESP_LOGI(TAG, "MQTT_EVENT_KEEPALIVE");
}
break;
default:
ESP_LOGI(TAG, "Other event id:%d", event->event_id);
break;