Compare commits

..

4 Commits

Author SHA1 Message Date
f2296a33e6 Create a simpler version of the OTA Update
Using no Broadcast logic for speed but its working now.
There is to much Acks going on but for the prototyp that is okay
2025-09-28 20:52:36 +02:00
7097e9e7ab Added Test Data Message for Game Development Testing 2025-09-27 15:57:52 +02:00
df35def702 Added Function to Read App Image size from Partition 2025-09-27 14:26:32 +02:00
337976e637 OTA Update nearly working but could not get image correctly transefered 2025-09-14 13:07:08 +02:00
12 changed files with 1072 additions and 408 deletions

View File

@ -49,6 +49,12 @@ flashCluster:
monitorMini: monitorMini:
idf.py monitor -p /dev/ttyACM0 idf.py monitor -p /dev/ttyACM0
monitorMini1:
idf.py monitor -p /dev/ttyACM1
monitorMini2:
idf.py monitor -p /dev/ttyACM2
flash0: flash0:
idf.py flash -p /dev/ttyUSB0 idf.py flash -p /dev/ttyUSB0
@ -66,3 +72,6 @@ monitor1:
monitor2: monitor2:
idf.py monitor -p /dev/ttyUSB2 idf.py monitor -p /dev/ttyUSB2
flash_second_ota:
parttool.py --port /dev/ttyACM0 write_partition --partition-name="ota_1" --input build/espAlox.bin

View File

