Add command queue dispatcher and VERSION UART handler.

Centralize command dispatch over a FreeRTOS queue so UART and future
ESP-NOW transports can register handlers; implement the protobuf VERSION
command with framed nanopb responses including build git hash.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-05-18 21:46:51 +02:00
co-authored by Cursor
parent 6b7ccb4256
commit 43a85ce697
12 changed files with 422 additions and 12 deletions
+60 -2
View File
@@ -1,3 +1,4 @@
#include "cmd_handler.h"
#include "driver/uart.h"
#include "driver/gpio.h"
#include "esp_log.h"
@@ -8,11 +9,40 @@
#include "portmacro.h"
#include "uart.h"
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
static const char *TAG = "[UART]";
static QueueHandle_t uart_cmd_queue;
static bool uart_enqueue_packet(const uart_packet_t *packet) {
if (packet->len == 0) {
return false;
}
generic_msg_t msg = {
.msg_id = packet->payload[0],
.len = packet->len > 1 ? packet->len - 1 : 0,
.payload = NULL,
};
if (msg.len > 0) {
msg.payload = malloc(msg.len);
if (msg.payload == NULL) {
ESP_LOGE(TAG, "failed to allocate command payload");
return false;
}
memcpy(msg.payload, &packet->payload[1], msg.len);
}
if (xQueueSend(uart_cmd_queue, &msg, 0) != pdPASS) {
free(msg.payload);
ESP_LOGW(TAG, "command queue full");
return false;
}
return true;
}
void init_uart(QueueHandle_t cmd_queue) {
uart_cmd_queue = cmd_queue;
uart_config_t uart_config = {// .baud_rate = 115200, // 921600, 115200
@@ -44,8 +74,9 @@ void uart_read_task(void *param) {
if (len > 0) {
for (int i = 0; i < len; ++i) {
if (parse_uart_byte(data[i], &packet)) {
ESP_LOGI("UART", "Paket empfangen! Länge: %d", packet.len);
xQueueSend(uart_cmd_queue, &packet, 0);
ESP_LOGI(TAG, "packet received, len=%d, cmd=0x%02x", packet.len,
packet.len > 0 ? packet.payload[0] : 0);
uart_enqueue_packet(&packet);
}
}
last_byte_time = xTaskGetTickCount();
@@ -107,3 +138,30 @@ bool parse_uart_byte(uint8_t byte, uart_packet_t *p) {
}
return false;
}
esp_err_t uart_send_framed(const uint8_t *payload, size_t len) {
if (payload == NULL || len == 0 || len > MAX_PAYLOAD_SIZE) {
return ESP_ERR_INVALID_ARG;
}
uint8_t checksum = 0;
for (size_t i = 0; i < len; i++) {
checksum ^= payload[i];
}
uint8_t frame[4 + MAX_PAYLOAD_SIZE];
size_t pos = 0;
frame[pos++] = START_MARKER;
frame[pos++] = (uint8_t)len;
memcpy(&frame[pos], payload, len);
pos += len;
frame[pos++] = checksum;
frame[pos++] = STOP_MARKER;
int written =
uart_write_bytes(UART_NUM, frame, pos);
if (written < 0 || (size_t)written != pos) {
return ESP_FAIL;
}
return ESP_OK;
}