我一直在使用带有 ESP-IDF 的 ESP32 进行一个项目,该项目将在启动网络堆栈之前检查其 NVS 内存中的 wifi 凭据。如果它有说凭据,它将以 STA 模式连接到 wifi 网络,如果它缺少它们,它将作为它自己的 AP 启动,以允许用户通过 HTTP 向它发送凭据。
在手动将我的测试凭据放入 NVS 后,我开始编写 AP 代码。完成所有 AP 代码和逻辑后,我使用 esptool 手动擦除闪存以强制开发板以该模式启动。这样做效果很好,我能够通过 HTTP 向它发送更新的凭据。
此时,板子在复位时尝试作为 STA 连接,但是,该SYSTEM_EVENT_STA_WPS_ER_PIN
事件一直被 wifi 事件循环捕获。此后董事会仅经历过此事件,并且此后完全无法连接到wifi。更奇怪的是,即使使用 git 回滚到以前的版本,问题仍然存在。
主程序
void app_main() {
// Start NVS
initNVS();
// Init Wifi Controller
initWifiController();
// Get Credentials to send to wifi
Creds creds = getCreds();
// Start wifi in STA mode with gathered creds
beginWifi(creds);
initializePins();
initializeTimers();
}
wifi控制器.c
void initWifiController(){
// * NVS must be initialized before wifi work can be done
// Handle when connected to the network
connectionSemaphore = xSemaphoreCreateBinary();
// Begin network stack
ESP_ERROR_CHECK(esp_netif_init());
// Create event loop for handling callbacks
ESP_ERROR_CHECK(esp_event_loop_create_default());
}
void beginWifi(Creds creds){
if(creds.status == ESP_OK){
ESP_LOGI(TAG, "Connection credentials have been found, connecting to network");
connectSTA(creds);
}
else if(creds.status == ESP_ERR_NVS_NOT_FOUND){
ESP_LOGW(TAG, "Missing credentials, starting as AP");
connectAP();
}
else{
ESP_LOGE(TAG, "ESP failed with error %s, not starting wifi", esp_err_to_name(creds.status));
}
void connectSTA(Creds creds){
ESP_LOGI(TAG, "Attempting to connect to wifi with following creds: %s | %s", creds.ssid, creds.pass);
// Set netif to sta
esp_netif_create_default_wifi_sta();
// Prepare and initialize wifi_init_config_t
wifi_init_config_t wifi_init_config = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&wifi_init_config));
// Register tracked events for event_handler
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, event_handler, NULL));
// TODO: Check if this can be used to avoid havng to use NVS manually
esp_wifi_set_storage(WIFI_STORAGE_RAM);
// Config struct for wifi details
wifi_config_t wifi_config = {};
// Copy casted info into wifi_config
// * https://www.esp32.com/viewtopic.php?f=13&t=14611
// * See above link for details on this
strcpy((char *)wifi_config.sta.ssid, creds.ssid);
strcpy((char *)wifi_config.sta.password, creds.pass);
esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config);
ESP_ERROR_CHECK(esp_wifi_start());
// ? Is this required to avoid a memory leak?
free(creds.pass);
free(creds.ssid);
}
void connectAP(){
// ? How important is it that these be called in this order?
ESP_LOGI(TAG, "Starting in AP Mode");
esp_netif_create_default_wifi_ap();
// TODO: maybe move this creation to initWifiController to avoid making it twice
wifi_init_config_t wifi_init_config = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&wifi_init_config));
// TODO: Consider moving this to init Wifi Controller to avoid running it twice as well
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
// Configuration for AP
wifi_config_t wifi_config = {
.ap = {
.ssid = "Grow System",
.password = "Password",
.ssid_len = strlen("Grow System"),
.max_connection = 4,
.authmode = WIFI_AUTH_WPA_WPA2_PSK
}
};
// TODO: Enable password support on AP configuration
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
ESP_LOGI(TAG, "Wifi connectAP finished");
registerEndPoints();
}
该代码本质上检查 NVS 的凭据,如果找到它们,它会返回一个包含它们的结构以及ESP_OK
. 如果未找到其中之一,则该结构将包含ESP_ERR_NVS_NOT_FOUND
. wifiController.c
然后接收这个creds
结构并调用beginWifi()
,然后调用connectSTA()
或connectAP()
基于status
结构的。当凭证存在时,connectSTA()
会调用,但由于未知原因,事件循环始终只接收SYSTEM_EVENT_STA_WPS_ER_PIN
事件。正如我之前提到的,即使将我的代码回滚到没有该connectAP()
功能的版本后,这种行为仍然存在。
因此,我有一种预感,这个问题可能与我手动擦除闪存时有关,而不是与代码有关。
头文件在其 typedef 中包含以下行来定义此事件。
SYSTEM_EVENT_STA_WPS_ER_PIN, /*!< ESP32 station wps pin code in enrollee mode */
我不知道这意味着什么,因为我没有故意在这个项目中包含任何关于 wps 的内容。
到目前为止,我的研究还没有返回任何非常有用的东西,所以如果有人知道什么SYSTEM_EVENT_STA_WPS_ER_PIN
是或可能导致我的问题,我将非常感激。如果您认为更多细节对解决此问题有用,请告诉我,我将非常乐意提供。