From 3655fc89d28de9a0a9ed2be3eaec9ded3026accb Mon Sep 17 00:00:00 2001 From: Terrence Date: Sun, 12 Jan 2025 10:25:43 +0800 Subject: [PATCH] wifi connect version 2 --- CMakeLists.txt | 2 +- flash.sh | 2 +- main/application.cc | 3 +- main/boards/common/wifi_board.cc | 105 ++++++++++++++++++++++--------- main/boards/common/wifi_board.h | 2 + main/display/display.cc | 2 + main/idf_component.yml | 4 +- main/settings.cc | 8 ++- 8 files changed, 91 insertions(+), 37 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5536104d..9300c1cc 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ # CMakeLists in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.16) -set(PROJECT_VER "0.9.8") +set(PROJECT_VER "0.9.9") include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(xiaozhi) diff --git a/flash.sh b/flash.sh index 2b4c2098..354b8492 100755 --- a/flash.sh +++ b/flash.sh @@ -1,2 +1,2 @@ #!/bin/sh -esptool.py -p /dev/ttyACM0 -b 2000000 write_flash 0 releases/v0.6.2_ML307/merged-binary.bin +esptool.py -p /dev/ttyACM0 -b 2000000 write_flash 0 releases/v0.9.9_bread-compact-wifi/merged-binary.bin diff --git a/main/application.cc b/main/application.cc index 876d5741..580004b3 100644 --- a/main/application.cc +++ b/main/application.cc @@ -324,6 +324,8 @@ void Application::Start() { protocol_->OnAudioChannelClosed([this, &board]() { board.SetPowerSaveMode(true); Schedule([this]() { + auto display = Board::GetInstance().GetDisplay(); + display->SetChatMessage("", ""); SetDeviceState(kDeviceStateIdle); }); }); @@ -548,7 +550,6 @@ void Application::SetDeviceState(DeviceState state) { case kDeviceStateIdle: display->SetStatus("待命"); display->SetEmotion("neutral"); - display->SetChatMessage("", ""); #ifdef CONFIG_IDF_TARGET_ESP32S3 audio_processor_.Stop(); #endif diff --git a/main/boards/common/wifi_board.cc b/main/boards/common/wifi_board.cc index cee969e5..9d5105da 100644 --- a/main/boards/common/wifi_board.cc +++ b/main/boards/common/wifi_board.cc @@ -18,6 +18,7 @@ #include #include +#include static const char *TAG = "WifiBoard"; @@ -35,39 +36,81 @@ static std::string rssi_to_string(int rssi) { } } -void WifiBoard::StartNetwork() { +WifiBoard::WifiBoard() { + Settings settings("wifi", true); + wifi_config_mode_ = settings.GetInt("force_ap") == 1; + if (wifi_config_mode_) { + ESP_LOGI(TAG, "force_ap is set to 1, reset to 0"); + settings.SetInt("force_ap", 0); + } +} + +void WifiBoard::EnterWifiConfigMode() { auto& application = Application::GetInstance(); auto display = Board::GetInstance().GetDisplay(); + application.SetDeviceState(kDeviceStateWifiConfiguring); + + auto& wifi_ap = WifiConfigurationAp::GetInstance(); + wifi_ap.SetSsidPrefix("Xiaozhi"); + wifi_ap.Start(); + + // 播报配置 WiFi 的提示 + application.Alert("Info", "Configuring WiFi"); + + // 显示 WiFi 配置 AP 的 SSID 和 Web 服务器 URL + std::string hint = "请在手机上连接热点 "; + hint += wifi_ap.GetSsid(); + hint += ",然后打开浏览器访问 "; + hint += wifi_ap.GetWebServerUrl(); + + display->SetStatus(hint); + + // Wait forever until reset after configuration + while (true) { + int free_sram = heap_caps_get_free_size(MALLOC_CAP_INTERNAL); + int min_free_sram = heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL); + ESP_LOGI(TAG, "Free internal: %u minimal internal: %u", free_sram, min_free_sram); + vTaskDelay(pdMS_TO_TICKS(10000)); + } +} + +void WifiBoard::StartNetwork() { + // User can press BOOT button while starting to enter WiFi configuration mode + if (wifi_config_mode_) { + EnterWifiConfigMode(); + return; + } + + // If no WiFi SSID is configured, enter WiFi configuration mode + auto& ssid_manager = SsidManager::GetInstance(); + auto ssid_list = ssid_manager.GetSsidList(); + if (ssid_list.empty()) { + wifi_config_mode_ = true; + EnterWifiConfigMode(); + return; + } + + auto& wifi_station = WifiStation::GetInstance(); + wifi_station.OnScanBegin([this]() { + auto display = Board::GetInstance().GetDisplay(); + display->ShowNotification("正在扫描 WiFi 网络", 30000); + }); + wifi_station.OnConnect([this](const std::string& ssid) { + auto display = Board::GetInstance().GetDisplay(); + display->ShowNotification(std::string("正在连接 ") + ssid, 30000); + }); + wifi_station.OnConnected([this](const std::string& ssid) { + auto display = Board::GetInstance().GetDisplay(); + display->ShowNotification(std::string("已连接 ") + ssid); + }); + wifi_station.Start(); // Try to connect to WiFi, if failed, launch the WiFi configuration AP - auto& wifi_station = WifiStation::GetInstance(); - display->SetStatus(std::string("正在连接 ") + wifi_station.GetSsid()); - wifi_station.Start(); - if (!wifi_station.IsConnected()) { - application.SetDeviceState(kDeviceStateWifiConfiguring); - - auto& wifi_ap = WifiConfigurationAp::GetInstance(); - wifi_ap.SetSsidPrefix("Xiaozhi"); - wifi_ap.Start(); - - // 播报配置 WiFi 的提示 - application.Alert("Info", "Configuring WiFi"); - - // 显示 WiFi 配置 AP 的 SSID 和 Web 服务器 URL - std::string hint = "请在手机上连接热点 "; - hint += wifi_ap.GetSsid(); - hint += ",然后打开浏览器访问 "; - hint += wifi_ap.GetWebServerUrl(); - - display->SetStatus(hint); - - // Wait forever until reset after configuration - while (true) { - int free_sram = heap_caps_get_free_size(MALLOC_CAP_INTERNAL); - int min_free_sram = heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL); - ESP_LOGI(TAG, "Free internal: %u minimal internal: %u", free_sram, min_free_sram); - vTaskDelay(pdMS_TO_TICKS(10000)); - } + if (!wifi_station.WaitForConnected(60 * 1000)) { + wifi_station.Stop(); + wifi_config_mode_ = true; + EnterWifiConfigMode(); + return; } } @@ -155,9 +198,9 @@ void WifiBoard::ResetWifiConfiguration() { // Reset the wifi station { Settings settings("wifi", true); - settings.EraseAll(); + settings.SetInt("force_ap", 1); } - GetDisplay()->ShowNotification("已重置 WiFi..."); + GetDisplay()->ShowNotification("进入配网模式..."); vTaskDelay(pdMS_TO_TICKS(1000)); // Reboot the device esp_restart(); diff --git a/main/boards/common/wifi_board.h b/main/boards/common/wifi_board.h index c16e7ef4..3327e2b9 100644 --- a/main/boards/common/wifi_board.h +++ b/main/boards/common/wifi_board.h @@ -7,6 +7,8 @@ class WifiBoard : public Board { protected: bool wifi_config_mode_ = false; + WifiBoard(); + void EnterWifiConfigMode(); virtual std::string GetBoardJson() override; public: diff --git a/main/display/display.cc b/main/display/display.cc index 50f5190a..0b55ff1c 100644 --- a/main/display/display.cc +++ b/main/display/display.cc @@ -63,6 +63,8 @@ void Display::SetStatus(const std::string &status) { } DisplayLockGuard lock(this); lv_label_set_text(status_label_, status.c_str()); + lv_obj_clear_flag(status_label_, LV_OBJ_FLAG_HIDDEN); + lv_obj_add_flag(notification_label_, LV_OBJ_FLAG_HIDDEN); } void Display::ShowNotification(const std::string ¬ification, int duration_ms) { diff --git a/main/idf_component.yml b/main/idf_component.yml index 6b07d0cb..e42932ee 100644 --- a/main/idf_component.yml +++ b/main/idf_component.yml @@ -2,9 +2,9 @@ dependencies: espressif/esp_lcd_ili9341: "==1.2.0" 78/esp_lcd_nv3023: "~1.0.0" - 78/esp-wifi-connect: "~1.4.1" + 78/esp-wifi-connect: "~2.0.1" 78/esp-opus-encoder: "~2.0.0" - 78/esp-ml307: "~1.7.0" + 78/esp-ml307: "~1.7.1" espressif/led_strip: "^2.4.1" espressif/esp_codec_dev: "~1.3.2" espressif/esp-sr: "^1.9.0" diff --git a/main/settings.cc b/main/settings.cc index fb63f477..b617b3c5 100644 --- a/main/settings.cc +++ b/main/settings.cc @@ -31,6 +31,9 @@ std::string Settings::GetString(const std::string& key, const std::string& defau std::string value; value.resize(length); ESP_ERROR_CHECK(nvs_get_str(nvs_handle_, key.c_str(), value.data(), &length)); + while (value.back() == '\0') { + value.pop_back(); + } return value; } @@ -66,7 +69,10 @@ void Settings::SetInt(const std::string& key, int32_t value) { void Settings::EraseKey(const std::string& key) { if (read_write_) { - ESP_ERROR_CHECK(nvs_erase_key(nvs_handle_, key.c_str())); + auto ret = nvs_erase_key(nvs_handle_, key.c_str()); + if (ret != ESP_ERR_NVS_NOT_FOUND) { + ESP_ERROR_CHECK(ret); + } } else { ESP_LOGW(TAG, "Namespace %s is not open for writing", ns_.c_str()); }