MQTT
如何使用 MQTT 配置服务器地址为自主云平台?
可以参考 MQTT 例程。
使用 ESP8266 release/v3.3 版本的 SDK 测试 examples/protocols/esp-mqtt/tcp 例程,配置 Wi-Fi 账号、密码,连接默认配置的服务器,出现连接失败,log 如下,是什么原因?
W (4211) MQTT_CLIENT: Connection refused, not authorized I (4217) MQTT_CLIENT: Error MQTT Connected I (4222) MQTT_CLIENT: Reconnect after 10000 ms I (4228) MQTT_EXAMPLE: MQTT_EVENT_DISCONNECTED I (19361) MQTT_CLIENT: Sending MQTT CONNECT message, type: 1, id: 0000当出现如上报错,表示服务器拒绝了连接,原因是客户端错误的 MQTT 用户名和密码导致服务端认证没有通过。建议您确认是否使用了正确的 MQTT 用户名和密码。
ESP-IDF 中 MQTT 组件 keepalive 的默认值是多少?
默认值为 120 s,在
mqtt_config.h
中通过MQTT_KEEPALIVE_TICK
定义。
MQTT 支持自动重连吗?
MQTT 的自动重连由 esp_mqtt_client_config_t 中的成员变量
disable_auto_reconnect
控制,该变量值默认为false
,表示使能自动重连。可以使用
reconnect_timeout_ms
设置重连超时时间。
ESP-IDF 支持的 MQTT 版本有哪些?
ESP-IDF 目前支持的 MQTT 版本为 MQTT 3.1,MQTT 3.1.1 和 MQTT 5.0。
ESP-IDF 里 Wi-Fi 连接断开的时候,之前 MQTT 上层协议申请的内存会自动释放吗?
不会自动释放,但对于用户而言不需要关心这部分内存。用户要关心的是 ESP 给用户封装的应用层。
对于 MQTT 应用层组件,用户初始化 MQTT 的时候会获得一个 MQTT 句柄,用户只需关心这个句柄里的内存,在不用 MQTT 的时候调用
stop
或者destroy
释放对应 MQTT 内存即可。对于 Wi-Fi 断开与连接,用户也不需要通过stop
或者destroy
释放这个 MQTT 句柄然后再重新申请 MQTT 句柄。因为 MQTT 组件里有自动重连机制。
ESP32-C3 MQTT 是否能不设置对应的 client_id
而将 client_id
默认配置为空字符串?
可以,可通过在应用代码里设置
set_null_client_id
为true
来实现。
使用 ESP-IDF MQTT 客户端发布 QoS 为 1 或者 2 的数据后,当 MQTT_EVENT_PUBLISHED
触发时是否意味着已经收到了对端合适的 ack 来证明这次发布已完成?还是仅仅只能说明成功发送了一次数据给服务器?
MQTT_EVENT_PUBLISHED
事件触发代表代理已确认收到客户端的发布的 QoS 为 1 或者 2 的消息,证明这次发布已经顺利完成。
ESP MQTT 客户端断开连接后,如何手动释放 MQTT 资源?
手动调用 esp_mqtt_client_destroy API 即可。
ESP32 Wi-Fi 和低功耗蓝牙共存时,MQTT keepalive 时间该如何配置?有没有什么合适的配置时间?
在 ESP32 中使用 Wi-Fi 和低功耗蓝牙共存时,应该合理配置 MQTT keepalive 时间。由于 Wi-Fi 和低功耗蓝牙都需要消耗系统资源,因此如果 keepalive 时间设置得太短,可能会导致系统负载过高,影响系统稳定性和性能。
通常情况下,建议根据实际情况设置 MQTT keepalive 时间,以确保设备在线的同时,尽可能减少系统资源的消耗。在 Wi-Fi 和低功耗蓝牙共存的情况下,可以考虑将 MQTT keepalive 时间设置为较长的时间,如可以配置为 30 s、60 s 等,这样可以减少设备与 MQTT broker 之间的通信次数,降低系统负载。
需要注意的是,如果 keepalive 时间设置得太长,当设备掉线时,可能需要等待较长时间才能发现设备离线,这可能会影响实时性和可靠性。因此,需要根据实际需求和系统性能来合理设置 MQTT keepalive 时间。
ESP MQTT 客户端的 disconnect 事件消息什么时候才会触发?
disconnect 消息只有在以下情况出现:
MQTT 建立连接时,TCP 连接错误
MQTT 建立连接时,MQTT 连接错误
自行主动调用了
disconnect
函数接收或发送数据异常
规定时间内没收到对端 MQTT
PING RESPONSE
发送 MQTT PING 请求失败
重新连接
ESP32 MQTT 客户端与服务器断开后会自动尝试重新连接吗?
ESP MQTT 客户端里的
esp_mqtt_client_config_t
结构体配置里有disable_auto_reconnect
参数,可以通过配置这个参数为true
或者false
来决定是否需要 MQTT 自动重连,MQTT 默认会自动进行重连。
如何检测 ESP32 是否已经与 MQTT 服务器断开?
检测 ESP32 是否已经与服务器断开可以使用 MQTT 的
PING
机制。也就是配置 ESP-MQTT 中esp_mqtt_client_config_t
结构体里的keepalive
参数disable_keepalive
和keepalive
,比如将disable_keepalive
配置为false
(默认参数也是false
,即默认开启 keepalive 机制),然后配置keepalive
参数为 120 s 来设置保活时间,默认为 120 s。这样 MQTT 客户端会定期发送PING
来检测和 MQTT 服务器的连接是否正常。
在连接 MQTT 服务器时遇到连接失败的情况,如何获取具体的错误原因并排查问题?
MQTT 连接失败时可以在 MQTT 事件
MQTT_EVENT_ERROR
里解析结构体esp_mqtt_error_codes_t
中的数据,详情请参考示例中的MQTT_EVENT_ERROR
事件。
如何调整 MQTT 的遗嘱消息发送时间?
可以通过缩短 MQTT 心跳时间来减少遗嘱消息的发送延迟。
MQTT 客户端在发送数据时遇到超时,如何确定问题出现在哪个网络层?
可以通过抓包分析来确定问题所在层,检查是在传输层、网络层还是数据链路层出现问题。具体失败环节可能是服务器未返回 ACK、服务器返回了 ACK 但 Wi-Fi 没有收到,或者数据包未成功发送。
为什么 MQTT 客户端在网络状况良好时仍然报告写入超时?
可能因为底层 LWIP 缓冲区已满,导致无法写入。这通常是由于缓冲区里的包没有收到对端的 ACK。具体原因可能包括服务器没有发送 ACK、服务器发送了 ACK 但 Wi-Fi 没有收到,或者数据包没有成功发出。
在使用 MQTT 通信时,为什么会出现内存骤降的情况?
MQTT 中的 outbox 会占用内存,对于 QoS 大于 0 的消息,只有在对端发送 MQTT 层的 ACK 后,相关内存才会被释放。可以通过配置 CONFIG_HEAP_USE_HOOKS 来跟踪内存的分配和释放情况。