The problem
MQTT over TLS connection fails on ESP32-C3 with ESPHome, but the exact same credentials work successfully on Linux using mosquitto_sub. The connection briefly succeeds (CONNACK received) but immediately disconnects with a TLS error.
Which version of ESPHome has the issue?
2025.9.1
What type of installation are you using?
Home Assistant Add-on
What platform are you using?
ESP32
Component causing the issue
mqtt
YAML Config
# ========= MQTT Connection Test - Simplified Version =========
# For testing OneNET MQTT connection
substitutions:
device_name: "mqtt-test-c3"
friendly_name: "MQTT-Test"
esphome:
name: ${device_name}
friendly_name: ${friendly_name}
on_boot:
priority: -10
then:
- delay: 8s # Wait for Wi-Fi + SNTP sync
- mqtt.enable: # Delayed MQTT startup
- logger.log: "System boot complete, MQTT enabled"
esp32:
board: airm2m_core_esp32c3
framework:
type: esp-idf
logger:
level: DEBUG
api:
json:
# Time synchronization - MQTT requires accurate timestamps
time:
- platform: sntp
id: sntp_time
servers:
- ntp.aliyun.com
- time.windows.com
timezone: Asia/Shanghai
on_time_sync:
- logger.log: "✓ Time synchronized successfully"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
on_connect:
- logger.log: "✓ Wi-Fi connected successfully"
on_disconnect:
- logger.log: "✗ Wi-Fi disconnected"
ota:
- platform: esphome
password: !secret ota_password
# MQTT Configuration - China Mobile OneNET Platform
mqtt:
broker: "nkKRY36VE6.mqttstls.acc.cmcconenet.cn" # OneNET MQTT server (Note: mqttstls not mqtts)
port: 8883 # TLS encrypted port
username: "nkKRY36VE6" # Product ID
password: "version=2018-10-31&res=products%2FnkKRY36VE6%2Fdevices%2Fmypanel&et=1791185468&method=md5&sign=v%2BxH6eBLz%2BI1NXNgzieDcA%3D%3D"
client_id: "mypanel" # Device name
clean_session: true
topic_prefix: null
enable_on_boot: false # Delayed startup, wait for SNTP sync
discovery: false
discovery_retain: false
skip_cert_cn_check: true # Skip certificate CN check
use_abbreviations: false # Disable abbreviations
idf_send_async: false # ESP-IDF synchronous send
reboot_timeout: 0s # Disable reboot timeout
keepalive: 60s
log_topic: null # Disable log topic
birth_message: # Disable birth message
will_message: # Disable will message
# OneNET MQTT TLS Certificate
certificate_authority: |-
-----BEGIN CERTIFICATE-----
MIIDOzCCAiOgAwIBAgIJAPCCNfxANtVEMA0GCSqGSIb3DQEBCwUAMDQxCzAJBgNV
BAYTAkNOMQ4wDAYDVQQKDAVDTUlPVDEVMBMGA1UEAwwMT25lTkVUIE1RVFRTMB4X
DTE5MDUyOTAxMDkyOFoXDTQ5MDUyMTAxMDkyOFowNDELMAkGA1UEBhMCQ04xDjAM
BgNVBAoMBUNNSU9UMRUwEwYDVQQDDAxPbmVORVQgTVFUVFMwggEiMA0GCSqGSIb3
DQEBAQUAA4IBDwAwggEKAoIBAQC/VvJ6lGWfy9PKdXKBdzY83OERB35AJhu+9jkx
5d4SOtZScTe93Xw9TSVRKrFwu5muGgPusyAlbQnFlZoTJBZY/745MG6aeli6plpR
r93G6qVN5VLoXAkvqKslLZlj6wXy70/e0GC0oMFzqSP0AY74icANk8dUFB2Q8usS
UseRafNBcYfqACzF/Wa+Fu/upBGwtl7wDLYZdCm3KNjZZZstvVB5DWGnqNX9HkTl
U9NBMS/7yph3XYU3mJqUZxryb8pHLVHazarNRppx1aoNroi+5/t3Fx/gEa6a5PoP
ouH35DbykmzvVE67GUGpAfZZtEFE1e0E/6IB84PE00llvy3pAgMBAAGjUDBOMB0G
A1UdDgQWBBTTi/q1F2iabqlS7yEoX1rbOsz5GDAfBgNVHSMEGDAWgBTTi/q1F2ia
bqlS7yEoX1rbOsz5GDAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAL
aqJ2FgcKLBBHJ8VeNSuGV2cxVYH1JIaHnzL6SlE5q7MYVg+Ofbs2PRlTiWGMazC7
q5RKVj9zj0z/8i3ScWrWXFmyp85ZHfuo/DeK6HcbEXJEOfPDvyMPuhVBTzuBIRJb
41M27NdIVCdxP6562n6Vp0gbE8kN10q+ksw8YBoLFP0D1da7D5WnSV+nwEIP+F4a
3ZX80bNt6tRj9XY0gM68mI60WXrF/qYL+NUz+D3Lw9bgDSXxpSN8JGYBR85BxBvR
NNAhsJJ3yoAvbPUQ4m8J/CoVKKgcWymS1pvEHmF47pgzbbjm5bdthlIx+swdiGFa
WzdhzTYwVkxBaU+xf/2w
-----END CERTIFICATE-----
# MQTT connection success callback
on_connect:
- logger.log:
level: INFO
format: "✓✓✓ MQTT Connected Successfully! ✓✓✓"
- lambda: |-
ESP_LOGI("mqtt_test", "========================================");
ESP_LOGI("mqtt_test", "✓ MQTT Connected to OneNET Platform!");
ESP_LOGI("mqtt_test", "✓ Broker: nkKRY36VE6.mqttstls.acc.cmcconenet.cn:8883");
ESP_LOGI("mqtt_test", "✓ Client ID: mypanel");
ESP_LOGI("mqtt_test", "========================================");
id(mqtt_connected) = true;
# MQTT disconnection callback
on_disconnect:
- logger.log:
level: WARN
format: "✗✗✗ MQTT Disconnected! ✗✗✗"
- lambda: |-
ESP_LOGW("mqtt_test", "========================================");
ESP_LOGW("mqtt_test", "✗ MQTT Connection Lost");
ESP_LOGW("mqtt_test", "✗ Will attempt auto-reconnect...");
ESP_LOGW("mqtt_test", "========================================");
id(mqtt_connected) = false;
# Subscribe to test topic
on_message:
- topic: "$sys/nkKRY36VE6/mypanel/thing/property/post_reply"
then:
- lambda: |-
ESP_LOGI("mqtt_test", "========================================");
ESP_LOGI("mqtt_test", "Received OneNET response message:");
ESP_LOGI("mqtt_test", "%s", x.c_str());
ESP_LOGI("mqtt_test", "========================================");
// Parse response code
if (x.find("\"code\":200") != std::string::npos) {
ESP_LOGI("mqtt_test", "✓✓✓ Data Upload Successful! ✓✓✓");
} else if (x.find("\"code\":") != std::string::npos) {
ESP_LOGW("mqtt_test", "✗✗✗ Data Upload Failed! ✗✗✗");
}
network:
# Global variables
globals:
- id: mqtt_connected
type: bool
initial_value: 'false'
- id: test_counter
type: int
initial_value: '0'
# MQTT connection status sensor
text_sensor:
- platform: template
name: "MQTT Status"
id: mqtt_status
icon: "mdi:cloud-check"
lambda: |-
if (id(mqtt_connected)) {
return std::string("✓ Connected");
} else {
return std::string("✗ Disconnected");
}
update_interval: 5s
# Test counter
sensor:
- platform: template
name: "Test Send Count"
id: test_send_count
icon: "mdi:counter"
lambda: |-
return id(test_counter);
update_interval: 10s
# Periodic connection status check: Display MQTT connection status every 30 seconds
interval:
- interval: 30s
then:
- lambda: |-
if (id(mqtt_connected)) {
ESP_LOGI("mqtt_test", "========================================");
ESP_LOGI("mqtt_test", "✓ MQTT Connection Maintained...");
ESP_LOGI("mqtt_test", "✓ Use manual button to send test data");
ESP_LOGI("mqtt_test", "========================================");
} else {
ESP_LOGW("mqtt_test", "⚠ MQTT Not Connected, Waiting for Reconnection...");
}
# Manual test button (can be triggered via Home Assistant)
button:
- platform: template
name: "Send Test Data"
icon: "mdi:send"
on_press:
- if:
condition:
mqtt.connected:
then:
- logger.log: "Manually triggered test upload..."
- lambda: |-
id(test_counter) += 1;
- mqtt.publish:
topic: "$sys/nkKRY36VE6/mypanel/thing/property/post"
payload: !lambda |-
#include <ArduinoJson.h>
// Get current timestamp
auto time_now = id(sntp_time).now();
int64_t timestamp = time_now.timestamp * 1000LL;
// Create JSON document
JsonDocument doc;
doc["id"] = to_string(millis());
doc["version"] = "1.0";
JsonObject params = doc["params"].to<JsonObject>();
JsonObject temp = params["temperature"].to<JsonObject>();
temp["value"] = 23.5;
temp["time"] = timestamp;
JsonObject hum = params["humidity"].to<JsonObject>();
hum["value"] = 55.0;
hum["time"] = timestamp;
JsonObject press = params["pressure"].to<JsonObject>();
press["value"] = 1015.0;
press["time"] = timestamp;
// Serialize
std::string json_msg;
serializeJson(doc, json_msg);
ESP_LOGI("mqtt_test", "Manually sending test data: %s", json_msg.c_str());
return json_msg;
else:
- logger.log:
level: ERROR
format: "✗ MQTT Not Connected, Cannot Send Data!"
Anything in the logs that might be useful for us?
[20:04:30.119][W][component:326]: mqtt cleared Warning flag
[20:04:30.119][I][mqtt:309]: Connected
[20:04:30.244][W][component:443]: mqtt took a long time for an operation (115 ms)
[20:04:30.244][W][component:446]: Components should block for at most 30 ms
[20:04:30.324][E][mqtt.idf:167]: MQTT_EVENT_ERROR
[20:04:30.324][E][mqtt.idf:169]: Last error code reported from esp-tls: 0x8008
[20:04:30.324][E][mqtt.idf:170]: Last tls stack error number: 0x0
[20:04:30.324][E][mqtt.idf:171]: Last captured errno : 0 (Success)
[20:04:30.324][D][esp-idf:000][mqtt_task]: E (15263) mqtt_client: esp_mqtt_handle_transport_read_error: transport_read(): EOF
[20:04:30.324][D][esp-idf:000][mqtt_task]: E (15264) mqtt_client: esp_mqtt_handle_transport_read_error: transport_read() error: errno=119
[20:04:30.324][D][esp-idf:000][mqtt_task]: E (15264) mqtt_client: mqtt_process_receive: mqtt_message_receive() returned -2
[20:04:30.324][W][mqtt:358]: Disconnected: TCP disconnected
Additional information
mosquitto_sub -h nkKRY36VE6.mqttstls.acc.cmcconenet.cn -p 8883 \
--cafile onenet.pem --insecure \
-i mypanel -u nkKRY36VE6 \
-P 'version=2018-10-31&res=products%2FnkKRY36VE6%2Fdevices%2Fmypanel&et=1791185468&method=md5&sign=v%2BxH6eBLz%2BI1NXNgzieDcA%3D%3D' \
-t '$sys/nkKRY36VE6/mypanel/#' \
-k 60 -d
Client mypanel sending CONNECT
Client mypanel received CONNACK (0)
Client mypanel sending SUBSCRIBE (Mid: 1, Topic: $sys/nkKRY36VE6/mypanel/#, QoS: 0, Options: 0x00)
Client mypanel received SUBACK
Subscribed (mid: 1): 0
Client mypanel sending CONNECT
Client mypanel received CONNACK (0)
Client mypanel sending SUBSCRIBE (Mid: 2, Topic: $sys/nkKRY36VE6/mypanel/#, QoS: 0, Options: 0x00)
Client mypanel received SUBACK
Subscribed (mid: 2): 0
Client mypanel sending CONNECT
Client mypanel received CONNACK (0)
Client mypanel sending SUBSCRIBE (Mid: 3, Topic: $sys/nkKRY36VE6/mypanel/#, QoS: 0, Options: 0x00)
Client mypanel received SUBACK
Subscribed (mid: 3): 0
It works in linux with same config.
github issue: