diff --git a/Makefile b/Makefile index 7056290..cbf6921 100644 --- a/Makefile +++ b/Makefile @@ -49,6 +49,12 @@ flashCluster: monitorMini: idf.py monitor -p /dev/ttyACM0 +monitorMini1: + idf.py monitor -p /dev/ttyACM1 + +monitorMini2: + idf.py monitor -p /dev/ttyACM2 + flash0: idf.py flash -p /dev/ttyUSB0 diff --git a/main/communication_handler.c b/main/communication_handler.c index 4ba93f4..b5a0f72 100644 --- a/main/communication_handler.c +++ b/main/communication_handler.c @@ -1,13 +1,14 @@ #include "communication_handler.h" -#include "ota_update.h" #include "esp_err.h" #include "esp_log.h" #include "esp_now.h" #include "esp_ota_ops.h" +#include "esp_partition.h" #include "esp_timer.h" #include "freertos/idf_additions.h" #include "freertos/task.h" -#include "esp_partition.h" +#include "message_structs.h" +#include "ota_update.h" #include "client_handler.h" #include @@ -16,7 +17,8 @@ #include #include -uint8_t broadcast_address[ESP_NOW_ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; +uint8_t broadcast_address[ESP_NOW_ETH_ALEN] = {0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF}; static const char *TAG = "ALOX - COM"; @@ -125,7 +127,8 @@ int add_peer(uint8_t *macAddr) { if (!IS_BROADCAST_ADDR(macAddr)) { int ret = add_client(esp_client_list, peerInfo.peer_addr); if (ret < 0) { - ESP_LOGE(TAG, "Client could not be added to client handler, removing it from esp now client list!"); + ESP_LOGE(TAG, "Client could not be added to client handler, removing " + "it from esp now client list!"); esp_now_del_peer(peerInfo.peer_addr); return -1; } @@ -160,29 +163,25 @@ BaseMessage MessageBuilder(CommandPages commandPage, PayloadUnion payload, void master_broadcast_task(void *param) { while (1) { - if (!g_ota_in_progress) { - BroadCastPayload payload = {}; + BroadCastPayload payload = {}; - BaseMessage message = MessageBuilder( - BroadCastPage, *(PayloadUnion *)&payload, sizeof(payload)); + BaseMessage message = MessageBuilder( + BroadCastPage, *(PayloadUnion *)&payload, sizeof(payload)); - ESP_ERROR_CHECK(esp_now_send(broadcast_address, (uint8_t *)&message, - sizeof(BaseMessage))); - } + ESP_ERROR_CHECK(esp_now_send(broadcast_address, (uint8_t *)&message, + sizeof(BaseMessage))); vTaskDelay(pdMS_TO_TICKS(5000)); } } void master_broadcast_ping(void *param) { while (1) { - if (!g_ota_in_progress) { - PingPayload payload = {}; - payload.timestamp = esp_timer_get_time(); - BaseMessage message = - MessageBuilder(PingPage, *(PayloadUnion *)&payload, sizeof(payload)); - ESP_ERROR_CHECK(esp_now_send(broadcast_address, (uint8_t *)&message, - sizeof(BaseMessage))); - } + PingPayload payload = {}; + payload.timestamp = esp_timer_get_time(); + BaseMessage message = + MessageBuilder(PingPage, *(PayloadUnion *)&payload, sizeof(payload)); + ESP_ERROR_CHECK(esp_now_send(broadcast_address, (uint8_t *)&message, + sizeof(BaseMessage))); vTaskDelay(pdMS_TO_TICKS(2500)); } } @@ -234,8 +233,8 @@ void master_RegisterCallback(const esp_now_recv_info_t *esp_now_info, GetStatusPayload payload = {}; replyMessage = MessageBuilder(GetStatusPage, *(PayloadUnion *)&payload, sizeof(payload)); - esp_now_send(esp_now_info->src_addr, - (uint8_t *)&replyMessage, sizeof(BaseMessage)); + esp_now_send(esp_now_info->src_addr, (uint8_t *)&replyMessage, + sizeof(BaseMessage)); break; default: break; @@ -275,9 +274,8 @@ void slave_broadcastCallback(const esp_now_recv_info_t *esp_now_info, replyMessage = MessageBuilder(RegisterPage, *(PayloadUnion *)&replyMessage.payload, sizeof(replyMessage.payload)); - esp_now_send(esp_now_info->src_addr, - (uint8_t *)&replyMessage, - sizeof(BaseMessage)); + esp_now_send(esp_now_info->src_addr, (uint8_t *)&replyMessage, + sizeof(BaseMessage)); hasMaster = true; } } @@ -295,7 +293,7 @@ void slave_getstatusCallback(const esp_now_recv_info_t *esp_now_info, BaseMessage replyMessage = MessageBuilder(StatusPage, *(PayloadUnion *)&payload, sizeof(payload)); esp_now_send(esp_now_info->src_addr, (uint8_t *)&replyMessage, - sizeof(BaseMessage)); + sizeof(BaseMessage)); } void slave_pingCallback(const esp_now_recv_info_t *esp_now_info, @@ -304,10 +302,10 @@ void slave_pingCallback(const esp_now_recv_info_t *esp_now_info, return; const BaseMessage *message = (const BaseMessage *)data; - BaseMessage replyMessage = MessageBuilder(PingPage, *(PayloadUnion *)&message->payload, - sizeof(message->payload)); + BaseMessage replyMessage = MessageBuilder( + PingPage, *(PayloadUnion *)&message->payload, sizeof(message->payload)); esp_now_send(esp_now_info->src_addr, (uint8_t *)&replyMessage, - sizeof(BaseMessage)); + sizeof(BaseMessage)); } void ESPNOW_RegisterSlaveCallbacks() { @@ -359,8 +357,8 @@ void client_receive_callback(const esp_now_recv_info_t *esp_now_info, // Initialize the esp_now_info struct to zeros memset(&msg_info.esp_now_info, 0, sizeof(esp_now_recv_info_t)); - // Now, allocate and copy the data pointed to by the pointers within esp_now_info - // src_addr + // Now, allocate and copy the data pointed to by the pointers within + // esp_now_info src_addr msg_info.esp_now_info.src_addr = malloc(6); if (msg_info.esp_now_info.src_addr) { memcpy(msg_info.esp_now_info.src_addr, esp_now_info->src_addr, 6); @@ -410,222 +408,25 @@ void client_monitor_task(void *pvParameters) { const esp_partition_t *ota_update_partition = NULL; -void master_ota_prepare_acknowledged_callback( - const esp_now_recv_info_t *esp_now_info, const uint8_t *data, - int data_len) { - ESP_LOGI(TAG, "Master received OTA_PREPARE_ACKNOWLEDGED"); - int client_id = get_client_id(esp_client_list, esp_now_info->src_addr); - if (client_id >= 0) { - esp_client_list->Clients[client_id].ota_status = OTA_PREPARING; - esp_client_list->Clients[client_id].last_seen = xTaskGetTickCount(); - - BaseMessage master_ready_msg = {}; - master_ready_msg = MessageBuilder(MASTER_READY_TO_SEND_CHUNKS, *(PayloadUnion *)&master_ready_msg.payload, 0); // Empty payload - esp_err_t err = esp_now_send(esp_now_info->src_addr, (uint8_t *)&master_ready_msg, sizeof(BaseMessage)); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Could not send MASTER_READY_TO_SEND_CHUNKS, %s", - esp_err_to_name(err)); - } else { - ESP_LOGI(TAG, "Sent MASTER_READY_TO_SEND_CHUNKS"); - } - } -} - -void master_client_ready_to_receive_chunks_callback( - const esp_now_recv_info_t *esp_now_info, const uint8_t *data, - int data_len) { - ESP_LOGI(TAG, "Master received OTA_READY_TO_RECEIVE"); - int client_id = get_client_id(esp_client_list, esp_now_info->src_addr); - if (client_id >= 0) { - esp_client_list->Clients[client_id].ota_status = OTA_UPDATING; - esp_client_list->Clients[client_id].last_seen = xTaskGetTickCount(); - - // Start sending chunks for block 0 to this specific client - esp_client_list->Clients[client_id].current_block_id = 0; - send_ota_block_chunks(client_id, 0); - - BaseMessage status_request_message = {}; - OTA_REQUEST_BLOCK_STATUS_Payload status_payload = {}; - status_payload.block_id = 0; - status_request_message = MessageBuilder( - OTA_REQUEST_BLOCK_STATUS, *(PayloadUnion *)&status_payload, - sizeof(status_payload)); - esp_now_send(esp_client_list->Clients[client_id].macAddr, - (uint8_t *)&status_request_message, sizeof(BaseMessage)); - } -} - -void master_ota_block_status_report_callback( - const esp_now_recv_info_t *esp_now_info, const uint8_t *data, - int data_len) { - const BaseMessage *message = (const BaseMessage *)data; - const OTA_BLOCK_STATUS_REPORT_Payload *payload = - &message->payload.ota_block_status_report_payload; - - int client_id = get_client_id(esp_client_list, esp_now_info->src_addr); - if (client_id < 0) { - return; - } - - esp_client_list->Clients[client_id].last_seen = xTaskGetTickCount(); - - if (payload->block_id == esp_client_list->Clients[client_id].current_block_id) { - uint32_t complete_bitmask = (1 << UPDATE_MAX_SEQUENZES) - 1; // Use UPDATE_MAX_SEQUENZES (20) for the bitmask - if (payload->chunk_bitmask == complete_bitmask) { - esp_client_list->Clients[client_id].retry_counter = 0; - BaseMessage commit_message = {}; - OTA_COMMIT_BLOCK_Payload commit_payload = { - .block_id = esp_client_list->Clients[client_id].current_block_id, - }; - commit_message = MessageBuilder(OTA_COMMIT_BLOCK, - *(PayloadUnion *)&commit_payload, - sizeof(commit_payload)); - esp_now_send(esp_now_info->src_addr, (uint8_t *)&commit_message, - sizeof(BaseMessage)); - } else { - if (esp_client_list->Clients[client_id].retry_counter > 3) { - esp_client_list->Clients[client_id].ota_status = OTA_FAILED; - return; - } - - uint8_t chunk_buffer[UPDATE_PAYLOAD_SIZE]; // Use constant - for (int i = 0; i < UPDATE_MAX_SEQUENZES; i++) { // Use UPDATE_MAX_SEQUENZES (20) for the loop limit - if (!((payload->chunk_bitmask >> i) & 1)) { - esp_partition_read(ota_update_partition, - (esp_client_list->Clients[client_id].current_block_id * - 4096) + - (i * UPDATE_PAYLOAD_SIZE), // Use constant - chunk_buffer, UPDATE_PAYLOAD_SIZE); // Use constant - - BaseMessage message = {}; - OTA_CHUNK_Payload chunk_payload = {}; - chunk_payload.block_id = - esp_client_list->Clients[client_id].current_block_id; - chunk_payload.chunk_id = i; - memcpy(chunk_payload.data, chunk_buffer, UPDATE_PAYLOAD_SIZE); // Use constant - - message = MessageBuilder(OTA_CHUNK, *(PayloadUnion *)&chunk_payload, - sizeof(chunk_payload)); - - esp_now_send(esp_now_info->src_addr, (uint8_t *)&message, - sizeof(BaseMessage)); - esp_client_list->Clients[client_id].resent_chunks_counter++; - } - } - esp_client_list->Clients[client_id].retry_counter++; - } - } -} - -void master_ota_block_committed_callback( - const esp_now_recv_info_t *esp_now_info, const uint8_t *data, - int data_len) { - const BaseMessage *message = (const BaseMessage *)data; - const OTA_BLOCK_COMMITTED_Payload *payload = - &message->payload.ota_block_committed_payload; - - int client_id = get_client_id(esp_client_list, esp_now_info->src_addr); - if (client_id < 0) { - return; - } - - esp_client_list->Clients[client_id].last_seen = xTaskGetTickCount(); - - if (payload->block_id == esp_client_list->Clients[client_id].current_block_id) { - esp_client_list->Clients[client_id].current_block_id++; - - const int total_size = ota_update_partition->size; - const int block_size = 4096; - const int num_blocks = (total_size + block_size - 1) / block_size; - - if (esp_client_list->Clients[client_id].current_block_id < num_blocks) { - send_ota_block_chunks(client_id, esp_client_list->Clients[client_id].current_block_id); - - BaseMessage status_request_message = {}; - OTA_REQUEST_BLOCK_STATUS_Payload status_payload = {}; - status_payload.block_id = esp_client_list->Clients[client_id].current_block_id; - status_request_message = MessageBuilder( - OTA_REQUEST_BLOCK_STATUS, *(PayloadUnion *)&status_payload, - sizeof(status_payload)); - esp_now_send(esp_client_list->Clients[client_id].macAddr, - (uint8_t *)&status_request_message, sizeof(BaseMessage)); - } else { - BaseMessage finish_message = {}; - OTA_FINISH_UPDATE_Payload finish_payload = {}; - finish_message = MessageBuilder(OTA_FINISH_UPDATE, - *(PayloadUnion *)&finish_payload, - sizeof(finish_payload)); - esp_now_send(esp_client_list->Clients[client_id].macAddr, - (uint8_t *)&finish_message, sizeof(BaseMessage)); - } - } -} - -void master_ota_update_status_callback( - const esp_now_recv_info_t *esp_now_info, const uint8_t *data, - int data_len) { - const BaseMessage *message = (const BaseMessage *)data; - const OTA_UPDATE_STATUS_Payload *payload = - &message->payload.ota_update_status_payload; - - int client_id = get_client_id(esp_client_list, esp_now_info->src_addr); - if (client_id < 0) { - return; - } - - esp_client_list->Clients[client_id].last_seen = xTaskGetTickCount(); - - if (payload->status == 0) { - esp_client_list->Clients[client_id].ota_status = OTA_SUCCESS; - } else { - esp_client_list->Clients[client_id].ota_status = OTA_FAILED; - } -} - -void send_ota_block_chunks(uint8_t client_id, uint16_t block_id) { - const int block_size = 4096; - const int chunk_size = 200; - const int num_chunks = block_size / chunk_size; - uint8_t chunk_buffer[200]; - - for (int j = 0; j < num_chunks; j++) { - esp_partition_read( - ota_update_partition, - (block_id * block_size) + - (j * chunk_size), - chunk_buffer, chunk_size); - - BaseMessage message = {}; - OTA_CHUNK_Payload payload = {}; - payload.block_id = block_id; - payload.chunk_id = j; - memcpy(payload.data, chunk_buffer, chunk_size); - - message = MessageBuilder(OTA_CHUNK, *(PayloadUnion *)&payload, sizeof(payload)); - - esp_now_send(esp_client_list->Clients[client_id].macAddr, (uint8_t *)&message, sizeof(BaseMessage)); - vTaskDelay(pdMS_TO_TICKS(10)); - } -} - void ESPNOW_RegisterOTAMaster() { + // Observe this States for all Slaves in ClientList + // OTA_SLAVE_PREPARING + // OTA_SLAVE_READY + // OTA_SLAVE_ERROR + // OTA_SLAVE_WRITE_FINISHED + // OTA_SLAVE_FINISHED + ESP_RegisterFunction(OTA_PREPARE_ACKNOWLEDGED, - master_ota_prepare_acknowledged_callback); + master_ota_prepare_acknowledge_callback); ESP_RegisterFunction(OTA_READY_TO_RECEIVE, - master_client_ready_to_receive_chunks_callback); - ESP_RegisterFunction(OTA_BLOCK_STATUS_REPORT, - master_ota_block_status_report_callback); - ESP_RegisterFunction(OTA_BLOCK_COMMITTED, - master_ota_block_committed_callback); - ESP_RegisterFunction(OTA_UPDATE_STATUS, master_ota_update_status_callback); + master_ota_ready_to_recieve_callback); + ESP_RegisterFunction(OTA_UPDATE_SLAVE_ACKED, + master_ota_update_slave_acknowledge_callback); } void ESPNOW_RegisterOTASlave() { ESP_RegisterFunction(OTA_PREPARE_FOR_UPDATE, slave_Prep_Upgrade_Callback); - ESP_RegisterFunction(OTA_CHUNK, slave_ota_chunk_callback); - ESP_RegisterFunction(OTA_REQUEST_BLOCK_STATUS, - slave_request_block_status_callback); - ESP_RegisterFunction(OTA_COMMIT_BLOCK, slave_commit_block_callback); - ESP_RegisterFunction(OTA_FINISH_UPDATE, slave_finish_update_callback); - ESP_RegisterFunction(MASTER_READY_TO_SEND_CHUNKS, slave_master_ready_to_send_chunks_callback); -} \ No newline at end of file + ESP_RegisterFunction(OTA_CHUNK, slave_Update_Chunk_Callback); + + ESP_RegisterFunction(OTA_FINISH_UPDATE, slave_Update_Finished_Callback); +} diff --git a/main/communication_handler.h b/main/communication_handler.h index f1ed973..9172a21 100644 --- a/main/communication_handler.h +++ b/main/communication_handler.h @@ -114,20 +114,9 @@ void client_receive_callback(const esp_now_recv_info_t *esp_now_info, const uint8_t *data, int data_len); void client_data_sending_task(void *param); void client_send_random_data_task(void *param); -#include "esp_partition.h" - -typedef struct { - const esp_partition_t *update_partition; -} master_ota_task_params_t; - - - -extern bool g_ota_in_progress; void client_monitor_task(void *pvParameters); void send_ota_block_chunks(uint8_t client_id, uint16_t block_id); -extern const esp_partition_t *ota_update_partition; - #endif diff --git a/main/main.c b/main/main.c index 5341494..4b36b51 100644 --- a/main/main.c +++ b/main/main.c @@ -1,7 +1,10 @@ #include "client_handler.h" #include "driver/gpio.h" #include "driver/uart.h" +#include "esp_app_desc.h" +#include "esp_app_format.h" #include "esp_err.h" +#include "esp_flash_partitions.h" #include "esp_image_format.h" #include "esp_log.h" #include "esp_log_buffer.h" @@ -22,9 +25,11 @@ #include "main.h" #include "ota_update.h" #include "uart_handler.h" +#include #include #include #include +#include #include #include @@ -38,6 +43,7 @@ static uint8_t send_message_payload_buffer[512]; uint32_t g_uart_firmware_total_size = 0; static MessageBrokerTaskParams_t broker_task_params; +static MasterOTA_TaskParams_t master_ota_task_params; static ESP_MessageBrokerTaskParams_t esp_broker_task_params; ClientList clientList = {.Clients = {{0}}, .ClientCount = 0}; @@ -207,7 +213,8 @@ void ota_monitor_task(void *param) { clientList.Clients[i].ota_status != OTA_FAILED) { all_done = false; - if ((xTaskGetTickCount() - clientList.Clients[i].last_seen) > timeout) { + if ((xTaskGetTickCount() - clientList.Clients[i].last_seen) > + timeout) { ESP_LOGE(TAG, "Client %d timed out", i); clientList.Clients[i].ota_status = OTA_FAILED; } @@ -227,7 +234,8 @@ void ota_monitor_task(void *param) { if (clientList.Clients[i].slotIsUsed) { ESP_LOGI(TAG, "Client %d [MAC: " MACSTR "]: %s, Resent Chunks: %d", i, MAC2STR(clientList.Clients[i].macAddr), - clientList.Clients[i].ota_status == OTA_SUCCESS ? "SUCCESS" : "FAILED", + clientList.Clients[i].ota_status == OTA_SUCCESS ? "SUCCESS" + : "FAILED", clientList.Clients[i].resent_chunks_counter); } } @@ -235,45 +243,24 @@ void ota_monitor_task(void *param) { vTaskDelete(NULL); } -void start_ota_update_espnow(uint8_t msgid, const uint8_t *payload, - size_t payload_len, uint8_t *send_payload_buffer, - size_t send_payload_buffer_size, - uint8_t *send_buffer, size_t send_buffer_size) { - ESP_LOGI(TAG, "Starting OTA update for all clients"); +void send_client_ota_start_message(uint8_t clientID, uint32_t app_size) { + BaseMessage message = {}; + OTA_PREPARE_FOR_UPDATE_Payload ota_payload = { + .total_size = app_size, + }; + message = MessageBuilder(OTA_PREPARE_FOR_UPDATE, + *(PayloadUnion *)&ota_payload, sizeof(ota_payload)); - const esp_partition_t *ota_update_partition; - - ota_update_partition = esp_ota_get_next_update_partition(NULL); - if (ota_update_partition == NULL) { - ESP_LOGE(TAG, "Failed to get update partition"); - return; + esp_err_t err = esp_now_send(clientList.Clients[clientID].macAddr, + (uint8_t *)&message, sizeof(BaseMessage)); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Could not send OTA PREPARE FOR UPDATE to " MACSTR ", %s", + MAC2STR(clientList.Clients[clientID].macAddr), + esp_err_to_name(err)); + } else { + ESP_LOGI(TAG, "Sent OTA PREPARE FOR UPDATE to " MACSTR, + MAC2STR(clientList.Clients[clientID].macAddr)); } - - g_ota_in_progress = true; - - for (int i = 0; i < MAX_CLIENTS; i++) { - if (clientList.Clients[i].slotIsUsed) { - clientList.Clients[i].ota_status = OTA_AWAITING_ACK; - clientList.Clients[i].last_seen = xTaskGetTickCount(); - - BaseMessage message = {}; - OTA_PREPARE_FOR_UPDATE_Payload ota_payload = { - .total_size = g_uart_firmware_total_size, // Use the size from UART - }; message = MessageBuilder(OTA_PREPARE_FOR_UPDATE, - *(PayloadUnion *)&ota_payload, sizeof(ota_payload)); - - esp_err_t err = esp_now_send(clientList.Clients[i].macAddr, (uint8_t *)&message, - sizeof(BaseMessage)); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Could not send OTA PREPARE FOR UPDATE to " MACSTR ", %s", - MAC2STR(clientList.Clients[i].macAddr), esp_err_to_name(err)); - } else { - ESP_LOGI(TAG, "Sent OTA PREPARE FOR UPDATE to " MACSTR, MAC2STR(clientList.Clients[i].macAddr)); - } - } - } - - xTaskCreate(ota_monitor_task, "ota_monitor_task", 4096, NULL, 5, NULL); } void app_main(void) { @@ -297,9 +284,10 @@ void app_main(void) { wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(&cfg)); wifi_config_t wifi_config = { - .sta = { - .channel = 1, - }, + .sta = + { + .channel = 1, + }, }; ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config)); @@ -323,15 +311,22 @@ void app_main(void) { esp_ota_img_states_t ota_state; if (esp_ota_get_state_partition(running, &ota_state) == ESP_OK) { if (ota_state == ESP_OTA_IMG_PENDING_VERIFY) { - bool diagnostic_is_ok = true; + bool diagnostic_is_ok = true; // TODO build in valid diagnostics if (diagnostic_is_ok) { esp_ota_mark_app_valid_cancel_rollback(); } else { + // esp_ota_mark_app_invalid_rollback(); Put this function at the start + // so when the esp crashes it can rollback esp_ota_mark_app_invalid_rollback_and_reboot(); } } } + const esp_partition_t *next_ota_partition = + esp_ota_get_next_update_partition(NULL); + int app_size = get_app_size(next_ota_partition); + ESP_LOGE(TAG, "App Size in Other Partition %d", app_size); + QueueHandle_t espnow_message_queue = xQueueCreate(10, sizeof(ESPNOW_MessageInfo)); ESP_InitMessageBroker(espnow_message_queue); @@ -340,6 +335,8 @@ void app_main(void) { xTaskCreate(ESP_MessageBrokerTask, "espnow_message_broker_task", 4096, (void *)&esp_broker_task_params, 4, NULL); + init_ota(); + if (isMaster) { ESP_LOGI(TAG, "Started in Mastermode"); ESPNOW_RegisterMasterCallbacks(); @@ -362,20 +359,23 @@ void app_main(void) { broker_task_params.payload_buffer_size = sizeof(send_message_payload_buffer); - xTaskCreate(MessageBrokerTask, "message_handler_task", 4096, + xTaskCreate(MessageBrokerTask, "MessageHandler", 4096, (void *)&broker_task_params, 5, NULL); - RegisterCallback(0x01, echoCallback); - RegisterCallback(0x02, versionCallback); - RegisterCallback(0x03, clientInfoCallback); -RegisterCallback(0x04, fakeDataCallback); + master_ota_task_params.client_list = &clientList; + xTaskCreate(MasterOTATask, "MasterOTATask", 4096, + (void *)&master_ota_task_params, 4, NULL); + + RegisterCallback(UART_ECHO, echoCallback); + RegisterCallback(UART_VERSION, versionCallback); + RegisterCallback(UART_CLIENT_INFO, clientInfoCallback); + RegisterCallback(UART_CLIENT_INPUT, fakeDataCallback); RegisterCallback(UART_OTA_START_ESPNOW, start_ota_update_espnow); - init_ota(); } else { ESP_LOGI(TAG, "Started in Slavemode"); ESPNOW_RegisterSlaveCallbacks(); + xTaskCreate(slave_ota_task, "SlaveOTATask", 4096, NULL, 4, NULL); ESPNOW_RegisterOTASlave(); - init_ota(); } -} \ No newline at end of file +} diff --git a/main/message_structs.h b/main/message_structs.h index d83d122..ba894fb 100644 --- a/main/message_structs.h +++ b/main/message_structs.h @@ -1,8 +1,9 @@ #ifndef MESSAGE_STRUCTS_H #define MESSAGE_STRUCTS_H -#include #include +#include +#include #define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] #define MACSTR "%02X:%02X:%02X:%02X:%02X:%02X" @@ -18,6 +19,7 @@ typedef enum { OTA_BLOCK_COMMITTED, OTA_FINISH_UPDATE, OTA_UPDATE_STATUS, + OTA_UPDATE_SLAVE_ACKED, MASTER_READY_TO_SEND_CHUNKS, StatusPage, GetStatusPage, @@ -43,6 +45,7 @@ typedef struct __attribute__((packed)) { typedef struct __attribute__((packed)) { uint16_t block_id; uint8_t chunk_id; + uint8_t data_len; uint8_t data[200]; } OTA_CHUNK_Payload; @@ -71,6 +74,14 @@ typedef struct __attribute__((packed)) { uint8_t status; // 0 = SUCCESS, 1 = FAILED } OTA_UPDATE_STATUS_Payload; +typedef struct __attribute__((packed)) { + uint16_t current_block_id; + uint16_t update_buffer_write_index; + uint32_t update_size; + uint16_t sequenz_counter; // how often the update buffer gets written + uint8_t status; // 0 = SUCCESS, 1 = FAILED +} OTA_UPDATE_ACK_Payload; + typedef struct __attribute__((packed)) { uint16_t version; // software version uint8_t runningPartition; diff --git a/main/ota_update.c b/main/ota_update.c index 2b35912..f2674db 100644 --- a/main/ota_update.c +++ b/main/ota_update.c @@ -1,8 +1,12 @@ #include "ota_update.h" +#include "client_handler.h" #include "communication_handler.h" #include "driver/uart.h" #include "esp_app_format.h" +#include "esp_err.h" #include "esp_log.h" +#include "esp_log_buffer.h" +#include "esp_now.h" #include "esp_ota_ops.h" #include "esp_partition.h" #include "esp_system.h" @@ -11,24 +15,33 @@ #include "freertos/task.h" #include "message_builder.h" #include "message_handler.h" +#include "message_structs.h" #include "uart_handler.h" #include "uart_msg_ids.h" +#include +#include +#include -extern uint32_t g_uart_firmware_total_size; - -static const char *TAG = "ALOX - OTA_SLAVE"; +static const char *TAG = "ALOX - OTA"; static QueueHandle_t ota_task_queue = NULL; static esp_ota_handle_t update_handle = 0; static uint8_t update_buffer[UPDATE_BUFFER_SIZE]; +static uint8_t update_buffer_chunk[250]; +static uint8_t update_buffer_chunk_len; static uint32_t chunk_bitmask; static uint16_t current_block_id; static uint16_t update_buffer_write_index; static uint32_t update_size; static uint16_t sequenz_counter; // how often the update buffer gets written +static esp_partition_t partition_to_read_update_from; +static uint32_t partition_to_read_from_read_index; +static ClientList *client_list; +static bool all_chunks_send; +static bool finished; -u_int32_t get_app_size(const esp_partition_t *app_size_partition) { +uint32_t get_app_size(const esp_partition_t *app_size_partition) { esp_app_desc_t app_desc; esp_ota_get_partition_description(app_size_partition, &app_desc); @@ -40,7 +53,7 @@ u_int32_t get_app_size(const esp_partition_t *app_size_partition) { return 0; } - u_int32_t data_len = sizeof(header); + uint32_t data_len = sizeof(header); for (int i = 0; i < header.segment_count; i++) { esp_image_segment_header_t segment_header; @@ -48,138 +61,275 @@ u_int32_t get_app_size(const esp_partition_t *app_size_partition) { sizeof(segment_header)); ESP_LOGI(TAG, "SEGMENT %d Address %d, Segment DataLen %d", i, segment_header.load_addr, segment_header.data_len); - data_len += segment_header.data_len + sizeof(segment_header); + uint32_t padded_len = (segment_header.data_len + 3) & ~3; + data_len += padded_len + sizeof(segment_header); } + + data_len += 1; + data_len += 32; + uint32_t padding = (16 - (data_len % 16)) % 16; + data_len += padding; + return data_len; } -void ota_task(void *pvParameter) { - ESP_LOGI(TAG, "ota_task started"); +int ota_send_finish(ClientList *client_list) { + // read flash and send data + BaseMessage replyMessage = {}; + OTA_FINISH_UPDATE_Payload payload = {}; + + ESP_LOGI(TAG, "OTA SEND FINISH"); + + replyMessage = MessageBuilder(OTA_FINISH_UPDATE, *(PayloadUnion *)&payload, + sizeof(payload)); + + for (int i = 0; i < MAX_CLIENTS; i++) { + if (client_list->Clients[i].slotIsUsed) { + if (client_list->Clients[i].ota_status == OTA_UPDATING) { + esp_now_send(client_list->Clients[i].macAddr, (uint8_t *)&replyMessage, + sizeof(BaseMessage)); + client_list->Clients[i].ota_status = OTA_AWAITING_ACK; + } + } + } + finished = true; + return 0; +} + +int ota_send_next_update_chunk(ClientList *client_list) { + // read flash and send data + BaseMessage replyMessage = {}; + OTA_CHUNK_Payload payload = {}; + + size_t actual_read = 200; + if (partition_to_read_from_read_index + actual_read > update_size) { + actual_read = update_size - partition_to_read_from_read_index; + } + + esp_err_t err = esp_partition_read(&partition_to_read_update_from, + partition_to_read_from_read_index, + payload.data, actual_read); + + if (actual_read < 200) { + ESP_LOG_BUFFER_HEX(TAG, payload.data, actual_read); + } + + if (err != ESP_OK) { + ESP_LOGE(TAG, "Could not read partition"); + } + + partition_to_read_from_read_index += actual_read; + payload.data_len = actual_read; + + ESP_LOGI(TAG, "READ %d Bytes Sendig it to all Clients waiting", actual_read); + ESP_LOGI(TAG, "READ PARTITION AT %d Bytes MAX Bytes %d", + partition_to_read_from_read_index, update_size); + + replyMessage = + MessageBuilder(OTA_CHUNK, *(PayloadUnion *)&payload, sizeof(payload)); + + for (int i = 0; i < MAX_CLIENTS; i++) { + if (client_list->Clients[i].slotIsUsed) { + if (client_list->Clients[i].ota_status == OTA_UPDATING) { + esp_now_send(client_list->Clients[i].macAddr, (uint8_t *)&replyMessage, + sizeof(BaseMessage)); + client_list->Clients[i].ota_status = OTA_AWAITING_ACK; + } + } + } + + if (partition_to_read_from_read_index == update_size) + return 1; // last update chunk send now finish it! + + return 0; +} + +void MasterOTATask(void *pvParameter) { + ESP_LOGI(TAG, "master_ota_task started"); ota_task_queue_message_t msg; + MasterOTA_TaskParams_t task_params = *(MasterOTA_TaskParams_t *)pvParameter; + client_list = task_params.client_list; + while (1) { if (xQueueReceive(ota_task_queue, &msg, portMAX_DELAY)) { - ESP_LOGI(TAG, "ota_task received command: %d", msg.command); + ESP_LOGI(TAG, "master ota_task received command: %d", msg.command); BaseMessage replyMessage = {}; switch (msg.command) { - case OTA_COMMAND_MASTER_READY: { - int part = prepare_ota_update(); + case OTA_SEND_SLAVES_PREPARE_MESSAGE: { + } + case OTA_SLAVE_WILL_PREPARE: { + int id = get_client_id(client_list, msg.mac_addr); + if (id < 0) { + // error + ESP_LOGE(TAG, "Error set OTA_PREPARE could not get client id"); + } + // just wait + // mark client that it will wait + ESP_LOGI(TAG, "MASTER OTA TASK: Marking Client %d as OTA_PREPARING", + id); + client_list->Clients[id].ota_status = OTA_PREPARING; + break; + } + case OTA_SLAVE_IS_PREPARED: { + // client is prepared check if all clients are preapred to send chunks + int id = get_client_id(client_list, msg.mac_addr); + if (id < 0) { + // error + } + if (client_list->Clients[id].ota_status == OTA_PREPARING) { + ESP_LOGI(TAG, "MASTER OTA TASK: Marking Client %d as OTA_UPDATING", + id); + client_list->Clients[id].ota_status = OTA_UPDATING; + } else { + ESP_LOGE(TAG, "MASTER OTA TASK: Client this should not happend"); + } + + bool start = true; + // check if all clients are prepared + for (int i = 0; i < MAX_CLIENTS; i++) { + if (client_list->Clients[i].slotIsUsed) { + if (client_list->Clients[i].ota_status != OTA_UPDATING) + start = false; + } + } + if (start) + ota_send_next_update_chunk(client_list); + break; + } + case OTA_SLAVE_ACKED: { + // mark client as acked check if all clients acked to send next message + int id = get_client_id(client_list, msg.mac_addr); + if (id < 0) { + // error + } + if (client_list->Clients[id].ota_status == OTA_AWAITING_ACK) { + ESP_LOGI(TAG, "OTA_SLAVE_ACKED Client %d Status Update OTA_UPDATING", + id); + client_list->Clients[id].ota_status = OTA_UPDATING; + } else { + ESP_LOGE(TAG, "OTA_SLAVE_ACKED Client %d Status Should not HAPPEND", + id); + } + + bool start = true; + // check if all clients are prepared + for (int i = 0; i < MAX_CLIENTS; i++) { + if (client_list->Clients[i].slotIsUsed) { + ESP_LOGI(TAG, "SLOT %d is USED", i); + if (client_list->Clients[i].ota_status != OTA_UPDATING) + start = false; + } + } + if (start) { + if (finished) + break; // dont need to send anything else + if (all_chunks_send) { + ota_send_finish(client_list); + break; + } + ESP_LOGE(TAG, "OTA_SLAVE_ACKED all clients have the status " + "OTA_UPDATING SENDING NEXT CHUNK"); + int end = ota_send_next_update_chunk(client_list); + if (end) { + all_chunks_send = true; + } + } + + break; + } + case OTA_SLAVE_ERROR: + break; + // mark client as error + case OTA_MASTER_SEND_PREAPRE_REQUEST: + break; + case OTA_MASTER_SEND_CHUNK: + break; + case OTA_MASTER_SEND_FINISH: + break; + } + } + } +} + +void slave_ota_task(void *pvParameter) { + ESP_LOGI(TAG, "slave_ota_task started"); + ota_task_queue_message_t msg; + BaseMessage replyMessage = {}; + while (1) { + if (xQueueReceive(ota_task_queue, &msg, portMAX_DELAY)) { + ESP_LOGI(TAG, "slave ota_task received command: %d", msg.command); + + switch (msg.command) { + case OTA_SEND_SLAVES_PREPARE_MESSAGE: + break; + case OTA_SLAVE_WILL_PREPARE: + break; + case OTA_SLAVE_IS_PREPARED: + break; + case OTA_SLAVE_ACKED: + break; + case OTA_SLAVE_ERROR: + break; + case OTA_MASTER_SEND_PREAPRE_REQUEST: { + ESP_LOGE(TAG, "START PREAPRE CALL"); + int part = prepare_ota_update(); // this part function is blocking OTA_READY_TO_RECEIVE_Payload payload = {}; if (part < 0) { payload.status = 1; // ERROR } else { payload.status = 0; // READY } + ESP_LOGE(TAG, "PREPARED %d", part); + replyMessage = MessageBuilder( OTA_READY_TO_RECEIVE, *(PayloadUnion *)&payload, sizeof(payload)); esp_now_send(msg.mac_addr, (uint8_t *)&replyMessage, sizeof(BaseMessage)); break; } - case OTA_COMMAND_PREPARE: { - OTA_PREPARE_ACKNOWLEDGED_Payload payload = {}; - replyMessage = - MessageBuilder(OTA_PREPARE_ACKNOWLEDGED, *(PayloadUnion *)&payload, - sizeof(payload)); + case OTA_MASTER_SEND_CHUNK: { + // TODO: Move Update_buffer_chunk in normal update buffer no need for + // the extra step... + // TODO: at the moment its just so i can use the write_ota_update + // function unmodified + ESP_LOGI(TAG, "Master send Chunk writing it!"); + + write_ota_update(update_buffer_chunk_len, update_buffer_chunk); + + ESP_LOGI(TAG, "AFTER WRITE_OTA_UPDATE!"); + + OTA_UPDATE_ACK_Payload payload = { + .update_buffer_write_index = update_buffer_write_index, + .current_block_id = current_block_id, + .sequenz_counter = sequenz_counter, + .status = 0, + }; + replyMessage = MessageBuilder( + OTA_UPDATE_SLAVE_ACKED, *(PayloadUnion *)&payload, sizeof(payload)); esp_now_send(msg.mac_addr, (uint8_t *)&replyMessage, sizeof(BaseMessage)); - chunk_bitmask = 0; - current_block_id = 0; break; } - case OTA_COMMAND_CHUNK: { - OTA_CHUNK_Payload *payload = &msg.payload.ota_chunk_payload; - ESP_LOGI(TAG, "OTA_CHUNK: block_id=%d, chunk_id=%d", payload->block_id, - payload->chunk_id); - if (payload->block_id == current_block_id) { - if (payload->chunk_id < UPDATE_MAX_SEQUENZES) { // UPDATE_MAX_SEQUENZES is 20 - memcpy(&update_buffer[payload->chunk_id * UPDATE_PAYLOAD_SIZE], payload->data, UPDATE_PAYLOAD_SIZE); - chunk_bitmask |= (1 << payload->chunk_id); - ESP_LOGD(TAG, "OTA_CHUNK: memcpy done, chunk_bitmask=0x%x", - chunk_bitmask); - } else { - ESP_LOGE(TAG, "OTA_CHUNK: Invalid chunk_id %d. Max allowed is %d", payload->chunk_id, UPDATE_MAX_SEQUENZES - 1); - // Optionally, send an error back to master or reset state - } - } else { - ESP_LOGW(TAG, "OTA_CHUNK: Mismatched block_id. Expected %d, got %d", - current_block_id, payload->block_id); - } - ESP_LOGD(TAG, "OTA_CHUNK: Calling vTaskDelay(10ms)"); - //vTaskDelay(pdMS_TO_TICKS(10)); - break; - } - case OTA_COMMAND_REQUEST_STATUS: { - OTA_REQUEST_BLOCK_STATUS_Payload *payload = - &msg.payload.ota_request_block_status_payload; - if (payload->block_id == current_block_id) { - OTA_BLOCK_STATUS_REPORT_Payload replyPayload = { - .block_id = current_block_id, - .chunk_bitmask = chunk_bitmask, - }; - replyMessage = MessageBuilder(OTA_BLOCK_STATUS_REPORT, - *(PayloadUnion *)&replyPayload, - sizeof(replyPayload)); - esp_now_send(msg.mac_addr, (uint8_t *)&replyMessage, - sizeof(BaseMessage)); - } - break; - } - case OTA_COMMAND_COMMIT: { - OTA_COMMIT_BLOCK_Payload *payload = - &msg.payload.ota_commit_block_payload; - ESP_LOGI(TAG, "OTA_COMMIT: block_id=%d", payload->block_id); - if (payload->block_id == current_block_id) { - uint32_t write_size = UPDATE_BUFFER_SIZE; - if ((current_block_id + 1) * UPDATE_BUFFER_SIZE > total_update_size) { - write_size = total_update_size % UPDATE_BUFFER_SIZE; - } - ESP_LOGI(TAG, "OTA_COMMIT: Writing %lu bytes to partition.", - write_size); - esp_err_t err = - esp_ota_write(update_handle, update_buffer, write_size); - if (err != ESP_OK) { - ESP_LOGE(TAG, "OTA_COMMIT: esp_ota_write failed (%s)", - esp_err_to_name(err)); - } - ESP_LOGD(TAG, "OTA_COMMIT: Calling vTaskDelay(10ms)"); - vTaskDelay(pdMS_TO_TICKS(10)); - - OTA_BLOCK_COMMITTED_Payload replyPayload = { - .block_id = current_block_id, - }; - replyMessage = MessageBuilder(OTA_BLOCK_COMMITTED, - *(PayloadUnion *)&replyPayload, - sizeof(replyPayload)); - esp_now_send(msg.mac_addr, (uint8_t *)&replyMessage, - sizeof(BaseMessage)); - - current_block_id++; - chunk_bitmask = 0; - ESP_LOGI(TAG, "OTA_COMMIT: Block %d committed. Next block_id=%d", - payload->block_id, current_block_id); - } else { - ESP_LOGW(TAG, "OTA_COMMIT: Mismatched block_id. Expected %d, got %d", - current_block_id, payload->block_id); - } - break; - - case OTA_COMMAND_FINISH: { + case OTA_MASTER_SEND_FINISH: { esp_err_t err = end_ota_update(); - OTA_UPDATE_STATUS_Payload ota_status_payload = {}; - ota_status_payload.status = (err == ESP_OK) ? 0 : 1; - replyMessage = MessageBuilder(OTA_UPDATE_STATUS, - *(PayloadUnion *)&ota_status_payload, - sizeof(ota_status_payload)); + int status = 0; + if (err != ESP_OK) { + status = 1; // TODO: Set real error + } + + ESP_LOGI(TAG, "UPDATE FERTIG STATUS %d should be 0", status); + + OTA_UPDATE_ACK_Payload payload = { + .update_buffer_write_index = update_buffer_write_index, + .current_block_id = current_block_id, + .sequenz_counter = sequenz_counter, + .status = status, + }; + replyMessage = MessageBuilder( + OTA_UPDATE_SLAVE_ACKED, *(PayloadUnion *)&payload, sizeof(payload)); esp_now_send(msg.mac_addr, (uint8_t *)&replyMessage, sizeof(BaseMessage)); - if (err == ESP_OK) { - esp_restart(); - } - break; - } - default: - ESP_LOGW(TAG, "Unknown command received: %d", msg.command); break; } } @@ -187,8 +337,6 @@ void ota_task(void *pvParameter) { } } -static uint32_t total_update_size = 0; - void start_uart_update(uint8_t msgid, const uint8_t *payload, size_t payload_len, uint8_t *send_payload_buffer, size_t send_payload_buffer_size, uint8_t *send_buffer, @@ -200,18 +348,12 @@ void start_uart_update(uint8_t msgid, const uint8_t *payload, update_size = 0; update_buffer_write_index = 0; sequenz_counter = 0; - - // Assuming payload contains total_size as uint32_2 at the beginning - if (payload_len >= sizeof(uint32_t)) { - g_uart_firmware_total_size = *(uint32_t *)payload; - ESP_LOGI(TAG, "UART OTA: Received total firmware size: %lu bytes", g_uart_firmware_total_size); - } else { - ESP_LOGE(TAG, "UART OTA: Payload too short for total firmware size."); - g_uart_firmware_total_size = 0; // Reset or handle error appropriately - } + all_chunks_send = false; + finished = false; int part = prepare_ota_update(); + // TODO: what does this do? maybe comment it out for now? if (part < 0) { send_payload_buffer[1] = (part * -1) & 0xff; } else { @@ -233,7 +375,11 @@ void start_uart_update(uint8_t msgid, const uint8_t *payload, } esp_err_t write_ota_update(uint32_t write_len, const uint8_t *payload) { + ESP_LOGI(TAG, "write_ota_update: write_len: %d", write_len); + ESP_LOGI(TAG, "write_ota_update: update_buffer_write_index: %d", + update_buffer_write_index); if (update_buffer_write_index + write_len > UPDATE_BUFFER_SIZE) { + ESP_LOGI(TAG, "write_ota_update: schreib das update weg!"); esp_err_t err = esp_ota_write(update_handle, update_buffer, update_buffer_write_index); if (err != ESP_OK) { @@ -315,7 +461,7 @@ void end_uart_update(uint8_t msgid, const uint8_t *payload, size_t payload_len, void init_ota() { ota_task_queue = xQueueCreate(50, sizeof(ota_task_queue_message_t)); - xTaskCreate(ota_task, "ota_task", 8192, NULL, 4, NULL); + RegisterCallback(UART_OTA_START, start_uart_update); RegisterCallback(UART_OTA_PAYLOAD, payload_uart_update); RegisterCallback(UART_OTA_END, end_uart_update); @@ -344,6 +490,7 @@ int prepare_ota_update() { esp_err_t end_ota_update() { if (update_buffer_write_index > 0) { + ESP_LOG_BUFFER_HEX(TAG, update_buffer, update_buffer_write_index); esp_err_t err = esp_ota_write(update_handle, update_buffer, update_buffer_write_index); vTaskDelay(1); @@ -354,11 +501,11 @@ esp_err_t end_ota_update() { } } - g_uart_firmware_total_size = update_size; esp_err_t err = esp_ota_end(update_handle); if (err != ESP_OK) { ESP_LOGE(TAG, "esp_ota_end failed: %s", esp_err_to_name(err)); - ESP_LOGI(TAG, "Total blocks written: %u, Last partial block size: %u", sequenz_counter, update_buffer_write_index); + ESP_LOGI(TAG, "Total blocks written: %u, Last partial block size: %u", + sequenz_counter, update_buffer_write_index); return err; } @@ -372,74 +519,142 @@ esp_err_t end_ota_update() { return err; } +// Acknoledge that the slave should prepare for an update +// Queues the Prepare Task beacuse it takes like 30 seconds void slave_Prep_Upgrade_Callback(const esp_now_recv_info_t *esp_now_info, const uint8_t *data, int data_len) { + ESP_LOGE(TAG, "SLAVE PREPARE FOR UPDATE Callback"); + + update_size = 0; + update_buffer_write_index = 0; + sequenz_counter = 0; + const BaseMessage *message = (const BaseMessage *)data; const OTA_PREPARE_FOR_UPDATE_Payload *payload = &message->payload.ota_prepare_for_update_payload; - total_update_size = payload->total_size; + // total_update_size = payload->total_size; - ota_task_queue_message_t msg = {.command = OTA_COMMAND_PREPARE}; + // Queue Command for Task to call the prepare method + ota_task_queue_message_t msg = {.command = OTA_MASTER_SEND_PREAPRE_REQUEST}; + memcpy(msg.mac_addr, esp_now_info->src_addr, ESP_NOW_ETH_ALEN); + if (xQueueSend(ota_task_queue, &msg, pdMS_TO_TICKS(10)) != pdTRUE) { + ESP_LOGE(TAG, "Failed to send prepare command to OTA task"); + } + ESP_LOGE(TAG, "SLAVE PREPARE CALLBACK AFTER QUEUE SEND"); + + // Tell the master that the slave will preapre + OTA_PREPARE_ACKNOWLEDGED_Payload *reply_payload; + BaseMessage reply_message = + MessageBuilder(OTA_PREPARE_ACKNOWLEDGED, *(PayloadUnion *)&reply_payload, + sizeof(OTA_PREPARE_ACKNOWLEDGED_Payload)); + ESP_ERROR_CHECK(esp_now_send(esp_now_info->src_addr, + (uint8_t *)&reply_message, sizeof(BaseMessage))); +} + +void slave_Update_Chunk_Callback(const esp_now_recv_info_t *esp_now_info, + const uint8_t *data, int data_len) { + const BaseMessage *message = (const BaseMessage *)data; + const OTA_CHUNK_Payload *payload = &message->payload.ota_chunk_payload; + + // copy data to update_buffer_chunk so that the write method can write it + // back later + memcpy(update_buffer_chunk, payload->data, payload->data_len); + update_buffer_chunk_len = payload->data_len; + + ESP_LOGI(TAG, "slave_update_Chunk_Callback got %d bytes from Master", + payload->data_len); + + // Queue Command for Task to call the ota_write_message method + ota_task_queue_message_t msg = {.command = OTA_MASTER_SEND_CHUNK}; memcpy(msg.mac_addr, esp_now_info->src_addr, ESP_NOW_ETH_ALEN); if (xQueueSend(ota_task_queue, &msg, pdMS_TO_TICKS(10)) != pdTRUE) { ESP_LOGE(TAG, "Failed to send prepare command to OTA task"); } } -void slave_ota_chunk_callback(const esp_now_recv_info_t *esp_now_info, - const uint8_t *data, int data_len) { +void slave_Update_Finished_Callback(const esp_now_recv_info_t *esp_now_info, + const uint8_t *data, int data_len) { const BaseMessage *message = (const BaseMessage *)data; - ota_task_queue_message_t msg = {.command = OTA_COMMAND_CHUNK}; + const OTA_FINISH_UPDATE_Payload *payload = + &message->payload.ota_finish_update_payload; + + ESP_LOGI(TAG, "slave_Update_Finished_Callback"); + + // Queue Command for Task to call the ota_write_message method + ota_task_queue_message_t msg = {.command = OTA_MASTER_SEND_FINISH}; memcpy(msg.mac_addr, esp_now_info->src_addr, ESP_NOW_ETH_ALEN); - memcpy(&msg.payload.ota_chunk_payload, &message->payload.ota_chunk_payload, - sizeof(OTA_CHUNK_Payload)); if (xQueueSend(ota_task_queue, &msg, pdMS_TO_TICKS(10)) != pdTRUE) { - ESP_LOGE(TAG, "Failed to send chunk to OTA task"); + ESP_LOGE(TAG, "Failed to send prepare command to OTA task"); } } -void slave_request_block_status_callback( +void start_ota_update_espnow(uint8_t msgid, const uint8_t *payload, + size_t payload_len, uint8_t *send_payload_buffer, + size_t send_payload_buffer_size, + uint8_t *send_buffer, size_t send_buffer_size) { + ESP_LOGI(TAG, "Starting OTA update for all clients"); + + const esp_partition_t *ota_update_partition; + + ota_update_partition = esp_ota_get_next_update_partition(NULL); + if (ota_update_partition == NULL) { + ESP_LOGE(TAG, "Failed to get update partition"); + return; + } + + update_size = get_app_size(ota_update_partition); + + partition_to_read_update_from = *ota_update_partition; + partition_to_read_from_read_index = 0; + + BaseMessage replyMessage = {}; + OTA_PREPARE_FOR_UPDATE_Payload replyPayload = {}; + + replyMessage = + MessageBuilder(OTA_PREPARE_FOR_UPDATE, *(PayloadUnion *)&replyPayload, + sizeof(replyPayload)); + + for (int i = 0; i < MAX_CLIENTS; i++) { + if (client_list->Clients[i].slotIsUsed) { + esp_now_send(client_list->Clients[i].macAddr, (uint8_t *)&replyMessage, + sizeof(BaseMessage)); + client_list->Clients[i].ota_status = OTA_READY; + } + } +} + +void master_ota_prepare_acknowledge_callback( const esp_now_recv_info_t *esp_now_info, const uint8_t *data, int data_len) { - const BaseMessage *message = (const BaseMessage *)data; - ota_task_queue_message_t msg = {.command = OTA_COMMAND_REQUEST_STATUS}; + ESP_LOGI(TAG, "entering master_ota_prepare_acknowledge_callback"); + // Queue Command for Task to call the ota_write_message method + ota_task_queue_message_t msg = {.command = OTA_SLAVE_WILL_PREPARE}; memcpy(msg.mac_addr, esp_now_info->src_addr, ESP_NOW_ETH_ALEN); - memcpy(&msg.payload.ota_request_block_status_payload, - &message->payload.ota_request_block_status_payload, - sizeof(OTA_REQUEST_BLOCK_STATUS_Payload)); if (xQueueSend(ota_task_queue, &msg, pdMS_TO_TICKS(10)) != pdTRUE) { - ESP_LOGE(TAG, "Failed to send block status request to OTA task"); + ESP_LOGE(TAG, "Failed to send prepare command to OTA task"); } } -void slave_commit_block_callback(const esp_now_recv_info_t *esp_now_info, - const uint8_t *data, int data_len) { - const BaseMessage *message = (const BaseMessage *)data; - ota_task_queue_message_t msg = {.command = OTA_COMMAND_COMMIT}; - memcpy(msg.mac_addr, esp_now_info->src_addr, ESP_NOW_ETH_ALEN); - memcpy(&msg.payload.ota_commit_block_payload, - &message->payload.ota_commit_block_payload, - sizeof(OTA_COMMIT_BLOCK_Payload)); - if (xQueueSend(ota_task_queue, &msg, pdMS_TO_TICKS(10)) != pdTRUE) { - ESP_LOGE(TAG, "Failed to send commit command to OTA task"); - } -} - -void slave_finish_update_callback(const esp_now_recv_info_t *esp_now_info, - const uint8_t *data, int data_len) { - ota_task_queue_message_t msg = {.command = OTA_COMMAND_FINISH}; - memcpy(msg.mac_addr, esp_now_info->src_addr, ESP_NOW_ETH_ALEN); - if (xQueueSend(ota_task_queue, &msg, pdMS_TO_TICKS(10)) != pdTRUE) { - ESP_LOGE(TAG, "Failed to send finish command to OTA task"); - } -} - -void slave_master_ready_to_send_chunks_callback( +void master_ota_ready_to_recieve_callback( const esp_now_recv_info_t *esp_now_info, const uint8_t *data, int data_len) { - ota_task_queue_message_t msg = {.command = OTA_COMMAND_MASTER_READY}; + ESP_LOGI(TAG, "entering master_ota_ready_to_recieve_callback"); + // Queue Command for Task to call the ota_write_message method + ota_task_queue_message_t msg = {.command = OTA_SLAVE_IS_PREPARED}; memcpy(msg.mac_addr, esp_now_info->src_addr, ESP_NOW_ETH_ALEN); if (xQueueSend(ota_task_queue, &msg, pdMS_TO_TICKS(10)) != pdTRUE) { - ESP_LOGE(TAG, "Failed to send master ready command to OTA task"); + ESP_LOGE(TAG, "Failed to send prepare command to OTA task"); + } +} + +void master_ota_update_slave_acknowledge_callback( + const esp_now_recv_info_t *esp_now_info, const uint8_t *data, + int data_len) { + ESP_LOGI(TAG, "entering master_ota_update_slave_acknowledge_callback"); + // Queue Command for Task to call the ota_write_message method + ota_task_queue_message_t msg = {.command = OTA_SLAVE_ACKED}; + memcpy(msg.mac_addr, esp_now_info->src_addr, ESP_NOW_ETH_ALEN); + if (xQueueSend(ota_task_queue, &msg, pdMS_TO_TICKS(10)) != pdTRUE) { + ESP_LOGE(TAG, "Failed to send prepare command to OTA task"); } } diff --git a/main/ota_update.h b/main/ota_update.h index 47295cd..8a0b652 100644 --- a/main/ota_update.h +++ b/main/ota_update.h @@ -1,49 +1,41 @@ #ifndef OTA_UPDATE_H #define OTA_UPDATE_H +#include "client_handler.h" #include "esp_err.h" -#include -#include #include "esp_now.h" #include "esp_partition.h" #include "message_structs.h" +#include +#include #define UPDATE_BUFFER_SIZE 4096 #define UPDATE_PAYLOAD_SIZE 200 #define UPDATE_MAX_SEQUENZES (UPDATE_BUFFER_SIZE / UPDATE_PAYLOAD_SIZE) typedef enum { - OTA_COMMAND_PREPARE, - OTA_COMMAND_CHUNK, - OTA_COMMAND_REQUEST_STATUS, - OTA_COMMAND_COMMIT, - OTA_COMMAND_FINISH, - OTA_COMMAND_MASTER_READY + OTA_SEND_SLAVES_PREPARE_MESSAGE, + OTA_SLAVE_WILL_PREPARE, + OTA_SLAVE_IS_PREPARED, + OTA_SLAVE_ACKED, + OTA_SLAVE_ERROR, + OTA_MASTER_SEND_PREAPRE_REQUEST, + OTA_MASTER_SEND_CHUNK, + OTA_MASTER_SEND_FINISH, } ota_command_t; typedef struct { - ota_command_t command; - uint8_t mac_addr[ESP_NOW_ETH_ALEN]; - union { - OTA_CHUNK_Payload ota_chunk_payload; - OTA_REQUEST_BLOCK_STATUS_Payload ota_request_block_status_payload; - OTA_COMMIT_BLOCK_Payload ota_commit_block_payload; - } payload; + ota_command_t command; + uint8_t mac_addr[ESP_NOW_ETH_ALEN]; } ota_task_queue_message_t; - -extern uint32_t g_uart_firmware_total_size; +typedef struct { + ClientList *client_list; +} MasterOTA_TaskParams_t; void init_ota(); -void ota_task(void *pvParameter); - -enum OTA_UPDATE_STATES { - IDEL, - START_REQUESTED, - WAITING_FOR_PAYLOAD, - WRITING_OTA_TO_PARTITION, - -}; +void MasterOTATask(void *pvParameter); +void slave_ota_task(void *pvParameter); u_int32_t get_app_size(const esp_partition_t *app_size_partition); @@ -53,29 +45,37 @@ esp_err_t end_ota_update(); void slave_Prep_Upgrade_Callback(const esp_now_recv_info_t *esp_now_info, const uint8_t *data, int data_len); -void slave_ota_chunk_callback(const esp_now_recv_info_t *esp_now_info, - const uint8_t *data, int data_len); -void slave_request_block_status_callback( - const esp_now_recv_info_t *esp_now_info, const uint8_t *data, - int data_len); -void slave_commit_block_callback(const esp_now_recv_info_t *esp_now_info, +void slave_Update_Chunk_Callback(const esp_now_recv_info_t *esp_now_info, const uint8_t *data, int data_len); -void slave_finish_update_callback(const esp_now_recv_info_t *esp_now_info, - const uint8_t *data, int data_len); -void slave_master_ready_to_send_chunks_callback(const esp_now_recv_info_t *esp_now_info, - const uint8_t *data, int data_len); +void slave_Update_Finished_Callback(const esp_now_recv_info_t *esp_now_info, + const uint8_t *data, int data_len); + +void master_ota_prepare_acknowledge_callback( + const esp_now_recv_info_t *esp_now_info, const uint8_t *data, int data_len); + +void master_ota_ready_to_recieve_callback( + const esp_now_recv_info_t *esp_now_info, const uint8_t *data, int data_len); + +void master_ota_update_slave_acknowledge_callback( + const esp_now_recv_info_t *esp_now_info, const uint8_t *data, int data_len); void start_uart_update(uint8_t msgid, const uint8_t *payload, size_t payload_len, uint8_t *send_payload_buffer, size_t send_payload_buffer_size, uint8_t *send_buffer, size_t send_buffer_size); void payload_uart_update(uint8_t msgid, const uint8_t *payload_data_from_uart, - size_t total_payload_len_from_uart, uint8_t *send_payload_buffer, + size_t total_payload_len_from_uart, + uint8_t *send_payload_buffer, size_t send_payload_buffer_size, uint8_t *send_buffer, size_t send_buffer_size); void end_uart_update(uint8_t msgid, const uint8_t *payload, size_t payload_len, - uint8_t *send_payload_buffer, - size_t send_payload_buffer_size, uint8_t *send_buffer, - size_t send_buffer_size); + uint8_t *send_payload_buffer, + size_t send_payload_buffer_size, uint8_t *send_buffer, + size_t send_buffer_size); + +void start_ota_update_espnow(uint8_t msgid, const uint8_t *payload, + size_t payload_len, uint8_t *send_payload_buffer, + size_t send_payload_buffer_size, + uint8_t *send_buffer, size_t send_buffer_size); #endif