Tuya MQTT standard protocol on an esp32

Let's chat here.


Post Reply
ra542
Posts: 1

Sorry if this isn't the right place for this post, Just wondering if someone maybe able to help

I'm trying to connect to the Tuya IoT Developer platform using https://developer.tuya.com/en/docs/iot/ ... 5nphxrj8f1 as a reference.
I've created a product in the developer portal already but can't seem to get my esp32 to connect to the Tuya MQTT servers.

Here's what I've written

Code: Select all

#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

//MQTT server
#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
  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);

        
}

In my final code I've replaced the deviceId and DeviceSecret with the credentials I've gotten from tuya

On Connecting to the MQTT Server I get

Code: Select all

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

According to https://pubsubclient.knolleary.net/api#state rc -4 means the server didn't respond within the keepalive time.

I've tried increasing the keep alive time to 60s but that doesn't change anything

Code: Select all

  uint16_t keepAlive = 60000;
  client.setKeepAlive(keepAlive);

When Testing with test.mosquitto.org and port 1883 without credentials it seems to work fine.
I'm not sure where I'm going wrong here. Any ideas/pointers would be greatly appreciated

愚者千虑必有一得
Posts: 454

Re: Tuya MQTT standard protocol on an esp32

Hello, we have released a new open-source SDK that supports connecting to Tuya Cloud via MQTT, as well as core functions such as network configuration, control, and upgrades through the Tuya APP. We will release support for ESP32 series June 15, 2024. You may want to wait a bit and then directly use this SDK.

The github is:https://github.com/tuya/tuya-open-sdk-for-device

Post Reply