在 ESP32 中尝试使用 @thingsboard 进行 OTA 固件更新

问题描述 投票:0回答:1

我正在尝试使用 ESP32 和 @thingsboard 社区版本执行 OTA 更新。我在 esp32 中使用 mqtt 来连接 Thingsboard。 我所取得的成就是:当我更新与我的设备和设备附加到仪表板的 Thingsboard DEVICE PROFILE 中的固件时,我收到通知,有效负载来自订阅的主题,并显示有效负载,并且显示 OTA 已初始化。但实际更新并未发生,因为 esp32 无法从 Thingsboard 获取 .bin 文件。如何才能实现真正的固件更新?

在事物板中: 我添加了边缘规则链并将其附加到根规则链。 设备配置文件、设备和仪表板的设置也已完成。

ESP32 脚本:(我知道我没有包含 update.h 和其他依赖项,因为 .bin 没有出现。)

输出:

Payload: {"fw_title":"OTA","fw_version":"1.4","fw_tag":"OTA 1.4","fw_size":823792,"fw_checksum_algorithm":"SHA256","fw_checksum":"a5a0c30171ae48e611efd254cd164f94427d128f57a0114d6e1eac7ba89bd7ec"}
// printing the received pyload
#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoOTA.h>

// WiFi credentials
const char* ssid = "CURRENT";
const char* password = "11111111";

// ThingsBoard MQTT broker configuration
const char* mqttServer = "111.93.67.82";
const int mqttPort = 7045;
const char* mqttAccessToken = "gGnF3jGV0pGp7uvuFlHz"; // Replace with your device access token
const char* mqttTopic = "v1/devices/me/attributes";
const char* mqttPassword = ""; // Leave empty if no password is required

WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);

bool otaUpdateRequested = false;

// OTA update started event handler
void handleOTAStart() {
  Serial.println("OTA update started");
}

// OTA update in progress event handler
void handleOTAProgress(unsigned int progress, unsigned int total) {
  Serial.printf("OTA update progress: %u%%\n", (progress / (total / 100)));
}

// OTA update completed event handler
void handleOTAEnd() {
  Serial.println("OTA update completed");
}

// OTA update error event handler
void handleOTAError(ota_error_t error) {
  Serial.printf("OTA update error[%u]: ", error);
  if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
  else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
  else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
  else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
  else if (error == OTA_END_ERROR) Serial.println("End Failed");
}

void setupOTA() {
  // Set the port for OTA updates
  ArduinoOTA.setPort(3232);

  // Set the hostname for the ESP32 device
  ArduinoOTA.setHostname("ESP32_OTA-DEVICE");

  // Set OTA event handlers
  ArduinoOTA.onStart(handleOTAStart);
  ArduinoOTA.onProgress(handleOTAProgress);
  ArduinoOTA.onEnd(handleOTAEnd);
  ArduinoOTA.onError(handleOTAError);

  // Uncomment and set a password if needed
  // ArduinoOTA.setPassword("YOUR_OTA_PASSWORD");

  // Start OTA server
  ArduinoOTA.begin();
}

void setupMQTT() {
  mqttClient.setServer(mqttServer, mqttPort);
  mqttClient.setCallback(mqttCallback);
}

void mqttCallback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] Payload: ");
  // Print the payload
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
  
  // Check if the topic is for OTA update
  if (strcmp(topic, "v1/devices/me/attributes") == 0) {
    if (length > 0) {
      // Process the received binary data here
      // For simplicity, we'll just set a flag to indicate OTA update
      Serial.println("OTA update requested");
      otaUpdateRequested = true;
    } else {
      Serial.println("Empty payload received");
    }
  } else {
    // Handle other topics if necessary
  }
}

