Files
xiaozhi-esp32/main/boards/common/wifi_board.cc
Xiaoxia 9ae34d3b45 feat: Add locales with OGG sounds (#1057)
* fix jiuchuan build problem

* feat: Add locales with OGG sounds

* fix building echoear

* Support ogg files frame duration <= 60
2025-08-12 18:41:00 +08:00

263 lines
8.2 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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 <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <esp_network.h>
#include <esp_log.h>
#include <wifi_station.h>
#include <wifi_configuration_ap.h>
#include <ssid_manager.h>
#include "afsk_demod.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);
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";
// 播报配置 WiFi 的提示
application.Alert(Lang::Strings::WIFI_CONFIG_MODE, hint.c_str(), "", Lang::Sounds::OGG_WIFICONFIG);
#if CONFIG_USE_ACOUSTIC_WIFI_PROVISIONING
auto display = Board::GetInstance().GetDisplay();
auto codec = Board::GetInstance().GetAudioCodec();
int channel = 1;
if (codec) {
channel = codec->input_channels();
}
ESP_LOGI(TAG, "Start receiving WiFi credentials from audio, input channels: %d", channel);
audio_wifi_config::ReceiveWifiCredentialsFromAudio(&application, &wifi_ap, display, channel);
#endif
// Wait forever until reset after configuration
while (true) {
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(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;
}
}
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;
}