我正在尝试使用 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
}
尝试此代码中的逻辑。也许对你有用。
`
#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);
}
`
注意: 这是示例代码,仅显示逻辑。根据我的需要修改的版本可以工作,因此它也应该适合您。如果您需要我澄清什么,请告诉我。