Skip to content
Snippets Groups Projects
mqtt_ota.cpp 2.64 KiB
Newer Older
#include "mqtt_ota.h"

#include "esp_log.h"
fxk8y's avatar
fxk8y committed
#include "esp_system.h"
#include "esp_ota_ops.h"

#include <qthing.h>

#define TAG "MQTT_OTA"

fxk8y's avatar
fxk8y committed

fxk8y's avatar
fxk8y committed
void default_ota_event(ota_event_t event);
ota_callback_t ota_handler = default_ota_event;

fxk8y's avatar
fxk8y committed
esp_ota_handle_t ota_handle = 0;
const esp_partition_t* partition = NULL;

void handle_ota_message(const multipart_message_t& message) {
fxk8y's avatar
fxk8y committed
    ESP_LOGD(TAG, "length=%d offset=%d", message.length, message.offset);
fxk8y's avatar
fxk8y committed

    esp_err_t err;

    if (message.offset == 0) {  // first ota message
        partition = esp_ota_get_next_update_partition(NULL);
        err = esp_ota_begin(partition, message.total_length, &ota_handle);
        if (err != ESP_OK) ESP_LOGW(TAG, "BEGIN OTA FAILED!");
fxk8y's avatar
fxk8y committed

        ota_event_t event = {
            .state = start,
            .error = err,
            .bytes_written = 0,
            .bytes_total = (uint32_t)message.total_length
        };
        ota_handler(event);
fxk8y's avatar
fxk8y committed
    }

    err = esp_ota_write(ota_handle, (const void*) message.payload, message.length);
    if (err != ESP_OK) ESP_LOGW(TAG, "WRITE OTA FAILED!");

fxk8y's avatar
fxk8y committed
    ota_event_t event = {
        .state = progress,
        .error = err,
        .bytes_written = (uint32_t)(message.length + message.offset),
        .bytes_total = (uint32_t)message.total_length
    };
    ota_handler(event);

fxk8y's avatar
fxk8y committed
    if (message.offset + message.length == message.total_length) {  // last ota message
        err = esp_ota_end(ota_handle);
        if (err != ESP_OK) ESP_LOGW(TAG, "END OTA FAILED!");
fxk8y's avatar
fxk8y committed

        ota_event_t event = {
            .state = success,
            .error = err,
            .bytes_written = (uint32_t)message.total_length,
            .bytes_total = (uint32_t)message.total_length
        };
        ota_handler(event);

fxk8y's avatar
fxk8y committed
        err = esp_ota_set_boot_partition(partition);
        if (err != ESP_OK) ESP_LOGW(TAG, "FINALIZE OTA FAILED!");
    }

}

fxk8y's avatar
fxk8y committed
void default_ota_event(ota_event_t event) {
    switch(event.state) {
        case start:
            ESP_LOGI(TAG, "OTA Start");
            break;
        case progress: {
            float pct = ((float)event.bytes_written / (float)event.bytes_total) * 100;
            ESP_LOGI(TAG, "OTA Progress %d%% (%d/%d KiB)", (int)pct, event.bytes_written / 1024, event.bytes_total / 1024);
            break;
        }
        case success:
            ESP_LOGI(TAG, "OTA Successful");
            break;
        case error:
            ESP_LOGW(TAG, "OTA Error 0x%x", event.error);
            break;
    }
}

void add_ota_callback(ota_callback_t handler) {
    ota_callback_t old_ota_handler = ota_handler;
    ota_handler = [old_ota_handler, handler](ota_event_t event){
        old_ota_handler(event);
        handler(event);
    };
}