@ -6,7 +6,9 @@ import (
"flag" "flag"
"fmt" "fmt"
"log" "log"
"math"
"os" "os"
"strconv"
"time" "time"
"github.com/pterm/pterm" "github.com/pterm/pterm"
@ -17,15 +19,17 @@ type ParserState int
const ( const (
// MISC // MISC
UART_ECHO = 0x01 UART_ECHO = 0x01
UART_VERSION = 0x02 UART_VERSION = 0x02
UART_CLIENT_INFO = 0x03 UART_CLIENT_INFO = 0x03
UART_CLIENT_INPUT = 0x04
// OTA // OTA
UART_OTA_START = 0x10 UART_OTA_START = 0x10
UART_OTA_PAYLOAD = 0x11 UART_OTA_PAYLOAD = 0x11
UART_OTA_END = 0x12 UART_OTA_END = 0x12
UART_OTA_STATUS = 0x13 UART_OTA_STATUS = 0x13
UART_OTA_START_ESPNOW = 0x14
) )
const ( const (
@ -198,30 +202,63 @@ func parse_uart_client_info_payload(payloadBuffer []byte, payload_len int) {
} }
} }
func parse_uart_client_input(payloadBuffer []byte, payload_len int) {
clientCount := payloadBuffer[1]
fmt.Printf("Client Count %d\n", clientCount)
clientInputLen := 13
for i := 0; i < int(clientCount); i++ {
offset := 2 + (i * clientInputLen)
// --- Client ID (uint8) ---
clientID := payloadBuffer[offset]
offset += 1
fmt.Printf("Client: %d\n", clientID)
// --- Lage X (float32) ---
xBits := binary.LittleEndian.Uint32(payloadBuffer[offset : offset+4])
lageX := math.Float32frombits(xBits)
offset += 4
fmt.Printf("\tLAGE_X: %f\n", lageX)
// --- Lage Y (float32) ---
yBits := binary.LittleEndian.Uint32(payloadBuffer[offset : offset+4])
lageY := math.Float32frombits(yBits)
offset += 4
fmt.Printf("\tLAGE_Y: %f\n", lageY)
// --- Bitmask (int32) ---
maskBits := binary.LittleEndian.Uint32(payloadBuffer[offset : offset+4])
bitmask := uint32(maskBits)
offset += 4
fmt.Printf("\tBITMASK: %032b\n", bitmask)
}
}
func message_receive_callback(mr MessageReceive) { func message_receive_callback(mr MessageReceive) {
log.Printf("Message Received: % 02X\n", mr.raw_message[:mr.raw_write_index]) log.Printf("Message Received: % 02X\n", mr.raw_message[:mr.raw_write_index])
switch mr.parsed_message[0] { switch mr.parsed_message[0] {
case byte(UART_ECHO): case byte(UART_ECHO):
break
case UART_VERSION: case UART_VERSION:
parse_uart_version_payload(mr.parsed_message, mr.write_index) parse_uart_version_payload(mr.parsed_message, mr.write_index)
break
case UART_CLIENT_INFO: case UART_CLIENT_INFO:
parse_uart_client_info_payload(mr.parsed_message, mr.write_index) parse_uart_client_info_payload(mr.parsed_message, mr.write_index)
break
case UART_OTA_START: case UART_OTA_START:
OTA_UpdateHandler.NewOTAMessage <- mr OTA_UpdateHandler.NewOTAMessage <- mr
break
case UART_OTA_PAYLOAD: case UART_OTA_PAYLOAD:
parse_uart_ota_payload_payload(mr.parsed_message, mr.write_index) parse_uart_ota_payload_payload(mr.parsed_message, mr.write_index)
OTA_UpdateHandler.NewOTAMessage <- mr OTA_UpdateHandler.NewOTAMessage <- mr
break
case UART_OTA_END: case UART_OTA_END:
OTA_UpdateHandler.NewOTAMessage <- mr OTA_UpdateHandler.NewOTAMessage <- mr
break
case UART_OTA_STATUS: case UART_OTA_STATUS:
OTA_UpdateHandler.NewOTAMessage <- mr OTA_UpdateHandler.NewOTAMessage <- mr
break case UART_CLIENT_INPUT:
parse_uart_client_input(mr.parsed_message, mr.write_index)
} }
} }
@ -239,7 +276,6 @@ func parseByte(mr *MessageReceive, pbyte byte) {
addByteToRawBuffer(mr, pbyte) addByteToRawBuffer(mr, pbyte)
} }
// ignore every other byte // ignore every other byte
break
case GET_MESSAGE_ID: case GET_MESSAGE_ID:
if pbyte == ESCAPE_BYTE { if pbyte == ESCAPE_BYTE {
mr.state = ESCAPED_MESSAGE_ID mr.state = ESCAPED_MESSAGE_ID
@ -247,11 +283,9 @@ func parseByte(mr *MessageReceive, pbyte byte) {
addByteToParsedBuffer(mr, pbyte) addByteToParsedBuffer(mr, pbyte)
mr.state = IN_PAYLOD mr.state = IN_PAYLOD
} }
break
case ESCAPED_MESSAGE_ID: case ESCAPED_MESSAGE_ID:
addByteToParsedBuffer(mr, pbyte) addByteToParsedBuffer(mr, pbyte)
mr.state = IN_PAYLOD mr.state = IN_PAYLOD
break
case IN_PAYLOD: case IN_PAYLOD:
if pbyte == ESCAPE_BYTE { if pbyte == ESCAPE_BYTE {
mr.state = ESCAPED_PAYLOAD_BYTE mr.state = ESCAPED_PAYLOAD_BYTE
@ -276,11 +310,9 @@ func parseByte(mr *MessageReceive, pbyte byte) {
} }
// normal case // normal case
addByteToParsedBuffer(mr, pbyte) addByteToParsedBuffer(mr, pbyte)
break
case ESCAPED_PAYLOAD_BYTE: case ESCAPED_PAYLOAD_BYTE:
addByteToParsedBuffer(mr, pbyte) addByteToParsedBuffer(mr, pbyte)
mr.state = IN_PAYLOD mr.state = IN_PAYLOD
break
default: default:
panic(fmt.Sprintf("unexpected main.ParserState: %#v", mr.state)) panic(fmt.Sprintf("unexpected main.ParserState: %#v", mr.state))
} }
@ -453,9 +485,11 @@ func main() {
for { for {
var input string var input string
_, err := fmt.Scanln(&input) var input2 string
_, err := fmt.Scanln(&input, &input2)
if err != nil { if err != nil {
log.Fatalf("Could not read from stdin") log.Fatalf("Could not read from stdin %v", err)
return
} }
fmt.Printf("Input %v", input) fmt.Printf("Input %v", input)
@ -468,28 +502,24 @@ func main() {
payload_buffer[0] = UART_ECHO payload_buffer[0] = UART_ECHO
n := buildMessage(payload_buffer, 1, send_buffer) n := buildMessage(payload_buffer, 1, send_buffer)
sendMessage(port, send_buffer[:n]) sendMessage(port, send_buffer[:n])
break
case "2": case "2":
payload_buffer := make([]byte, 1024) payload_buffer := make([]byte, 1024)
send_buffer := make([]byte, 1024) send_buffer := make([]byte, 1024)
payload_buffer[0] = UART_VERSION payload_buffer[0] = UART_VERSION
n := buildMessage(payload_buffer, 1, send_buffer) n := buildMessage(payload_buffer, 1, send_buffer)
sendMessage(port, send_buffer[:n]) sendMessage(port, send_buffer[:n])
break
case "3": case "3":
payload_buffer := make([]byte, 1024) payload_buffer := make([]byte, 1024)
send_buffer := make([]byte, 1024) send_buffer := make([]byte, 1024)
payload_buffer[0] = UART_CLIENT_INFO payload_buffer[0] = UART_CLIENT_INFO
n := buildMessage(payload_buffer, 1, send_buffer) n := buildMessage(payload_buffer, 1, send_buffer)
sendMessage(port, send_buffer[:n]) sendMessage(port, send_buffer[:n])
break
case "4": // start update case "4": // start update
payload_buffer := make([]byte, 1024) payload_buffer := make([]byte, 1024)
send_buffer := make([]byte, 1024) send_buffer := make([]byte, 1024)
payload_buffer[0] = UART_OTA_START payload_buffer[0] = UART_OTA_START
n := buildMessage(payload_buffer, 1, send_buffer) n := buildMessage(payload_buffer, 1, send_buffer)
sendMessage(port, send_buffer[:n]) sendMessage(port, send_buffer[:n])
break
case "5": // send payload case "5": // send payload
payload_buffer := make([]byte, 1024) payload_buffer := make([]byte, 1024)
send_buffer := make([]byte, 1024) send_buffer := make([]byte, 1024)
@ -499,8 +529,25 @@ func main() {
} }
n := buildMessage(payload_buffer, 201, send_buffer) n := buildMessage(payload_buffer, 201, send_buffer)
sendMessage(port, send_buffer[:n]) sendMessage(port, send_buffer[:n])
break
case "6": // end update 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
n := buildMessage(payload_buffer, 1, send_buffer)
sendMessage(port, send_buffer[:n])
case "8": // Get Fake Client Input
payload_buffer := make([]byte, 1024)
send_buffer := make([]byte, 1024)
payload_buffer[0] = UART_CLIENT_INPUT
seed, err := strconv.Atoi(input2)
if err != nil {
log.Printf("Could not parse %v to a number", input2)
return
}
payload_buffer[1] = byte(seed)
n := buildMessage(payload_buffer, 2, send_buffer)
sendMessage(port, send_buffer[:n])
default: default:
fmt.Printf("Not a valid input") fmt.Printf("Not a valid input")
} }

View File

@ -1,6 +1,7 @@
#include "client_handler.h" #include "client_handler.h"
#include "communication_handler.h"
#include "esp_log.h" #include "esp_log.h"
#include "freertos/task.h"
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
@ -40,6 +41,8 @@ int add_client(ClientList *list, const uint8_t *client_mac) {
list->Clients[slot].slotIsUsed = true; list->Clients[slot].slotIsUsed = true;
list->Clients[slot].isAvailable = 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); memcpy(list->Clients[slot].macAddr, client_mac, MAC_LENGTH);
list->ClientCount++; list->ClientCount++;
return CLIENT_OK; return CLIENT_OK;

View File

@ -21,6 +21,16 @@ enum ClientErrors {
CLIENT_INVALID_ID = -4, 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 { typedef struct {
bool slotIsUsed; bool slotIsUsed;
bool isAvailable; bool isAvailable;
@ -29,6 +39,12 @@ typedef struct {
TickType_t lastSuccessfullPing; TickType_t lastSuccessfullPing;
TickType_t lastPing; TickType_t lastPing;
uint16_t clientVersion; 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; } ClientInfo;
typedef struct { typedef struct {

View File

@ -1,19 +1,28 @@
#include "communication_handler.h"
#include "esp_err.h" #include "esp_err.h"
#include "esp_log.h" #include "esp_log.h"
#include "esp_now.h" #include "esp_now.h"
#include "esp_ota_ops.h"
#include "esp_partition.h"
#include "esp_timer.h" #include "esp_timer.h"
#include "freertos/idf_additions.h" #include "freertos/idf_additions.h"
#include "freertos/task.h"
#include "message_structs.h"
#include "ota_update.h"
#include "client_handler.h" #include "client_handler.h"
#include "communication_handler.h"
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/types.h> #include <sys/types.h>
uint8_t broadcast_address[ESP_NOW_ETH_ALEN] = {0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF};
static const char *TAG = "ALOX - COM"; static const char *TAG = "ALOX - COM";
static QueueHandle_t messageQueue = NULL;
static struct ESP_MessageBroker mr; static struct ESP_MessageBroker mr;
static QueueHandle_t ESP_recieved_message_queue; static QueueHandle_t ESP_recieved_message_queue;
@ -62,7 +71,6 @@ void ESP_MessageBrokerTask(void *param) {
ESP_MessageBrokerTaskParams_t *task_params = ESP_MessageBrokerTaskParams_t *task_params =
(ESP_MessageBrokerTaskParams_t *)param; (ESP_MessageBrokerTaskParams_t *)param;
// Extrahiere die einzelnen Parameter
QueueHandle_t msg_queue = task_params->message_queue; QueueHandle_t msg_queue = task_params->message_queue;
if (msg_queue == NULL) { if (msg_queue == NULL) {
@ -75,40 +83,23 @@ void ESP_MessageBrokerTask(void *param) {
while (1) { while (1) {
if (xQueueReceive(msg_queue, &received_msg, portMAX_DELAY)) { 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; const BaseMessage *message = (const BaseMessage *)received_msg.data;
ESP_LOGI(TAG, "Broker searching for command page %d", for (int i = 0; i < mr.num_direct_callbacks; i++) {
message->commandPage);
for (int i = 0; i < mr.num_direct_callbacks;
i++) { // TODO: there should not be a loop needed here
if (mr.FunctionList[i].MSGID == message->commandPage) { if (mr.FunctionList[i].MSGID == message->commandPage) {
mr.FunctionList[i].callback(&received_msg.esp_now_info, mr.FunctionList[i].callback(&received_msg.esp_now_info,
received_msg.data, received_msg.data_len); received_msg.data, received_msg.data_len);
ESP_LOGI(TAG, "Broker found matching msgid %d",
mr.FunctionList[i].MSGID);
free_ESPNOW_MessageInfo(&received_msg); 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 bool hasMaster = false;
static ClientList *esp_client_list; static ClientList *esp_client_list;
static uint8_t channelNumber = 0; static uint8_t channelNumber = 0;
#define MAC_STRING_BUFFER_SIZE 18
int init_com(ClientList *clients, uint8_t wifi_channel) { int init_com(ClientList *clients, uint8_t wifi_channel) {
// Initialisiere die Kommunikations-Warteschlange
messageQueue = xQueueCreate(MESSAGE_QUEUE_SIZE, sizeof(ESPNOW_MessageInfo)); messageQueue = xQueueCreate(MESSAGE_QUEUE_SIZE, sizeof(ESPNOW_MessageInfo));
if (messageQueue == NULL) { if (messageQueue == NULL) {
ESP_LOGE(TAG, "Message queue creation failed"); ESP_LOGE(TAG, "Message queue creation failed");
@ -125,13 +116,13 @@ int add_peer(uint8_t *macAddr) {
esp_now_peer_info_t peerInfo = { esp_now_peer_info_t peerInfo = {
.channel = channelNumber, .channel = channelNumber,
.ifidx = ESP_IF_WIFI_STA, .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); memcpy(peerInfo.peer_addr, macAddr, ESP_NOW_ETH_ALEN);
esp_err_t result = esp_now_add_peer(&peerInfo); esp_err_t result = esp_now_add_peer(&peerInfo);
if (result == ESP_OK) { if (result == ESP_OK) {
ESP_LOGI(TAG, "Peer added: " MACSTR, MAC2STR(peerInfo.peer_addr)); ESP_LOGI(TAG, "Peer added");
if (!IS_BROADCAST_ADDR(macAddr)) { if (!IS_BROADCAST_ADDR(macAddr)) {
int ret = add_client(esp_client_list, peerInfo.peer_addr); int ret = add_client(esp_client_list, peerInfo.peer_addr);
@ -147,7 +138,6 @@ int add_peer(uint8_t *macAddr) {
ESP_LOGW(TAG, "Peer already exists."); ESP_LOGW(TAG, "Peer already exists.");
int id = get_client_id(esp_client_list, peerInfo.peer_addr); int id = get_client_id(esp_client_list, peerInfo.peer_addr);
if (id >= 0) { if (id >= 0) {
ESP_LOGI(TAG, "Client found again, welcome back!");
esp_client_list->Clients[id].isAvailable = true; esp_client_list->Clients[id].isAvailable = true;
} }
} else { } else {
@ -180,8 +170,6 @@ void master_broadcast_task(void *param) {
ESP_ERROR_CHECK(esp_now_send(broadcast_address, (uint8_t *)&message, ESP_ERROR_CHECK(esp_now_send(broadcast_address, (uint8_t *)&message,
sizeof(BaseMessage))); sizeof(BaseMessage)));
// ESP_LOGI(TAG, "Broadcast Message sent");
vTaskDelay(pdMS_TO_TICKS(5000)); vTaskDelay(pdMS_TO_TICKS(5000));
} }
} }
@ -194,7 +182,6 @@ void master_broadcast_ping(void *param) {
MessageBuilder(PingPage, *(PayloadUnion *)&payload, sizeof(payload)); MessageBuilder(PingPage, *(PayloadUnion *)&payload, sizeof(payload));
ESP_ERROR_CHECK(esp_now_send(broadcast_address, (uint8_t *)&message, ESP_ERROR_CHECK(esp_now_send(broadcast_address, (uint8_t *)&message,
sizeof(BaseMessage))); sizeof(BaseMessage)));
// ESP_LOGI(TAG, "Broadcast PING Message sent");
vTaskDelay(pdMS_TO_TICKS(2500)); vTaskDelay(pdMS_TO_TICKS(2500));
} }
} }
@ -203,15 +190,12 @@ void master_ping_task(void *param) {
while (1) { while (1) {
for (size_t i = 0; i < MAX_CLIENTS; i++) { for (size_t i = 0; i < MAX_CLIENTS; i++) {
if (esp_client_list->Clients[i].isAvailable) { 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 = {}; PingPayload payload = {};
payload.timestamp = esp_timer_get_time(); payload.timestamp = esp_timer_get_time();
BaseMessage message = MessageBuilder( BaseMessage message = MessageBuilder(
PingPage, *(PayloadUnion *)&payload, sizeof(payload)); PingPage, *(PayloadUnion *)&payload, sizeof(payload));
esp_now_send(esp_client_list->Clients[i].macAddr, (uint8_t *)&message, esp_now_send(esp_client_list->Clients[i].macAddr, (uint8_t *)&message,
sizeof(BaseMessage)); sizeof(BaseMessage));
ESP_LOGI(TAG, "SENDING PING!!!!");
} }
} }
vTaskDelay(pdMS_TO_TICKS(1000)); vTaskDelay(pdMS_TO_TICKS(1000));
@ -221,8 +205,7 @@ void master_ping_task(void *param) {
void master_StatusCallback(const esp_now_recv_info_t *esp_now_info, void master_StatusCallback(const esp_now_recv_info_t *esp_now_info,
const uint8_t *data, int data_len) { const uint8_t *data, int data_len) {
const BaseMessage *message = (const BaseMessage *)data; const BaseMessage *message = (const BaseMessage *)data;
ESP_LOGI(TAG, "SRC");
ESP_LOGI(TAG, "SRC " MACSTR, MAC2STR(esp_now_info->src_addr));
ESP_LOGI(TAG, ESP_LOGI(TAG,
"Status Message Received: status: %d, runningPartition: %d, uptime: " "Status Message Received: status: %d, runningPartition: %d, uptime: "
"%d, version: %d", "%d, version: %d",
@ -235,81 +218,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, void master_RegisterCallback(const esp_now_recv_info_t *esp_now_info,
const uint8_t *data, int data_len) { const uint8_t *data, int data_len) {
BaseMessage replyMessage = {}; BaseMessage replyMessage = {};
const BaseMessage *message = (const BaseMessage *)data;
ESP_LOGI(TAG, "WILL REGISTER DEVICE");
esp_now_peer_info_t checkPeerInfo; esp_now_peer_info_t checkPeerInfo;
esp_err_t checkPeer = esp_err_t checkPeer =
esp_now_get_peer(esp_now_info->src_addr, &checkPeerInfo); esp_now_get_peer(esp_now_info->src_addr, &checkPeerInfo);
switch (checkPeer) { switch (checkPeer) {
case (ESP_OK): case (ESP_OK):
ESP_LOGI(TAG, "CLIENT BEKANNT");
int id = get_client_id(esp_client_list, esp_now_info->src_addr); 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].isAvailable = true;
esp_client_list->Clients[id].lastSuccessfullPing = xTaskGetTickCount(); 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; break;
case (ESP_ERR_ESPNOW_NOT_FOUND): case (ESP_ERR_ESPNOW_NOT_FOUND):
ESP_LOGI(TAG, "CLIENT WIRD IN DIE LISTE AUFGENOMMEN " MACSTR, add_peer(esp_now_info->src_addr);
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");
GetStatusPayload payload = {}; GetStatusPayload payload = {};
replyMessage = MessageBuilder(GetStatusPage, *(PayloadUnion *)&payload, replyMessage = MessageBuilder(GetStatusPage, *(PayloadUnion *)&payload,
sizeof(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,
(uint8_t *)&replyMessage, sizeof(BaseMessage)); sizeof(BaseMessage));
if (err != ESP_OK) {
ESP_LOGE(TAG, "Could not send Message Error %s", esp_err_to_name(err));
}
break; break;
default: default:
ESP_LOGI(TAG, "Unknown Message %i", checkPeer); break;
} }
} }
void master_pingCallback(const esp_now_recv_info_t *esp_now_info, void master_pingCallback(const esp_now_recv_info_t *esp_now_info,
const uint8_t *data, int data_len) { const uint8_t *data, int data_len) {
BaseMessage replyMessage = {};
const BaseMessage *message = (const BaseMessage *)data; const BaseMessage *message = (const BaseMessage *)data;
ESP_LOGI(TAG, "GOT PING MESSAGE");
uint32_t currentTime = esp_timer_get_time(); uint32_t currentTime = esp_timer_get_time();
uint32_t diff = currentTime - message->payload.ping_payload.timestamp; 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); int id = get_client_id(esp_client_list, esp_now_info->src_addr);
if (id >= 0) { if (id >= 0) {
esp_client_list->Clients[id].lastSuccessfullPing = xTaskGetTickCount(); esp_client_list->Clients[id].lastSuccessfullPing = xTaskGetTickCount();
esp_client_list->Clients[id].lastPing = (diff / 1000); 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, void master_broadcastCallback(const esp_now_recv_info_t *esp_now_info,
const uint8_t *data, int data_len) { 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));
}
void ESPNOW_RegisterMasterCallbacks() { void ESPNOW_RegisterMasterCallbacks() {
ESP_RegisterFunction(StatusPage, master_StatusCallback); ESP_RegisterFunction(StatusPage, master_StatusCallback);
@ -320,31 +267,22 @@ void ESPNOW_RegisterMasterCallbacks() {
void slave_broadcastCallback(const esp_now_recv_info_t *esp_now_info, void slave_broadcastCallback(const esp_now_recv_info_t *esp_now_info,
const uint8_t *data, int data_len) { const uint8_t *data, int data_len) {
BaseMessage replyMessage = {};
const BaseMessage *message = (const BaseMessage *)data;
ESP_LOGI(TAG, "GOT BROADCAST MESSAGE");
if (!hasMaster) { if (!hasMaster) {
if (IS_BROADCAST_ADDR(esp_now_info->des_addr)) { 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); add_peer(esp_now_info->src_addr);
BaseMessage replyMessage = {};
replyMessage = replyMessage =
MessageBuilder(RegisterPage, *(PayloadUnion *)&message->payload, MessageBuilder(RegisterPage, *(PayloadUnion *)&replyMessage.payload,
sizeof(message->payload)); sizeof(replyMessage.payload));
ESP_ERROR_CHECK(esp_now_send(esp_now_info->src_addr, esp_now_send(esp_now_info->src_addr, (uint8_t *)&replyMessage,
(uint8_t *)&replyMessage, sizeof(BaseMessage));
sizeof(BaseMessage)));
hasMaster = true; 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, void slave_getstatusCallback(const esp_now_recv_info_t *esp_now_info,
const uint8_t *data, int data_len) { const uint8_t *data, int data_len) {
BaseMessage replyMessage = {};
const BaseMessage *message = (const BaseMessage *)data;
StatusPayload payload = { StatusPayload payload = {
.status = 1, .status = 1,
.runningPartition = 1, .runningPartition = 1,
@ -352,24 +290,22 @@ void slave_getstatusCallback(const esp_now_recv_info_t *esp_now_info,
.version = 0x0002, .version = 0x0002,
}; };
replyMessage = BaseMessage replyMessage =
MessageBuilder(StatusPage, *(PayloadUnion *)&payload, sizeof(payload)); MessageBuilder(StatusPage, *(PayloadUnion *)&payload, sizeof(payload));
ESP_ERROR_CHECK(esp_now_send(esp_now_info->src_addr, (uint8_t *)&replyMessage, 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, void slave_pingCallback(const esp_now_recv_info_t *esp_now_info,
const uint8_t *data, int data_len) { const uint8_t *data, int data_len) {
if (!hasMaster) if (!hasMaster)
return; return;
BaseMessage replyMessage = {};
const BaseMessage *message = (const BaseMessage *)data; const BaseMessage *message = (const BaseMessage *)data;
BaseMessage replyMessage = MessageBuilder(
ESP_LOGI(TAG, "GOT PING MESSAGE"); PingPage, *(PayloadUnion *)&message->payload, sizeof(message->payload));
replyMessage = MessageBuilder(PingPage, *(PayloadUnion *)&message->payload, esp_now_send(esp_now_info->src_addr, (uint8_t *)&replyMessage,
sizeof(message->payload)); sizeof(BaseMessage));
ESP_ERROR_CHECK(esp_now_send(esp_now_info->src_addr, (uint8_t *)&replyMessage,
sizeof(BaseMessage)));
} }
void ESPNOW_RegisterSlaveCallbacks() { void ESPNOW_RegisterSlaveCallbacks() {
@ -380,30 +316,23 @@ void ESPNOW_RegisterSlaveCallbacks() {
void master_receive_callback(const esp_now_recv_info_t *esp_now_info, void master_receive_callback(const esp_now_recv_info_t *esp_now_info,
const uint8_t *data, int data_len) { 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); uint8_t *copied_data = (uint8_t *)malloc(data_len);
if (copied_data == NULL) { if (copied_data == NULL) {
ESP_LOGE(TAG, "Failed to allocate memory for message data.");
return; return;
} }
memcpy(copied_data, data, data_len); memcpy(copied_data, data, data_len);
// Fülle die neue Struktur mit kopierten Daten
ESPNOW_MessageInfo msg_info; ESPNOW_MessageInfo msg_info;
msg_info.esp_now_info.src_addr = malloc(6); msg_info.esp_now_info.src_addr = malloc(6);
if (msg_info.esp_now_info.src_addr) { if (msg_info.esp_now_info.src_addr) {
memcpy(msg_info.esp_now_info.src_addr, esp_now_info->src_addr, 6); 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); msg_info.esp_now_info.des_addr = malloc(6);
if (msg_info.esp_now_info.des_addr) { if (msg_info.esp_now_info.des_addr) {
memcpy(msg_info.esp_now_info.des_addr, esp_now_info->des_addr, 6); 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)); msg_info.esp_now_info.rx_ctrl = malloc(sizeof(wifi_pkt_rx_ctrl_t));
if (msg_info.esp_now_info.rx_ctrl) { if (msg_info.esp_now_info.rx_ctrl) {
memcpy(msg_info.esp_now_info.rx_ctrl, esp_now_info->rx_ctrl, memcpy(msg_info.esp_now_info.rx_ctrl, esp_now_info->rx_ctrl,
@ -413,48 +342,47 @@ void master_receive_callback(const esp_now_recv_info_t *esp_now_info,
msg_info.data = copied_data; msg_info.data = copied_data;
msg_info.data_len = data_len; msg_info.data_len = data_len;
if (xQueueSend(ESP_recieved_message_queue, &msg_info, portMAX_DELAY) != 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_receive_callback(const esp_now_recv_info_t *esp_now_info, void client_receive_callback(const esp_now_recv_info_t *esp_now_info,
const uint8_t *data, int data_len) { 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); uint8_t *copied_data = (uint8_t *)malloc(data_len);
if (copied_data == NULL) { if (copied_data == NULL) {
ESP_LOGE(TAG, "Failed to allocate memory for message data.");
return; return;
} }
memcpy(copied_data, data, data_len); memcpy(copied_data, data, data_len);
// Fülle die neue Struktur mit kopierten Daten
ESPNOW_MessageInfo msg_info; 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 = copied_data;
msg_info.data_len = data_len; msg_info.data_len = data_len;
if (xQueueSend(ESP_recieved_message_queue, &msg_info, portMAX_DELAY) != 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));
}
} }
void client_monitor_task(void *pvParameters) { void client_monitor_task(void *pvParameters) {
@ -471,11 +399,34 @@ void client_monitor_task(void *pvParameters) {
if (time_diff > timeout_ticks) { if (time_diff > timeout_ticks) {
esp_client_list->Clients[i].isAvailable = false; 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); vTaskDelay(interval_ticks);
} }
} }
const esp_partition_t *ota_update_partition = NULL;
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_acknowledge_callback);
ESP_RegisterFunction(OTA_READY_TO_RECEIVE,
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_Update_Chunk_Callback);
ESP_RegisterFunction(OTA_FINISH_UPDATE, slave_Update_Finished_Callback);
}

View File

@ -12,91 +12,30 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <sys/types.h> #include <sys/types.h>
#include "esp_partition.h"
#include "message_structs.h"
#define BROADCAST_INTERVAL_MS 500 #define BROADCAST_INTERVAL_MS 500
#define CLIENT_TIMEOUT_MS 5000 // 5 Sekunden Timeout #define CLIENT_TIMEOUT_MS 5000 // 5 Sekunden Timeout
#define CHECK_INTERVAL_MS 1000 // Jede Sekunde überprüfen #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] extern uint8_t broadcast_address[ESP_NOW_ETH_ALEN];
#define MACSTR "%02X:%02X:%02X:%02X:%02X:%02X" #define IS_BROADCAST_ADDR(addr) (memcmp(addr, broadcast_address, ESP_NOW_ETH_ALEN) == 0)
#define MESSAGE_QUEUE_SIZE 10 #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)) { 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; StatusPayload status_payload;
ConfigPayload config_payload; ConfigPayload config_payload;
PingPayload ping_payload; PingPayload ping_payload;
@ -156,6 +95,8 @@ void ESP_MessageBrokerTask(void *param);
void ESPNOW_RegisterMasterCallbacks(); void ESPNOW_RegisterMasterCallbacks();
void ESPNOW_RegisterSlaveCallbacks(); void ESPNOW_RegisterSlaveCallbacks();
void ESPNOW_RegisterOTAMaster();
void ESPNOW_RegisterOTASlave();
int init_com(ClientList *clients, uint8_t wifi_channel); int init_com(ClientList *clients, uint8_t wifi_channel);
int getNextFreeClientId(); int getNextFreeClientId();
@ -173,6 +114,9 @@ void client_receive_callback(const esp_now_recv_info_t *esp_now_info,
const uint8_t *data, int data_len); const uint8_t *data, int data_len);
void client_data_sending_task(void *param); void client_data_sending_task(void *param);
void client_send_random_data_task(void *param); void client_send_random_data_task(void *param);
void client_monitor_task(void *pvParameters); void client_monitor_task(void *pvParameters);
void send_ota_block_chunks(uint8_t client_id, uint16_t block_id);
#endif #endif

View File

@ -1,7 +1,11 @@
#include "client_handler.h" #include "client_handler.h"
#include "driver/gpio.h" #include "driver/gpio.h"
#include "driver/uart.h" #include "driver/uart.h"
#include "esp_app_desc.h"
#include "esp_app_format.h"
#include "esp_err.h" #include "esp_err.h"
#include "esp_flash_partitions.h"
#include "esp_image_format.h"
#include "esp_log.h" #include "esp_log.h"
#include "esp_log_buffer.h" #include "esp_log_buffer.h"
#include "esp_ota_ops.h" #include "esp_ota_ops.h"
@ -21,9 +25,11 @@
#include "main.h" #include "main.h"
#include "ota_update.h" #include "ota_update.h"
#include "uart_handler.h" #include "uart_handler.h"
#include <math.h>
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/types.h> #include <sys/types.h>
@ -34,12 +40,72 @@ static const char *TAG = "ALOX - MAIN";
static const uint16_t version = 0x0001; static const uint16_t version = 0x0001;
static uint8_t send_message_buffer[1024]; static uint8_t send_message_buffer[1024];
static uint8_t send_message_payload_buffer[512]; static uint8_t send_message_payload_buffer[512];
uint32_t g_uart_firmware_total_size = 0;
static MessageBrokerTaskParams_t broker_task_params; static MessageBrokerTaskParams_t broker_task_params;
static MasterOTA_TaskParams_t master_ota_task_params;
static ESP_MessageBrokerTaskParams_t esp_broker_task_params; static ESP_MessageBrokerTaskParams_t esp_broker_task_params;
ClientList clientList = {.Clients = {{0}}, .ClientCount = 0}; ClientList clientList = {.Clients = {{0}}, .ClientCount = 0};
size_t build_ClientInfoPart(uint8_t clientid, float_t lagex, float_t lagey,
int32_t bitmask, uint8_t *outputArray,
size_t outputArrayOffset, size_t outputArraySize) {
size_t offset = outputArrayOffset;
memcpy(&outputArray[offset], &clientid, sizeof(clientid));
offset += sizeof(clientid);
// lagex (typischerweise 4 Bytes)
memcpy(&outputArray[offset], &lagex, sizeof(lagex));
offset += sizeof(lagex);
// lagey (typischerweise 4 Bytes)
memcpy(&outputArray[offset], &lagey, sizeof(lagey));
offset += sizeof(lagey);
// bitmask (4 Bytes)
memcpy(&outputArray[offset], &bitmask, sizeof(bitmask));
offset += sizeof(bitmask);
return offset - outputArrayOffset;
}
void fakeDataCallback(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 seed = payload[1];
ESP_LOGI(TAG, "Sending Fake Client Infos with seed %d", seed);
srand(seed);
size_t offset = 1;
send_payload_buffer[0] = 3; // Client Count
offset +=
build_ClientInfoPart(1, rand() * 1.0, rand() * 1.0, rand() * 1,
send_payload_buffer, 1, send_payload_buffer_size);
offset += build_ClientInfoPart(2, rand() * 2.0, rand() * 2.0, rand() * 2,
send_payload_buffer, offset,
send_payload_buffer_size);
offset += build_ClientInfoPart(3, rand() * 3.0, rand() * 3.0, rand() * 3,
send_payload_buffer, offset,
send_payload_buffer_size);
int len = build_message(UART_CLIENT_INPUT, send_payload_buffer, offset,
send_buffer, send_buffer_size);
if (len < 0) {
ESP_LOGE(TAG,
"Error Building UART Message: payload_len, %d, sendbuffer_size: "
"%d, mes_len(error): %d",
payload_len, send_buffer_size, len);
return;
}
uart_write_bytes(MASTER_UART, send_buffer, len);
}
void echoCallback(uint8_t msgid, const uint8_t *payload, size_t payload_len, void echoCallback(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_payload_buffer, size_t send_payload_buffer_size,
uint8_t *send_buffer, size_t send_buffer_size) { uint8_t *send_buffer, size_t send_buffer_size) {
@ -104,27 +170,9 @@ void clientInfoCallback(uint8_t msgid, const uint8_t *payload,
send_payload_buffer[0] = clientList.ClientCount; send_payload_buffer[0] = clientList.ClientCount;
uint8_t offsetMult = 0; uint8_t offsetMult = 0;
uint8_t used_slots = 0;
for (int i = 0; i < MAX_CLIENTS; i++) { for (int i = 0; i < MAX_CLIENTS; i++) {
if (clientList.Clients[i].slotIsUsed) { 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++); size_t offset = 1 + (entryLength * offsetMult++);
ESP_LOGE("SPECIAL", "OFFSET %d", offset);
send_payload_buffer[offset] = i; send_payload_buffer[offset] = i;
send_payload_buffer[offset + 1] = clientList.Clients[i].isAvailable; send_payload_buffer[offset + 1] = clientList.Clients[i].isAvailable;
send_payload_buffer[offset + 2] = clientList.Clients[i].slotIsUsed; send_payload_buffer[offset + 2] = clientList.Clients[i].slotIsUsed;
@ -142,8 +190,6 @@ void clientInfoCallback(uint8_t msgid, const uint8_t *payload,
int len = build_message(UART_CLIENT_INFO, send_payload_buffer, int len = build_message(UART_CLIENT_INFO, send_payload_buffer,
needed_buffer_size, send_buffer, send_buffer_size); needed_buffer_size, send_buffer, send_buffer_size);
// ESP_LOG_BUFFER_HEX("SEND BUFFER: ", send_buffer, send_buffer_size);
if (len < 0) { if (len < 0) {
ESP_LOGE(TAG, ESP_LOGE(TAG,
"Error Building UART Message: payload_len, %d, sendbuffer_size: " "Error Building UART Message: payload_len, %d, sendbuffer_size: "
@ -154,6 +200,69 @@ void clientInfoCallback(uint8_t msgid, const uint8_t *payload,
uart_write_bytes(MASTER_UART, send_buffer, len); 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 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));
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));
}
}
void app_main(void) { void app_main(void) {
ESP_LOGI(TAG, "Starting Alox Powerpod Version %d Build: %s", version, ESP_LOGI(TAG, "Starting Alox Powerpod Version %d Build: %s", version,
BUILD_GIT_HASH); BUILD_GIT_HASH);
@ -166,12 +275,10 @@ void app_main(void) {
} }
ESP_ERROR_CHECK(ret); ESP_ERROR_CHECK(ret);
// GPIO-Pin für Moduserkennung
gpio_reset_pin(MASTER_MODE_PIN); gpio_reset_pin(MASTER_MODE_PIN);
gpio_set_direction(MASTER_MODE_PIN, GPIO_MODE_INPUT); gpio_set_direction(MASTER_MODE_PIN, GPIO_MODE_INPUT);
bool isMaster = (gpio_get_level(MASTER_MODE_PIN) == 0); bool isMaster = (gpio_get_level(MASTER_MODE_PIN) == 0);
// ESP-NOW Initialisieren
ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default()); ESP_ERROR_CHECK(esp_event_loop_create_default());
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
@ -198,65 +305,27 @@ void app_main(void) {
ESP_LOGE(TAG, "Could not Init ESP NOW Communication!"); 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(); const esp_partition_t *running = esp_ota_get_running_partition();
ESP_LOGI(TAG, "OTA: Running Partition: %s", running->label); 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; esp_ota_img_states_t ota_state;
if (esp_ota_get_state_partition(running, &ota_state) == ESP_OK) { 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) { if (ota_state == ESP_OTA_IMG_PENDING_VERIFY) {
// run diagnostic function ... bool diagnostic_is_ok = true; // TODO build in valid diagnostics
bool diagnostic_is_ok = true; // TODO: a real function that checks if
// everything is running properly
if (diagnostic_is_ok) { if (diagnostic_is_ok) {
ESP_LOGI( esp_ota_mark_app_valid_cancel_rollback();
TAG,
"Diagnostics completed successfully! Continuing execution ...");
// esp_ota_mark_app_valid_cancel_rollback();
} else { } else {
ESP_LOGE( // esp_ota_mark_app_invalid_rollback(); Put this function at the start
TAG, // so when the esp crashes it can rollback
"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 esp_partition_t *next_ota_partition =
const char nvs_namespace_name[] = "saved_clients"; esp_ota_get_next_update_partition(NULL);
ret = nvs_flash_init_partition(nvs_part_name); int app_size = get_app_size(next_ota_partition);
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ESP_LOGE(TAG, "App Size in Other Partition %d", app_size);
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 = QueueHandle_t espnow_message_queue =
xQueueCreate(10, sizeof(ESPNOW_MessageInfo)); xQueueCreate(10, sizeof(ESPNOW_MessageInfo));
@ -266,25 +335,23 @@ void app_main(void) {
xTaskCreate(ESP_MessageBrokerTask, "espnow_message_broker_task", 4096, xTaskCreate(ESP_MessageBrokerTask, "espnow_message_broker_task", 4096,
(void *)&esp_broker_task_params, 4, NULL); (void *)&esp_broker_task_params, 4, NULL);
// Tasks starten basierend auf Master/Client init_ota();
if (isMaster) { if (isMaster) {
ESP_LOGI(TAG, "Started in Mastermode"); ESP_LOGI(TAG, "Started in Mastermode");
ESPNOW_RegisterMasterCallbacks(); ESPNOW_RegisterMasterCallbacks();
ESPNOW_RegisterOTAMaster();
add_peer(broadcast_address); add_peer(broadcast_address);
xTaskCreate(master_broadcast_task, "MasterBroadcast", 4096, NULL, 1, NULL); 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, xTaskCreate(master_broadcast_ping, "MasterBroadcastPing", 4096, NULL, 1,
NULL); NULL);
// xTaskCreate(client_monitor_task, "MonitorClientTask", 4096, NULL, 1,
// NULL);
QueueHandle_t parsed_message_queue = QueueHandle_t parsed_message_queue =
xQueueCreate(10, sizeof(ParsedMessage_t)); xQueueCreate(10, sizeof(ParsedMessage_t));
init_uart(parsed_message_queue); init_uart(parsed_message_queue);
InitMessageBroker(); InitMessageBroker();
// Initialisiere die Parameterstruktur
broker_task_params.message_queue = parsed_message_queue; broker_task_params.message_queue = parsed_message_queue;
broker_task_params.send_buffer = send_message_buffer; broker_task_params.send_buffer = send_message_buffer;
broker_task_params.send_buffer_size = sizeof(send_message_buffer); broker_task_params.send_buffer_size = sizeof(send_message_buffer);
@ -292,22 +359,23 @@ void app_main(void) {
broker_task_params.payload_buffer_size = broker_task_params.payload_buffer_size =
sizeof(send_message_payload_buffer); sizeof(send_message_payload_buffer);
xTaskCreate(MessageBrokerTask, "message_handler_task", 4096, xTaskCreate(MessageBrokerTask, "MessageHandler", 4096,
(void *)&broker_task_params, 5, NULL); (void *)&broker_task_params, 5, NULL);
RegisterCallback(0x01, echoCallback); master_ota_task_params.client_list = &clientList;
RegisterCallback(0x02, versionCallback); xTaskCreate(MasterOTATask, "MasterOTATask", 4096,
RegisterCallback(0x03, clientInfoCallback); (void *)&master_ota_task_params, 4, NULL);
init_ota(); 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);
// xTaskCreate(uart_status_task, "MasterUartStatusTask", 4096, NULL, 1,
// NULL); xTaskCreate(SendClientInfoTask, "SendCientInfo", 4096, NULL, 1,
// NULL);
} else { } else {
ESP_LOGI(TAG, "Started in Slavemode"); ESP_LOGI(TAG, "Started in Slavemode");
ESPNOW_RegisterSlaveCallbacks(); ESPNOW_RegisterSlaveCallbacks();
// xTaskCreate(client_data_sending_task, "ClientDataSending", 4096, NULL, 1, xTaskCreate(slave_ota_task, "SlaveOTATask", 4096, NULL, 4, NULL);
// NULL); ESPNOW_RegisterOTASlave();
} }
} }

View File

@ -19,5 +19,4 @@
#elif CONFIG_IDF_TARGET_ESP32C3 #elif CONFIG_IDF_TARGET_ESP32C3
#define MASTER_MODE_PIN GPIO_NUM_0 // Jumper-Erkennungspin #define MASTER_MODE_PIN GPIO_NUM_0 // Jumper-Erkennungspin
#endif #endif
#endif #endif

124
main/message_structs.h Normal file
View File

@ -0,0 +1,124 @@
#ifndef MESSAGE_STRUCTS_H
#define MESSAGE_STRUCTS_H
#include <stdbool.h>
#include <stdint.h>
#include <sys/types.h>
#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,
OTA_UPDATE_SLAVE_ACKED,
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_len;
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 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;
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

View File

@ -1,61 +1,340 @@
#include "ota_update.h" #include "ota_update.h"
#include "client_handler.h"
#include "communication_handler.h"
#include "driver/uart.h" #include "driver/uart.h"
#include "esp_app_format.h"
#include "esp_err.h" #include "esp_err.h"
#include "esp_log.h" #include "esp_log.h"
#include "esp_log_buffer.h"
#include "esp_now.h"
#include "esp_ota_ops.h" #include "esp_ota_ops.h"
#include "esp_partition.h" #include "esp_partition.h"
#include "esp_system.h" #include "esp_system.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "message_builder.h" #include "message_builder.h"
#include "message_handler.h" #include "message_handler.h"
#include "message_structs.h"
#include "uart_handler.h" #include "uart_handler.h"
#include "uart_msg_ids.h" #include "uart_msg_ids.h"
#include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h>
#include <string.h> #include <string.h>
#define MAX(a, b) ((a) > (b) ? (a) : (b)) static const char *TAG = "ALOX - OTA";
#define MIN(a, b) ((a) < (b) ? (a) : (b))
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[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 uint16_t update_buffer_write_index;
static uint32_t update_size; static uint32_t update_size;
static uint16_t sequenz_counter; // how often the update buffer gets written static uint16_t sequenz_counter; // how often the update buffer gets written
static const char *TAG = "ALOX - OTA"; static esp_partition_t partition_to_read_update_from;
static esp_ota_handle_t update_handle; static uint32_t partition_to_read_from_read_index;
static ClientList *client_list;
static bool all_chunks_send;
static bool finished;
int prepare_ota_update() { uint32_t get_app_size(const esp_partition_t *app_size_partition) {
const esp_partition_t *running = esp_ota_get_running_partition(); esp_app_desc_t app_desc;
ESP_LOGI(TAG, "OTA: Running Partition: %s", running->label); esp_ota_get_partition_description(app_size_partition, &app_desc);
int part = 0;
char partition_to_update[] = "ota_0"; esp_image_header_t header;
if (strcmp(running->label, "ota_0") == 0) {
strcpy(partition_to_update, "ota_1"); esp_partition_read(app_size_partition, 0, &header, sizeof(header));
part = 1; if (header.magic != ESP_IMAGE_HEADER_MAGIC) {
ESP_LOGE(TAG, "KEIN VALIDER HEADER");
return 0;
} }
const esp_partition_t *update_partition = esp_partition_find_first( uint32_t data_len = sizeof(header);
ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_ANY, partition_to_update);
// Check if the partition was found for (int i = 0; i < header.segment_count; i++) {
if (update_partition == NULL) { esp_image_segment_header_t segment_header;
ESP_LOGE(TAG, "Failed to find OTA partition: %s", partition_to_update); esp_partition_read(app_size_partition, data_len, &segment_header,
return -1; // Or handle the error appropriately sizeof(segment_header));
ESP_LOGI(TAG, "SEGMENT %d Address %d, Segment DataLen %d", i,
segment_header.load_addr, segment_header.data_len);
uint32_t padded_len = (segment_header.data_len + 3) & ~3;
data_len += padded_len + sizeof(segment_header);
} }
ESP_LOGI(TAG, "Gonna write OTA Update in Partition: %s", data_len += 1;
update_partition->label); data_len += 32;
uint32_t padding = (16 - (data_len % 16)) % 16;
data_len += padding;
return data_len;
}
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);
}
esp_err_t err =
esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle);
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_LOGE(TAG, "esp_ota_begin failed (%s)", esp_err_to_name(err)); ESP_LOGE(TAG, "Could not read partition");
esp_ota_abort(update_handle);
return -2;
} }
ESP_LOGI(TAG, "OTA update started successfully."); partition_to_read_from_read_index += actual_read;
return part; 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, "master ota_task received command: %d", msg.command);
BaseMessage replyMessage = {};
switch (msg.command) {
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_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));
break;
}
case OTA_MASTER_SEND_FINISH: {
esp_err_t err = end_ota_update();
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));
break;
}
}
}
}
} }
void start_uart_update(uint8_t msgid, const uint8_t *payload, void start_uart_update(uint8_t msgid, const uint8_t *payload,
@ -67,13 +346,14 @@ void start_uart_update(uint8_t msgid, const uint8_t *payload,
vTaskPrioritySet(NULL, 2); vTaskPrioritySet(NULL, 2);
update_size = 0; update_size = 0;
update_buffer_write_index = 0;
sequenz_counter = 0;
all_chunks_send = false;
finished = false;
int part = prepare_ota_update(); int part = prepare_ota_update();
// Message: // TODO: what does this do? maybe comment it out for now?
// byte partition
// byte error
if (part < 0) { if (part < 0) {
send_payload_buffer[1] = (part * -1) & 0xff; send_payload_buffer[1] = (part * -1) & 0xff;
} else { } else {
@ -95,20 +375,18 @@ 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_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, "write_ota_update: write_len: %d", write_len);
// ESP_LOGI(TAG, "Writing Data to Update BUffer Sequence %d, writing Data ESP_LOGI(TAG, "write_ota_update: update_buffer_write_index: %d",
// %d", update_buffer_write_index);
// sequenz_counter, write_len); if (update_buffer_write_index + write_len > UPDATE_BUFFER_SIZE) {
// write to ota ESP_LOGI(TAG, "write_ota_update: schreib das update weg!");
esp_err_t err = esp_err_t err =
esp_ota_write(update_handle, update_buffer, update_buffer_write_index); esp_ota_write(update_handle, update_buffer, update_buffer_write_index);
if (err != ESP_OK) { if (err != ESP_OK) {
return err; return err;
} }
update_buffer_write_index = 0; update_buffer_write_index = 0;
sequenz_counter++; sequenz_counter++;
return err;
} }
memcpy(&update_buffer[update_buffer_write_index], payload, write_len); memcpy(&update_buffer[update_buffer_write_index], payload, write_len);
@ -116,16 +394,23 @@ esp_err_t write_ota_update(uint32_t write_len, const uint8_t *payload) {
return ESP_OK; return ESP_OK;
} }
void payload_uart_update(uint8_t msgid, const uint8_t *payload, void payload_uart_update(uint8_t msgid, const uint8_t *payload_data_from_uart,
size_t payload_len, 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_payload_buffer_size, uint8_t *send_buffer,
size_t send_buffer_size) { 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; 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) { if (err != ESP_OK) {
ESP_LOGE(TAG, "GOT ESP ERROR WRITE OTA %d", err); ESP_LOGE(TAG, "GOT ESP ERROR WRITE OTA %d", err);
@ -142,44 +427,13 @@ void payload_uart_update(uint8_t msgid, const uint8_t *payload,
ESP_LOGE(TAG, ESP_LOGE(TAG,
"Error Building UART Message: payload_len, %d, sendbuffer_size: " "Error Building UART Message: payload_len, %d, sendbuffer_size: "
"%d, mes_len(error): %d", "%d, mes_len(error): %d",
payload_len, send_buffer_size, len); total_payload_len_from_uart, send_buffer_size, len);
return; return;
} }
uart_write_bytes(MASTER_UART, send_buffer, len); 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, void end_uart_update(uint8_t msgid, const uint8_t *payload, size_t payload_len,
uint8_t *send_payload_buffer, uint8_t *send_payload_buffer,
size_t send_payload_buffer_size, uint8_t *send_buffer, size_t send_payload_buffer_size, uint8_t *send_buffer,
@ -188,7 +442,6 @@ void end_uart_update(uint8_t msgid, const uint8_t *payload, size_t payload_len,
esp_err_t err = end_ota_update(); esp_err_t err = end_ota_update();
// message ret esp_err_t
int send_payload_len = 1; int send_payload_len = 1;
send_payload_buffer[0] = err & 0xff; send_payload_buffer[0] = err & 0xff;
int len = build_message(UART_OTA_END, send_payload_buffer, send_payload_len, int len = build_message(UART_OTA_END, send_payload_buffer, send_payload_len,
@ -206,10 +459,202 @@ void end_uart_update(uint8_t msgid, const uint8_t *payload, size_t payload_len,
vTaskPrioritySet(NULL, 1); vTaskPrioritySet(NULL, 1);
} }
void write_ota_update_from_uart_task(void *param) {}
void init_ota() { void init_ota() {
ota_task_queue = xQueueCreate(50, sizeof(ota_task_queue_message_t));
RegisterCallback(UART_OTA_START, start_uart_update); RegisterCallback(UART_OTA_START, start_uart_update);
RegisterCallback(UART_OTA_PAYLOAD, payload_uart_update); RegisterCallback(UART_OTA_PAYLOAD, payload_uart_update);
RegisterCallback(UART_OTA_END, end_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_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);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Error writing remaining data to partition: %s",
esp_err_to_name(err));
return err;
}
}
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;
}
// 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;
// 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_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;
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);
if (xQueueSend(ota_task_queue, &msg, pdMS_TO_TICKS(10)) != pdTRUE) {
ESP_LOGE(TAG, "Failed to send prepare command to OTA task");
}
}
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) {
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);
if (xQueueSend(ota_task_queue, &msg, pdMS_TO_TICKS(10)) != pdTRUE) {
ESP_LOGE(TAG, "Failed to send prepare command to OTA task");
}
}
void master_ota_ready_to_recieve_callback(
const esp_now_recv_info_t *esp_now_info, const uint8_t *data,
int data_len) {
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 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");
}
}

View File

@ -1,25 +1,81 @@
#ifndef OTA_UPDATE_H #ifndef OTA_UPDATE_H
#define OTA_UPDATE_H #define OTA_UPDATE_H
#include "client_handler.h"
#include "esp_err.h" #include "esp_err.h"
#include "esp_now.h"
#include "esp_partition.h"
#include "message_structs.h"
#include <stdint.h> #include <stdint.h>
#include <sys/types.h> #include <sys/types.h>
#define UPDATE_BUFFER_SIZE 4000
#define UPDATE_BUFFER_SIZE 4096
#define UPDATE_PAYLOAD_SIZE 200 #define UPDATE_PAYLOAD_SIZE 200
#define UPDATE_MAX_SEQUENZES (UPDATE_BUFFER_SIZE / UPDATE_PAYLOAD_SIZE) #define UPDATE_MAX_SEQUENZES (UPDATE_BUFFER_SIZE / UPDATE_PAYLOAD_SIZE)
typedef enum {
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];
} ota_task_queue_message_t;
typedef struct {
ClientList *client_list;
} MasterOTA_TaskParams_t;
void init_ota(); void init_ota();
void MasterOTATask(void *pvParameter);
void slave_ota_task(void *pvParameter);
enum OTA_UPDATE_STATES { u_int32_t get_app_size(const esp_partition_t *app_size_partition);
IDEL,
START_REQUESTED,
WAITING_FOR_PAYLOAD,
WRITING_OTA_TO_PARTITION,
};
int prepare_ota_update(); int prepare_ota_update();
esp_err_t write_ota_update(uint32_t write_len, const uint8_t *payload); esp_err_t write_ota_update(uint32_t write_len, const uint8_t *payload);
esp_err_t end_ota_update(); 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_Update_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);
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 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);
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 #endif

View File

@ -6,12 +6,14 @@ enum UART_MSG_IDS {
UART_ECHO = 0x01, UART_ECHO = 0x01,
UART_VERSION = 0x02, UART_VERSION = 0x02,
UART_CLIENT_INFO = 0x03, UART_CLIENT_INFO = 0x03,
UART_CLIENT_INPUT = 0x04,
// OTA // OTA
UART_OTA_START = 0x10, UART_OTA_START = 0x10,
UART_OTA_PAYLOAD = 0x11, UART_OTA_PAYLOAD = 0x11,
UART_OTA_END = 0x12, UART_OTA_END = 0x12,
UART_OTA_STATUS = 0x13, UART_OTA_STATUS = 0x13,
UART_OTA_START_ESPNOW = 0x14,
}; };
#endif #endif