wifi_board.cc 8.7 KB

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