forked from xiaozhi/xiaozhi-esp32
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a3dfc003e | ||
|
|
fc355605f5 |
@@ -4,7 +4,7 @@
|
||||
# CMakeLists in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
set(PROJECT_VER "1.9.2")
|
||||
set(PROJECT_VER "1.9.0")
|
||||
|
||||
# Add this line to disable the specific warning
|
||||
add_compile_options(-Wno-missing-field-initializers)
|
||||
|
||||
@@ -508,10 +508,7 @@ config USE_AUDIO_PROCESSOR
|
||||
config USE_DEVICE_AEC
|
||||
bool "Enable Device-Side AEC"
|
||||
default n
|
||||
depends on USE_AUDIO_PROCESSOR && (BOARD_TYPE_ESP_BOX_3 || BOARD_TYPE_ESP_BOX || BOARD_TYPE_ESP_BOX_LITE || BOARD_TYPE_LICHUANG_DEV \
|
||||
|| BOARD_TYPE_ESP32S3_KORVO2_V3 || BOARD_TYPE_ESP32S3_Touch_AMOLED_1_75 || BOARD_TYPE_ESP32S3_Touch_AMOLED_2_06 \
|
||||
|| BOARD_TYPE_ESP32P4_WIFI6_Touch_LCD_4B || BOARD_TYPE_ESP32P4_WIFI6_Touch_LCD_XC || BOARD_TYPE_ESP_S3_LCD_EV_Board_2 \
|
||||
|| BOARD_TYPE_ECHOEAR)
|
||||
depends on USE_AUDIO_PROCESSOR && (BOARD_TYPE_ESP_BOX_3 || BOARD_TYPE_ESP_BOX || BOARD_TYPE_ESP_BOX_LITE || BOARD_TYPE_LICHUANG_DEV || BOARD_TYPE_ESP32S3_KORVO2_V3 || BOARD_TYPE_ESP32S3_Touch_AMOLED_1_75 || BOARD_TYPE_ESP32S3_Touch_AMOLED_2_06 || BOARD_TYPE_ESP32P4_WIFI6_Touch_LCD_4B || BOARD_TYPE_ESP32P4_WIFI6_Touch_LCD_XC || BOARD_TYPE_ESP_S3_LCD_EV_Board_2)
|
||||
help
|
||||
因为性能不够,不建议和微信聊天界面风格同时开启
|
||||
|
||||
|
||||
@@ -332,9 +332,6 @@ void Application::Start() {
|
||||
/* Setup the display */
|
||||
auto display = board.GetDisplay();
|
||||
|
||||
// Print board name/version info
|
||||
display->SetChatMessage("system", SystemInfo::GetUserAgent().c_str());
|
||||
|
||||
/* Setup the audio service */
|
||||
auto codec = board.GetAudioCodec();
|
||||
audio_service_.Initialize(codec);
|
||||
@@ -352,12 +349,6 @@ void Application::Start() {
|
||||
};
|
||||
audio_service_.SetCallbacks(callbacks);
|
||||
|
||||
// Start the main event loop task with priority 3
|
||||
xTaskCreate([](void* arg) {
|
||||
((Application*)arg)->MainEventLoop();
|
||||
vTaskDelete(NULL);
|
||||
}, "main_event_loop", 2048 * 4, this, 3, &main_event_loop_task_handle_);
|
||||
|
||||
/* Start the clock timer to update the status bar */
|
||||
esp_timer_start_periodic(clock_timer_handle_, 1000000);
|
||||
|
||||
@@ -532,6 +523,9 @@ void Application::Schedule(std::function<void()> callback) {
|
||||
// If other tasks need to access the websocket or chat state,
|
||||
// they should use Schedule to call this function
|
||||
void Application::MainEventLoop() {
|
||||
// Raise the priority of the main event loop to avoid being interrupted by background tasks (which has priority 2)
|
||||
vTaskPrioritySet(NULL, 3);
|
||||
|
||||
while (true) {
|
||||
auto bits = xEventGroupWaitBits(event_group_, MAIN_EVENT_SCHEDULE |
|
||||
MAIN_EVENT_SEND_AUDIO |
|
||||
@@ -743,20 +737,11 @@ bool Application::CanEnterSleepMode() {
|
||||
}
|
||||
|
||||
void Application::SendMcpMessage(const std::string& payload) {
|
||||
if (protocol_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure you are using main thread to send MCP message
|
||||
if (xTaskGetCurrentTaskHandle() == main_event_loop_task_handle_) {
|
||||
ESP_LOGI(TAG, "Send MCP message in main thread");
|
||||
protocol_->SendMcpMessage(payload);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Send MCP message in sub thread");
|
||||
Schedule([this, payload = std::move(payload)]() {
|
||||
Schedule([this, payload]() {
|
||||
if (protocol_) {
|
||||
protocol_->SendMcpMessage(payload);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Application::SetAecMode(AecMode mode) {
|
||||
|
||||
@@ -82,7 +82,6 @@ private:
|
||||
bool aborted_ = false;
|
||||
int clock_ticks_ = 0;
|
||||
TaskHandle_t check_new_version_task_handle_ = nullptr;
|
||||
TaskHandle_t main_event_loop_task_handle_ = nullptr;
|
||||
|
||||
void OnWakeWordDetected();
|
||||
void CheckNewVersion(Ota& ota);
|
||||
@@ -90,19 +89,4 @@ private:
|
||||
void SetListeningMode(ListeningMode mode);
|
||||
};
|
||||
|
||||
|
||||
class TaskPriorityReset {
|
||||
public:
|
||||
TaskPriorityReset(BaseType_t priority) {
|
||||
original_priority_ = uxTaskPriorityGet(NULL);
|
||||
vTaskPrioritySet(NULL, priority);
|
||||
}
|
||||
~TaskPriorityReset() {
|
||||
vTaskPrioritySet(NULL, original_priority_);
|
||||
}
|
||||
|
||||
private:
|
||||
BaseType_t original_priority_;
|
||||
};
|
||||
|
||||
#endif // _APPLICATION_H_
|
||||
|
||||
@@ -100,11 +100,11 @@ void AudioService::Start() {
|
||||
|
||||
#if CONFIG_USE_AUDIO_PROCESSOR
|
||||
/* Start the audio input task */
|
||||
xTaskCreate([](void* arg) {
|
||||
xTaskCreatePinnedToCore([](void* arg) {
|
||||
AudioService* audio_service = (AudioService*)arg;
|
||||
audio_service->AudioInputTask();
|
||||
vTaskDelete(NULL);
|
||||
}, "audio_input", 2048 * 3, this, 8, &audio_input_task_handle_);
|
||||
}, "audio_input", 2048 * 3, this, 8, &audio_input_task_handle_, 1);
|
||||
|
||||
/* Start the audio output task */
|
||||
xTaskCreate([](void* arg) {
|
||||
|
||||
@@ -519,13 +519,12 @@ private:
|
||||
|
||||
void InitializeSpi()
|
||||
{
|
||||
spi_bus_config_t bus_config = TAIJIPI_ST77916_PANEL_BUS_QSPI_CONFIG(QSPI_PIN_NUM_LCD_PCLK,
|
||||
QSPI_PIN_NUM_LCD_DATA0,
|
||||
QSPI_PIN_NUM_LCD_DATA1,
|
||||
QSPI_PIN_NUM_LCD_DATA2,
|
||||
QSPI_PIN_NUM_LCD_DATA3,
|
||||
QSPI_LCD_H_RES * 80 * sizeof(uint16_t));
|
||||
// bus_config.isr_cpu_id = ESP_INTR_CPU_AFFINITY_1;
|
||||
const spi_bus_config_t bus_config = TAIJIPI_ST77916_PANEL_BUS_QSPI_CONFIG(QSPI_PIN_NUM_LCD_PCLK,
|
||||
QSPI_PIN_NUM_LCD_DATA0,
|
||||
QSPI_PIN_NUM_LCD_DATA1,
|
||||
QSPI_PIN_NUM_LCD_DATA2,
|
||||
QSPI_PIN_NUM_LCD_DATA3,
|
||||
QSPI_LCD_H_RES * 80 * sizeof(uint16_t));
|
||||
ESP_ERROR_CHECK(spi_bus_initialize(QSPI_LCD_HOST, &bus_config, SPI_DMA_CH_AUTO));
|
||||
}
|
||||
|
||||
@@ -563,7 +562,11 @@ private:
|
||||
|
||||
#if USE_LVGL_DEFAULT
|
||||
display_ = new SpiLcdDisplay(panel_io, panel,
|
||||
DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY);
|
||||
DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY, {
|
||||
.text_font = &font_puhui_20_4,
|
||||
.icon_font = &font_awesome_20_4,
|
||||
.emoji_font = font_emoji_64_init(),
|
||||
});
|
||||
#else
|
||||
display_ = new anim::EmoteDisplay(panel, panel_io);
|
||||
#endif
|
||||
|
||||
@@ -111,8 +111,8 @@ static void InitializeGraphics(esp_lcd_panel_handle_t panel, gfx_handle_t* engin
|
||||
};
|
||||
|
||||
gfx_cfg.task.task_stack_caps = MALLOC_CAP_DEFAULT;
|
||||
gfx_cfg.task.task_affinity = 1;
|
||||
gfx_cfg.task.task_priority = 1;
|
||||
gfx_cfg.task.task_affinity = 0;
|
||||
gfx_cfg.task.task_priority = 5;
|
||||
gfx_cfg.task.task_stack = 20 * 1024;
|
||||
|
||||
*engine_handle = gfx_emote_init(&gfx_cfg);
|
||||
@@ -303,7 +303,6 @@ bool EmoteEngine::OnFlushIoReady(esp_lcd_panel_io_handle_t panel_io,
|
||||
esp_lcd_panel_io_event_data_t* edata,
|
||||
void* user_ctx)
|
||||
{
|
||||
gfx_emote_flush_ready(user_ctx, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -314,6 +313,7 @@ void EmoteEngine::OnFlush(gfx_handle_t handle, int x_start, int y_start,
|
||||
if (panel) {
|
||||
esp_lcd_panel_draw_bitmap(panel, x_start, y_start, x_end, y_end, color_data);
|
||||
}
|
||||
gfx_emote_flush_ready(handle, true);
|
||||
}
|
||||
|
||||
// EmoteDisplay implementation
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
|
||||
#define TAG "SURFERC3114TFT"
|
||||
|
||||
LV_FONT_DECLARE(font_puhui_20_4);
|
||||
LV_FONT_DECLARE(font_awesome_20_4);
|
||||
LV_FONT_DECLARE(font_puhui_16_4);
|
||||
LV_FONT_DECLARE(font_awesome_16_4);
|
||||
|
||||
class SurferC3114TFT : public WifiBoard {
|
||||
private:
|
||||
@@ -148,8 +148,8 @@ private:
|
||||
display_ = new SpiLcdDisplay(panel_io_, panel_,
|
||||
DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY,
|
||||
{
|
||||
.text_font = &font_puhui_20_4,
|
||||
.icon_font = &font_awesome_20_4,
|
||||
.text_font = &font_puhui_16_4,
|
||||
.icon_font = &font_awesome_16_4,
|
||||
.emoji_font = font_emoji_32_init(),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "lcd_display.h"
|
||||
|
||||
#include <vector>
|
||||
#include <font_awesome_symbols.h>
|
||||
#include <esp_log.h>
|
||||
#include <esp_err.h>
|
||||
#include <esp_lvgl_port.h>
|
||||
@@ -349,4 +350,4 @@ CustomLcdDisplay::CustomLcdDisplay(esp_lcd_panel_io_handle_t panel_io, esp_lcd_p
|
||||
}
|
||||
|
||||
SetupUI();
|
||||
}
|
||||
}
|
||||
@@ -117,9 +117,6 @@ SpiLcdDisplay::SpiLcdDisplay(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_h
|
||||
ESP_LOGI(TAG, "Initialize LVGL port");
|
||||
lvgl_port_cfg_t port_cfg = ESP_LVGL_PORT_INIT_CONFIG();
|
||||
port_cfg.task_priority = 1;
|
||||
#if CONFIG_SOC_CPU_CORES_NUM > 1
|
||||
port_cfg.task_affinity = 1;
|
||||
#endif
|
||||
lvgl_port_init(&port_cfg);
|
||||
|
||||
ESP_LOGI(TAG, "Adding LCD display");
|
||||
@@ -181,9 +178,7 @@ RgbLcdDisplay::RgbLcdDisplay(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_h
|
||||
ESP_LOGI(TAG, "Initialize LVGL port");
|
||||
lvgl_port_cfg_t port_cfg = ESP_LVGL_PORT_INIT_CONFIG();
|
||||
port_cfg.task_priority = 1;
|
||||
#if CONFIG_SOC_CPU_CORES_NUM > 1
|
||||
port_cfg.task_affinity = 1;
|
||||
#endif
|
||||
port_cfg.timer_period_ms = 50;
|
||||
lvgl_port_init(&port_cfg);
|
||||
|
||||
ESP_LOGI(TAG, "Adding LCD display");
|
||||
@@ -242,10 +237,6 @@ MipiLcdDisplay::MipiLcdDisplay(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel
|
||||
|
||||
ESP_LOGI(TAG, "Initialize LVGL port");
|
||||
lvgl_port_cfg_t port_cfg = ESP_LVGL_PORT_INIT_CONFIG();
|
||||
port_cfg.task_priority = 1;
|
||||
#if CONFIG_SOC_CPU_CORES_NUM > 1
|
||||
port_cfg.task_affinity = 1;
|
||||
#endif
|
||||
lvgl_port_init(&port_cfg);
|
||||
|
||||
ESP_LOGI(TAG, "Adding LCD display");
|
||||
|
||||
@@ -23,9 +23,6 @@ OledDisplay::OledDisplay(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_handl
|
||||
lvgl_port_cfg_t port_cfg = ESP_LVGL_PORT_INIT_CONFIG();
|
||||
port_cfg.task_priority = 1;
|
||||
port_cfg.task_stack = 6144;
|
||||
#if CONFIG_SOC_CPU_CORES_NUM > 1
|
||||
port_cfg.task_affinity = 1;
|
||||
#endif
|
||||
lvgl_port_init(&port_cfg);
|
||||
|
||||
ESP_LOGI(TAG, "Adding OLED display");
|
||||
|
||||
@@ -15,7 +15,7 @@ dependencies:
|
||||
78/esp_lcd_nv3023: ~1.0.0
|
||||
78/esp-wifi-connect: ~2.5.2
|
||||
78/esp-opus-encoder: ~2.4.1
|
||||
78/esp-ml307: ~3.3.5
|
||||
78/esp-ml307: ~3.3.1
|
||||
78/xiaozhi-fonts: ~1.5.2
|
||||
espressif/led_strip: ~3.0.1
|
||||
espressif/esp_codec_dev: ~1.4.0
|
||||
|
||||
@@ -27,4 +27,5 @@ extern "C" void app_main(void)
|
||||
// Launch the application
|
||||
auto& app = Application::GetInstance();
|
||||
app.Start();
|
||||
app.MainEventLoop();
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
#define TAG "MCP"
|
||||
|
||||
#define DEFAULT_TOOLCALL_STACK_SIZE 6144
|
||||
|
||||
McpServer::McpServer() {
|
||||
}
|
||||
|
||||
@@ -98,9 +100,6 @@ void McpServer::AddCommonTools() {
|
||||
Property("question", kPropertyTypeString)
|
||||
}),
|
||||
[camera](const PropertyList& properties) -> ReturnValue {
|
||||
// Lower the priority to do the camera capture
|
||||
TaskPriorityReset priority_reset(1);
|
||||
|
||||
if (!camera->Capture()) {
|
||||
return "{\"success\": false, \"message\": \"Failed to capture photo\"}";
|
||||
}
|
||||
@@ -236,7 +235,13 @@ void McpServer::ParseMessage(const cJSON* json) {
|
||||
ReplyError(id_int, "Invalid arguments");
|
||||
return;
|
||||
}
|
||||
DoToolCall(id_int, std::string(tool_name->valuestring), tool_arguments);
|
||||
auto stack_size = cJSON_GetObjectItem(params, "stackSize");
|
||||
if (stack_size != nullptr && !cJSON_IsNumber(stack_size)) {
|
||||
ESP_LOGE(TAG, "tools/call: Invalid stackSize");
|
||||
ReplyError(id_int, "Invalid stackSize");
|
||||
return;
|
||||
}
|
||||
DoToolCall(id_int, std::string(tool_name->valuestring), tool_arguments, stack_size ? stack_size->valueint : DEFAULT_TOOLCALL_STACK_SIZE);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Method not implemented: %s", method_str.c_str());
|
||||
ReplyError(id_int, "Method not implemented: " + method_str);
|
||||
@@ -311,7 +316,7 @@ void McpServer::GetToolsList(int id, const std::string& cursor) {
|
||||
ReplyResult(id, json);
|
||||
}
|
||||
|
||||
void McpServer::DoToolCall(int id, const std::string& tool_name, const cJSON* tool_arguments) {
|
||||
void McpServer::DoToolCall(int id, const std::string& tool_name, const cJSON* tool_arguments, int stack_size) {
|
||||
auto tool_iter = std::find_if(tools_.begin(), tools_.end(),
|
||||
[&tool_name](const McpTool* tool) {
|
||||
return tool->name() == tool_name;
|
||||
@@ -353,9 +358,15 @@ void McpServer::DoToolCall(int id, const std::string& tool_name, const cJSON* to
|
||||
return;
|
||||
}
|
||||
|
||||
// Use main thread to call the tool
|
||||
auto& app = Application::GetInstance();
|
||||
app.Schedule([this, id, tool_iter, arguments = std::move(arguments)]() {
|
||||
// Start a task to receive data with stack size
|
||||
esp_pthread_cfg_t cfg = esp_pthread_get_default_config();
|
||||
cfg.thread_name = "tool_call";
|
||||
cfg.stack_size = stack_size;
|
||||
cfg.prio = 1;
|
||||
esp_pthread_set_cfg(&cfg);
|
||||
|
||||
// Use a thread to call the tool to avoid blocking the main thread
|
||||
tool_call_thread_ = std::thread([this, id, tool_iter, arguments = std::move(arguments)]() {
|
||||
try {
|
||||
ReplyResult(id, (*tool_iter)->Call(arguments));
|
||||
} catch (const std::exception& e) {
|
||||
@@ -363,4 +374,5 @@ void McpServer::DoToolCall(int id, const std::string& tool_name, const cJSON* to
|
||||
ReplyError(id, e.what());
|
||||
}
|
||||
});
|
||||
tool_call_thread_.detach();
|
||||
}
|
||||
@@ -285,9 +285,10 @@ private:
|
||||
void ReplyError(int id, const std::string& message);
|
||||
|
||||
void GetToolsList(int id, const std::string& cursor);
|
||||
void DoToolCall(int id, const std::string& tool_name, const cJSON* tool_arguments);
|
||||
void DoToolCall(int id, const std::string& tool_name, const cJSON* tool_arguments, int stack_size);
|
||||
|
||||
std::vector<McpTool*> tools_;
|
||||
std::thread tool_call_thread_;
|
||||
};
|
||||
|
||||
#endif // MCP_SERVER_H
|
||||
|
||||
@@ -51,9 +51,11 @@ std::string Ota::GetCheckVersionUrl() {
|
||||
|
||||
std::unique_ptr<Http> Ota::SetupHttp() {
|
||||
auto& board = Board::GetInstance();
|
||||
auto app_desc = esp_app_get_description();
|
||||
|
||||
auto network = board.GetNetwork();
|
||||
auto http = network->CreateHttp(0);
|
||||
auto user_agent = SystemInfo::GetUserAgent();
|
||||
auto user_agent = std::string(BOARD_NAME "/") + app_desc->version;
|
||||
http->SetHeader("Activation-Version", has_serial_number_ ? "2" : "1");
|
||||
http->SetHeader("Device-Id", SystemInfo::GetMacAddress().c_str());
|
||||
http->SetHeader("Client-Id", board.GetUuid());
|
||||
|
||||
@@ -47,12 +47,6 @@ std::string SystemInfo::GetChipModelName() {
|
||||
return std::string(CONFIG_IDF_TARGET);
|
||||
}
|
||||
|
||||
std::string SystemInfo::GetUserAgent() {
|
||||
auto app_desc = esp_app_get_description();
|
||||
auto user_agent = std::string(BOARD_NAME "/") + app_desc->version;
|
||||
return user_agent;
|
||||
}
|
||||
|
||||
esp_err_t SystemInfo::PrintTaskCpuUsage(TickType_t xTicksToWait) {
|
||||
#define ARRAY_SIZE_OFFSET 5
|
||||
TaskStatus_t *start_array = NULL, *end_array = NULL;
|
||||
|
||||
@@ -13,7 +13,6 @@ public:
|
||||
static size_t GetFreeHeapSize();
|
||||
static std::string GetMacAddress();
|
||||
static std::string GetChipModelName();
|
||||
static std::string GetUserAgent();
|
||||
static esp_err_t PrintTaskCpuUsage(TickType_t xTicksToWait);
|
||||
static void PrintTaskList();
|
||||
static void PrintHeapStats();
|
||||
|
||||
@@ -54,6 +54,7 @@ CONFIG_LV_USE_IMGFONT=y
|
||||
CONFIG_LV_USE_ASSERT_STYLE=y
|
||||
CONFIG_LV_USE_GIF=y
|
||||
CONFIG_LV_USE_LODEPNG=y
|
||||
CONFIG_LV_USE_TJPGD=y
|
||||
|
||||
# Use compressed font
|
||||
CONFIG_LV_FONT_FMT_TXT_LARGE=y
|
||||
|
||||
Reference in New Issue
Block a user