diff --git a/goTool/main.go b/goTool/main.go index 1aef0f5..9da00fd 100644 --- a/goTool/main.go +++ b/goTool/main.go @@ -22,10 +22,11 @@ const ( UART_CLIENT_INFO = 0x03 // OTA - UART_OTA_START = 0x10 - UART_OTA_PAYLOAD = 0x11 - UART_OTA_END = 0x12 - UART_OTA_STATUS = 0x13 + UART_OTA_START = 0x10 + UART_OTA_PAYLOAD = 0x11 + UART_OTA_END = 0x12 + UART_OTA_STATUS = 0x13 + UART_OTA_START_ESPNOW = 0x14 ) const ( @@ -501,6 +502,13 @@ func main() { sendMessage(port, send_buffer[:n]) break case "6": // end update + case "7": // Start OTA for ESP-NOW clients + payload_buffer := make([]byte, 1024) + send_buffer := make([]byte, 1024) + payload_buffer[0] = UART_OTA_START_ESPNOW // Use the new constant + n := buildMessage(payload_buffer, 1, send_buffer) + sendMessage(port, send_buffer[:n]) + break default: fmt.Printf("Not a valid input") } diff --git a/main/client_handler.c b/main/client_handler.c index cebaa95..7be3a4d 100644 --- a/main/client_handler.c +++ b/main/client_handler.c @@ -1,6 +1,7 @@ #include "client_handler.h" -#include "communication_handler.h" + #include "esp_log.h" +#include "freertos/task.h" #include #include #include @@ -40,6 +41,8 @@ int add_client(ClientList *list, const uint8_t *client_mac) { list->Clients[slot].slotIsUsed = true; list->Clients[slot].isAvailable = true; + list->Clients[slot].last_seen = xTaskGetTickCount(); + list->Clients[slot].retry_counter = 0; memcpy(list->Clients[slot].macAddr, client_mac, MAC_LENGTH); list->ClientCount++; return CLIENT_OK; diff --git a/main/client_handler.h b/main/client_handler.h index 5761379..d057d2e 100644 --- a/main/client_handler.h +++ b/main/client_handler.h @@ -21,6 +21,16 @@ enum ClientErrors { CLIENT_INVALID_ID = -4, }; +typedef enum { + OTA_IDLE, + OTA_AWAITING_ACK, + OTA_PREPARING, + OTA_READY, + OTA_UPDATING, + OTA_FAILED, + OTA_SUCCESS, +} ota_status_t; + typedef struct { bool slotIsUsed; bool isAvailable; @@ -29,6 +39,12 @@ typedef struct { TickType_t lastSuccessfullPing; TickType_t lastPing; uint16_t clientVersion; + ota_status_t ota_status; + uint16_t current_block_id; + uint32_t chunk_bitmask; + uint32_t resent_chunks_counter; + uint8_t retry_counter; + TickType_t last_seen; } ClientInfo; typedef struct { diff --git a/main/communication_handler.c b/main/communication_handler.c index f9a6279..4ba93f4 100644 --- a/main/communication_handler.c +++ b/main/communication_handler.c @@ -1,19 +1,26 @@ +#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_timer.h" #include "freertos/idf_additions.h" +#include "freertos/task.h" +#include "esp_partition.h" #include "client_handler.h" -#include "communication_handler.h" #include #include #include #include #include +uint8_t broadcast_address[ESP_NOW_ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + static const char *TAG = "ALOX - COM"; +static QueueHandle_t messageQueue = NULL; static struct ESP_MessageBroker mr; static QueueHandle_t ESP_recieved_message_queue; @@ -62,7 +69,6 @@ void ESP_MessageBrokerTask(void *param) { ESP_MessageBrokerTaskParams_t *task_params = (ESP_MessageBrokerTaskParams_t *)param; - // Extrahiere die einzelnen Parameter QueueHandle_t msg_queue = task_params->message_queue; if (msg_queue == NULL) { @@ -75,40 +81,23 @@ void ESP_MessageBrokerTask(void *param) { while (1) { if (xQueueReceive(msg_queue, &received_msg, portMAX_DELAY)) { - ESP_LOGI(TAG, "Broker got message trying to relay it now"); const BaseMessage *message = (const BaseMessage *)received_msg.data; - ESP_LOGI(TAG, "Broker searching for command page %d", - message->commandPage); - for (int i = 0; i < mr.num_direct_callbacks; - i++) { // TODO: there should not be a loop needed here + for (int i = 0; i < mr.num_direct_callbacks; i++) { if (mr.FunctionList[i].MSGID == message->commandPage) { mr.FunctionList[i].callback(&received_msg.esp_now_info, received_msg.data, received_msg.data_len); - ESP_LOGI(TAG, "Broker found matching msgid %d", - mr.FunctionList[i].MSGID); free_ESPNOW_MessageInfo(&received_msg); } } - for (int i = 0; i < mr.num_direct_callbacks; i++) { - // if (mr.FunctionList[i].MSGID == received_msg.msgid) { - // TODO: Not yet implemented - // Only send data to task, task should be created beforhead and wait - // for new data in the queue. - //} - } } } } -QueueHandle_t messageQueue = NULL; // Warteschlange für empfangene Nachrichten static bool hasMaster = false; static ClientList *esp_client_list; static uint8_t channelNumber = 0; -#define MAC_STRING_BUFFER_SIZE 18 - int init_com(ClientList *clients, uint8_t wifi_channel) { - // Initialisiere die Kommunikations-Warteschlange messageQueue = xQueueCreate(MESSAGE_QUEUE_SIZE, sizeof(ESPNOW_MessageInfo)); if (messageQueue == NULL) { ESP_LOGE(TAG, "Message queue creation failed"); @@ -125,19 +114,18 @@ int add_peer(uint8_t *macAddr) { esp_now_peer_info_t peerInfo = { .channel = channelNumber, .ifidx = ESP_IF_WIFI_STA, - .encrypt = false, // Keine Verschlüsselung // TODO: should be changed + .encrypt = false, }; memcpy(peerInfo.peer_addr, macAddr, ESP_NOW_ETH_ALEN); esp_err_t result = esp_now_add_peer(&peerInfo); if (result == ESP_OK) { - ESP_LOGI(TAG, "Peer added: " MACSTR, MAC2STR(peerInfo.peer_addr)); + ESP_LOGI(TAG, "Peer added"); 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; } @@ -147,7 +135,6 @@ int add_peer(uint8_t *macAddr) { ESP_LOGW(TAG, "Peer already exists."); int id = get_client_id(esp_client_list, peerInfo.peer_addr); if (id >= 0) { - ESP_LOGI(TAG, "Client found again, welcome back!"); esp_client_list->Clients[id].isAvailable = true; } } else { @@ -173,28 +160,29 @@ BaseMessage MessageBuilder(CommandPages commandPage, PayloadUnion payload, void master_broadcast_task(void *param) { while (1) { - BroadCastPayload payload = {}; + if (!g_ota_in_progress) { + 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_LOGI(TAG, "Broadcast Message sent"); + 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) { - 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))); - // ESP_LOGI(TAG, "Broadcast PING Message sent"); + 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))); + } vTaskDelay(pdMS_TO_TICKS(2500)); } } @@ -203,15 +191,12 @@ void master_ping_task(void *param) { while (1) { for (size_t i = 0; i < MAX_CLIENTS; i++) { if (esp_client_list->Clients[i].isAvailable) { - ESP_LOGI(TAG, "SEND PING TO %zu: " MACSTR, i, - MAC2STR(esp_client_list->Clients[i].macAddr)); PingPayload payload = {}; payload.timestamp = esp_timer_get_time(); BaseMessage message = MessageBuilder( PingPage, *(PayloadUnion *)&payload, sizeof(payload)); esp_now_send(esp_client_list->Clients[i].macAddr, (uint8_t *)&message, sizeof(BaseMessage)); - ESP_LOGI(TAG, "SENDING PING!!!!"); } } vTaskDelay(pdMS_TO_TICKS(1000)); @@ -221,8 +206,7 @@ void master_ping_task(void *param) { void master_StatusCallback(const esp_now_recv_info_t *esp_now_info, const uint8_t *data, int data_len) { const BaseMessage *message = (const BaseMessage *)data; - - ESP_LOGI(TAG, "SRC " MACSTR, MAC2STR(esp_now_info->src_addr)); + ESP_LOGI(TAG, "SRC"); ESP_LOGI(TAG, "Status Message Received: status: %d, runningPartition: %d, uptime: " "%d, version: %d", @@ -235,81 +219,45 @@ void master_StatusCallback(const esp_now_recv_info_t *esp_now_info, void master_RegisterCallback(const esp_now_recv_info_t *esp_now_info, const uint8_t *data, int data_len) { BaseMessage replyMessage = {}; - const BaseMessage *message = (const BaseMessage *)data; - ESP_LOGI(TAG, "WILL REGISTER DEVICE"); esp_now_peer_info_t checkPeerInfo; esp_err_t checkPeer = esp_now_get_peer(esp_now_info->src_addr, &checkPeerInfo); switch (checkPeer) { case (ESP_OK): - ESP_LOGI(TAG, "CLIENT BEKANNT"); int id = get_client_id(esp_client_list, esp_now_info->src_addr); esp_client_list->Clients[id].isAvailable = true; esp_client_list->Clients[id].lastSuccessfullPing = xTaskGetTickCount(); - ESP_LOGI(TAG, "Updated client %d last ping time to %lu", id, - esp_client_list->Clients[id].lastSuccessfullPing); - break; - case (ESP_ERR_ESPNOW_NOT_INIT): - ESP_LOGI(TAG, "Not initalised"); - break; - case (ESP_ERR_ESPNOW_ARG): - ESP_LOGI(TAG, "ESP ERR ESPNOW_ARG"); break; case (ESP_ERR_ESPNOW_NOT_FOUND): - ESP_LOGI(TAG, "CLIENT WIRD IN DIE LISTE AUFGENOMMEN " MACSTR, - MAC2STR(esp_now_info->src_addr)); - int peer_err = add_peer(esp_now_info->src_addr); - if (peer_err < 0) { - ESP_LOGE(TAG, "Could not add ESP TO ClientList %d", peer_err); - } - ESP_LOGI(TAG, "FRAGE CLIENT STATUS AN"); - + add_peer(esp_now_info->src_addr); GetStatusPayload payload = {}; replyMessage = MessageBuilder(GetStatusPage, *(PayloadUnion *)&payload, sizeof(payload)); - esp_err_t err = esp_now_send(esp_now_info->src_addr, + esp_now_send(esp_now_info->src_addr, (uint8_t *)&replyMessage, sizeof(BaseMessage)); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Could not send Message Error %s", esp_err_to_name(err)); - } - break; default: - ESP_LOGI(TAG, "Unknown Message %i", checkPeer); + break; } } void master_pingCallback(const esp_now_recv_info_t *esp_now_info, const uint8_t *data, int data_len) { - BaseMessage replyMessage = {}; const BaseMessage *message = (const BaseMessage *)data; - ESP_LOGI(TAG, "GOT PING MESSAGE"); uint32_t currentTime = esp_timer_get_time(); uint32_t diff = currentTime - message->payload.ping_payload.timestamp; - ESP_LOGI(TAG, "Start: %lu, End: %lu, Diff: %lu, Ping: %lu", - message->payload.ping_payload.timestamp, currentTime, diff, - diff / 1000); // ping in ms - int id = get_client_id(esp_client_list, esp_now_info->src_addr); if (id >= 0) { esp_client_list->Clients[id].lastSuccessfullPing = xTaskGetTickCount(); esp_client_list->Clients[id].lastPing = (diff / 1000); - ESP_LOGI(TAG, "Updated client %d: " MACSTR " last ping time to %lu", id, - MAC2STR(esp_now_info->src_addr), - esp_client_list->Clients[id].lastSuccessfullPing); } } void master_broadcastCallback(const esp_now_recv_info_t *esp_now_info, - const uint8_t *data, int data_len) { - ESP_LOGI(TAG, - "Master should not recieve Broadcast is there another master " - "Calling got message from " MACSTR, - MAC2STR(esp_now_info->src_addr)); -} + const uint8_t *data, int data_len) {} void ESPNOW_RegisterMasterCallbacks() { ESP_RegisterFunction(StatusPage, master_StatusCallback); @@ -320,31 +268,23 @@ void ESPNOW_RegisterMasterCallbacks() { void slave_broadcastCallback(const esp_now_recv_info_t *esp_now_info, const uint8_t *data, int data_len) { - BaseMessage replyMessage = {}; - const BaseMessage *message = (const BaseMessage *)data; - - ESP_LOGI(TAG, "GOT BROADCAST MESSAGE"); if (!hasMaster) { if (IS_BROADCAST_ADDR(esp_now_info->des_addr)) { - ESP_LOGI(TAG, "GOT BROADCAST MESSAGE ATTEMPTING TO REGISTER TO MASTER!"); add_peer(esp_now_info->src_addr); + BaseMessage replyMessage = {}; replyMessage = - MessageBuilder(RegisterPage, *(PayloadUnion *)&message->payload, - sizeof(message->payload)); - ESP_ERROR_CHECK(esp_now_send(esp_now_info->src_addr, + MessageBuilder(RegisterPage, *(PayloadUnion *)&replyMessage.payload, + sizeof(replyMessage.payload)); + esp_now_send(esp_now_info->src_addr, (uint8_t *)&replyMessage, - sizeof(BaseMessage))); + sizeof(BaseMessage)); hasMaster = true; } - } else { - ESP_LOGI(TAG, "Already have master wont register by the new one"); } } + void slave_getstatusCallback(const esp_now_recv_info_t *esp_now_info, const uint8_t *data, int data_len) { - BaseMessage replyMessage = {}; - const BaseMessage *message = (const BaseMessage *)data; - StatusPayload payload = { .status = 1, .runningPartition = 1, @@ -352,24 +292,22 @@ void slave_getstatusCallback(const esp_now_recv_info_t *esp_now_info, .version = 0x0002, }; - replyMessage = + BaseMessage replyMessage = MessageBuilder(StatusPage, *(PayloadUnion *)&payload, sizeof(payload)); - ESP_ERROR_CHECK(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)); } + void slave_pingCallback(const esp_now_recv_info_t *esp_now_info, const uint8_t *data, int data_len) { if (!hasMaster) return; - BaseMessage replyMessage = {}; const BaseMessage *message = (const BaseMessage *)data; - - ESP_LOGI(TAG, "GOT PING MESSAGE"); - replyMessage = MessageBuilder(PingPage, *(PayloadUnion *)&message->payload, + BaseMessage replyMessage = MessageBuilder(PingPage, *(PayloadUnion *)&message->payload, sizeof(message->payload)); - ESP_ERROR_CHECK(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)); } void ESPNOW_RegisterSlaveCallbacks() { @@ -380,30 +318,23 @@ void ESPNOW_RegisterSlaveCallbacks() { void master_receive_callback(const esp_now_recv_info_t *esp_now_info, const uint8_t *data, int data_len) { - ESP_LOGI(TAG, "MASTER GOT MESSAGE"); - - // Allokiere Speicher für die Daten und kopiere sie uint8_t *copied_data = (uint8_t *)malloc(data_len); if (copied_data == NULL) { - ESP_LOGE(TAG, "Failed to allocate memory for message data."); return; } memcpy(copied_data, data, data_len); - // Fülle die neue Struktur mit kopierten Daten ESPNOW_MessageInfo msg_info; 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); } - // Speicher für des_addr kopieren msg_info.esp_now_info.des_addr = malloc(6); if (msg_info.esp_now_info.des_addr) { memcpy(msg_info.esp_now_info.des_addr, esp_now_info->des_addr, 6); } - // rx_ctrl Struktur kopieren msg_info.esp_now_info.rx_ctrl = malloc(sizeof(wifi_pkt_rx_ctrl_t)); if (msg_info.esp_now_info.rx_ctrl) { memcpy(msg_info.esp_now_info.rx_ctrl, esp_now_info->rx_ctrl, @@ -413,48 +344,47 @@ void master_receive_callback(const esp_now_recv_info_t *esp_now_info, msg_info.data = copied_data; msg_info.data_len = data_len; - if (xQueueSend(ESP_recieved_message_queue, &msg_info, portMAX_DELAY) != - pdPASS) { - // Fehlerbehandlung: Queue voll oder Senden fehlgeschlagen - ESP_LOGE(TAG, "Failed to send parsed message to queue."); - } - return; + xQueueSend(ESP_recieved_message_queue, &msg_info, portMAX_DELAY); } void client_receive_callback(const esp_now_recv_info_t *esp_now_info, const uint8_t *data, int data_len) { - ESP_LOGI(TAG, "SLAVE GOT MESSAGE"); - ESP_LOGI(TAG, "Received message from: " MACSTR, - MAC2STR(esp_now_info->src_addr)); - uint8_t *copied_data = (uint8_t *)malloc(data_len); if (copied_data == NULL) { - ESP_LOGE(TAG, "Failed to allocate memory for message data."); return; } memcpy(copied_data, data, data_len); - // Fülle die neue Struktur mit kopierten Daten ESPNOW_MessageInfo msg_info; - memcpy(&msg_info.esp_now_info, esp_now_info, sizeof(esp_now_recv_info_t)); + // 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 + 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); + } else { + free(copied_data); + return; + } + + // des_addr + msg_info.esp_now_info.des_addr = malloc(6); + if (msg_info.esp_now_info.des_addr) { + memcpy(msg_info.esp_now_info.des_addr, esp_now_info->des_addr, 6); + } else { + free(msg_info.esp_now_info.src_addr); + free(copied_data); + return; + } + + msg_info.esp_now_info.rx_ctrl = NULL; // Set to NULL as we are not copying it + msg_info.data = copied_data; msg_info.data_len = data_len; - if (xQueueSend(ESP_recieved_message_queue, &msg_info, portMAX_DELAY) != - pdPASS) { - // Fehlerbehandlung: Queue voll oder Senden fehlgeschlagen - ESP_LOGE(TAG, "Failed to send parsed message to queue."); - } - return; -} - -void client_data_sending_task(void *param) { - while (1) { - const char *dataToSend = "DATA:42"; - ESP_LOGI(TAG, "SEND DATA"); - esp_now_send(NULL, (uint8_t *)dataToSend, strlen(dataToSend)); - vTaskDelay(pdMS_TO_TICKS(5000)); - } + xQueueSend(ESP_recieved_message_queue, &msg_info, portMAX_DELAY); } void client_monitor_task(void *pvParameters) { @@ -471,11 +401,231 @@ void client_monitor_task(void *pvParameters) { if (time_diff > timeout_ticks) { esp_client_list->Clients[i].isAvailable = false; - ESP_LOGW(TAG, "Client %d (MAC: " MACSTR ") is unavailable", - MAC2STR(esp_client_list->Clients[i].macAddr)); } } } vTaskDelay(interval_ticks); } } + +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() { + ESP_RegisterFunction(OTA_PREPARE_ACKNOWLEDGED, + master_ota_prepare_acknowledged_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); +} + +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 diff --git a/main/communication_handler.h b/main/communication_handler.h index fa65b06..f1ed973 100644 --- a/main/communication_handler.h +++ b/main/communication_handler.h @@ -12,91 +12,30 @@ #include #include #include +#include "esp_partition.h" +#include "message_structs.h" #define BROADCAST_INTERVAL_MS 500 #define CLIENT_TIMEOUT_MS 5000 // 5 Sekunden Timeout #define CHECK_INTERVAL_MS 1000 // Jede Sekunde überprüfen -static uint8_t broadcast_address[ESP_NOW_ETH_ALEN] = {0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF}; -#define IS_BROADCAST_ADDR(addr) \ - (memcmp(addr, broadcast_address, ESP_NOW_ETH_ALEN) == 0) -#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] -#define MACSTR "%02X:%02X:%02X:%02X:%02X:%02X" +extern uint8_t broadcast_address[ESP_NOW_ETH_ALEN]; +#define IS_BROADCAST_ADDR(addr) (memcmp(addr, broadcast_address, ESP_NOW_ETH_ALEN) == 0) #define MESSAGE_QUEUE_SIZE 10 -typedef enum { - OTA_PREP_UPGRADE, - OTA_SEND_PAYLOAD, - OTA_WRITE_UPDATE_BUFFER, - OTA_SEND_MISSING, - OTA_UPDATE_INFO, - OTA_END_UPGRADE, - StatusPage, - GetStatusPage, - ConfigPage, - PingPage, - BroadCastPage, - RegisterPage, -} CommandPages; - -typedef struct __attribute__((packed)) { - -} OTA_PREP_UPGRADE_Payload; - -typedef struct __attribute__((packed)) { -} OTA_SEND_PAYLOAD_Payload; -typedef struct __attribute__((packed)) { -} OTA_WRITE_UPDATE_BUFFER_Payload; -typedef struct __attribute__((packed)) { -} OTA_SEND_MISSING_Payload; -typedef struct __attribute__((packed)) { -} OTA_UPDATE_INFO_Payload; -typedef struct __attribute__((packed)) { -} OTA_END_UPGRADE_Payload; - -typedef struct __attribute__((packed)) { - uint16_t version; // software version - uint8_t runningPartition; - uint8_t status; - uint32_t uptime; -} StatusPayload; - -typedef struct __attribute__((packed)) { -} GetStatusPayload; - -typedef struct __attribute__((packed)) { - uint8_t timeslot; -} ConfigPayload; - -typedef struct __attribute__((packed)) { - uint32_t timestamp; -} PingPayload; - -typedef struct __attribute__((packed)) { -} BroadCastPayload; - -typedef struct __attribute__((packed)) { - bool familierClient; -} RegisterPayload; - -// TODO: Check checksum fields -typedef struct __attribute__((packed)) { - uint16_t length; // length of complete firmware - uint8_t checksum; // checksum of firmware -} FirmwarePrepPayload; - -// TODO: Check checksum fields -typedef struct __attribute__((packed)) { - uint8_t length; - uint8_t checksum; - uint32_t address; - uint8_t payload[240]; // TODO: need a way to figure out a safe value for this -} FirmwarePayload; - typedef union __attribute__((packed)) { + OTA_PREPARE_FOR_UPDATE_Payload ota_prepare_for_update_payload; + OTA_PREPARE_ACKNOWLEDGED_Payload ota_prepare_acknowledged_payload; + OTA_READY_TO_RECEIVE_Payload ota_ready_to_receive_payload; + OTA_CHUNK_Payload ota_chunk_payload; + OTA_REQUEST_BLOCK_STATUS_Payload ota_request_block_status_payload; + OTA_BLOCK_STATUS_REPORT_Payload ota_block_status_report_payload; + OTA_COMMIT_BLOCK_Payload ota_commit_block_payload; + OTA_BLOCK_COMMITTED_Payload ota_block_committed_payload; + OTA_FINISH_UPDATE_Payload ota_finish_update_payload; + OTA_UPDATE_STATUS_Payload ota_update_status_payload; StatusPayload status_payload; ConfigPayload config_payload; PingPayload ping_payload; @@ -156,6 +95,8 @@ void ESP_MessageBrokerTask(void *param); void ESPNOW_RegisterMasterCallbacks(); void ESPNOW_RegisterSlaveCallbacks(); +void ESPNOW_RegisterOTAMaster(); +void ESPNOW_RegisterOTASlave(); int init_com(ClientList *clients, uint8_t wifi_channel); int getNextFreeClientId(); @@ -173,6 +114,20 @@ 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 6e88c3a..cd4debf 100644 --- a/main/main.c +++ b/main/main.c @@ -2,6 +2,7 @@ #include "driver/gpio.h" #include "driver/uart.h" #include "esp_err.h" +#include "esp_image_format.h" #include "esp_log.h" #include "esp_log_buffer.h" #include "esp_ota_ops.h" @@ -34,6 +35,7 @@ static const char *TAG = "ALOX - MAIN"; static const uint16_t version = 0x0001; static uint8_t send_message_buffer[1024]; static uint8_t send_message_payload_buffer[512]; +uint32_t g_uart_firmware_total_size = 0; static MessageBrokerTaskParams_t broker_task_params; static ESP_MessageBrokerTaskParams_t esp_broker_task_params; @@ -104,27 +106,9 @@ void clientInfoCallback(uint8_t msgid, const uint8_t *payload, send_payload_buffer[0] = clientList.ClientCount; uint8_t offsetMult = 0; - uint8_t used_slots = 0; for (int i = 0; i < MAX_CLIENTS; i++) { if (clientList.Clients[i].slotIsUsed) { - used_slots++; - } - } - - uint8_t loop_sanity_counter = 0; - - for (int i = 0; i < MAX_CLIENTS; i++) { - if (clientList.Clients[i].slotIsUsed) { - loop_sanity_counter++; - if (loop_sanity_counter > clientList.ClientCount) { - ESP_LOGE("SPECIAL", - "ERROR SANITY CHECK FAILED: loop_sanity_count: %d, " - "client_count: %d", - loop_sanity_counter, clientList.ClientCount); - } size_t offset = 1 + (entryLength * offsetMult++); - - ESP_LOGE("SPECIAL", "OFFSET %d", offset); send_payload_buffer[offset] = i; send_payload_buffer[offset + 1] = clientList.Clients[i].isAvailable; send_payload_buffer[offset + 2] = clientList.Clients[i].slotIsUsed; @@ -142,8 +126,6 @@ void clientInfoCallback(uint8_t msgid, const uint8_t *payload, int len = build_message(UART_CLIENT_INFO, send_payload_buffer, needed_buffer_size, send_buffer, send_buffer_size); - // ESP_LOG_BUFFER_HEX("SEND BUFFER: ", send_buffer, send_buffer_size); - if (len < 0) { ESP_LOGE(TAG, "Error Building UART Message: payload_len, %d, sendbuffer_size: " @@ -154,6 +136,88 @@ void clientInfoCallback(uint8_t msgid, const uint8_t *payload, uart_write_bytes(MASTER_UART, send_buffer, len); } +bool g_ota_in_progress = false; + +void ota_monitor_task(void *param) { + const TickType_t timeout = pdMS_TO_TICKS(10000); // 10 seconds + + while (g_ota_in_progress) { + bool all_done = true; + for (int i = 0; i < MAX_CLIENTS; i++) { + if (clientList.Clients[i].slotIsUsed) { + if (clientList.Clients[i].ota_status != OTA_SUCCESS && + clientList.Clients[i].ota_status != OTA_FAILED) { + all_done = false; + + if ((xTaskGetTickCount() - clientList.Clients[i].last_seen) > timeout) { + ESP_LOGE(TAG, "Client %d timed out", i); + clientList.Clients[i].ota_status = OTA_FAILED; + } + } + } + } + + if (all_done) { + g_ota_in_progress = false; + } + + vTaskDelay(pdMS_TO_TICKS(1000)); + } + + ESP_LOGI(TAG, "OTA Operation Finished."); + for (int i = 0; i < MAX_CLIENTS; i++) { + 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].resent_chunks_counter); + } + } + + 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"); + + 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; + } + + 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) { ESP_LOGI(TAG, "Starting Alox Powerpod Version %d Build: %s", version, BUILD_GIT_HASH); @@ -166,21 +230,18 @@ void app_main(void) { } ESP_ERROR_CHECK(ret); - // GPIO-Pin für Moduserkennung gpio_reset_pin(MASTER_MODE_PIN); gpio_set_direction(MASTER_MODE_PIN, GPIO_MODE_INPUT); bool isMaster = (gpio_get_level(MASTER_MODE_PIN) == 0); - // ESP-NOW Initialisieren ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_event_loop_create_default()); 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)); @@ -198,66 +259,21 @@ void app_main(void) { ESP_LOGE(TAG, "Could not Init ESP NOW Communication!"); } - esp_partition_iterator_t partition_iter = esp_partition_find( - ESP_PARTITION_TYPE_ANY, ESP_PARTITION_SUBTYPE_ANY, NULL); - - while (partition_iter != NULL) { - const esp_partition_t *part1 = esp_partition_get(partition_iter); - ESP_LOGI(TAG, "Partition: %s, Address: %d, Size %d", part1->label, - part1->address, part1->size); - partition_iter = esp_partition_next(partition_iter); - } - const esp_partition_t *running = esp_ota_get_running_partition(); ESP_LOGI(TAG, "OTA: Running Partition: %s", running->label); - uint8_t ota_part_count = esp_ota_get_app_partition_count(); - ESP_LOGI(TAG, "OTA: Got %d OTA Partitions", ota_part_count); esp_ota_img_states_t ota_state; if (esp_ota_get_state_partition(running, &ota_state) == ESP_OK) { - ESP_LOGI(TAG, "OTA: Partition State : %d", ota_state); if (ota_state == ESP_OTA_IMG_PENDING_VERIFY) { - // run diagnostic function ... - bool diagnostic_is_ok = true; // TODO: a real function that checks if - // everything is running properly + bool diagnostic_is_ok = true; if (diagnostic_is_ok) { - ESP_LOGI( - TAG, - "Diagnostics completed successfully! Continuing execution ..."); - // esp_ota_mark_app_valid_cancel_rollback(); + esp_ota_mark_app_valid_cancel_rollback(); } else { - ESP_LOGE( - TAG, - "Diagnostics failed! Start rollback to the previous version ..."); - // esp_ota_mark_app_invalid_rollback_and_reboot(); + esp_ota_mark_app_invalid_rollback_and_reboot(); } } } - const char nvs_part_name[] = "nvs_data"; - const char nvs_namespace_name[] = "saved_clients"; - ret = nvs_flash_init_partition(nvs_part_name); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES || - ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { - ESP_ERROR_CHECK(nvs_flash_erase_partition(nvs_part_name)); - ret = nvs_flash_init_partition(nvs_part_name); - } - ESP_ERROR_CHECK(ret); - nvs_handle_t nt; - ESP_ERROR_CHECK(nvs_open_from_partition(nvs_part_name, nvs_namespace_name, - NVS_READWRITE, &nt)); - - int32_t outval; - ret = nvs_get_i32(nt, "test_entry", &outval); - if (ret == ESP_ERR_NVS_NOT_FOUND) { - ESP_ERROR_CHECK(nvs_set_i32(nt, "test_entry", 6969)); - ESP_ERROR_CHECK(nvs_commit(nt)); - ESP_LOGE(TAG, "Nichts im Flash gefunden hab was dahin geschrieben"); - } else if (ret == ESP_OK) { - ESP_LOGE(TAG, "DAS WAR IM FLASH %d", outval); - } - nvs_close(nt); - QueueHandle_t espnow_message_queue = xQueueCreate(10, sizeof(ESPNOW_MessageInfo)); ESP_InitMessageBroker(espnow_message_queue); @@ -266,25 +282,21 @@ void app_main(void) { xTaskCreate(ESP_MessageBrokerTask, "espnow_message_broker_task", 4096, (void *)&esp_broker_task_params, 4, NULL); - // Tasks starten basierend auf Master/Client if (isMaster) { ESP_LOGI(TAG, "Started in Mastermode"); ESPNOW_RegisterMasterCallbacks(); + ESPNOW_RegisterOTAMaster(); add_peer(broadcast_address); xTaskCreate(master_broadcast_task, "MasterBroadcast", 4096, NULL, 1, NULL); - // xTaskCreate(master_ping_task, "MasterPing", 4096, NULL, 1, NULL); xTaskCreate(master_broadcast_ping, "MasterBroadcastPing", 4096, NULL, 1, NULL); - // xTaskCreate(client_monitor_task, "MonitorClientTask", 4096, NULL, 1, - // NULL); QueueHandle_t parsed_message_queue = xQueueCreate(10, sizeof(ParsedMessage_t)); init_uart(parsed_message_queue); InitMessageBroker(); - // Initialisiere die Parameterstruktur broker_task_params.message_queue = parsed_message_queue; broker_task_params.send_buffer = send_message_buffer; broker_task_params.send_buffer_size = sizeof(send_message_buffer); @@ -298,16 +310,13 @@ void app_main(void) { RegisterCallback(0x01, echoCallback); RegisterCallback(0x02, versionCallback); RegisterCallback(0x03, clientInfoCallback); + RegisterCallback(UART_OTA_START_ESPNOW, start_ota_update_espnow); init_ota(); - - // xTaskCreate(uart_status_task, "MasterUartStatusTask", 4096, NULL, 1, - // NULL); xTaskCreate(SendClientInfoTask, "SendCientInfo", 4096, NULL, 1, - // NULL); } else { ESP_LOGI(TAG, "Started in Slavemode"); ESPNOW_RegisterSlaveCallbacks(); - // xTaskCreate(client_data_sending_task, "ClientDataSending", 4096, NULL, 1, - // NULL); + ESPNOW_RegisterOTASlave(); + init_ota(); } -} +} \ No newline at end of file diff --git a/main/main.h b/main/main.h index 1772c06..7ca5b05 100644 --- a/main/main.h +++ b/main/main.h @@ -19,5 +19,4 @@ #elif CONFIG_IDF_TARGET_ESP32C3 #define MASTER_MODE_PIN GPIO_NUM_0 // Jumper-Erkennungspin #endif - #endif diff --git a/main/message_structs.h b/main/message_structs.h new file mode 100644 index 0000000..d83d122 --- /dev/null +++ b/main/message_structs.h @@ -0,0 +1,113 @@ +#ifndef MESSAGE_STRUCTS_H +#define MESSAGE_STRUCTS_H + +#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" + +typedef enum { + OTA_PREPARE_FOR_UPDATE, + OTA_PREPARE_ACKNOWLEDGED, + OTA_READY_TO_RECEIVE, + OTA_CHUNK, + OTA_REQUEST_BLOCK_STATUS, + OTA_BLOCK_STATUS_REPORT, + OTA_COMMIT_BLOCK, + OTA_BLOCK_COMMITTED, + OTA_FINISH_UPDATE, + OTA_UPDATE_STATUS, + MASTER_READY_TO_SEND_CHUNKS, + StatusPage, + GetStatusPage, + ConfigPage, + PingPage, + BroadCastPage, + RegisterPage, +} CommandPages; + +typedef struct __attribute__((packed)) { + uint32_t total_size; + uint32_t block_size; +} OTA_PREPARE_FOR_UPDATE_Payload; + +typedef struct __attribute__((packed)) { + // Empty +} OTA_PREPARE_ACKNOWLEDGED_Payload; + +typedef struct __attribute__((packed)) { + uint8_t status; // 0 = READY, 1 = ERROR +} OTA_READY_TO_RECEIVE_Payload; + +typedef struct __attribute__((packed)) { + uint16_t block_id; + uint8_t chunk_id; + uint8_t data[200]; +} OTA_CHUNK_Payload; + +typedef struct __attribute__((packed)) { + uint16_t block_id; +} OTA_REQUEST_BLOCK_STATUS_Payload; + +typedef struct __attribute__((packed)) { + uint16_t block_id; + uint32_t chunk_bitmask; +} OTA_BLOCK_STATUS_REPORT_Payload; + +typedef struct __attribute__((packed)) { + uint16_t block_id; +} OTA_COMMIT_BLOCK_Payload; + +typedef struct __attribute__((packed)) { + uint16_t block_id; +} OTA_BLOCK_COMMITTED_Payload; + +typedef struct __attribute__((packed)) { + // Empty +} OTA_FINISH_UPDATE_Payload; + +typedef struct __attribute__((packed)) { + uint8_t status; // 0 = SUCCESS, 1 = FAILED +} OTA_UPDATE_STATUS_Payload; + +typedef struct __attribute__((packed)) { + uint16_t version; // software version + uint8_t runningPartition; + uint8_t status; + uint32_t uptime; +} StatusPayload; + +typedef struct __attribute__((packed)) { +} GetStatusPayload; + +typedef struct __attribute__((packed)) { + uint8_t timeslot; +} ConfigPayload; + +typedef struct __attribute__((packed)) { + uint32_t timestamp; +} PingPayload; + +typedef struct __attribute__((packed)) { +} BroadCastPayload; + +typedef struct __attribute__((packed)) { + bool familierClient; +} RegisterPayload; + +// TODO: Check checksum fields +typedef struct __attribute__((packed)) { + uint16_t length; // length of complete firmware + uint8_t checksum; // checksum of firmware +} FirmwarePrepPayload; + +// TODO: Check checksum fields +typedef struct __attribute__((packed)) { + uint8_t length; + uint8_t checksum; + uint32_t address; + uint8_t payload[240]; // TODO: need a way to figure out a safe value for this +} FirmwarePayload; + +#endif // MESSAGE_STRUCTS_H diff --git a/main/ota_update.c b/main/ota_update.c index cf0c448..c86b96e 100644 --- a/main/ota_update.c +++ b/main/ota_update.c @@ -1,63 +1,167 @@ #include "ota_update.h" +#include "communication_handler.h" #include "driver/uart.h" -#include "esp_err.h" #include "esp_log.h" #include "esp_ota_ops.h" #include "esp_partition.h" #include "esp_system.h" +#include "freertos/FreeRTOS.h" +#include "freertos/queue.h" +#include "freertos/task.h" #include "message_builder.h" #include "message_handler.h" #include "uart_handler.h" #include "uart_msg_ids.h" -#include -#include -#include -#define MAX(a, b) ((a) > (b) ? (a) : (b)) -#define MIN(a, b) ((a) < (b) ? (a) : (b)) +extern uint32_t g_uart_firmware_total_size; +static const char *TAG = "ALOX - OTA_SLAVE"; + +static QueueHandle_t ota_task_queue = NULL; + +static esp_ota_handle_t update_handle = 0; static uint8_t update_buffer[UPDATE_BUFFER_SIZE]; +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 const char *TAG = "ALOX - OTA"; -static esp_ota_handle_t update_handle; +void ota_task(void *pvParameter) { + ESP_LOGI(TAG, "ota_task started"); + ota_task_queue_message_t msg; + while (1) { + if (xQueueReceive(ota_task_queue, &msg, portMAX_DELAY)) { + ESP_LOGI(TAG, "ota_task received command: %d", msg.command); + BaseMessage replyMessage = {}; -int prepare_ota_update() { - const esp_partition_t *running = esp_ota_get_running_partition(); - ESP_LOGI(TAG, "OTA: Running Partition: %s", running->label); - int part = 0; + switch (msg.command) { + case OTA_COMMAND_MASTER_READY: { + int part = prepare_ota_update(); + OTA_READY_TO_RECEIVE_Payload payload = {}; + if (part < 0) { + payload.status = 1; // ERROR + } else { + payload.status = 0; // READY + } + 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)); + 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)); - char partition_to_update[] = "ota_0"; - if (strcmp(running->label, "ota_0") == 0) { - strcpy(partition_to_update, "ota_1"); - part = 1; + 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: { + 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)); + 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; + } + } + } } - - const esp_partition_t *update_partition = esp_partition_find_first( - ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_ANY, partition_to_update); - - // Check if the partition was found - if (update_partition == NULL) { - ESP_LOGE(TAG, "Failed to find OTA partition: %s", partition_to_update); - return -1; // Or handle the error appropriately - } - - ESP_LOGI(TAG, "Gonna write OTA Update in Partition: %s", - update_partition->label); - - esp_err_t err = - esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle); - if (err != ESP_OK) { - ESP_LOGE(TAG, "esp_ota_begin failed (%s)", esp_err_to_name(err)); - esp_ota_abort(update_handle); - return -2; - } - - ESP_LOGI(TAG, "OTA update started successfully."); - return part; } +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, @@ -67,13 +171,20 @@ void start_uart_update(uint8_t msgid, const uint8_t *payload, vTaskPrioritySet(NULL, 2); 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 + } int part = prepare_ota_update(); - // Message: - // byte partition - // byte error - if (part < 0) { send_payload_buffer[1] = (part * -1) & 0xff; } else { @@ -95,20 +206,14 @@ 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) { - if (update_buffer_write_index > UPDATE_BUFFER_SIZE - write_len) { - // ESP_LOGI(TAG, "Writing Data to Update BUffer Sequence %d, writing Data - // %d", - // sequenz_counter, write_len); - // write to ota + if (update_buffer_write_index + write_len > UPDATE_BUFFER_SIZE) { esp_err_t err = esp_ota_write(update_handle, update_buffer, update_buffer_write_index); if (err != ESP_OK) { return err; } - update_buffer_write_index = 0; sequenz_counter++; - return err; } memcpy(&update_buffer[update_buffer_write_index], payload, write_len); @@ -116,16 +221,23 @@ esp_err_t write_ota_update(uint32_t write_len, const uint8_t *payload) { return ESP_OK; } -void payload_uart_update(uint8_t msgid, const uint8_t *payload, - size_t payload_len, uint8_t *send_payload_buffer, +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 send_payload_buffer_size, uint8_t *send_buffer, size_t send_buffer_size) { - // ESP_LOGI(TAG, "OTA Update Payload Uart Command"); - uint32_t write_len = MIN(UPDATE_PAYLOAD_SIZE, payload_len); + const uint8_t *actual_firmware_data = payload_data_from_uart; + + uint32_t write_len = total_payload_len_from_uart; + + if (update_size == 0) { + ESP_LOGI(TAG, "First chunk received. write_len: %d", write_len); + } + update_size += write_len; - esp_err_t err = write_ota_update(write_len, payload); + esp_err_t err = write_ota_update(write_len, actual_firmware_data); if (err != ESP_OK) { ESP_LOGE(TAG, "GOT ESP ERROR WRITE OTA %d", err); @@ -142,44 +254,13 @@ void payload_uart_update(uint8_t msgid, const uint8_t *payload, ESP_LOGE(TAG, "Error Building UART Message: payload_len, %d, sendbuffer_size: " "%d, mes_len(error): %d", - payload_len, send_buffer_size, len); + total_payload_len_from_uart, send_buffer_size, len); return; } uart_write_bytes(MASTER_UART, send_buffer, len); } -esp_err_t end_ota_update() { - esp_err_t err = - esp_ota_write(update_handle, update_buffer, update_buffer_write_index); - if (err != ESP_OK) { - ESP_LOGE(TAG, "GOT ESP ERROR WRITE OTA %d", err); - } - - err = esp_ota_end(update_handle); - if (err != ESP_OK) { - ESP_LOGE(TAG, "GOT ESP ERROR WRITE OTA %d", err); - } - - ESP_LOGE(TAG, "UPDATE ENDE UPDATGE SIZE SIND %d BYTES", update_size); - - // Hol dir die zuletzt geschriebene Partition - const esp_partition_t *partition = esp_ota_get_next_update_partition(NULL); - if (partition == NULL) { - ESP_LOGE(TAG, "Failed to get updated partition"); - err = ESP_FAIL; - } - - // Setze sie als Boot-Partition - ESP_LOGE(TAG, "Setzte nächste Partition auf %s", partition->label); - err = esp_ota_set_boot_partition(partition); - if (err != ESP_OK) { - ESP_LOGE(TAG, "esp_ota_set_boot_partition failed: %s", - esp_err_to_name(err)); - } - return err; -} - 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, @@ -188,7 +269,6 @@ void end_uart_update(uint8_t msgid, const uint8_t *payload, size_t payload_len, esp_err_t err = end_ota_update(); - // message ret esp_err_t int send_payload_len = 1; send_payload_buffer[0] = err & 0xff; int len = build_message(UART_OTA_END, send_payload_buffer, send_payload_len, @@ -206,10 +286,133 @@ void end_uart_update(uint8_t msgid, const uint8_t *payload, size_t payload_len, vTaskPrioritySet(NULL, 1); } -void write_ota_update_from_uart_task(void *param) {} - 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); } + +int prepare_ota_update() { + const esp_partition_t *running = esp_ota_get_running_partition(); + ESP_LOGI(TAG, "Running Partition: %s", running->label); + const esp_partition_t *update_partition = + esp_ota_get_next_update_partition(NULL); + if (update_partition == NULL) { + ESP_LOGE(TAG, "Failed to find OTA partition."); + return -1; + } + + ESP_LOGI(TAG, "Writing OTA Update to Partition: %s", update_partition->label); + + esp_err_t err = + esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "esp_ota_begin failed (%s)", esp_err_to_name(err)); + return -2; + } + return 0; +} + +esp_err_t end_ota_update() { + if (update_buffer_write_index > 0) { + esp_err_t err = + esp_ota_write(update_handle, update_buffer, update_buffer_write_index); + vTaskDelay(1); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error writing remaining data to partition: %s", + esp_err_to_name(err)); + return err; + } + } + + 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); + return err; + } + + const esp_partition_t *update_partition = + esp_ota_get_next_update_partition(NULL); + err = esp_ota_set_boot_partition(update_partition); + if (err != ESP_OK) { + ESP_LOGE(TAG, "esp_ota_set_boot_partition failed: %s", + esp_err_to_name(err)); + } + return err; +} + +void slave_Prep_Upgrade_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_PREPARE_FOR_UPDATE_Payload *payload = + &message->payload.ota_prepare_for_update_payload; + total_update_size = payload->total_size; + + ota_task_queue_message_t msg = {.command = OTA_COMMAND_PREPARE}; + 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) { + const BaseMessage *message = (const BaseMessage *)data; + ota_task_queue_message_t msg = {.command = OTA_COMMAND_CHUNK}; + 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"); + } +} + +void slave_request_block_status_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}; + 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"); + } +} + +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( + 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}; + 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"); + } +} diff --git a/main/ota_update.h b/main/ota_update.h index 6433486..0979909 100644 --- a/main/ota_update.h +++ b/main/ota_update.h @@ -4,11 +4,37 @@ #include "esp_err.h" #include #include -#define UPDATE_BUFFER_SIZE 4000 +#include "esp_now.h" +#include "message_structs.h" + +#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_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_task_queue_message_t; + + +extern uint32_t g_uart_firmware_total_size; + void init_ota(); +void ota_task(void *pvParameter); enum OTA_UPDATE_STATES { IDEL, @@ -22,4 +48,31 @@ int prepare_ota_update(); esp_err_t write_ota_update(uint32_t write_len, const uint8_t *payload); 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, + 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 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 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); + #endif diff --git a/main/uart_msg_ids.h b/main/uart_msg_ids.h index 9e90345..a684e2e 100644 --- a/main/uart_msg_ids.h +++ b/main/uart_msg_ids.h @@ -12,6 +12,7 @@ enum UART_MSG_IDS { UART_OTA_PAYLOAD = 0x11, UART_OTA_END = 0x12, UART_OTA_STATUS = 0x13, + UART_OTA_START_ESPNOW = 0x14, }; #endif