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:
@@ -33,12 +33,20 @@ static void handle_accel_stream(const uint8_t *data, size_t len) {
|
||||
alox_UartMessage uart_msg;
|
||||
alox_AccelStreamRequest req = alox_AccelStreamRequest_init_zero;
|
||||
|
||||
if (uart_cmd_decode(data, len, &uart_msg) == ESP_OK) {
|
||||
if (len > 0) {
|
||||
if (uart_cmd_decode(data, len, &uart_msg) != ESP_OK) {
|
||||
ESP_LOGW(TAG, "decode failed");
|
||||
reply(false, 0, false, 0);
|
||||
return;
|
||||
}
|
||||
const alox_AccelStreamRequest *req_ptr = UART_CMD_REQ(
|
||||
&uart_msg, alox_UartMessage_accel_stream_request_tag, accel_stream_request);
|
||||
if (req_ptr != NULL) {
|
||||
req = *req_ptr;
|
||||
if (req_ptr == NULL) {
|
||||
ESP_LOGW(TAG, "missing accel_stream_request");
|
||||
reply(false, 0, false, 0);
|
||||
return;
|
||||
}
|
||||
req = *req_ptr;
|
||||
}
|
||||
|
||||
if (req.write) {
|
||||
|
||||
+21
-7
@@ -67,14 +67,28 @@ static void handle_battery_status(const uint8_t *data, size_t len) {
|
||||
|
||||
if (len > 0) {
|
||||
alox_UartMessage uart_msg;
|
||||
if (uart_cmd_decode(data, len, &uart_msg) == ESP_OK) {
|
||||
const alox_BatteryStatusRequest *req_ptr = UART_CMD_REQ(
|
||||
&uart_msg, alox_UartMessage_battery_status_request_tag,
|
||||
battery_status_request);
|
||||
if (req_ptr != NULL) {
|
||||
req = *req_ptr;
|
||||
}
|
||||
if (uart_cmd_decode(data, len, &uart_msg) != ESP_OK) {
|
||||
ESP_LOGW(TAG, "decode failed");
|
||||
alox_UartMessage response;
|
||||
uart_cmd_init_response(&response, alox_MessageType_BATTERY_STATUS,
|
||||
alox_UartMessage_battery_status_response_tag);
|
||||
response.payload.battery_status_response.success = false;
|
||||
uart_cmd_send(&response, TAG);
|
||||
return;
|
||||
}
|
||||
const alox_BatteryStatusRequest *req_ptr = UART_CMD_REQ(
|
||||
&uart_msg, alox_UartMessage_battery_status_request_tag,
|
||||
battery_status_request);
|
||||
if (req_ptr == NULL) {
|
||||
ESP_LOGW(TAG, "missing battery_status_request");
|
||||
alox_UartMessage response;
|
||||
uart_cmd_init_response(&response, alox_MessageType_BATTERY_STATUS,
|
||||
alox_UartMessage_battery_status_response_tag);
|
||||
response.payload.battery_status_response.success = false;
|
||||
uart_cmd_send(&response, TAG);
|
||||
return;
|
||||
}
|
||||
req = *req_ptr;
|
||||
}
|
||||
|
||||
alox_UartMessage response;
|
||||
|
||||
+8
-21
@@ -1,4 +1,5 @@
|
||||
#include "cmd_handler.h"
|
||||
#include "ota_session.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
@@ -88,33 +89,19 @@ esp_err_t msg_register_handler(uint16_t id, msg_callback_t cb) {
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t msg_post(uint16_t id, const uint8_t *data, size_t len) {
|
||||
if (cmd_queue == NULL) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
generic_msg_t msg = {.msg_id = id, .len = len, .payload = NULL};
|
||||
if (len > 0) {
|
||||
msg.payload = malloc(len);
|
||||
if (msg.payload == NULL) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
memcpy(msg.payload, data, len);
|
||||
}
|
||||
|
||||
if (xQueueSend(cmd_queue, &msg, pdMS_TO_TICKS(100)) != pdPASS) {
|
||||
free(msg.payload);
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void vCmdDispatcherTask(void *param) {
|
||||
(void)param;
|
||||
generic_msg_t msg;
|
||||
|
||||
while (1) {
|
||||
if (xQueueReceive(cmd_queue, &msg, portMAX_DELAY) == pdPASS) {
|
||||
if (!ota_session_uart_cmd_allowed(msg.msg_id)) {
|
||||
ESP_LOGW(TAG, "reject %s (0x%02x) during OTA session",
|
||||
message_type_name(msg.msg_id), (unsigned)msg.msg_id);
|
||||
free(msg.payload);
|
||||
continue;
|
||||
}
|
||||
|
||||
bool handled = false;
|
||||
for (int i = 0; i < handler_count; i++) {
|
||||
if (handlers[i].msg_id == msg.msg_id) {
|
||||
|
||||
@@ -21,6 +21,5 @@ void init_cmdHandler(QueueHandle_t queue);
|
||||
void vCmdDispatcherTask(void *param);
|
||||
|
||||
esp_err_t msg_register_handler(uint16_t id, msg_callback_t cb);
|
||||
esp_err_t msg_post(uint16_t id, const uint8_t *data, size_t len);
|
||||
|
||||
#endif
|
||||
|
||||
+43
-19
@@ -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) {
|
||||
|
||||
@@ -9,13 +9,29 @@ static void handle_ota_slave_progress(const uint8_t *data, size_t len) {
|
||||
alox_UartMessage uart_msg;
|
||||
uint32_t filter = 0;
|
||||
|
||||
if (uart_cmd_decode(data, len, &uart_msg) == ESP_OK) {
|
||||
if (len > 0) {
|
||||
if (uart_cmd_decode(data, len, &uart_msg) != ESP_OK) {
|
||||
ESP_LOGW(TAG, "decode failed");
|
||||
alox_UartMessage response;
|
||||
uart_cmd_init_response(
|
||||
&response, alox_MessageType_OTA_SLAVE_PROGRESS,
|
||||
alox_UartMessage_ota_slave_progress_response_tag);
|
||||
uart_cmd_send(&response, TAG);
|
||||
return;
|
||||
}
|
||||
const alox_OtaSlaveProgressRequest *req =
|
||||
UART_CMD_REQ(&uart_msg, alox_UartMessage_ota_slave_progress_request_tag,
|
||||
ota_slave_progress_request);
|
||||
if (req != NULL) {
|
||||
filter = req->client_id;
|
||||
if (req == NULL) {
|
||||
ESP_LOGW(TAG, "missing ota_slave_progress_request");
|
||||
alox_UartMessage response;
|
||||
uart_cmd_init_response(
|
||||
&response, alox_MessageType_OTA_SLAVE_PROGRESS,
|
||||
alox_UartMessage_ota_slave_progress_response_tag);
|
||||
uart_cmd_send(&response, TAG);
|
||||
return;
|
||||
}
|
||||
filter = req->client_id;
|
||||
}
|
||||
|
||||
alox_UartMessage response;
|
||||
|
||||
@@ -39,12 +39,20 @@ static void handle_tap_notify(const uint8_t *data, size_t len) {
|
||||
alox_UartMessage uart_msg;
|
||||
alox_TapNotifyRequest req = alox_TapNotifyRequest_init_zero;
|
||||
|
||||
if (uart_cmd_decode(data, len, &uart_msg) == ESP_OK) {
|
||||
if (len > 0) {
|
||||
if (uart_cmd_decode(data, len, &uart_msg) != ESP_OK) {
|
||||
ESP_LOGW(TAG, "decode failed");
|
||||
reply(0, false, 0, false, false, false);
|
||||
return;
|
||||
}
|
||||
const alox_TapNotifyRequest *req_ptr = UART_CMD_REQ(
|
||||
&uart_msg, alox_UartMessage_tap_notify_request_tag, tap_notify_request);
|
||||
if (req_ptr != NULL) {
|
||||
req = *req_ptr;
|
||||
if (req_ptr == NULL) {
|
||||
ESP_LOGW(TAG, "missing tap_notify_request");
|
||||
reply(0, false, 0, false, false, false);
|
||||
return;
|
||||
}
|
||||
req = *req_ptr;
|
||||
}
|
||||
|
||||
if (req.write) {
|
||||
|
||||
Reference in New Issue
Block a user