Page 1 of 1

OTA Update through MQTT fails

Posted: Wed Oct 30, 2024 1:10 pm
by nasir916
Hello Everyone
I am working on implementing OTA updates received via MQTT in an ESP32 project using the ESP-IDF framework. The OTA update process involves receiving packets over MQTT. However, when I attempt to finalize the OTA update, it does not go through. I have added debug statements to trace the process and it is stopped on "Update handle is invalid. Cannot finalize OTA.". I am using platformio with esp idf framework.
Below you can find my code for mqtt event handler where all this is happening.
Could anyone suggest what might be causing this issue or where I should look for potential problems?

Thanks in advance

void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) {
esp_mqtt_event_handle_t event = (esp_mqtt_event_handle_t) event_data;

switch (event->event_id) {
case MQTT_EVENT_CONNECTED:
ESP_LOGI(TAG, "MQTT connected");
esp_mqtt_client_subscribe(mqtt_client, UPDATE_TOPIC, 1);
break;

case MQTT_EVENT_DATA:
if (event->topic_len == strlen(UPDATE_TOPIC) && strncmp(event->topic, UPDATE_TOPIC, event->topic_len) == 0) {
ESP_LOGI(TAG, "Received OTA data: %.*s", event->data_len, event->data);

// Allocate memory for the payload and null-terminate it
char* json_payload = (char*) malloc(event->data_len + 1);
if (!json_payload) {
ESP_LOGE(TAG, "Failed to allocate memory for JSON payload");
return;
}
memcpy(json_payload, event->data, event->data_len);
json_payload[event->data_len] = '\0';

ESP_LOGI(TAG, "Full JSON payload received: %s", json_payload);

if (json_payload[0] != '{' || json_payload[event->data_len - 1] != '}') {
ESP_LOGE(TAG, "Invalid JSON format: %s", json_payload);
free(json_payload);
return;
}

cJSON* json = cJSON_Parse(json_payload);
free(json_payload);

if (!json) {
ESP_LOGE(TAG, "JSON parsing error");
return;
}

// Check for EOF to finalize OTA
cJSON* eof = cJSON_GetObjectItem(json, "EOF");
if (eof && cJSON_IsString(eof) && strlen(eof->valuestring) == 0) {
ESP_LOGI(TAG, "Received EOF, finalizing OTA update");

if (update_handle != ESP_OTA_HANDLE_INVALID) {
esp_err_t end_result = esp_ota_end(update_handle);
if (end_result != ESP_OK) {
ESP_LOGE(TAG, "esp_ota_end failed: %s", esp_err_to_name(end_result));
update_handle = ESP_OTA_HANDLE_INVALID;
cJSON_Delete(json);
return;
}

esp_err_t boot_result = esp_ota_set_boot_partition(update_partition);
if (boot_result != ESP_OK) {
ESP_LOGE(TAG, "esp_ota_set_boot_partition failed: %s", esp_err_to_name(boot_result));
cJSON_Delete(json);
return;
}

ESP_LOGI(TAG, "Restarting the device...");
esp_restart();
} else {
ESP_LOGE(TAG, "Update handle is invalid. Cannot finalize OTA.");
}
} else {
// Get the packet sequence number
cJSON* packet_num = cJSON_GetObjectItem(json, "i");
if (packet_num && cJSON_IsNumber(packet_num)) {
packet_counter = packet_num->valueint;
}

// Only decode base64 if this is not the first or last packet
if (packet_counter > 1 && !eof) {
cJSON* payload = cJSON_GetObjectItem(json, "p");
if (payload && cJSON_IsString(payload)) {
const char* b64_data = payload->valuestring;
char binary_data[CHUNK_SIZE];

int decoded_size = base64_decode(binary_data, b64_data);
if (decoded_size < 0) {
ESP_LOGE(TAG, "Failed to decode base64 data");
cJSON_Delete(json);
return;
}

// Initialize update handle if not already done
if (update_handle == ESP_OTA_HANDLE_INVALID) {
update_partition = esp_ota_get_next_update_partition(NULL);
if (!update_partition) {
ESP_LOGE(TAG, "No available partition for OTA update");
cJSON_Delete(json);
return;
}

esp_err_t begin_result = esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle);
if (begin_result != ESP_OK) {
ESP_LOGE(TAG, "esp_ota_begin failed: %s", esp_err_to_name(begin_result));
update_handle = ESP_OTA_HANDLE_INVALID;
cJSON_Delete(json);
return;
}
ESP_LOGI(TAG, "OTA begin succeeded, update_handle: %lu", (unsigned long)update_handle);
}

// Only write if update_handle is valid
if (update_handle != ESP_OTA_HANDLE_INVALID) {
esp_err_t write_result = esp_ota_write(update_handle, binary_data, decoded_size);
if (write_result != ESP_OK) {
ESP_LOGE(TAG, "Failed to write OTA data: %s", esp_err_to_name(write_result));
} else {
ESP_LOGI(TAG, "Wrote %d bytes to OTA", decoded_size);
}
} else {
ESP_LOGE(TAG, "Update handle is invalid during write.");
}
} else {
ESP_LOGE(TAG, "Base64 payload missing or invalid");
}
} else {
ESP_LOGI(TAG, "Skipping base64 decoding for first or last payload");
}
}

cJSON_Delete(json);
}
break;

case MQTT_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "MQTT disconnected");
break;

case MQTT_EVENT_ERROR:
ESP_LOGE(TAG, "MQTT event error");
break;

default:
break;
}
}

Re: OTA Update through MQTT fails

Posted: Wed Oct 30, 2024 11:57 pm
by ESP_Sprite
What does your debug log look like? Are you sure ota_begin is called in the first place?

Re: OTA Update through MQTT fails

Posted: Thu Oct 31, 2024 1:08 pm
by nasir916
Yeah it got fixed , it was not going in the ota begin condition.