diff --git a/main/boards/common/power_save_timer.cc b/main/boards/common/power_save_timer.cc index f17afbe0..522e64c5 100644 --- a/main/boards/common/power_save_timer.cc +++ b/main/boards/common/power_save_timer.cc @@ -1,5 +1,6 @@ #include "power_save_timer.h" #include "application.h" +#include "settings.h" #include @@ -28,6 +29,12 @@ PowerSaveTimer::~PowerSaveTimer() { void PowerSaveTimer::SetEnabled(bool enabled) { if (enabled && !enabled_) { + Settings settings("wifi", false); + if (!settings.GetBool("sleep_mode", true)) { + ESP_LOGI(TAG, "Power save timer is disabled by settings"); + return; + } + ticks_ = 0; enabled_ = enabled; ESP_ERROR_CHECK(esp_timer_start_periodic(power_save_timer_, 1000000)); diff --git a/main/boards/common/press_to_talk_mcp_tool.cc b/main/boards/common/press_to_talk_mcp_tool.cc new file mode 100644 index 00000000..d6b0bc96 --- /dev/null +++ b/main/boards/common/press_to_talk_mcp_tool.cc @@ -0,0 +1,57 @@ +#include "press_to_talk_mcp_tool.h" +#include + +static const char* TAG = "PressToTalkMcpTool"; + +PressToTalkMcpTool::PressToTalkMcpTool() + : press_to_talk_enabled_(false) { +} + +void PressToTalkMcpTool::Initialize() { + // 从设置中读取当前状态 + Settings settings("vendor"); + press_to_talk_enabled_ = settings.GetInt("press_to_talk", 0) != 0; + + // 注册MCP工具 + auto& mcp_server = McpServer::GetInstance(); + mcp_server.AddTool("self.set_press_to_talk", + "Switch between press to talk mode (长按说话) and click to talk mode (单击说话).\n" + "The mode can be `press_to_talk` or `click_to_talk`.", + PropertyList({ + Property("mode", kPropertyTypeString) + }), + [this](const PropertyList& properties) -> ReturnValue { + return HandleSetPressToTalk(properties); + }); + + ESP_LOGI(TAG, "PressToTalkMcpTool initialized, current mode: %s", + press_to_talk_enabled_ ? "press_to_talk" : "click_to_talk"); +} + +bool PressToTalkMcpTool::IsPressToTalkEnabled() const { + return press_to_talk_enabled_; +} + +ReturnValue PressToTalkMcpTool::HandleSetPressToTalk(const PropertyList& properties) { + auto mode = properties["mode"].value(); + + if (mode == "press_to_talk") { + SetPressToTalkEnabled(true); + ESP_LOGI(TAG, "Switched to press to talk mode"); + return true; + } else if (mode == "click_to_talk") { + SetPressToTalkEnabled(false); + ESP_LOGI(TAG, "Switched to click to talk mode"); + return true; + } + + throw std::runtime_error("Invalid mode: " + mode); +} + +void PressToTalkMcpTool::SetPressToTalkEnabled(bool enabled) { + press_to_talk_enabled_ = enabled; + + Settings settings("vendor", true); + settings.SetInt("press_to_talk", enabled ? 1 : 0); + ESP_LOGI(TAG, "Press to talk enabled: %d", enabled); +} \ No newline at end of file diff --git a/main/boards/common/press_to_talk_mcp_tool.h b/main/boards/common/press_to_talk_mcp_tool.h new file mode 100644 index 00000000..3231a286 --- /dev/null +++ b/main/boards/common/press_to_talk_mcp_tool.h @@ -0,0 +1,29 @@ +#ifndef PRESS_TO_TALK_MCP_TOOL_H +#define PRESS_TO_TALK_MCP_TOOL_H + +#include "mcp_server.h" +#include "settings.h" + +// 可复用的按键说话模式MCP工具类 +class PressToTalkMcpTool { +private: + bool press_to_talk_enabled_; + +public: + PressToTalkMcpTool(); + + // 初始化工具,注册到MCP服务器 + void Initialize(); + + // 获取当前按键说话模式状态 + bool IsPressToTalkEnabled() const; + +private: + // MCP工具的回调函数 + ReturnValue HandleSetPressToTalk(const PropertyList& properties); + + // 内部方法:设置press to talk状态并保存到设置 + void SetPressToTalkEnabled(bool enabled); +}; + +#endif // PRESS_TO_TALK_MCP_TOOL_H \ No newline at end of file diff --git a/main/boards/common/sleep_timer.cc b/main/boards/common/sleep_timer.cc index f4f3d08d..3490f6ce 100644 --- a/main/boards/common/sleep_timer.cc +++ b/main/boards/common/sleep_timer.cc @@ -2,6 +2,7 @@ #include "application.h" #include "board.h" #include "display.h" +#include "settings.h" #include #include @@ -32,6 +33,12 @@ SleepTimer::~SleepTimer() { void SleepTimer::SetEnabled(bool enabled) { if (enabled && !enabled_) { + Settings settings("wifi", false); + if (!settings.GetBool("sleep_mode", true)) { + ESP_LOGI(TAG, "Power save timer is disabled by settings"); + return; + } + ticks_ = 0; enabled_ = enabled; ESP_ERROR_CHECK(esp_timer_start_periodic(sleep_timer_, 1000000)); diff --git a/main/boards/xmini-c3-4g/xmini_c3_4g_board.cc b/main/boards/xmini-c3-4g/xmini_c3_4g_board.cc index 8c3bc733..3e260b07 100644 --- a/main/boards/xmini-c3-4g/xmini_c3_4g_board.cc +++ b/main/boards/xmini-c3-4g/xmini_c3_4g_board.cc @@ -10,6 +10,7 @@ #include "sleep_timer.h" #include "font_awesome_symbols.h" #include "adc_battery_monitor.h" +#include "press_to_talk_mcp_tool.h" #include #include @@ -31,9 +32,9 @@ private: esp_lcd_panel_handle_t panel_ = nullptr; Display* display_ = nullptr; Button boot_button_; - bool press_to_talk_enabled_ = false; SleepTimer* sleep_timer_ = nullptr; AdcBatteryMonitor* adc_battery_monitor_ = nullptr; + PressToTalkMcpTool* press_to_talk_tool_ = nullptr; void InitializeBatteryMonitor() { adc_battery_monitor_ = new AdcBatteryMonitor(ADC_UNIT_1, ADC_CHANNEL_4, 100000, 100000, GPIO_NUM_12); @@ -145,44 +146,25 @@ private: void InitializeButtons() { boot_button_.OnClick([this]() { auto& app = Application::GetInstance(); - if (!press_to_talk_enabled_) { + if (!press_to_talk_tool_ || !press_to_talk_tool_->IsPressToTalkEnabled()) { app.ToggleChatState(); } }); boot_button_.OnPressDown([this]() { - if (press_to_talk_enabled_) { + if (press_to_talk_tool_ && press_to_talk_tool_->IsPressToTalkEnabled()) { Application::GetInstance().StartListening(); } }); boot_button_.OnPressUp([this]() { - if (press_to_talk_enabled_) { + if (press_to_talk_tool_ && press_to_talk_tool_->IsPressToTalkEnabled()) { Application::GetInstance().StopListening(); } }); } void InitializeTools() { - Settings settings("vendor"); - press_to_talk_enabled_ = settings.GetInt("press_to_talk", 0) != 0; - - auto& mcp_server = McpServer::GetInstance(); - mcp_server.AddTool("self.set_press_to_talk", - "Switch between press to talk mode (长按说话) and click to talk mode (单击说话).\n" - "The mode can be `press_to_talk` or `click_to_talk`.", - PropertyList({ - Property("mode", kPropertyTypeString) - }), - [this](const PropertyList& properties) -> ReturnValue { - auto mode = properties["mode"].value(); - if (mode == "press_to_talk") { - SetPressToTalkEnabled(true); - return true; - } else if (mode == "click_to_talk") { - SetPressToTalkEnabled(false); - return true; - } - throw std::runtime_error("Invalid mode: " + mode); - }); + press_to_talk_tool_ = new PressToTalkMcpTool(); + press_to_talk_tool_->Initialize(); } public: @@ -220,18 +202,6 @@ public: return true; } - void SetPressToTalkEnabled(bool enabled) { - press_to_talk_enabled_ = enabled; - - Settings settings("vendor", true); - settings.SetInt("press_to_talk", enabled ? 1 : 0); - ESP_LOGI(TAG, "Press to talk enabled: %d", enabled); - } - - bool IsPressToTalkEnabled() { - return press_to_talk_enabled_; - } - virtual void SetPowerSaveMode(bool enabled) override { if (!enabled) { sleep_timer_->WakeUp(); diff --git a/main/boards/xmini-c3-v3/xmini_c3_board.cc b/main/boards/xmini-c3-v3/xmini_c3_board.cc index 0814e3f0..07a5fc7a 100644 --- a/main/boards/xmini-c3-v3/xmini_c3_board.cc +++ b/main/boards/xmini-c3-v3/xmini_c3_board.cc @@ -10,6 +10,7 @@ #include "power_save_timer.h" #include "font_awesome_symbols.h" #include "adc_battery_monitor.h" +#include "press_to_talk_mcp_tool.h" #include #include @@ -31,9 +32,9 @@ private: esp_lcd_panel_handle_t panel_ = nullptr; Display* display_ = nullptr; Button boot_button_; - bool press_to_talk_enabled_ = false; PowerSaveTimer* power_save_timer_ = nullptr; AdcBatteryMonitor* adc_battery_monitor_ = nullptr; + PressToTalkMcpTool* press_to_talk_tool_ = nullptr; void InitializePowerManager() { adc_battery_monitor_ = new AdcBatteryMonitor(ADC_UNIT_1, ADC_CHANNEL_3, 100000, 100000, GPIO_NUM_12); @@ -140,7 +141,7 @@ private: if (app.GetDeviceState() == kDeviceStateStarting && !WifiStation::GetInstance().IsConnected()) { ResetWifiConfiguration(); } - if (!press_to_talk_enabled_) { + if (!press_to_talk_tool_ || !press_to_talk_tool_->IsPressToTalkEnabled()) { app.ToggleChatState(); } }); @@ -148,39 +149,20 @@ private: if (power_save_timer_) { power_save_timer_->WakeUp(); } - if (press_to_talk_enabled_) { + if (press_to_talk_tool_ && press_to_talk_tool_->IsPressToTalkEnabled()) { Application::GetInstance().StartListening(); } }); boot_button_.OnPressUp([this]() { - if (press_to_talk_enabled_) { + if (press_to_talk_tool_ && press_to_talk_tool_->IsPressToTalkEnabled()) { Application::GetInstance().StopListening(); } }); } void InitializeTools() { - Settings settings("vendor"); - press_to_talk_enabled_ = settings.GetInt("press_to_talk", 0) != 0; - - auto& mcp_server = McpServer::GetInstance(); - mcp_server.AddTool("self.set_press_to_talk", - "Switch between press to talk mode (长按说话) and click to talk mode (单击说话).\n" - "The mode can be `press_to_talk` or `click_to_talk`.", - PropertyList({ - Property("mode", kPropertyTypeString) - }), - [this](const PropertyList& properties) -> ReturnValue { - auto mode = properties["mode"].value(); - if (mode == "press_to_talk") { - SetPressToTalkEnabled(true); - return true; - } else if (mode == "click_to_talk") { - SetPressToTalkEnabled(false); - return true; - } - throw std::runtime_error("Invalid mode: " + mode); - }); + press_to_talk_tool_ = new PressToTalkMcpTool(); + press_to_talk_tool_->Initialize(); } public: @@ -216,18 +198,6 @@ public: return true; } - void SetPressToTalkEnabled(bool enabled) { - press_to_talk_enabled_ = enabled; - - Settings settings("vendor", true); - settings.SetInt("press_to_talk", enabled ? 1 : 0); - ESP_LOGI(TAG, "Press to talk enabled: %d", enabled); - } - - bool IsPressToTalkEnabled() { - return press_to_talk_enabled_; - } - virtual void SetPowerSaveMode(bool enabled) override { if (!enabled) { power_save_timer_->WakeUp(); diff --git a/main/boards/xmini-c3/xmini_c3_board.cc b/main/boards/xmini-c3/xmini_c3_board.cc index add3e67c..20a6e323 100644 --- a/main/boards/xmini-c3/xmini_c3_board.cc +++ b/main/boards/xmini-c3/xmini_c3_board.cc @@ -9,6 +9,7 @@ #include "config.h" #include "power_save_timer.h" #include "font_awesome_symbols.h" +#include "press_to_talk_mcp_tool.h" #include #include @@ -29,8 +30,8 @@ private: esp_lcd_panel_handle_t panel_ = nullptr; Display* display_ = nullptr; Button boot_button_; - bool press_to_talk_enabled_ = false; PowerSaveTimer* power_save_timer_ = nullptr; + PressToTalkMcpTool* press_to_talk_tool_ = nullptr; void InitializePowerSaveTimer() { #if CONFIG_USE_ESP_WAKE_WORD @@ -126,7 +127,7 @@ private: if (app.GetDeviceState() == kDeviceStateStarting && !WifiStation::GetInstance().IsConnected()) { ResetWifiConfiguration(); } - if (!press_to_talk_enabled_) { + if (!press_to_talk_tool_ || !press_to_talk_tool_->IsPressToTalkEnabled()) { app.ToggleChatState(); } }); @@ -134,39 +135,20 @@ private: if (power_save_timer_) { power_save_timer_->WakeUp(); } - if (press_to_talk_enabled_) { + if (press_to_talk_tool_ && press_to_talk_tool_->IsPressToTalkEnabled()) { Application::GetInstance().StartListening(); } }); boot_button_.OnPressUp([this]() { - if (press_to_talk_enabled_) { + if (press_to_talk_tool_ && press_to_talk_tool_->IsPressToTalkEnabled()) { Application::GetInstance().StopListening(); } }); } void InitializeTools() { - Settings settings("vendor"); - press_to_talk_enabled_ = settings.GetInt("press_to_talk", 0) != 0; - - auto& mcp_server = McpServer::GetInstance(); - mcp_server.AddTool("self.set_press_to_talk", - "Switch between press to talk mode (长按说话) and click to talk mode (单击说话).\n" - "The mode can be `press_to_talk` or `click_to_talk`.", - PropertyList({ - Property("mode", kPropertyTypeString) - }), - [this](const PropertyList& properties) -> ReturnValue { - auto mode = properties["mode"].value(); - if (mode == "press_to_talk") { - SetPressToTalkEnabled(true); - return true; - } else if (mode == "click_to_talk") { - SetPressToTalkEnabled(false); - return true; - } - throw std::runtime_error("Invalid mode: " + mode); - }); + press_to_talk_tool_ = new PressToTalkMcpTool(); + press_to_talk_tool_->Initialize(); } public: @@ -198,16 +180,11 @@ public: return &audio_codec; } - void SetPressToTalkEnabled(bool enabled) { - press_to_talk_enabled_ = enabled; - - Settings settings("vendor", true); - settings.SetInt("press_to_talk", enabled ? 1 : 0); - ESP_LOGI(TAG, "Press to talk enabled: %d", enabled); - } - - bool IsPressToTalkEnabled() { - return press_to_talk_enabled_; + virtual void SetPowerSaveMode(bool enabled) override { + if (!enabled) { + power_save_timer_->WakeUp(); + } + WifiBoard::SetPowerSaveMode(enabled); } }; diff --git a/main/settings.cc b/main/settings.cc index 751a5f46..3b40622b 100644 --- a/main/settings.cc +++ b/main/settings.cc @@ -67,6 +67,27 @@ void Settings::SetInt(const std::string& key, int32_t value) { } } +bool Settings::GetBool(const std::string& key, bool default_value) { + if (nvs_handle_ == 0) { + return default_value; + } + + uint8_t value; + if (nvs_get_u8(nvs_handle_, key.c_str(), &value) != ESP_OK) { + return default_value; + } + return value != 0; +} + +void Settings::SetBool(const std::string& key, bool value) { + if (read_write_) { + ESP_ERROR_CHECK(nvs_set_u8(nvs_handle_, key.c_str(), value ? 1 : 0)); + dirty_ = true; + } else { + ESP_LOGW(TAG, "Namespace %s is not open for writing", ns_.c_str()); + } +} + void Settings::EraseKey(const std::string& key) { if (read_write_) { auto ret = nvs_erase_key(nvs_handle_, key.c_str()); diff --git a/main/settings.h b/main/settings.h index 0fe13885..7eb596ec 100644 --- a/main/settings.h +++ b/main/settings.h @@ -13,6 +13,8 @@ public: void SetString(const std::string& key, const std::string& value); int32_t GetInt(const std::string& key, int32_t default_value = 0); void SetInt(const std::string& key, int32_t value); + bool GetBool(const std::string& key, bool default_value = false); + void SetBool(const std::string& key, bool value); void EraseKey(const std::string& key); void EraseAll();