- Switch UART0 for protocol I/O (USB bridge), disable ESP-IDF console - Wire all 21 command handlers into dispatch table (was only 4) - Add configure command handler (name, io_cap, device_class) - Add bt_classic_is_enabled()/bt_ble_is_enabled() for live status - Fix cJSON_False misuse in get_status (type constant, not boolean) - Fix esp_bt_gap_set_cod() to use esp_bt_cod_t bitfield struct - Fix auth_cmpl.auth_mode → lk_type for ESP-IDF v5.3 - Replace deprecated esp_bt_dev_set_device_name with stack-specific API - Remove unused bytes_to_hex, obsolete kconfig symbols - Use large partition table (1.5MB) for dual-mode BT stack Verified on ESP32-D0WD-V3 rev 3.1, /dev/ttyUSB4, all commands tested.
138 lines
3.4 KiB
C
138 lines
3.4 KiB
C
#include "uart_handler.h"
|
|
#include "protocol.h"
|
|
|
|
#include "driver/uart.h"
|
|
#include "esp_log.h"
|
|
#include "esp_timer.h"
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/semphr.h"
|
|
#include "cJSON.h"
|
|
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
static const char *TAG = "uart";
|
|
static SemaphoreHandle_t tx_mutex;
|
|
|
|
/*
|
|
* Use UART0 — the dev board's USB bridge connects here.
|
|
* ESP-IDF console is disabled (CONFIG_ESP_CONSOLE_NONE=y) so we own UART0.
|
|
* Default UART0 pins (TX=GPIO1, RX=GPIO3) route through the USB bridge.
|
|
*/
|
|
|
|
void uart_handler_init(void)
|
|
{
|
|
uart_config_t cfg = {
|
|
.baud_rate = PROTO_BAUD_RATE,
|
|
.data_bits = UART_DATA_8_BITS,
|
|
.parity = UART_PARITY_DISABLE,
|
|
.stop_bits = UART_STOP_BITS_1,
|
|
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
|
.source_clk = UART_SCLK_DEFAULT,
|
|
};
|
|
|
|
ESP_ERROR_CHECK(uart_param_config(PROTO_UART_NUM, &cfg));
|
|
/* UART0 default pins (TX=1, RX=3) — no set_pin needed */
|
|
ESP_ERROR_CHECK(uart_driver_install(PROTO_UART_NUM,
|
|
PROTO_RX_BUF_SIZE, PROTO_TX_BUF_SIZE,
|
|
0, NULL, 0));
|
|
|
|
tx_mutex = xSemaphoreCreateMutex();
|
|
assert(tx_mutex);
|
|
|
|
ESP_LOGI(TAG, "UART%d ready (USB bridge @ %d baud)",
|
|
PROTO_UART_NUM, PROTO_BAUD_RATE);
|
|
}
|
|
|
|
char *uart_read_line(void)
|
|
{
|
|
static char buf[PROTO_MAX_LINE];
|
|
int pos = 0;
|
|
|
|
for (;;) {
|
|
uint8_t byte;
|
|
int n = uart_read_bytes(PROTO_UART_NUM, &byte, 1, portMAX_DELAY);
|
|
if (n <= 0) {
|
|
continue;
|
|
}
|
|
|
|
if (byte == '\n') {
|
|
if (pos == 0) {
|
|
continue; /* skip empty lines */
|
|
}
|
|
buf[pos] = '\0';
|
|
return strdup(buf);
|
|
}
|
|
|
|
if (byte == '\r') {
|
|
continue; /* ignore carriage returns */
|
|
}
|
|
|
|
if (pos < PROTO_MAX_LINE - 1) {
|
|
buf[pos++] = (char)byte;
|
|
} else {
|
|
/* line too long -- discard and reset */
|
|
ESP_LOGE(TAG, "line overflow (%d bytes), discarding", pos);
|
|
pos = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
void uart_send_line(const char *json_line)
|
|
{
|
|
if (!json_line) {
|
|
return;
|
|
}
|
|
|
|
xSemaphoreTake(tx_mutex, portMAX_DELAY);
|
|
|
|
size_t len = strlen(json_line);
|
|
uart_write_bytes(PROTO_UART_NUM, json_line, len);
|
|
uart_write_bytes(PROTO_UART_NUM, "\n", 1);
|
|
|
|
xSemaphoreGive(tx_mutex);
|
|
}
|
|
|
|
void uart_send_response(const char *id, const char *status, cJSON *data)
|
|
{
|
|
cJSON *root = cJSON_CreateObject();
|
|
cJSON_AddStringToObject(root, "type", MSG_TYPE_RESP);
|
|
cJSON_AddStringToObject(root, "id", id);
|
|
cJSON_AddStringToObject(root, "status", status);
|
|
|
|
if (data) {
|
|
cJSON_AddItemToObject(root, "data", data);
|
|
} else {
|
|
cJSON_AddObjectToObject(root, "data");
|
|
}
|
|
|
|
char *out = cJSON_PrintUnformatted(root);
|
|
uart_send_line(out);
|
|
|
|
free(out);
|
|
cJSON_Delete(root);
|
|
}
|
|
|
|
void uart_send_event(const char *event_name, cJSON *data)
|
|
{
|
|
int64_t ts_ms = esp_timer_get_time() / 1000;
|
|
|
|
cJSON *root = cJSON_CreateObject();
|
|
cJSON_AddStringToObject(root, "type", MSG_TYPE_EVENT);
|
|
cJSON_AddStringToObject(root, "event", event_name);
|
|
|
|
if (data) {
|
|
cJSON_AddItemToObject(root, "data", data);
|
|
} else {
|
|
cJSON_AddObjectToObject(root, "data");
|
|
}
|
|
|
|
cJSON_AddNumberToObject(root, "ts", (double)ts_ms);
|
|
|
|
char *out = cJSON_PrintUnformatted(root);
|
|
uart_send_line(out);
|
|
|
|
free(out);
|
|
cJSON_Delete(root);
|
|
}
|