void reconnectMQTT() {
  while (!mqttClient.connected()) {
    Serial.print("Attempting MQTT connection...");
    if (mqttClient.connect(mqttAccessToken, mqttAccessToken, mqttPassword)) {
      Serial.println("connected");
      mqttClient.subscribe(mqttTopic);
    } else {
      Serial.print("failed, rc=");
      Serial.print(mqttClient.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
  }
}

// setup() and loop() functions...
void setup() {
  Serial.begin(115200);
  Serial.println("Booting");

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Serial.println("Connection Failed! Rebooting...");
    delay(5000);
    ESP.restart();
  }

  setupOTA();
  setupMQTT();
}

void loop() {
  if (!mqttClient.connected()) {
    reconnectMQTT();
  }
  mqttClient.loop();
  
  if (otaUpdateRequested) {
    Serial.println("Initiating OTA update...");
    otaUpdateRequested = false; // Reset the flag
    ArduinoOTA.begin(); // Start OTA update
  }
  ArduinoOTA.handle(); // Handle OTA update process
  // Your main application code goes here
}

arduino mqtt esp32 thingsboard ota
1个回答
0
投票

尝试此代码中的逻辑。也许对你有用。

`

#include <Arduino.h>
#include <ArduinoJson.h>
#include <WiFi.h>

#include <HTTPClient.h>
#include <ESP32httpUpdate.h>

#define USE_SERIAL Serial

TaskHandle_t Task1;

int updateRetryCount = 3;

String gsCurr_Title = "<title>";
String gsCurr_Version = "<version>";
String deviceCred= "<Access Token>";

String giServerName = "<serverURL>";
void setup() {

  USE_SERIAL.begin(115200);
  pinMode(2, OUTPUT);
  // USE_SERIAL.setDebugOutput(true);
  USE_SERIAL.println();
  USE_SERIAL.println();
  USE_SERIAL.println();

  gvconnectwifi();
  OTA_Update();
}

void gvconnectwifi() {
  WiFi.begin("<SSID>", "<Password>");
  Serial.println("Connected to wifi:");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.println("Connecting to WiFi..");
  }

  Serial.println("Connected to the WiFi network");
}

void OTA_Update() {

  String tsPayload;
  if ((WiFi.status() == WL_CONNECTED)) {

    HTTPClient http;
    String tsServerPath_getinfo = giServerName + "/api/v1/"+deviceCred+"/attributes?sharedKeys=fw_title,fw_version,fw_location";
    http.begin(tsServerPath_getinfo.c_str());

    int tiHttpResponseCode = http.GET();

    if (tiHttpResponseCode > 0) {
      Serial.print("HTTP Response code: ");
      Serial.println(tiHttpResponseCode);
      tsPayload = http.getString();
    }
    else {
      Serial.print("Error code: ");
      Serial.println(tiHttpResponseCode);
    }
    http.end();

    StaticJsonDocument<2048> doc;
    deserializeJson(doc, tsPayload);

    String tsTitle = doc["shared"]["fw_title"];
    String tsVersion = doc["shared"]["fw_version"];

    Serial.println(tsTitle);
    Serial.println(tsVersion);
    String tsServerPath_Firmware = giServerName + "/api/v1/"+deviceCred+"/firmware?title=" + tsTitle + "&version=" + tsVersion;

    if (gsCurr_Version != tsVersion || gsCurr_Location != tsLocation) {
      t_httpUpdate_return ret = ESPhttpUpdate.update(tsServerPath_Firmware.c_str());

      switch (ret) {
        case HTTP_UPDATE_FAILED:
          USE_SERIAL.printf("HTTP_UPDATE_FAILD Error (%d): %s", ESPhttpUpdate.getLastError(), ESPhttpUpdate.getLastErrorString().c_str());
          Serial.println("");
          gvsend_info(tsTitle, tsVersion, tsLocation, "FAILED");
          if (updateRetryCount > 0) {
            updateRetryCount--;
            USE_SERIAL.printf("Retrying update, attempts left: %d", updateRetryCount);
            delay(5000); // Add a delay before retrying (adjust as needed)
            OTA_Update();
          } else {
            USE_SERIAL.println("Max retry attempts reached. Giving up.");
          }
          break;

        case HTTP_UPDATE_OK:
          USE_SERIAL.println("HTTP_UPDATE_OK");
          gvsend_info(tsTitle, tsVersion, tsLocation, "UPDATED");
          break;
      }
    } else {
      gvsend_info(gsCurr_Title, gsCurr_Version, gsCurr_Location, "UPDATED");
    }
  }
}

void gvsend_info(String tsTitle, String tsVersion, String tsLocation, String State) {

  HTTPClient http;
  String tsServerPath_sendinfo = giServerName + "/api/v1/" + deviceCred + "/telemetry";
  http.begin(tsServerPath_sendinfo.c_str());
  DynamicJsonDocument doc_SendInfo(2048);

  if (State == "UPDATED") {
    doc_SendInfo["current_fw_title"] = tsTitle;
    doc_SendInfo["current_fw_version"] = tsVersion;
  } else {
    doc_SendInfo["fw_error"] = "Firmwate Update Failed";
  }

  doc_SendInfo["fw_state"] = State;

  char buff[256];
  serializeJson(doc_SendInfo, buff );

  int tiHttpResponseCode_send = http.POST(buff);

  Serial.print("HTTP_send Response code: ");
  Serial.println(tiHttpResponseCode_send);
  Serial.print("Sending buffer: ");
  Serial.println(buff);

  http.end();
}

void loop() {
  digitalWrite(2, HIGH);
  USE_SERIAL.println("HIGH");
  delay(2000);

  digitalWrite(2, LOW);
  USE_SERIAL.println("LOW");
  delay(500);
}

`

注意: 这是示例代码,仅显示逻辑。根据我的需要修改的版本可以工作,因此它也应该适合您。如果您需要我澄清什么,请告诉我。

© www.soinside.com 2019 - 2024. All rights reserved.