powerpods/main/cmd/cmd_handler.c
simon 490e0ee61f Add UART SET_LOG_LEVEL for runtime master ESP-IDF logging.
Expose the command via goTool CLI/REST and dashboard controls so log verbosity can be tuned without reflashing.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-06 18:03:34 +02:00

127 lines
3.5 KiB
C

#include "cmd_handler.h"
#include "ota_session.h"
#include "esp_err.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/idf_additions.h"
#include "uart_messages.pb.h"
#include <stdlib.h>
#include <string.h>
#define MAX_HANDLERS 32
static const char *TAG = "[CMDH]";
static QueueHandle_t cmd_queue;
static msg_binding_t handlers[MAX_HANDLERS];
static int handler_count;
static const char *message_type_name(uint16_t id) {
switch ((alox_MessageType)id) {
case alox_MessageType_ACK:
return "ACK";
case alox_MessageType_ECHO:
return "ECHO";
case alox_MessageType_VERSION:
return "VERSION";
case alox_MessageType_CLIENT_INFO:
return "CLIENT_INFO";
case alox_MessageType_CLIENT_INPUT:
return "CLIENT_INPUT";
case alox_MessageType_ACCEL_DEADZONE:
return "ACCEL_DEADZONE";
case alox_MessageType_ESPNOW_UNICAST_TEST:
return "ESPNOW_UNICAST_TEST";
case alox_MessageType_LED_RING:
return "LED_RING";
case alox_MessageType_OTA_START:
return "OTA_START";
case alox_MessageType_OTA_PAYLOAD:
return "OTA_PAYLOAD";
case alox_MessageType_OTA_END:
return "OTA_END";
case alox_MessageType_OTA_STATUS:
return "OTA_STATUS";
case alox_MessageType_OTA_START_ESPNOW:
return "OTA_START_ESPNOW";
case alox_MessageType_OTA_SLAVE_PROGRESS:
return "OTA_SLAVE_PROGRESS";
case alox_MessageType_FIND_ME:
return "FIND_ME";
case alox_MessageType_RESTART:
return "RESTART";
case alox_MessageType_ACCEL_STREAM:
return "ACCEL_STREAM";
case alox_MessageType_BATTERY_STATUS:
return "BATTERY_STATUS";
case alox_MessageType_TAP_NOTIFY:
return "TAP_NOTIFY";
case alox_MessageType_CACHE_STATUS:
return "CACHE_STATUS";
case alox_MessageType_ESPNOW_ECHO_PING:
return "ESPNOW_ECHO_PING";
case alox_MessageType_SET_LOG_LEVEL:
return "SET_LOG_LEVEL";
default:
return "UNKNOWN";
}
}
void init_cmdHandler(QueueHandle_t queue) {
cmd_queue = queue;
if (xTaskCreate(vCmdDispatcherTask, "cmd_dispatch", 8192, NULL, 5, NULL) !=
pdPASS) {
ESP_LOGE(TAG, "failed to create cmd_dispatch task");
}
}
esp_err_t msg_register_handler(uint16_t id, msg_callback_t cb) {
if (cb == NULL) {
return ESP_ERR_INVALID_ARG;
}
for (int i = 0; i < handler_count; i++) {
if (handlers[i].msg_id == id) {
handlers[i].callback = cb;
return ESP_OK;
}
}
if (handler_count >= MAX_HANDLERS) {
return ESP_ERR_NO_MEM;
}
handlers[handler_count].msg_id = id;
handlers[handler_count].callback = cb;
handler_count++;
return ESP_OK;
}
void vCmdDispatcherTask(void *param) {
(void)param;
generic_msg_t msg;
while (1) {
if (xQueueReceive(cmd_queue, &msg, portMAX_DELAY) == pdPASS) {
if (!ota_session_uart_cmd_allowed(msg.msg_id)) {
ESP_LOGW(TAG, "reject %s (0x%02x) during OTA session",
message_type_name(msg.msg_id), (unsigned)msg.msg_id);
free(msg.payload);
continue;
}
bool handled = false;
for (int i = 0; i < handler_count; i++) {
if (handlers[i].msg_id == msg.msg_id) {
ESP_LOGI(TAG, "trigger command %s (0x%02x)", message_type_name(msg.msg_id),
(unsigned)msg.msg_id);
handlers[i].callback(msg.payload, msg.len);
handled = true;
break;
}
}
if (!handled) {
ESP_LOGW(TAG, "no handler for %s (0x%02x)", message_type_name(msg.msg_id),
(unsigned)msg.msg_id);
}
free(msg.payload);
}
}
}