ESP32基于C/C++向Azure IoT发送消息时出现超时问题求助
解决ESP32 Azure IoT Hub消息发送超时问题
我帮你分析了日志和代码,核心问题是ESP32成功建立了WiFi和IoT Hub连接,但发送事件时始终超时,错误提示Waiting for send confirmation, time is up还伴随TLS销毁的状态异常。下面是几个针对性的排查和修复方案:
1. 延长发送超时时间
Azure IoT Hub Arduino SDK默认的发送超时在某些网络环境下可能不够用,你可以手动调整这个阈值:
- 找到日志里提到的
Esp32MQTTClient.cpp文件(路径:/Users/stephanedeluca/Library/Arduino15/packages/esp32/hardware/esp32/1.0.6/libraries/AzureIoT/src/Esp32MQTTClient.cpp) - 定位到
SendEventOnce函数的第316行,把超时时间从10000ms左右调整到20000ms甚至更长,比如:// 原超时判断 if (millis() - start_time > 10000) { // 修改为 if (millis() - start_time > 20000) { }
2. 优化MQTT心跳配置
ESP32和IoT Hub的MQTT连接可能因为心跳间隔设置不合理导致隐性断开,建议在初始化后添加心跳配置:
在Esp32MQTTClient_Init成功后,加入这行代码:
// 设置MQTT心跳间隔为30秒(IoT Hub建议范围是2-300秒) Esp32MQTTClient_SetOption(MQTT_OPT_KEEPALIVE_INTERVAL, 30);
3. 升级ESP32核心和Azure IoT SDK
你当前用的ESP32核心版本是1.0.6,Azure IoT SDK是1.1.23,这两个版本都比较旧,存在不少已知的网络兼容性bug:
- 把ESP32 Arduino核心升级到最新稳定版(比如2.x系列)
- 同步升级Azure IoT Hub Arduino库到最新版本,新版本修复了很多TLS和MQTT发送相关的问题
4. 调整消息发送逻辑
你的代码现在每5秒就发送一次消息,可能造成消息堆积或连接压力过大,建议优化:
- 增加发送失败后的重试延迟,不要立刻再次发送
- 发送前先检查IoT Hub连接状态,确保连接正常再发送:
调整后的loop函数示例:void loop() { if (hasIoTHub) { IOTHUB_CLIENT_CONNECTION_STATUS status; // 先确认连接已认证 if (Esp32MQTTClient_GetConnectionStatus(&status) == IOTHUB_CLIENT_CONNECTION_AUTHENTICATED) { Serial.println("============ start sending events."); char buff[128]; snprintf(buff, 128, "{\"batteries\":{\"0\":{\"current\": 1234.5}}}"); if (Esp32MQTTClient_SendEvent(buff)) { Serial.println("============ Sending data succeeded"); } else { Serial.printf ("xxxxxxxxxxxx Failure sending data: %s...", buff); Serial.println(); delay(10000); // 失败后延迟10秒再重试 } } else { Serial.println("============ IoT Hub connection not authenticated, waiting..."); } delay(5000); } }
5. 排查网络环境
- 确认ESP32所在网络没有防火墙或代理拦截MQTT端口(Azure IoT Hub使用8883端口,必须确保该端口开放)
- 尝试切换到2.4GHz WiFi网络,旧版本ESP32核心对5GHz WiFi的兼容性较差
完整修改后的代码示例
#include <WiFi.h> #include "Esp32MQTTClient.h" // Please input the SSID and password of WiFi const char* ssid = "XXX"; const char* password = "XXX"; /*String containing Hostname, Device Id & Device Key in the format: */ /* "HostName=<host_name>;DeviceId=<device_id>;SharedAccessKey=<device_key>" */ /* "HostName=<host_name>;DeviceId=<device_id>;SharedAccessSignature=<device_sas_token>" */ static const char* connectionString = "XXX"; static bool hasIoTHub = false; void setup() { Serial.begin(115200); Serial.println("============ Starting connecting WiFi."); delay(10); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println("\n============ WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); if (!Esp32MQTTClient_Init((const uint8_t*)connectionString)) { hasIoTHub = false; Serial.println("============ Initializing IoT hub failed."); return; } // 设置MQTT心跳间隔 Esp32MQTTClient_SetOption(MQTT_OPT_KEEPALIVE_INTERVAL, 30); hasIoTHub = true; } void loop() { if (hasIoTHub) { IOTHUB_CLIENT_CONNECTION_STATUS status; if (Esp32MQTTClient_GetConnectionStatus(&status) == IOTHUB_CLIENT_CONNECTION_AUTHENTICATED) { Serial.println("============ start sending events."); char buff[128]; snprintf(buff, 128, "{\"batteries\":{\"0\":{\"current\": 1234.5}}}"); if (Esp32MQTTClient_SendEvent(buff)) { Serial.println("============ Sending data succeeded"); } else { Serial.printf ("xxxxxxxxxxxx Failure sending data: %s...", buff); Serial.println(); delay(10000); // 失败后延迟10秒再重试 } } else { Serial.println("============ IoT Hub connection lost, waiting for reconnection..."); } delay(5000); } }
内容的提问来源于stack exchange,提问作者Stéphane de Luca
相关产品推荐
相关产品推荐

