Fix web OTA upload and isolate OTA sessions across firmware and goTool.

Split ESP-NOW into core/master/slave modules, block non-OTA UART traffic during updates, and hold the host serial port exclusively so dashboard polling cannot interleave with firmware uploads.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-05-31 16:35:18 +02:00
co-authored by Cursor
parent 0cbc4d0644
commit 0eea27a876
29 changed files with 1828 additions and 1416 deletions
+43 -19
View File
@@ -81,8 +81,6 @@ static const ota_espnow_progress_cbs_t s_dist_progress = {
static void ota_prepare_task(void *param) {
uint32_t total_size = (uint32_t)(uintptr_t)param;
send_ota_status(OTA_UART_ST_PREPARING, 0);
int slot = ota_uart_prepare(total_size);
if (slot < 0) {
send_ota_failed(1);
@@ -116,27 +114,32 @@ static void handle_ota_start(const uint8_t *data, size_t len) {
const alox_OtaStartPayload *req_ptr =
UART_CMD_REQ(&uart_msg, alox_UartMessage_ota_start_tag, ota_start);
if (req_ptr != NULL) {
req = *req_ptr;
if (req_ptr == NULL) {
ESP_LOGW(TAG, "OTA_START: missing ota_start payload");
send_ota_failed(3);
return;
}
req = *req_ptr;
if (req.total_size == 0) {
ESP_LOGW(TAG, "OTA_START: total_size required");
send_ota_failed( 3);
send_ota_failed(3);
return;
}
if (ota_uart_is_active()) {
ESP_LOGW(TAG, "OTA_START while session active");
send_ota_failed( 4);
send_ota_failed(4);
return;
}
send_ota_status(OTA_UART_ST_PREPARING, 0);
if (xTaskCreate(ota_prepare_task, "ota_prepare", OTA_PREPARE_STACK,
(void *)(uintptr_t)req.total_size, OTA_PREPARE_PRIO,
NULL) != pdPASS) {
ESP_LOGE(TAG, "failed to create ota_prepare task");
send_ota_failed( 5);
send_ota_failed(5);
}
}
@@ -293,31 +296,28 @@ static void handle_ota_end(const uint8_t *data, size_t len) {
}
}
static void handle_ota_start_espnow(const uint8_t *data, size_t len) {
(void)data;
(void)len;
if (ota_uart_is_active()) {
send_ota_failed( 40);
return;
}
static void ota_start_espnow_task(void *param) {
(void)param;
const esp_partition_t *part = NULL;
uint32_t image_size = 0;
if (!ota_uart_get_staged_image(&part, &image_size)) {
send_ota_failed( 41);
send_ota_failed(41);
vTaskDelete(NULL);
return;
}
esp_err_t err = ota_espnow_distribute(part, image_size, &s_dist_progress);
esp_err_t err = ota_espnow_distribute(part, image_size, &s_dist_progress);
if (err != ESP_OK) {
send_ota_failed( 42);
send_ota_failed(42);
vTaskDelete(NULL);
return;
}
err = ota_uart_apply_boot();
if (err != ESP_OK) {
send_ota_failed( (uint32_t)err);
send_ota_failed((uint32_t)err);
vTaskDelete(NULL);
return;
}
@@ -329,6 +329,30 @@ static void handle_ota_start_espnow(const uint8_t *data, size_t len) {
response.payload.ota_status.error = 0;
uart_cmd_send(&response, TAG);
led_ring_ota_success();
vTaskDelete(NULL);
}
static void handle_ota_start_espnow(const uint8_t *data, size_t len) {
(void)data;
(void)len;
if (ota_uart_is_active()) {
send_ota_failed(40);
return;
}
const esp_partition_t *part = NULL;
uint32_t image_size = 0;
if (!ota_uart_get_staged_image(&part, &image_size)) {
send_ota_failed(41);
return;
}
if (xTaskCreate(ota_start_espnow_task, "ota_espnow", OTA_DIST_STACK, NULL,
OTA_DIST_PRIO, NULL) != pdPASS) {
ESP_LOGE(TAG, "failed to create ota_start_espnow task");
send_ota_failed(43);
}
}
void cmd_ota_register(void) {