Fixed Bug in UART Protokol

This commit is contained in:
simon 2025-07-23 16:48:55 +02:00
parent beef75f31c
commit 50ee8009fc
11 changed files with 2314 additions and 128 deletions

54
main/client_handler.c Normal file
View File

@ -0,0 +1,54 @@
#include "client_handler.h"
#include "communication_handler.h"
#include "esp_log.h"
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
int get_client_id(ClientList *list, const uint8_t *client_mac) {
for (int i = 0; i < MAX_CLIENTS; i++) {
if (memcmp(client_mac, list->Clients[i].macAddr, MAC_LENGTH) == 0) {
return i;
}
}
return CLIENT_DOES_NOT_EXISTS;
}
// TODO: Sanity check when list full then list->count should be MAX_CLIENTS
int get_next_free_slot(ClientList *list) {
for (int i = 0; i < MAX_CLIENTS; i++) {
// if slot is not used return index
if (!list->Clients[i].slotIsUsed) {
return i;
}
}
// list is full
return CLIENT_LIST_FULL;
}
int add_client(ClientList *list, const uint8_t *client_mac) {
if (get_client_id(list, client_mac) >= 0) {
// Client already exists dont add to list
return CLIENT_EXISTS;
}
int slot = get_next_free_slot(list);
if (slot < 0) {
// Client list full
return CLIENT_LIST_FULL;
}
list->Clients[slot].slotIsUsed = true;
list->Clients[slot].isAvailable = true;
memcpy(list->Clients[slot].macAddr, client_mac, MAC_LENGTH);
list->ClientCount++;
return CLIENT_OK;
}
int remove_client(ClientList *list, const uint8_t client_id) {
if (client_id >= MAX_CLIENTS)
return CLIENT_INVALID_ID; // invalid index
list->Clients[client_id].slotIsUsed = false;
list->ClientCount--;
return CLIENT_OK;
}

43
main/client_handler.h Normal file
View File

@ -0,0 +1,43 @@
#ifndef CLIENT_HANDLER_H
#define CLIENT_HANDLER_H
#include "portmacro.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/_intsup.h>
#include <sys/types.h>
#define MAX_CLIENTS 16
#define MAC_LENGTH 6
enum ClientErrors {
CLIENT_OK = 0,
CLIENT_EXISTS = -1,
CLIENT_DOES_NOT_EXISTS = -2,
CLIENT_LIST_FULL = -3,
CLIENT_INVALID_ID = -4,
};
typedef struct {
bool slotIsUsed;
bool isAvailable;
uint8_t clientID;
uint8_t macAddr[MAC_LENGTH];
TickType_t lastSuccessfullPing;
TickType_t lastPing;
} ClientInfo;
typedef struct {
ClientInfo Clients[MAX_CLIENTS];
uint8_t ClientCount;
} ClientList;
int get_client_id(ClientList *list, const uint8_t *client_mac);
int add_client(ClientList *list, const uint8_t *client_mac);
int remove_client(ClientList *list, const uint8_t clientid);
int get_next_free_slot(ClientList *list);
#endif

View File

