Embedded ESP-IDF wifi事件环路即使在代码回滚后也会继续接收系统\u事件\u STA\u WPS\u ER\u PIN
我一直在使用ESP32和ESP-IDF进行一个项目,该项目将在启动网络堆栈之前检查其NVS内存中的wifi凭据。如果它有上述凭据,它将以STA模式连接到wifi网络,如果没有凭据,它将作为自己的AP启动,以允许用户通过HTTP向其发送凭据 在手动将测试凭证放入NVS后,我开始编写AP代码。完成所有AP代码和逻辑后,我用esptool手动擦除闪存,以强制板以该模式启动。这样做效果很好,我能够通过HTTP向它发送更新的凭据 此时,电路板试图在复位时连接为STA,但是wifi事件环路一直捕捉到Embedded ESP-IDF wifi事件环路即使在代码回滚后也会继续接收系统\u事件\u STA\u WPS\u ER\u PIN,embedded,esp32,esp-idf,Embedded,Esp32,Esp Idf,我一直在使用ESP32和ESP-IDF进行一个项目,该项目将在启动网络堆栈之前检查其NVS内存中的wifi凭据。如果它有上述凭据,它将以STA模式连接到wifi网络,如果没有凭据,它将作为自己的AP启动,以允许用户通过HTTP向其发送凭据 在手动将测试凭证放入NVS后,我开始编写AP代码。完成所有AP代码和逻辑后,我用esptool手动擦除闪存,以强制板以该模式启动。这样做效果很好,我能够通过HTTP向它发送更新的凭据 此时,电路板试图在复位时连接为STA,但是wifi事件环路一直捕捉到系统事件
系统事件\u STA\u WPS\u ER\u PIN
事件。此后,董事会仅经历了这一事件,并且从那时起完全无法连接到wifi。更奇怪的是,即使使用git回滚到以前的版本,问题仍然存在
main.c
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();
}
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();
}
wifiController.c
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();
}
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\u OK
的结构。如果其中一个未找到,则结构将包含ESP\u ERR\u NVS\u not\u found
wifiController.c
然后接收此creds
结构并调用beginWifi()
,然后根据结构的状态调用connectSTA()
或connectAP()
。当凭据存在时,调用connectSTA()
,但由于未知原因,事件循环始终只接收SYSTEM\u event\u STA\u WPS\u ER\u PIN
事件。正如我前面提到的,即使将代码回滚到没有connectAP()
函数的版本,这种行为仍然存在
因此,我有一种预感,这个问题可能与我手动擦除闪存时有关,而不是与代码有关
头文件的typedef中包含以下行以定义此事件
SYSTEM_EVENT_STA_WPS_ER_PIN, /*!< ESP32 station wps pin code in enrollee mode */
SYSTEM\u EVENT\u STA\u WPS\u ER\u PIN,/*!
我不知道这意味着什么,因为我没有故意在这个项目中包含任何关于wps的内容
到目前为止,我的研究还没有得到任何令人难以置信的有用信息,因此如果有人知道什么是系统事件
,或者什么可能导致我的问题,我将非常感激。如果您认为更多细节有助于解决此问题,请告诉我,我将非常乐意提供。有助于解决此问题。
我正在学习使用ESP32 wifi,查看您的邮件,ESP idf和ESP-32技术手册。没有多少信息,我找到了这个URI
问候
更新:对照示例地图中的sdkconfig文件检查项目地图中的sdkconfig文件,查看wifi配置设置。我已经深入研究这个问题好几天了,我还没有找到根本原因,但已经找到了一个解决方法和有关该问题的一些详细信息。持续出现的SYSTEM\u EVENT\u STA\u WPS\u ER\u PIN
事件实际上是由芯片试图使用WPS注册PIN模式连接到路由器引起的。据推测,这会产生一个八位数长的pin,可以放入路由器,让它能够连接。我真的不知道它为什么这样做,但我相信这可能与我如何设置AP模式有关。我现在主要的困惑是为什么回滚代码并没有修复它
对于“解决方法”,我发现闪动Espressif的示例STA wifi连接代码成功地解决了这个问题。芯片一旦闪现,就正确地连接到了我的网络,我可以重新刷新自己的代码,而不会出现任何问题。这对我来说似乎非常奇怪,所以我的一部分人认为可能芯片因为某种原因无法连接到我的网络,代码中的一个边缘案例导致它进入了注册模式
以下是我用来“修复”问题的代码的链接:
我会将此答案标记为正确,并继续查找根本问题。如果其他人知道这可能是什么原因,请随时发布,我将更新正确答案。如果我发现了根本问题,我也会更新这个答案
编辑:在继续挖掘之后,我认为问题实际上是由于我的代码中存在大量错误造成的。特别是,我打电话给esp\u netif\u create\u default\u wifi\u sta()
,然后没有设置WI-FI模式。我需要添加esp\u wifi\u set\u mode(wifi\u mode\u STA)
,这在我的程序中是不存在的。我相信在不改变wifi模式的情况下将网络堆栈设置为sta是导致我的问题的原因。虽然链接的文档可能有用,但其中的摘录或解决原始问题的摘要将更有用。