MQTT 调试工具使用示例

[English]

有关 MQTT 的常见问题请参考 MQTT FAQ

以下通过具体案例说明 ESP-IDF MQTT 报错的排查方法,并展示调试工具如何帮助快速确认问题原因和最终解决方案。

示例:esp-tls: [sock=54] select() timeout

此问题对应的完整 log 往往为:

E (15220) esp-tls: [sock=54] select() timeout
E (15220) transport_base: Failed to open a new connection: 32774
E (15220) mqtt_client: Error transport connect
I (15220) mqtt_example: MQTT_EVENT_ERROR
E (15220) mqtt_example: Last error reported from esp-tls: 0x8006

报错分析:

  • TLS 错误码 0x8006 对应 ESP_ERR_ESP_TLS_CONNECTION_TIMEOUT,说明 TCP 连接阶段超时,底层 socket 等待服务器响应时未在设定时间内收到数据,导致传输层连接建立失败。

可能的原因:

在 TCP 连接建立阶段,客户端(ESP 设备)与服务器之间通过三次握手(Three-way Handshake)建立可靠的传输连接。具体流程如下:

当出现 TCP 连接超时问题时,可以从以下三个角度出发进行排查:

  1. 设备端是否成功发送/接收数据包

  2. 服务器是否成功发送/接收数据包

  3. 路由器是否成功转发数据包

情况一:Broker 不可用

  1. 开启 lwIP 层 TCP Debug Log 查看设备端是否发送 SYN 数据包:

开启 Debug Log 后观察到如下信息,表明在 TCP 连接阶段,设备端已发送 SYN 数据包,但尚未收到服务器响应,说明超时问题可能是由于服务器未返回 SYN + ACK 或设备端未收到 SYN + ACK 导致。

  1. 使用 MQTT 测试工具 验证目标 Broker 及网络情况。

  • 使用 MQTTX 进行测试,输入相关参数:

    • Name:用户自定义

    • Host:目标 Broker 地址

    • Port:按实际情况输入端口,明文 MQTT 默认端口为 1883,TLS MQTT 默认端口为 8883,该示例使用明文 MQTT

    • 按实际情况选择是否启用 SSL/TLS

  • 连接至目标 Broker,根据测试工具日志可以发现,测试工具多次尝试重连,依然无法连接,故可以判断,该问题可能由于 Broker 不可用导致服务器未返回 ACK 数据包,或网络不稳定导致路由器未能成功转发数据包。

  1. 更换 Broker 后,设备成功建立连接,从而确认问题是 Broker 不可用导致。

备注

若更换 Broker 后仍无法解决问题,可参考情况二进行进一步排查。

情况二:Wi-Fi 未能成功接收并转发数据包

若更换 Broker 后,设备仍然无法连接,需通过 无线抓包 查看设备和服务器之间的通信情况。

  • 设置 过滤器,显示设备和服务器之间的 TCP 数据流,方便观察 TLS 握手是否成功。

    • 对于 TCP 数据包需要结合设备 IP,服务器 IP,以及 TCP 进行过滤。

    tcp && ((ip.src == 设备IP && ip.dst == 服务器IP) ||
            (ip.src == 服务器IP && ip.dst == 设备IP))
    
  • 观察抓包信息发现:

    • 设备端发送了 SYN 包;

    • 服务器返回了 SYN + ACK 包;

    • 设备端 没有 返回 ACK 包。

  • 结合设备端 Debug Log,没有显示接收到服务器发送的 SYN + ACK 包,说明服务器的数据包被路由器成功转发却没有到达设备端,由此判断可能是 Wi-Fi 链路接收(RX)部分的问题。