#include "wifi_board.h" #include "display.h" #include "application.h" #include "system_info.h" #include "font_awesome_symbols.h" #include "settings.h" #include "assets/lang_config.h" #include #include #include #include #include #include #include "ssid_manager_c.h" #include "afsk_demod.h" #include "blufi.h" static const char *TAG = "WifiBoard"; 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); } } std::string WifiBoard::GetBoardType() { return "wifi"; } void WifiBoard::EnterWifiConfigMode() { auto& application = Application::GetInstance(); application.SetDeviceState(kDeviceStateWifiConfiguring); blufi_entry_func(); #if 0 auto& wifi_ap = WifiConfigurationAp::GetInstance(); wifi_ap.SetLanguage(Lang::CODE); wifi_ap.SetSsidPrefix("Xiaozhi"); wifi_ap.Start(); // 显示 WiFi 配置 AP 的 SSID 和 Web 服务器 URL std::string hint = Lang::Strings::CONNECT_TO_HOTSPOT; hint += wifi_ap.GetSsid(); hint += Lang::Strings::ACCESS_VIA_BROWSER; hint += wifi_ap.GetWebServerUrl(); hint += "\n\n"; #endif // 播报配置 WiFi 的提示 application.Alert(Lang::Strings::WIFI_CONFIG_MODE, "blufi", "", Lang::Sounds::P3_WIFICONFIG); #if CONFIG_USE_ACOUSTIC_WIFI_PROVISIONING audio_wifi_config::ReceiveWifiCredentialsFromAudio(&application, &wifi_ap); #endif // 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 // 创建SSID管理器实例并检查SSID列表 SsidManager* ssid_manager = ssid_manager_create(); if (ssid_manager == NULL) { ESP_LOGE(TAG, "Failed to create SSID manager"); } // 获取SSID数量 int ssid_count = ssid_manager_get_count(ssid_manager); if (ssid_count == 0) { wifi_config_mode_ = true; EnterWifiConfigMode(); // 释放管理器资源 ssid_manager_destroy(ssid_manager); return; } // 使用SSID列表... for (int i = 0; i < ssid_count; i++) { const char* ssid = ssid_manager_get_ssid(ssid_manager, i); const char* password = ssid_manager_get_password(ssid_manager, i); ESP_LOGI(TAG, "SSID %d: %s, Password: %s", i, ssid, password); } // 使用完成后释放资源 ssid_manager_destroy(ssid_manager); auto& wifi_station = WifiStation::GetInstance(); wifi_station.OnScanBegin([this]() { auto display = Board::GetInstance().GetDisplay(); display->ShowNotification(Lang::Strings::SCANNING_WIFI, 30000); }); wifi_station.OnConnect([this](const std::string& ssid) { auto display = Board::GetInstance().GetDisplay(); std::string notification = Lang::Strings::CONNECT_TO; notification += ssid; notification += "..."; display->ShowNotification(notification.c_str(), 30000); }); wifi_station.OnConnected([this](const std::string& ssid) { auto display = Board::GetInstance().GetDisplay(); std::string notification = Lang::Strings::CONNECTED_TO; notification += ssid; display->ShowNotification(notification.c_str(), 30000); }); wifi_station.Start(); // Try to connect to WiFi, if failed, launch the WiFi configuration AP if (!wifi_station.WaitForConnected(60 * 1000)) { wifi_station.Stop(); wifi_config_mode_ = true; EnterWifiConfigMode(); return; } Board::GetInstance().internetConnet=1; } NetworkInterface* WifiBoard::GetNetwork() { static EspNetwork network; return &network; } const char* WifiBoard::GetNetworkStateIcon() { if (wifi_config_mode_) { return FONT_AWESOME_WIFI; } auto& wifi_station = WifiStation::GetInstance(); if (!wifi_station.IsConnected()) { return FONT_AWESOME_WIFI_OFF; } int8_t rssi = wifi_station.GetRssi(); if (rssi >= -60) { return FONT_AWESOME_WIFI; } else if (rssi >= -70) { return FONT_AWESOME_WIFI_FAIR; } else { return FONT_AWESOME_WIFI_WEAK; } } std::string WifiBoard::GetBoardJson() { // Set the board type for OTA auto& wifi_station = WifiStation::GetInstance(); std::string board_json = R"({)"; board_json += R"("type":")" + std::string(BOARD_TYPE) + R"(",)"; board_json += R"("name":")" + std::string(BOARD_NAME) + R"(",)"; if (!wifi_config_mode_) { board_json += R"("ssid":")" + wifi_station.GetSsid() + R"(",)"; board_json += R"("rssi":)" + std::to_string(wifi_station.GetRssi()) + R"(,)"; board_json += R"("channel":)" + std::to_string(wifi_station.GetChannel()) + R"(,)"; board_json += R"("ip":")" + wifi_station.GetIpAddress() + R"(",)"; } board_json += R"("mac":")" + SystemInfo::GetMacAddress() + R"(")"; board_json += R"(})"; return board_json; } void WifiBoard::SetPowerSaveMode(bool enabled) { auto& wifi_station = WifiStation::GetInstance(); wifi_station.SetPowerSaveMode(enabled); } void WifiBoard::ResetWifiConfiguration() { // Set a flag and reboot the device to enter the network configuration mode { Settings settings("wifi", true); settings.SetInt("force_ap", 1); } GetDisplay()->ShowNotification(Lang::Strings::ENTERING_WIFI_CONFIG_MODE); vTaskDelay(pdMS_TO_TICKS(1000)); // Reboot the device esp_restart(); } std::string WifiBoard::GetDeviceStatusJson() { /* * 返回设备状态JSON * * 返回的JSON结构如下: * { * "audio_speaker": { * "volume": 70 * }, * "screen": { * "brightness": 100, * "theme": "light" * }, * "battery": { * "level": 50, * "charging": true * }, * "network": { * "type": "wifi", * "ssid": "Xiaozhi", * "rssi": -60 * }, * "chip": { * "temperature": 25 * } * } */ auto& board = Board::GetInstance(); auto root = cJSON_CreateObject(); // Audio speaker auto audio_speaker = cJSON_CreateObject(); auto audio_codec = board.GetAudioCodec(); if (audio_codec) { cJSON_AddNumberToObject(audio_speaker, "volume", audio_codec->output_volume()); } cJSON_AddItemToObject(root, "audio_speaker", audio_speaker); // Screen brightness auto backlight = board.GetBacklight(); auto screen = cJSON_CreateObject(); if (backlight) { cJSON_AddNumberToObject(screen, "brightness", backlight->brightness()); } auto display = board.GetDisplay(); if (display && display->height() > 64) { // For LCD display only cJSON_AddStringToObject(screen, "theme", display->GetTheme().c_str()); } cJSON_AddItemToObject(root, "screen", screen); // Battery int battery_level = 0; bool charging = false; bool discharging = false; if (board.GetBatteryLevel(battery_level, charging, discharging)) { cJSON* battery = cJSON_CreateObject(); cJSON_AddNumberToObject(battery, "level", battery_level); cJSON_AddBoolToObject(battery, "charging", charging); cJSON_AddItemToObject(root, "battery", battery); } // Network auto network = cJSON_CreateObject(); auto& wifi_station = WifiStation::GetInstance(); cJSON_AddStringToObject(network, "type", "wifi"); cJSON_AddStringToObject(network, "ssid", wifi_station.GetSsid().c_str()); int rssi = wifi_station.GetRssi(); if (rssi >= -60) { cJSON_AddStringToObject(network, "signal", "strong"); } else if (rssi >= -70) { cJSON_AddStringToObject(network, "signal", "medium"); } else { cJSON_AddStringToObject(network, "signal", "weak"); } cJSON_AddItemToObject(root, "network", network); // Chip float esp32temp = 0.0f; if (board.GetTemperature(esp32temp)) { auto chip = cJSON_CreateObject(); cJSON_AddNumberToObject(chip, "temperature", esp32temp); cJSON_AddItemToObject(root, "chip", chip); } auto json_str = cJSON_PrintUnformatted(root); std::string json(json_str); cJSON_free(json_str); cJSON_Delete(root); return json; }