@ -1,41 +1,33 @@
#include "esp_log.h"
#include "esp_now.h"
#include "esp_timer.h"
#include "freertos/idf_additions.h"
#include "client_handler.h"
#include "communication_handler.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
static const char *TAG = "ALOX - COM";
QueueHandle_t messageQueue = NULL; // Warteschlange für empfangene Nachrichten
ClientInfo clients[MAX_CLIENTS] = {
0}; // Clients statisch initialisieren, alle auf 0 gesetzt
size_t numClients = 0;
size_t activeClients = 0;
bool hasMaster = false;
static ClientList *esp_client_list;
void init_com() {
#define MAC_STRING_BUFFER_SIZE 18
void init_com(ClientList *clients) {
// Initialisiere die Kommunikations-Warteschlange
messageQueue = xQueueCreate(MESSAGE_QUEUE_SIZE, sizeof(BaseMessage));
if (messageQueue == NULL) {
ESP_LOGE(TAG, "Message queue creation failed");
}
// Weitere Initialisierungen, falls nötig
numClients = 0;
activeClients = 0;
esp_client_list = clients;
hasMaster = false;
}
// return any inactive client field for new usage
int getNextFreeClientId() {
for (int i = 0; i < MAX_CLIENTS; i++) {
if (!clients[i].isAvailable) {
return i;
}
}
return -1;
}
void add_peer(uint8_t *macAddr) {
esp_now_peer_info_t peerInfo = {
.channel =
@ -53,41 +45,29 @@ void add_peer(uint8_t *macAddr) {
peerInfo.peer_addr[4], peerInfo.peer_addr[5]);
if (!IS_BROADCAST_ADDR(macAddr)) {
if (numClients >= MAX_CLIENTS) {
ESP_LOGW(TAG, "Cannot add more clients, maximum reached.");
return;
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_now_del_peer(peerInfo.peer_addr);
}
ClientInfo newClient = {};
memcpy(newClient.macAddr, macAddr, ESP_NOW_ETH_ALEN);
newClient.isAvailable = true;
newClient.lastSuccessfullPing = xTaskGetTickCount();
newClient.lastPing = 0;
clients[getNextFreeClientId()] = newClient;
ESP_LOGI(TAG, "New client added.");
}
} else if (result == ESP_ERR_ESPNOW_EXIST) {
ESP_LOGW(TAG, "Peer already exists.");
// Überprüfen, ob der Client bereits existiert
for (int i = 0; i < numClients; i++) {
if (memcmp(clients[i].macAddr, macAddr, ESP_NOW_ETH_ALEN) == 0) {
int id = get_client_id(esp_client_list, peerInfo.peer_addr);
if (id >= 0) {
ESP_LOGI(TAG, "Client found again, welcome back!");
clients[i].isAvailable = true; // Reaktiviere den Client
break;
}
esp_client_list->Clients[id].isAvailable = true;
}
} else {
ESP_LOGE(TAG, "Failed to add peer: %s", esp_err_to_name(result));
}
}
// UNSAFE ACCROSS THREADS BUT EZ TO USE
const char *MACtoString(uint8_t *macAddr) {
static char output[18]; // 17 Zeichen + 1 für Nullterminierung
sprintf(output, "%02X:%02X:%02X:%02X:%02X:%02X", macAddr[0], macAddr[1],
void MACtoString(const uint8_t *macAddr, char *outputBuffer) {
sprintf(outputBuffer, "%02X:%02X:%02X:%02X:%02X:%02X", macAddr[0], macAddr[1],
macAddr[2], macAddr[3], macAddr[4], macAddr[5]);
return output;
}
BaseMessage MessageBuilder(CommandPages commandPage, PayloadUnion payload,
@ -135,16 +115,17 @@ void master_broadcast_ping(void *param) {
}
void master_ping_task(void *param) {
char macBuffer[MAC_STRING_BUFFER_SIZE];
while (1) {
for (size_t i = 0; i < MAX_CLIENTS; i++) {
if (clients[i].isAvailable) {
ESP_LOGI(TAG, "SEND PING TO %zu: %s", i,
MACtoString(clients[i].macAddr));
if (esp_client_list->Clients[i].isAvailable) {
MACtoString(esp_client_list->Clients[i].macAddr, macBuffer);
ESP_LOGI(TAG, "SEND PING TO %zu: %s", i, macBuffer);
PingPayload payload = {};
payload.timestamp = esp_timer_get_time();
BaseMessage message = MessageBuilder(
PingPage, *(PayloadUnion *)&payload, sizeof(payload));
esp_now_send(clients[i].macAddr, (uint8_t *)&message,
esp_now_send(esp_client_list->Clients[i].macAddr, (uint8_t *)&message,
sizeof(BaseMessage));
ESP_LOGI(TAG, "SENDING PING!!!!");
}
@ -155,6 +136,7 @@ void master_ping_task(void *param) {
void master_receive_callback(const esp_now_recv_info_t *esp_now_info,
const uint8_t *data, int data_len) {
char macBuffer[MAC_STRING_BUFFER_SIZE];
ESP_LOGI(TAG, "MASTER GOT MESSAGE");
const BaseMessage *message = (const BaseMessage *)data;
@ -171,18 +153,13 @@ void master_receive_callback(const esp_now_recv_info_t *esp_now_info,
message->payload.ping_payload.timestamp, currentTime, diff,
diff / 1000); // ping in ms
for (int i = 0; i < MAX_CLIENTS; i++) {
// Überprüfen, ob der Client existiert und die MAC-Adresse übereinstimmt
if (clients[i].isAvailable &&
memcmp(clients[i].macAddr, esp_now_info->src_addr,
ESP_NOW_ETH_ALEN) == 0) {
clients[i].lastSuccessfullPing = xTaskGetTickCount();
clients[i].lastPing = (diff/1000);
ESP_LOGI(TAG, "Updated client %d: %s last ping time to %lu", i,
MACtoString(clients[i].macAddr),
clients[i].lastSuccessfullPing);
break;
}
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);
MACtoString(esp_now_info->src_addr, macBuffer);
ESP_LOGI(TAG, "Updated client %d: %s last ping time to %lu", id,
macBuffer, esp_client_list->Clients[id].lastSuccessfullPing);
}
break;
case BroadCastPage:
@ -197,18 +174,11 @@ void master_receive_callback(const esp_now_recv_info_t *esp_now_info,
switch (checkPeer) {
case (ESP_OK):
ESP_LOGI(TAG, "CLIENT BEKANNT");
for (int i = 0; i < MAX_CLIENTS; i++) {
// client in liste wiederfinden
if (!clients[i].isAvailable &&
memcmp(clients[i].macAddr, esp_now_info->src_addr,
ESP_NOW_ETH_ALEN) == 0) {
clients[i].isAvailable = true;
clients[i].lastSuccessfullPing = xTaskGetTickCount();
ESP_LOGI(TAG, "Updated client %d last ping time to %lu", i,
clients[i].lastSuccessfullPing);
break;
}
}
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");
@ -229,14 +199,12 @@ void master_receive_callback(const esp_now_recv_info_t *esp_now_info,
break;
}
}
void client_receive_callback(const esp_now_recv_info_t *esp_now_info,
const uint8_t *data, int data_len) {
char macBuffer[MAC_STRING_BUFFER_SIZE];
ESP_LOGI(TAG, "SLAVE GOT MESSAGE");
ESP_LOGI(TAG, "Received message from: %02X:%02X:%02X:%02X:%02X:%02X",
esp_now_info->src_addr[0], esp_now_info->src_addr[1],
esp_now_info->src_addr[2], esp_now_info->src_addr[3],
esp_now_info->src_addr[4], esp_now_info->src_addr[5]);
MACtoString(esp_now_info->src_addr, macBuffer);
ESP_LOGI(TAG, "Received message from: %s", macBuffer);
ESP_LOGI(TAG, "Message: %.*s", data_len, data);
BaseMessage replyMessage = {};
@ -289,6 +257,7 @@ void client_data_sending_task(void *param) {
}
void client_monitor_task(void *pvParameters) {
char macBuffer[MAC_STRING_BUFFER_SIZE];
TickType_t timeout_ticks =
pdMS_TO_TICKS(CLIENT_TIMEOUT_MS); // Timeout in Ticks
TickType_t interval_ticks =
@ -298,18 +267,15 @@ void client_monitor_task(void *pvParameters) {
TickType_t now = xTaskGetTickCount(); // Aktuelle Zeit in Ticks
for (int i = 0; i < MAX_CLIENTS; i++) {
if (clients[i].isAvailable) {
TickType_t time_diff = now - clients[i].lastSuccessfullPing;
if (esp_client_list->Clients[i].isAvailable) {
TickType_t time_diff =
now - esp_client_list->Clients[i].lastSuccessfullPing;
// Prüfen, ob der Client als "nicht verfügbar" markiert werden soll
if (time_diff > timeout_ticks) {
clients[i].isAvailable = false;
ESP_LOGW(
TAG,
"Client %d (MAC: %02X:%02X:%02X:%02X:%02X:%02X) is unavailable",
i, clients[i].macAddr[0], clients[i].macAddr[1],
clients[i].macAddr[2], clients[i].macAddr[3],
clients[i].macAddr[4], clients[i].macAddr[5]);
esp_client_list->Clients[i].isAvailable = false;
MACtoString(esp_client_list->Clients[i].macAddr, macBuffer);
ESP_LOGW(TAG, "Client %d (MAC: %s) is unavailable", macBuffer);
}
}
}
@ -318,7 +284,3 @@ void client_monitor_task(void *pvParameters) {
vTaskDelay(interval_ticks);
}
}
ClientInfo *get_client_info(int entry) {
return &clients[entry];
}

View File

@ -1,6 +1,7 @@
#ifndef COMMUNICATION_HANDLER_H
#define COMMUNICATION_HANDLER_H
#include "client_handler.h"
#include <esp_now.h>
#include <esp_wifi.h>
#include <freertos/FreeRTOS.h>
@ -20,7 +21,6 @@ static uint8_t broadcast_address[ESP_NOW_ETH_ALEN] = {0xFF, 0xFF, 0xFF,
#define IS_BROADCAST_ADDR(addr) \
(memcmp(addr, broadcast_address, ESP_NOW_ETH_ALEN) == 0)
#define MAX_CLIENTS 19
#define MESSAGE_QUEUE_SIZE 10
typedef enum {
@ -63,18 +63,10 @@ typedef struct {
static_assert(sizeof(BaseMessage) <= 255,
"BaseMessage darf nicht größer als 255 sein");
typedef struct {
uint8_t macAddr[ESP_NOW_ETH_ALEN];
int rssi;
bool isAvailable;
TickType_t lastSuccessfullPing;
TickType_t lastPing;
} ClientInfo;
void init_com();
void init_com(ClientList *clients);
int getNextFreeClientId();
void add_peer(uint8_t *macAddr);
const char *MACtoString(uint8_t *macAddr);
void MACtoString(const uint8_t *macAddr, char *outputBuffer);
BaseMessage MessageBuilder(CommandPages commandPage, PayloadUnion payload,
size_t payload_size);
@ -89,6 +81,4 @@ void client_receive_callback(const esp_now_recv_info_t *esp_now_info,
void client_data_sending_task(void *param);
void client_monitor_task(void *pvParameters);
ClientInfo *get_client_info(int entry);
#endif

View File

@ -1,3 +1,4 @@
#include "client_handler.h"
#include "driver/gpio.h"
#include "driver/uart.h"
#include "esp_log.h"
@ -11,6 +12,7 @@
#include "message_parser.h"
#include "nvs_flash.h"
#include "glob.h"
#include "communication_handler.h"
#include "main.h"
#include "portmacro.h"
@ -23,23 +25,44 @@
#include "message_builder.h"
typedef struct {
QueueHandle_t message_queue;
uint8_t *send_buffer;
size_t send_buffer_size;
} MessageBrokerTaskParams_t;
static const char *TAG = "ALOX - MAIN";
static const uint16_t version = 0x0001;
static uint8_t send_message_buffer[1024];
static MessageBrokerTaskParams_t broker_task_params;
void echoCallback(uint8_t msgid, const uint8_t *payload, size_t payload_len) {
ClientList clientList = {.Clients = {{0}}, .ClientCount = 0};
typedef void (*RegisterTaskCallback)(uint8_t msgid, const uint8_t *payload,
size_t payload_len, uint8_t *send_buffer,
size_t send_buffer_size);
void echoCallback(uint8_t msgid, const uint8_t *payload, size_t payload_len,
uint8_t *send_buffer, size_t send_buffer_size) {
// Code für den Button-Press
ESP_LOGI(TAG, "Echo command 0x01...");
uint8_t send_buffer[64];
size_t len = build_message(0x01, payload, payload_len, send_buffer,
sizeof(send_buffer));
int len =
build_message(0x01, payload, payload_len, 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 versionCallback(uint8_t msgid, const uint8_t *payload,
size_t payload_len) {
void versionCallback(uint8_t msgid, const uint8_t *payload, size_t payload_len,
uint8_t *send_buffer, size_t send_buffer_size) {
// Code für den Button-Press
ESP_LOGI(TAG, "Version command 0x02...");
uint8_t send_buffer[64];
size_t git_build_hash_len = strlen(BUILD_GIT_HASH);
uint8_t send_payload[2 + git_build_hash_len];
@ -47,8 +70,74 @@ void versionCallback(uint8_t msgid, const uint8_t *payload,
send_payload[1] = (uint8_t)((version >> 8) & 0xFF);
memcpy(&send_payload[2], &BUILD_GIT_HASH, git_build_hash_len);
size_t len = build_message(0x02, send_payload, sizeof(send_payload),
send_buffer, sizeof(send_buffer));
int len = build_message(0x02, send_payload, sizeof(send_payload), 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 clientInfoCallback(uint8_t msgid, const uint8_t *payload,
size_t payload_len, uint8_t *send_buffer,
size_t send_buffer_size) {
ESP_LOGI(TAG, "Client Info Command 0x03...");
static uint8_t entryLength = 17;
ESP_LOGE(TAG, "clientList.ClientCount = %d", clientList.ClientCount);
uint8_t payload_size = 1 + entryLength * clientList.ClientCount;
ESP_LOGE(TAG, "payload_size = %d", payload_size);
uint8_t send_payload[payload_size];
send_payload[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++;
}
}
ESP_LOGE("SPECIAL", "USED SLOTS: %d", 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", "DAS KANN NICHT SEIN");
ESP_LOGE("SPECIAL", "loop_santy_count: %d, client_count: %d", loop_sanity_counter, clientList.ClientCount);
}
size_t offset = 1 + (entryLength * offsetMult++);
ESP_LOGE("SPECIAL", "OFFSET %d", offset);
send_payload[offset] = i;
send_payload[offset + 1] = clientList.Clients[i].isAvailable;
send_payload[offset + 2] = clientList.Clients[i].slotIsUsed;
memcpy(&send_payload[offset + 3], clientList.Clients[i].macAddr,
MAC_LENGTH);
memcpy(&send_payload[offset + 9], &clientList.Clients[i].lastPing, 4);
memcpy(&send_payload[offset + 13],
&clientList.Clients[i].lastSuccessfullPing, 4);
}
}
int len = build_message(0x04, send_payload, sizeof(send_payload), 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);
}
@ -81,8 +170,8 @@ void app_main(void) {
// denselben Kanal verwenden
},
};
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
ESP_ERROR_CHECK(esp_now_init());
@ -92,36 +181,42 @@ void app_main(void) {
ESP_ERROR_CHECK(esp_now_register_recv_cb(client_receive_callback));
}
init_com();
init_com(&clientList);
// Tasks starten basierend auf Master/Client
if (isMaster) {
ESP_LOGI(TAG, "Started in Mastermode");
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,
// 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);
xTaskCreate(MessageBrokerTask, "message_handler_task", 4096,
(void *)&parsed_message_queue, 5, NULL);
(void *)&broker_task_params, 5, NULL);
RegisterCallback(0x01, echoCallback);
RegisterCallback(0x02, versionCallback);
RegisterCallback(0x03, clientInfoCallback);
// xTaskCreate(uart_status_task, "MasterUartStatusTask", 4096, NULL, 1,
// NULL); xTaskCreate(SendClientInfoTask, "SendCientInfo", 4096, NULL, 1,
// NULL);
} else {
ESP_LOGI(TAG, "Started in Slavemode");
//xTaskCreate(client_data_sending_task, "ClientDataSending", 4096, NULL, 1,
// NULL);
xTaskCreate(client_data_sending_task, "ClientDataSending", 4096, NULL, 1,
NULL);
}
}

View File

@ -1,4 +1,5 @@
#include "message_builder.h"
#include "esp_log.h"
#include "message_parser.h"
#include <stdbool.h>
#include <stddef.h>
@ -7,8 +8,8 @@ bool needs_stuffing_byte(uint8_t byte) {
return (byte == StartByte || byte == EscapeByte || byte == EndByte);
}
bool add_byte_with_length_check(uint8_t byte, uint8_t write_index,
uint8_t *data, uint8_t max_length) {
bool add_byte_with_length_check(uint8_t byte, size_t write_index, uint8_t *data,
size_t max_length) {
if (write_index >= max_length) {
return false;
}
@ -19,6 +20,8 @@ bool add_byte_with_length_check(uint8_t byte, uint8_t write_index,
int build_message(uint8_t msgid, const uint8_t *payload, size_t payload_len,
uint8_t *msg_buffer, size_t msg_buffer_size) {
ESP_LOGE("BM", "payload_len %d, msg_buffer_size %d", payload_len + 4,
msg_buffer_size);
if (payload_len + 4 > msg_buffer_size) {
return PayloadBiggerThenBuffer;
}
@ -72,5 +75,6 @@ int build_message(uint8_t msgid, const uint8_t *payload, size_t payload_len,
msg_buffer[write_index++] = checksum;
msg_buffer[write_index++] = EndByte;
ESP_LOGE("BM", "MESSAGE FERTIG GEBAUT");
return write_index;
}

View File

@ -6,6 +6,12 @@
static struct MessageBroker mr;
static char *TAG = "ALOX - Message Handler";
typedef struct {
QueueHandle_t message_queue;
uint8_t *send_buffer;
size_t send_buffer_size;
} MessageBrokerTaskParams_t;
void InitMessageBroker() {
mr.num_direct_callbacks = 0;
mr.num_task_callbacks = 0;
@ -28,7 +34,12 @@ void RegisterTask(uint8_t msgid, RegisterTaskCallback callback) {
void MessageBrokerTask(void *param) {
ParsedMessage_t received_msg;
QueueHandle_t msg_queue = *(QueueHandle_t *)param;
MessageBrokerTaskParams_t *task_params = (MessageBrokerTaskParams_t *)param;
// Extrahiere die einzelnen Parameter
QueueHandle_t msg_queue = task_params->message_queue;
uint8_t *send_message_buffer = task_params->send_buffer;
size_t send_message_buffer_size = task_params->send_buffer_size;
if (msg_queue == NULL) {
ESP_LOGE(TAG, "Message queue not initialized. Terminating task.");
@ -44,8 +55,9 @@ void MessageBrokerTask(void *param) {
for (int i = 0; i < mr.num_direct_callbacks; i++) {
if (mr.FunctionList[i].MSGID == received_msg.msgid) {
mr.FunctionList[i].callback(received_msg.msgid, received_msg.data,
received_msg.payload_len);
mr.FunctionList[i].callback(
received_msg.msgid, received_msg.data, received_msg.payload_len,
send_message_buffer, send_message_buffer_size);
}
}
for (int i = 0; i < mr.num_direct_callbacks; i++) {

View File

@ -6,9 +6,12 @@
#include <stdint.h>
typedef void (*RegisterFunctionCallback)(uint8_t msgid, const uint8_t *payload,
size_t payload_len);
size_t payload_len,
uint8_t *send_buffer,
size_t send_buffer_size);
typedef void (*RegisterTaskCallback)(uint8_t msgid, const uint8_t *payload,
size_t payload_len);
size_t payload_len, uint8_t *send_buffer,
size_t send_buffer_size);
struct RegisterdFunction {
uint8_t MSGID;

View File

@ -1283,9 +1283,9 @@ CONFIG_HAL_DEFAULT_ASSERTION_LEVEL=2
#
# Heap memory debugging
#
CONFIG_HEAP_POISONING_DISABLED=y
# CONFIG_HEAP_POISONING_DISABLED is not set
# CONFIG_HEAP_POISONING_LIGHT is not set
# CONFIG_HEAP_POISONING_COMPREHENSIVE is not set
CONFIG_HEAP_POISONING_COMPREHENSIVE=y
CONFIG_HEAP_TRACING_OFF=y
# CONFIG_HEAP_TRACING_STANDALONE is not set
# CONFIG_HEAP_TRACING_TOHOST is not set

1908
sdkconfig.old Normal file

File diff suppressed because it is too large Load Diff

115
tools/message_builder.py Normal file
View File

@ -0,0 +1,115 @@
import enum
START_BYTE = 0xAA
ESCAPE_BYTE = 0xBB
END_BYTE = 0xCC
class MessageBuilderError(Exception):
"""Basisklasse für Fehler des Message Builders."""
pass
class PayloadTooLargeError(MessageBuilderError):
"""Ausnahme, wenn der Payload zu groß für den Puffer ist."""
def __init__(self, required_size, buffer_size):
super().__init__(f"Payload ({
required_size} bytes) ist größer als der verfügbare Puffer ({buffer_size} bytes).")
self.required_size = required_size
self.buffer_size = buffer_size
class BufferOverflowError(MessageBuilderError):
"""Ausnahme, wenn der Puffer während des Bauens überläuft."""
def __init__(self, current_size, max_size, byte_to_add=None):
msg = f"Pufferüberlauf: Aktuelle Größe {
current_size}, Max. Größe {max_size}."
if byte_to_add is not None:
msg += f" Versuch, Byte 0x{byte_to_add:02X} hinzuzufügen."
super().__init__(msg)
self.current_size = current_size
self.max_size = max_size
self.byte_to_add = byte_to_add
class MessageBuilder:
"""
Klasse zum Aufbau von UART-Nachrichten gemäß dem definierten Protokoll,
inklusive Stuffing und Checksummenberechnung.
"""
def __init__(self):
pass
def _needs_stuffing_byte(self, byte: int) -> bool:
"""
Prüft, ob ein Byte ein Stuffing-Byte benötigt (d.h. ob es ein Steuerbyte ist).
"""
return (byte == START_BYTE or byte == ESCAPE_BYTE or byte == END_BYTE)
def _add_byte_with_length_check(self, byte: int, buffer: bytearray, max_length: int):
"""
Fügt ein Byte zum Puffer hinzu und prüft auf Pufferüberlauf.
Löst BufferOverflowError aus, wenn der Puffer voll ist.
"""
if len(buffer) >= max_length:
raise BufferOverflowError(len(buffer), max_length, byte)
buffer.append(byte)
def build_message(self, msgid: int, payload: bytes, msg_buffer_size: int) -> bytes:
"""
Baut eine vollständige UART-Nachricht.
Args:
msgid (int): Die Message ID (0-255).
payload (bytes): Die Nutzdaten der Nachricht als Byte-Objekt.
msg_buffer_size (int): Die maximale Größe des Ausgabepuffers.
Dies ist die maximale Länge der *fertigen* Nachricht.
Returns:
bytes: Die fertig aufgebaute Nachricht als Byte-Objekt.
Raises:
PayloadTooLargeError: Wenn der Payload (mit Overhead) den Puffer überschreiten würde.
BufferOverflowError: Wenn während des Bauens ein Pufferüberlauf auftritt.
"""
if len(payload) + 4 > msg_buffer_size:
raise PayloadTooLargeError(len(payload) + 4, msg_buffer_size)
checksum = 0
msg_buffer = bytearray()
# 1. StartByte hinzufügen
self._add_byte_with_length_check(
START_BYTE, msg_buffer, msg_buffer_size)
# 2. Message ID hinzufügen (mit Stuffing)
if self._needs_stuffing_byte(msgid):
self._add_byte_with_length_check(
ESCAPE_BYTE, msg_buffer, msg_buffer_size)
self._add_byte_with_length_check(msgid, msg_buffer, msg_buffer_size)
checksum ^= msgid
# 3. Payload-Bytes hinzufügen (mit Stuffing)
for byte_val in payload:
if self._needs_stuffing_byte(byte_val):
self._add_byte_with_length_check(
ESCAPE_BYTE, msg_buffer, msg_buffer_size)
self._add_byte_with_length_check(
byte_val, msg_buffer, msg_buffer_size)
checksum ^= byte_val
# 4. Checksumme hinzufügen (mit Stuffing)
if self._needs_stuffing_byte(checksum):
self._add_byte_with_length_check(
ESCAPE_BYTE, msg_buffer, msg_buffer_size)
self._add_byte_with_length_check(checksum, msg_buffer, msg_buffer_size)
# 5. EndByte hinzufügen
self._add_byte_with_length_check(END_BYTE, msg_buffer, msg_buffer_size)
# Konvertiere bytearray zu unveränderlichem bytes-Objekt
return bytes(msg_buffer)