ESP32-S3连接AWS IoT Core时MQTT连接失败问题排查
ESP-IDF连接AWS IoT Core MQTT失败问题排查
问题描述
我使用ESP-IDF编写了与AWS IoT Core进行MQTT通信的测试代码,实现了事件处理逻辑,将根CA存入全局CA存储,并配置了MQTT参数,但连接时出现错误。
测试代码
const char *mqtt_broker_url = "xxxxxxxxxxxxx.iot.ap-northeast-2.amazonaws.com"; const char *mqtt_client_id = "ESP-TEST"; const uint16_t mqtt_port = 8883; extern const uint8_t root_ca_pem_start[] asm("_binary_root_ca_pem_start"); extern const uint8_t root_ca_pem_end[] asm("_binary_root_ca_pem_end"); extern const uint8_t device_cert_crt_start[] asm("_binary_certificate_pem_crt_start"); extern const uint8_t device_cert_crt_end[] asm("_binary_certificate_pem_crt_end"); extern const uint8_t device_private_key_start[] asm("_binary_private_pem_key_start"); extern const uint8_t device_private_key_end[] asm("_binary_private_pem_key_end"); void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) { ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%ld", base, event_id); } void app_main(void) { ...WIFI CONNECT... //Wait for WiFi to connect vTaskDelay(5000 / portTICK_PERIOD_MS); ESP_ERROR_CHECK(esp_tls_init_global_ca_store()); ESP_ERROR_CHECK(esp_tls_set_global_ca_store( (const unsigned char *)root_ca_pem_start, root_ca_pem_end - root_ca_pem_start )); vTaskDelay(5000 / portTICK_PERIOD_MS); esp_mqtt_client_config_t mqtt_cfg = { .broker.address.hostname = mqtt_broker_url, .broker.address.port = mqtt_port, .broker.address.transport = MQTT_TRANSPORT_OVER_SSL, .broker.verification.use_global_ca_store = true, .credentials.authentication.certificate = (const char *)device_cert_crt_start, .credentials.authentication.certificate_len = device_cert_crt_end - device_cert_crt_start, .credentials.authentication.key = (const char *)device_private_key_start, .credentials.authentication.key_len = device_private_key_end - device_private_key_start, .task.priority = MAX_PRIROTY - 2, .task.stack_size = 1024 * 8, }; esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg); esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL); esp_mqtt_client_start(client); }
错误日志
E (489371) esp-tls-mbedtls: read error :-0x004C: E (489371) transport_base: esp_tls_conn_read error, errno=Socket is not connected E (489381) mqtt_client: esp_mqtt_handle_transport_read_error: transport_read() error: errno=128 E (489391) mqtt_client: esp_mqtt_connect: mqtt_message_receive() returned -1 E (489391) mqtt_client: MQTT connect failed
问题排查与修复方案
1. WiFi连接检查不可靠
硬编码vTaskDelay(5000)等待WiFi连接非常不可靠,实际环境中WiFi建立连接的时间不确定,可能导致MQTT客户端在WiFi未完全就绪时发起连接,引发socket错误。
修复:
替换硬等待逻辑,改为循环检查连接状态:
// 循环等待WiFi连接完成 while (wifi_sta_get_connect_status() != WIFI_CONNECTED) { vTaskDelay(100 / portTICK_PERIOD_MS); }
2. 任务优先级拼写错误
配置中MAX_PRIROTY是拼写错误,正确应为MAX_PRIORITY,错误的宏会导致任务优先级设置异常,可能影响MQTT任务的正常运行。
修复:
将.task.priority = MAX_PRIROTY - 2改为.task.priority = MAX_PRIORITY - 2
3. 证书/密钥未正确嵌入固件
如果CMakeLists.txt中未配置嵌入证书和密钥文件,_binary_xxx_start等符号会无效,导致加载的证书/密钥为空,引发TLS验证失败。
修复:
在项目的CMakeLists.txt中添加EMBED_FILES指令,将所需的PEM文件嵌入固件:
idf_component_register(SRCS "main.c" EMBED_FILES "root_ca.pem" "certificate.pem.crt" "private.pem.key")
4. TLS证书验证失败(错误码-0x004C)
错误码-0x004C对应MBEDTLS的MBEDTLS_ERR_X509_CERT_VERIFY_FAILED,说明证书链验证不通过,可能的原因及修复:
- 根CA错误:确认使用AWS官方提供的根CA(如Amazon Root CA 1,可从AWS IoT控制台下载)
- 证书未激活:登录AWS IoT控制台,检查设备证书状态为「激活」
- 策略权限不足:验证IoT策略包含允许
iot:Connect的权限,资源需覆盖当前客户端ID:{ "Effect": "Allow", "Action": "iot:Connect", "Resource": "arn:aws:iot:ap-northeast-2:你的AWS账号ID:client/ESP-TEST" }
5. 增强事件处理函数排查细节
当前事件处理函数仅打印基础事件信息,无法获取连接失败的具体错误细节,建议扩展函数以输出更多调试信息:
void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) { esp_mqtt_event_t *event = (esp_mqtt_event_t *)event_data; switch (event_id) { case MQTT_EVENT_ERROR: ESP_LOGE(TAG, "MQTT错误类型: 0x%x", event->error_handle->error_type); if (event->error_handle->esp_tls_last_esp_err != 0) { ESP_LOGE(TAG, "ESP TLS错误码: 0x%x", event->error_handle->esp_tls_last_esp_err); } if (event->error_handle->esp_tls_stack_err != 0) { ESP_LOGE(TAG, "TLS栈错误码: 0x%x", event->error_handle->esp_tls_stack_err); } break; case MQTT_EVENT_CONNECTED: ESP_LOGI(TAG, "MQTT连接成功"); break; default: ESP_LOGD(TAG, "事件来源: %s, 事件ID: %ld", base, event_id); break; } }
内容的提问来源于stack exchange,提问作者user23469883
相关产品推荐
相关产品推荐

