MQTT TCP 示例
示例说明
本示例展示如何在 ESP32 上配置 MQTT 客户端,并通过 TCP 与 Broker 建立连接,演示连接状态管理及消息收发的基本操作。通过该示例,开发者可以学习 MQTT 客户端在 TCP 下的初始化流程及事件回调处理方法,为后续实现具体消息交互提供参考。
运行方法
示例完整代码见 mqtt tcp 示例。运行前需要配置 Wi-Fi 或以太网或 Thread,详见示例目录下的 README.md 文件。
备注
若示例运行后出现 esp-tls 错误,可通过查看 报错排查 文档查找对应原因和可能的解决办法。也可通过 ESP TLS 返回值 查找对应返回值。
通过以上方法,可发现若出现如下错误,其原因可能是连接超时。此时应检查网络是否通畅,例如可使用 MQTT 工具,如 MQTTX 访问此 MQTT Broker,或尝试更换 MQTT Broker 等。
E (15139) mqtt_example: Last error reported from esp-tls: 0x8006
头文件说明
本示例所使用的头文件涵盖了 FreeRTOS 任务管理、系统工具模块、蓝牙控制器与协议栈接口以及 BLE GATT 服务相关 API 等功能模块,构建了 BLE 初始化、Profile 管理、事件处理与数据交互的核心功能。
各头文件按功能分类如下:
标准 C 库功能:提供数据类型定义、内存管理、字符串操作和输入输出支持,用于底层数据处理和通用算法实现。
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
系统与硬件接口:提供 ESP32 系统控制和非易失性存储操作接口,用于芯片管理、复位、深度睡眠及存储配置参数。
#include "esp_system.h"
#include "nvs_flash.h"
网络与事件管理:提供网络接口初始化和事件循环机制,用于 TCP/IP 通信及事件驱动的系统响应。
#include "esp_event.h"
#include "esp_netif.h"
#include "protocol_examples_common.h"
日志与调试支持:提供统一的日志打印接口,支持模块标签和日志等级,用于开发和调试。
#include "esp_log.h"
MQTT 客户端功能:提供 MQTT 客户端配置、连接建立、事件回调和消息收发接口,用于实现 IoT 设备与 Broker 的通信。
#include "mqtt_client.h"
任务函数说明
该示例包含了三个任务函数,分别用于 MQTT 客户端初始化、事件回调处理以及错误信息打印,帮助学习理解客户端的配置、连接及事件驱动通信逻辑。
MQTT 客户端初始化
mqtt_app_start()
用于初始化 MQTT 客户端并注册事件回调,准备客户端连接与消息处理。
其执行逻辑为:
配置结构体:具体结构体成员可参考 MQTT API,各结构体成员配置说明可参考 MQTT 结构体配置说明。
该示例中仅配置了 服务器地址 的
uri
。因为完整 URI 已经包含了协议类型、主机名和端口信息,客户端会优先使用 URI 建立连接;同时,由于示例使用 TCP 明文传输,不涉及 TLS 加密或服务器验证,因此无需配置证书或验证参数,从而简化了客户端配置流程。
手动输入 URI:除使用默认 URI 外,也可选择通过标准输入获取 URI,该步骤仅在启用宏
CONFIG_BROKER_URL_FROM_STDIN
时执行。
创建字符数组变量
line[]
,用于存储用户输入的 Broker URI,数组长度为 128。判断配置的 Broker 地址是否为
"FROM_STDIN"
,该标记表示当前不使用默认 URI,而是需要用户从标准输入提供实际 URI。
从标准输入读取字符串并保存至变量
line
,将结构体中的uri
设置为该变量。打印确认信息,显示最终的 Broker URI。
如果初始配置的 Broker 地址不是
"FROM_STDIN"
,则认为配置错误,打印错误日志并终止程序执行,避免在无效配置下继续运行。
初始化/启动 MQTT 客户端
事件回调函数
mqtt_event_handler()
是 MQTT 客户端事件回调函数,用于在客户端运行过程中集中处理各种事件,例如连接建立、断开、消息发布与订阅结果、消息接收及错误情况,从而实现客户端和 Broker 的交互逻辑。客户端可能触发的事件可参考 事件。
其执行逻辑为:
打印调试信息,标记当前触发的事件来源和事件 ID。
将传入的事件数据和事件客户端转换为对应的类型。
创建整形变量
msg_id
,用于后续接收发布或订阅操作的返回值。通过事件 ID 区分事件类型,并针对不同事件执行对应操作:
MQTT_EVENT_CONNECTED
:
打印事件类型。
调用
esp_mqtt_client_publish()
发布一条消息到指定主题并打印结果,用于验证客户端连接后是否能正常发送数据。API 介绍及参数说明可参考 MQTT API。两次调用
esp_mqtt_client_subscribe()
分别订阅同一主题不同 QoS 等级的消息,并打印结果,通过对比不同 QoS 的消息接收情况,可以验证客户端处理机制并判断 Broker 投递策略是否正常。API 介绍及参数说明可参考 MQTT API。调用
esp_mqtt_client_unsubscribe()
取消订阅指定主题并打印结果,展示取消订阅流程,说明客户端可以动态调整订阅。API 介绍及参数说明可参考 MQTT API。备注
示例中立即取消订阅只是用于展示 API 调用顺序,实际使用中通常不会立即取消刚订阅的主题;对业务逻辑而言,应在收到相应的确认事件后再继续后续操作。
MQTT_EVENT_DISCONNECTED
:打印日志以便定位断开连接的时间点。
MQTT_EVENT_SUBSCRIBED
:打印事件类型后调用esp_mqtt_client_publish()
发布一条消息以验证订阅结果。
MQTT_EVENT_UNSUBSCRIBED
:打印日志以便定位取消订阅的时间点。
MQTT_EVENT_PUBLISHED
:打印日志以便定位发布消息的时间点。
MQTT_EVENT_DATA
:打印事件类型及接收到的主题和消息内容,用于消息处理和调试。
MQTT_EVENT_ERROR
:对于 TCP 传输错误,调用任务函数log_error_if_nonzero()
检查相关错误字段,便于定位问题。其他事件:打印事件 ID。
备注
事件处理逻辑可根据实际应用需求进行调整,此处示例仅用于演示客户端如何响应常见 MQTT 事件及调用发布、订阅、取消订阅等操作的基本流程。
错误信息打印
log_error_if_nonzero()
是一个辅助函数,用于检查传入的错误码 error_code
,并在错误码非零时打印对应的错误信息 message
,以便调试和排查问题。
主函数说明
该函数作为程序入口,用于完成系统初始化、网络配置以及 MQTT 客户端的启动与事件回调注册。
其执行流程为:
打印日志,程序启动信息、剩余堆内存以及使用的 ESP-IDF 版本。
调用
esp_log_level_set()
分别设置各个模块的日志等级,用于控制各模块输出的日志详细程度,包括 MQTT 客户端、示例程序、传输层和 TLS 等模块。API 介绍及参数说明可参考 日志库。调用
nvs_flash_init()
初始化 非易失性存储,为系统及 MQTT 客户端提供存储支持。API 介绍及参数说明可参考 NVS API。调用
esp_netif_init()
初始化网络接口层 ESP-NETIF,准备 Wi-Fi 或以太网功能。调用
esp_event_loop_create_default()
创建默认 事件循环,为系统及 MQTT 客户端事件处理提供基础。API 介绍及参数说明可参考 事件循环库。调用
example_connect()
配置并连接网络(Wi-Fi 或以太网),确保设备具备联网能力。调用任务函数
mqtt_app_start()
初始化并启动 MQTT 客户端,同时注册事件回调函数以处理连接、订阅、发布和接收消息等事件。