Problem with OTA update ESP32. Bytes lost

130 views Asked by At

good afternoon, I hope someone can help me with the following problem.

Situation: I have a flutter app connected to a websockets server hosted on esp32 with the links2004/websockets library (https://github.com/Links2004/arduinoWebSockets). I try to pass the firmware through the socket as binary, this process is correct, I also add an identifier byte (to know that I am in update) and the next one to know if it is the last one, to conclude I add a byte at the end as a result of calculating the checksum of the frame.

At both ends I check the checksum and the amount of data but I get the following error:

premature end: res:0, pos:864256/1966080

Most relevant code and debugging traces:

    esp_err_t Updater::handleUpdateData(const uint8_t *data, size_t length)
    {
    //debug vars.
    static int k;
    static int j;
    if (!isUpdateInProgress)
    {
        logger().log("Fatal error, the update isn't started", debug_info_t::WARNING_D);
        return ESP_FAIL;
    }
    if (length < 3)
    {   
        //As I said, I add 3 bytes, therefore at least the frame must contain 3 bytes
        logger().log("Frame length is incosistent, frame is broken", debug_info_t::WARNING_D);
        return ESP_FAIL;
    }
    //To check that it is the last frame, I mark it with the 0xff flag
    bool isLastFragment = (data[1] == 0xFF);

    //the last byte of the frame contains the checksum
    uint8_t receivedChecksum = data[length - 1];
    uint8_t calculatedChecksum = getChecksum(data + 2, length - 3);

    if (calculatedChecksum != receivedChecksum)
    {
        //At this point, if the checksum does not match it would throw an error
        logger().log("Checksum mismatch.", debug_info_t::WARNING_D);
        return ESP_FAIL;
    }

    k+=length-3;
    logger().log(std::to_string(k).c_str());    
    //We write the data to the OTA partition and store its result, to verify that it is exactly           
    //the length received minus the 3 bytes that are not from the firmware
    size_t result=Update.write(const_cast<uint8_t *>(data) + 2, length - 3);
    if ( result!= length - 3) 
    {
      
        logger().log("Failed to write OTA update data.", debug_info_t::WARNING_D);
        return ESP_FAIL;
    }else{
        //debug to check how many bytes are being written to each packet
        std::string s="Packet"+std::to_string(j)+" writted"+ std::to_string(result);
        j++;
        logger().log(s.c_str());
    }

    if (isLastFragment)
    {
        
        std::string lastPacket="Last packet length: "+std::to_string(length-3);
        logger().log(lastPacket.c_str());
        if (!Update.end())
        {
            logger().log("Failed to finalize OTA update.", debug_info_t::WARNING_D);
            return ESP_FAIL;
        }
        else if (Update.isFinished())
        {
            logger().log("OTA update completed successfully.", debug_info_t::DEBUG_D);
           
            ESP.restart(); 
        }
        else
        {
            logger().log("OTA update not finished.", debug_info_t::WARNING_D);
            return ESP_FAIL;
        }
    }

    return ESP_OK;
    }
Debug traces flutter side:
I/flutter ( 5132):packet 0=> 10048

.....
I/flutter ( 5132):packet 85=> 864128
I/flutter ( 5132):packet 86=> 865712

Debug traces ESP32 side:

[INFO]: Packet0 writted=>10048
[INFO]: total=>10048
....
[INFO]: Packet85 writted=>10048
[INFO]: total=> 864128
[INFO]: Packet86 writted=>1584
[INFO]: total=> 865712

Viewing the properties of my firmware.bin file according to the OS explorer (liux), the firmware occupies 865712 bytes.

So I get the following error message: [ 19662][E][Updater.cpp:284] end(): premature end: res:0, pos:864256/1966080

1456bytes have been lost and I don't understand why.

If anyone can help me I would be very grateful.

1

There are 1 answers

0
WikiLift On

After a few intensive tests, I finally got it, I leave the implementation of the class in case it helps someone, thank you very much anyway. Remember that I use 2 bytes at the beginning and one at the end for the checksum.

#include "update_ota.h"
#include "log/log_service.h"

bool Updater::initializeOta(const esp_partition_t **update_partition, 
esp_ota_handle_t *ota_handle, char *log_buffer)
{
*update_partition = esp_ota_get_next_update_partition(nullptr);
if (*update_partition == nullptr)
{
    logger().log("No OTA partition found");
    return false;
}
isUpdateInProgress = true;

esp_err_t err = esp_ota_begin(*update_partition, OTA_SIZE_UNKNOWN, 
ota_handle);
if (err != ESP_OK)
{
    snprintf(log_buffer, sizeof(log_buffer), "esp_ota_begin failed (%s)", 
esp_err_to_name(err));
    logger().log(log_buffer);
    return false;
}

return true;
}
bool Updater::isLastFragment(const uint8_t *data)
{
return data[1] == 0xFF;
}


bool Updater::writeOtaData(esp_ota_handle_t ota_handle, const uint8_t 
*data, 
size_t length, char *log_buffer)
{
esp_err_t err = esp_ota_write(ota_handle, data + 2, length - 3);
if (err != ESP_OK)
{
    snprintf(log_buffer, sizeof(log_buffer), "esp_ota_write failed (%s)", 
esp_err_to_name(err));
    logger().log(log_buffer);
    esp_ota_abort(ota_handle);
    return false;
}
return true;
}

esp_err_t Updater::finalizeOta(esp_ota_handle_t ota_handle, const 
esp_partition_t *update_partition, char *log_buffer)
{
esp_err_t err = esp_ota_end(ota_handle);
if (err != ESP_OK)
{
    snprintf(log_buffer, sizeof(log_buffer), "esp_ota_end failed (%s)", 
esp_err_to_name(err));
    logger().log(log_buffer);
    return ESP_FAIL;
}

err = esp_ota_set_boot_partition(update_partition);
if (err != ESP_OK)
{
    snprintf(log_buffer, sizeof(log_buffer), "esp_ota_set_boot_partition 
failed (%s)", esp_err_to_name(err));
    logger().log(log_buffer);
    return ESP_FAIL;
}

logger().log("OTA update completed successfully, rebooting...");
vTaskDelay(pdMS_TO_TICKS(1000));
esp_restart();
return ESP_OK;
}

bool Updater::validatePacket(const uint8_t *data, size_t length, char 
*log_buffer, esp_ota_handle_t ota_handle)
{
if (length < 3)
{
    logger().log("Received packet size is too small");
    return false;
}
bool isLastFragment = (data[1] == 0xFF);
uint8_t receivedChecksum = data[length - 1];
uint8_t calculatedChecksum = getChecksum(data + 2, length - 3);
if (calculatedChecksum != receivedChecksum)
{
    logger().log("Checksum mismatch");
    esp_ota_abort(ota_handle);
    return false;
}
return true;
}
esp_err_t Updater::handleUpdateData(const uint8_t *data, size_t length)
{
static const esp_partition_t *update_partition = nullptr;
static esp_ota_handle_t ota_handle;

char log_buffer[128];

if (!isUpdateInProgress)
{
    if (!initializeOta(&update_partition, &ota_handle, log_buffer))
    {
        return ESP_FAIL;
    }
}

if (!validatePacket(data, length, log_buffer, ota_handle))
{
    return ESP_FAIL;
}

if (!writeOtaData(ota_handle, data, length, log_buffer))
{
    return ESP_FAIL;
}

if (isLastFragment(data))
{
    return finalizeOta(ota_handle, update_partition, log_buffer);
}

return ESP_OK;
}