wifi_board.cc 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. #include "wifi_board.h"
  2. #include "display.h"
  3. #include "application.h"
  4. #include "system_info.h"
  5. #include "font_awesome_symbols.h"
  6. #include "settings.h"
  7. #include "assets/lang_config.h"
  8. #include <freertos/FreeRTOS.h>
  9. #include <freertos/task.h>
  10. #include <esp_network.h>
  11. #include <esp_log.h>
  12. #include <wifi_station.h>
  13. #include <wifi_configuration_ap.h>
  14. #include "ssid_manager_c.h"
  15. #include "afsk_demod.h"
  16. #include "blufi.h"
  17. static const char *TAG = "WifiBoard";
  18. WifiBoard::WifiBoard() {
  19. Settings settings("wifi", true);
  20. wifi_config_mode_ = settings.GetInt("force_ap") == 1;
  21. if (wifi_config_mode_) {
  22. ESP_LOGI(TAG, "force_ap is set to 1, reset to 0");
  23. settings.SetInt("force_ap", 0);
  24. }
  25. }
  26. std::string WifiBoard::GetBoardType() {
  27. return "wifi";
  28. }
  29. void WifiBoard::EnterWifiConfigMode() {
  30. auto& application = Application::GetInstance();
  31. application.SetDeviceState(kDeviceStateWifiConfiguring);
  32. blufi_entry_func();
  33. #if 0
  34. auto& wifi_ap = WifiConfigurationAp::GetInstance();
  35. wifi_ap.SetLanguage(Lang::CODE);
  36. wifi_ap.SetSsidPrefix("Xiaozhi");
  37. wifi_ap.Start();
  38. // 显示 WiFi 配置 AP 的 SSID 和 Web 服务器 URL
  39. std::string hint = Lang::Strings::CONNECT_TO_HOTSPOT;
  40. hint += wifi_ap.GetSsid();
  41. hint += Lang::Strings::ACCESS_VIA_BROWSER;
  42. hint += wifi_ap.GetWebServerUrl();
  43. hint += "\n\n";
  44. #endif
  45. // 播报配置 WiFi 的提示
  46. application.Alert(Lang::Strings::WIFI_CONFIG_MODE, "blufi", "", Lang::Sounds::P3_WIFICONFIG);
  47. #if CONFIG_USE_ACOUSTIC_WIFI_PROVISIONING
  48. audio_wifi_config::ReceiveWifiCredentialsFromAudio(&application, &wifi_ap);
  49. #endif
  50. // Wait forever until reset after configuration
  51. while (true) {
  52. int free_sram = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
  53. int min_free_sram = heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL);
  54. ESP_LOGI(TAG, "Free internal: %u minimal internal: %u", free_sram, min_free_sram);
  55. vTaskDelay(pdMS_TO_TICKS(10000));
  56. }
  57. }
  58. void WifiBoard::StartNetwork() {
  59. // User can press BOOT button while starting to enter WiFi configuration mode
  60. if (wifi_config_mode_) {
  61. EnterWifiConfigMode();
  62. return;
  63. }
  64. // If no WiFi SSID is configured, enter WiFi configuration mode
  65. // 创建SSID管理器实例并检查SSID列表
  66. SsidManager* ssid_manager = ssid_manager_create();
  67. if (ssid_manager == NULL) {
  68. ESP_LOGE(TAG, "Failed to create SSID manager");
  69. }
  70. // 获取SSID数量
  71. int ssid_count = ssid_manager_get_count(ssid_manager);
  72. if (ssid_count == 0) {
  73. wifi_config_mode_ = true;
  74. EnterWifiConfigMode();
  75. // 释放管理器资源
  76. ssid_manager_destroy(ssid_manager);
  77. return;
  78. }
  79. // 使用SSID列表...
  80. for (int i = 0; i < ssid_count; i++) {
  81. const char* ssid = ssid_manager_get_ssid(ssid_manager, i);
  82. const char* password = ssid_manager_get_password(ssid_manager, i);
  83. ESP_LOGI(TAG, "SSID %d: %s, Password: %s", i, ssid, password);
  84. }
  85. // 使用完成后释放资源
  86. ssid_manager_destroy(ssid_manager);
  87. auto& wifi_station = WifiStation::GetInstance();
  88. wifi_station.OnScanBegin([this]() {
  89. auto display = Board::GetInstance().GetDisplay();
  90. display->ShowNotification(Lang::Strings::SCANNING_WIFI, 30000);
  91. });
  92. wifi_station.OnConnect([this](const std::string& ssid) {
  93. auto display = Board::GetInstance().GetDisplay();
  94. std::string notification = Lang::Strings::CONNECT_TO;
  95. notification += ssid;
  96. notification += "...";
  97. display->ShowNotification(notification.c_str(), 30000);
  98. });
  99. wifi_station.OnConnected([this](const std::string& ssid) {
  100. auto display = Board::GetInstance().GetDisplay();
  101. std::string notification = Lang::Strings::CONNECTED_TO;
  102. notification += ssid;
  103. display->ShowNotification(notification.c_str(), 30000);
  104. });
  105. wifi_station.Start();
  106. // Try to connect to WiFi, if failed, launch the WiFi configuration AP
  107. if (!wifi_station.WaitForConnected(60 * 1000)) {
  108. wifi_station.Stop();
  109. wifi_config_mode_ = true;
  110. EnterWifiConfigMode();
  111. return;
  112. }
  113. Board::GetInstance().internetConnet=1;
  114. }
  115. NetworkInterface* WifiBoard::GetNetwork() {
  116. static EspNetwork network;
  117. return &network;
  118. }
  119. const char* WifiBoard::GetNetworkStateIcon() {
  120. if (wifi_config_mode_) {
  121. return FONT_AWESOME_WIFI;
  122. }
  123. auto& wifi_station = WifiStation::GetInstance();
  124. if (!wifi_station.IsConnected()) {
  125. return FONT_AWESOME_WIFI_OFF;
  126. }
  127. int8_t rssi = wifi_station.GetRssi();
  128. if (rssi >= -60) {
  129. return FONT_AWESOME_WIFI;
  130. } else if (rssi >= -70) {
  131. return FONT_AWESOME_WIFI_FAIR;
  132. } else {
  133. return FONT_AWESOME_WIFI_WEAK;
  134. }
  135. }
  136. std::string WifiBoard::GetBoardJson() {
  137. // Set the board type for OTA
  138. auto& wifi_station = WifiStation::GetInstance();
  139. std::string board_json = R"({)";
  140. board_json += R"("type":")" + std::string(BOARD_TYPE) + R"(",)";
  141. board_json += R"("name":")" + std::string(BOARD_NAME) + R"(",)";
  142. if (!wifi_config_mode_) {
  143. board_json += R"("ssid":")" + wifi_station.GetSsid() + R"(",)";
  144. board_json += R"("rssi":)" + std::to_string(wifi_station.GetRssi()) + R"(,)";
  145. board_json += R"("channel":)" + std::to_string(wifi_station.GetChannel()) + R"(,)";
  146. board_json += R"("ip":")" + wifi_station.GetIpAddress() + R"(",)";
  147. }
  148. board_json += R"("mac":")" + SystemInfo::GetMacAddress() + R"(")";
  149. board_json += R"(})";
  150. return board_json;
  151. }
  152. void WifiBoard::SetPowerSaveMode(bool enabled) {
  153. auto& wifi_station = WifiStation::GetInstance();
  154. wifi_station.SetPowerSaveMode(enabled);
  155. }
  156. void WifiBoard::ResetWifiConfiguration() {
  157. // Set a flag and reboot the device to enter the network configuration mode
  158. {
  159. Settings settings("wifi", true);
  160. settings.SetInt("force_ap", 1);
  161. }
  162. GetDisplay()->ShowNotification(Lang::Strings::ENTERING_WIFI_CONFIG_MODE);
  163. vTaskDelay(pdMS_TO_TICKS(1000));
  164. // Reboot the device
  165. esp_restart();
  166. }
  167. std::string WifiBoard::GetDeviceStatusJson() {
  168. /*
  169. * 返回设备状态JSON
  170. *
  171. * 返回的JSON结构如下:
  172. * {
  173. * "audio_speaker": {
  174. * "volume": 70
  175. * },
  176. * "screen": {
  177. * "brightness": 100,
  178. * "theme": "light"
  179. * },
  180. * "battery": {
  181. * "level": 50,
  182. * "charging": true
  183. * },
  184. * "network": {
  185. * "type": "wifi",
  186. * "ssid": "Xiaozhi",
  187. * "rssi": -60
  188. * },
  189. * "chip": {
  190. * "temperature": 25
  191. * }
  192. * }
  193. */
  194. auto& board = Board::GetInstance();
  195. auto root = cJSON_CreateObject();
  196. // Audio speaker
  197. auto audio_speaker = cJSON_CreateObject();
  198. auto audio_codec = board.GetAudioCodec();
  199. if (audio_codec) {
  200. cJSON_AddNumberToObject(audio_speaker, "volume", audio_codec->output_volume());
  201. }
  202. cJSON_AddItemToObject(root, "audio_speaker", audio_speaker);
  203. // Screen brightness
  204. auto backlight = board.GetBacklight();
  205. auto screen = cJSON_CreateObject();
  206. if (backlight) {
  207. cJSON_AddNumberToObject(screen, "brightness", backlight->brightness());
  208. }
  209. auto display = board.GetDisplay();
  210. if (display && display->height() > 64) { // For LCD display only
  211. cJSON_AddStringToObject(screen, "theme", display->GetTheme().c_str());
  212. }
  213. cJSON_AddItemToObject(root, "screen", screen);
  214. // Battery
  215. int battery_level = 0;
  216. bool charging = false;
  217. bool discharging = false;
  218. if (board.GetBatteryLevel(battery_level, charging, discharging)) {
  219. cJSON* battery = cJSON_CreateObject();
  220. cJSON_AddNumberToObject(battery, "level", battery_level);
  221. cJSON_AddBoolToObject(battery, "charging", charging);
  222. cJSON_AddItemToObject(root, "battery", battery);
  223. }
  224. // Network
  225. auto network = cJSON_CreateObject();
  226. auto& wifi_station = WifiStation::GetInstance();
  227. cJSON_AddStringToObject(network, "type", "wifi");
  228. cJSON_AddStringToObject(network, "ssid", wifi_station.GetSsid().c_str());
  229. int rssi = wifi_station.GetRssi();
  230. if (rssi >= -60) {
  231. cJSON_AddStringToObject(network, "signal", "strong");
  232. } else if (rssi >= -70) {
  233. cJSON_AddStringToObject(network, "signal", "medium");
  234. } else {
  235. cJSON_AddStringToObject(network, "signal", "weak");
  236. }
  237. cJSON_AddItemToObject(root, "network", network);
  238. // Chip
  239. float esp32temp = 0.0f;
  240. if (board.GetTemperature(esp32temp)) {
  241. auto chip = cJSON_CreateObject();
  242. cJSON_AddNumberToObject(chip, "temperature", esp32temp);
  243. cJSON_AddItemToObject(root, "chip", chip);
  244. }
  245. auto json_str = cJSON_PrintUnformatted(root);
  246. std::string json(json_str);
  247. cJSON_free(json_str);
  248. cJSON_Delete(root);
  249. return json;
  250. }