You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ESP32连接NCP MQTT持续报rc=-2错误,求排查解决方法

ESP32连接NCP MQTT持续报rc=-2错误排查求助

问题概述

在Arduino IDE中开发ESP32向NCP MQTT发送消息的代码,已确认WiFi连接正常,尝试过8883和1883两个端口,但连接时持续出现rc=-2错误,怀疑密钥文件或通信协议存在问题,不确定是否需要调整Arduino IDE或Windows设置,请求协助排查。

完整代码

#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <PubSubClient.h>

#define root_ca \
"-----BEGIN CERTIFICATE-----\n" \
"MIIDuT**********************************************************\n" \
"-----END CERTIFICATE-----\n"

#define client_cert \
"-----BEGIN CERTIFICATE-----\n" \
"MIIESj**********************************************************\n" \
"-----END CERTIFICATE-----\n"

#define private_key \
"-----BEGIN PRIVATE KEY-----\n" \
"MIIEow**********************************************************\n" \
"-----END PRIVATE KEY-----\n"

const char* ssid = "5021";
const char* password = "12345678";
const char* mqtt_server = "ssl://msg01.cloudiot.ntruss.com";
const int mqtt_port = 8883;

WiFiClientSecure espClient;
PubSubClient client(espClient);

long lastMsg = 0;
char msg[256];
int msgCount = 0;

void setup_wifi() {
  delay(10);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
  }
}

void reconnect() {
  if (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    unsigned long startTime = millis();

    if (client.connect("arduinoClient")) {
      Serial.println("connected");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      delay(5000);
    }

    Serial.print("Connection attempt took ");
    Serial.print(millis() - startTime);
    Serial.println(" ms");
  }
}

void setup() {
  Serial.begin(115200);
  setup_wifi();
  char *dest3;
  char *dest1;
  char *dest2;
  dest1 = (char *)malloc(sizeof(char) * (strlen(root_ca) + 1));
  strcpy(dest1, root_ca);
    dest2 = (char *)malloc(sizeof(char) * (strlen(client_cert) + 1));
  strcpy(dest2, client_cert);
    dest3 = (char *)malloc(sizeof(char) * (strlen(private_key) + 1));
  strcpy(dest3, private_key);
  espClient.setCACert(dest1);
  espClient.setCertificate(dest2); 
  espClient.setPrivateKey(dest3);
  client.setServer(mqtt_server, mqtt_port);
}

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  if(client.connected() ) {
    Serial.print("Client connected");
  }
}

已完成的排查动作

  • 确认WiFi连接状态正常
  • 尝试切换MQTT端口为8883和1883
  • 参考多方资料调整代码结构

排查建议

1. 修正MQTT服务器地址格式

PubSubClient的setServer方法不需要携带ssl://前缀,因为WiFiClientSecure已明确使用SSL/TLS通信,前缀会导致地址解析错误,这是rc=-2的常见诱因。修改为:

const char* mqtt_server = "msg01.cloudiot.ntruss.com";

2. 简化证书传递方式

代码中手动malloc并拷贝证书的操作容易引入内存错误,直接使用宏定义的字符串传入即可:

void setup() {
  Serial.begin(115200);
  setup_wifi();
  espClient.setCACert(root_ca);
  espClient.setCertificate(client_cert); 
  espClient.setPrivateKey(private_key);
  client.setServer(mqtt_server, mqtt_port);
}

3. 验证证书完整性

  • 确保root_ca、client_cert、private_key的每一行末尾\n完整,包括证书首尾的行
  • 检查证书内容无截断(代码中用*替代的部分需完整保留原始内容)

4. 指定SSL/TLS版本

NCP IoT平台可能要求特定的SSL/TLS版本,可手动指定适配:

espClient.setTLSVersion(TLSv1_2); // 若无效可尝试TLSv1_1

5. 调整MQTT客户端ID

部分服务器对客户端ID有唯一性要求,建议使用ESP32的MAC地址作为客户端ID:

void reconnect() {
  if (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    unsigned long startTime = millis();
    String clientId = "ESP32-" + WiFi.macAddress();
    if (client.connect(clientId.c_str())) {
      Serial.println("connected");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      delay(5000);
    }
    Serial.print("Connection attempt took ");
    Serial.print(millis() - startTime);
    Serial.println(" ms");
  }
}

6. 检查开发环境

  • 更新ESP32开发板包至最新版本,旧版本可能存在WiFiClientSecure兼容性问题
  • 确保PubSubClient库版本为2.8.0及以上

7. 网络环境验证

  • 确认Windows防火墙或路由器未拦截8883端口的出站流量
  • 使用MQTTX等第三方客户端,用相同的证书、密钥、地址和端口连接,验证服务器端是否正常

内容的提问来源于stack exchange,提问作者김민석

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 11:50:14