Reputation: 11
I am trying to perform OTA update using ESP32 and @thingsboard community version. I am using mqtt in esp32 to connect with Thingsboard. What I have achieved is: When I am updating firmware in Thingsboard DEVICE PROFILE which is attached with my device and device to dashboard, I am getting notification that payload load arrived from subscribed topic and showing payload as well as it is showing that OTA Initialized. But actual update is not happening because in no way esp32 getting the .bin file from Thingsboard. How can I achieve actual firmware update?
In thingsboard: I have added edge rule chain and attached that with root rule chain. Setup of device profile, device and dashboard is also done.
ESP32 script: (I know I have not included update.h and other dependencies because .bin not coming up.)
OUTPUT:
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
}
Upvotes: 0
Views: 626
Reputation: 1
Try the logic from this code. Maybe it would be of some use to you.
`
#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);
}
`
Note: This is a sample code that only shows the logic. The version modified to my needs works so it should work for you too. Please let me know if there's anything you need me to clarify.
Upvotes: 0