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

ESP32连接涂鸦MQTT标准协议失败求助(错误码rc=-4)

涂鸦IoT MQTT连接失败排查求助

问题背景

我参考涂鸦IoT的MQTT协议文档,在开发者平台创建了产品,但ESP32始终无法连接涂鸦MQTT服务器。测试连接公开MQTT服务器(test.mosquitto.org:1883)正常,说明基础MQTT功能没问题。

错误信息

连接时返回:

failed , rc=-4 try again in 5 seconds failed

根据PubSubClient文档,rc=-4表示服务器未在保活时间内响应,尝试将保活时间设为60秒后问题依旧。

代码实现

#include <Seeed_mbedtls.h>

#define KEY_SIZE 32  // 256 bits for HMAC-SHA256
#define OUTPUT_SIZE 32 // SHA-256 outputs 32 bytes

// Your 256-bit secret key (32 bytes)
String str = "DeviceSecret";
const uint8_t* deviceSecret = (const uint8_t*)str.c_str();

#include <WiFi.h>
WiFiClient wifiClient;

#include <time.h>     // include time library

// (utc+) TZ in hours
long timezone = 0; 
byte daysavetime = 0;

#include <PubSubClient.h>
PubSubClient client(wifiClient);

// Set up wifi
#define SSID "SSID"
#define WIFI_PWD "pwd"

// MQTT set up
#define MQTT_BROKER "m1.tuyacn.com"
#define MQTT_PORT (8883)

String compute_hmac_sha256(const uint8_t *key, size_t key_len, const uint8_t *input, size_t input_len) {
    mbedtls_md_context_t ctx;
    const mbedtls_md_info_t *md_info;
    uint8_t hmac_output[32]; // SHA-256 outputs 32 bytes

    mbedtls_md_init(&ctx);
    md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);

    if (md_info == NULL) {
        Serial.println("Failed to get MD info for SHA256");
        mbedtls_md_free(&ctx);
        return String();
    }

    if (mbedtls_md_setup(&ctx, md_info, 1) != 0) {
        Serial.println("Failed to setup MD context");
        mbedtls_md_free(&ctx);
        return String();
    }

    if (mbedtls_md_hmac_starts(&ctx, key, key_len) != 0) {
        Serial.println("Failed to start HMAC");
        mbedtls_md_free(&ctx);
        return String();
    }

    if (mbedtls_md_hmac_update(&ctx, input, input_len) != 0) {
        Serial.println("Failed to update HMAC");
        mbedtls_md_free(&ctx);
        return String();
    }

    if (mbedtls_md_hmac_finish(&ctx, hmac_output) != 0) {
        Serial.println("Failed to finish HMAC");
        mbedtls_md_free(&ctx);
        return String();
    }

    mbedtls_md_free(&ctx);

    // Convert the HMAC output to a hexadecimal string
    String hmac_str;
    for (int i = 0; i < sizeof(hmac_output); i++) {
        char buf[3];
        sprintf(buf, "%02x", hmac_output[i]);
        hmac_str += buf;
    }

    return hmac_str;
}

// the setup function runs once when you press reset or power the board
void setup() {
   Serial.begin(9600);
    Serial.print("Connecting to " SSID);
  WiFi.begin(SSID, WIFI_PWD); // attempt to connect to an existing wifi
  //Wait for wifi to connect
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(" . ");
    }
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  //Time Server Set up
  Serial.println("Contacting Time Server");
  configTime(3600*timezone, daysavetime*3600, "time.nist.gov", "0.pool.ntp.org", "1.pool.ntp.org");
  delay(1000);

  time_t now;
  time(&now); 

  //MQTT Credentials set up
  String MQTT_USERNAME = "deviceID|signMethod=hmacSha256,timestamp=" + String(now) +",secureMode=1,accessType=1";

      // Your original const char* message
    const char *message = "deviceId=deviceID,timestamp=,secureMode=1,accessType=1";

    // The String you want to insert
    String additional = String(now);

    // Convert the original message to a String
    String messageString = String(message);

    // Insert the additional String at the 43rd position
    size_t insertPos = 42; // Position to insert
    messageString = messageString.substring(0, insertPos) + additional + messageString.substring(insertPos);

    // Convert the modified message back to const char*
    const char* final_message = messageString.c_str();

  // Compute HMAC-SHA256
  String MQTT_PWD = compute_hmac_sha256(deviceSecret, KEY_SIZE, (const uint8_t *)final_message, strlen(final_message));
  Serial.println(now);

  Serial.print("MQTT_PWD: ");
  Serial.println(MQTT_PWD);

 Serial.println("init successfull");
 String tuyalink = "tuyalink_DeviceId";
    // Handle MQTT connection.
  client.setServer(MQTT_BROKER, MQTT_PORT); // set broker settings
  // 尝试过设置更长保活时间,无效
  // uint16_t keepAlive = 60;
  // client.setKeepAlive(keepAlive);
  while (! client.connected()) { // check connected status
    if ( client.connect(tuyalink.c_str(),MQTT_USERNAME.c_str(),MQTT_PWD.c_str())){ // connect with random id
      Serial.println("MQTT connected."); // report success
      //client.subscribe("Test/ra542");
    } else {
      Serial. printf (" failed , rc=%d try again in 5 seconds", client.state ()); // report error
      delay(5000); // wait 5 seconds
    }
  }
}

// the loop function runs over and over again forever
void loop() {
Serial.println("Hello World!");
delay(5000);
}

注:代码中已替换实际的deviceId和DeviceSecret,SSID和WiFi密码也已替换为真实值。

已尝试的排查步骤

  • 确认WiFi连接正常,能获取IP并访问公网
  • 测试连接test.mosquitto.org:1883无凭证连接成功,排除PubSubClient库和ESP32硬件问题
  • 增加MQTT保活时间至60秒,问题依旧
  • 检查NTP时间同步,已获取到正确的UTC时间

请求帮助

希望得到排查思路或具体的修复建议,比如签名计算是否正确、MQTT参数是否符合涂鸦要求、SSL连接是否有问题等。

内容的提问来源于stack exchange,提问作者Ryan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 17:17:32