两种ESP32-IDF的WiFi运行后任意时候重新配网的写法,第1种写法代码相对简单,但是感觉在配网的时候有可能WIFI_EVENT_STA_START事件不一定会被触发,这样会导致无法连接到路由器,虽然我在测试的时候没出现这个问题,但是我在前面的项目种做了类似的写法,这个事件就是部会触发,触发配置信息为空,所以个人觉得第2种比较稳定一些,只是代码相对较复杂一点:
1、在执行重新配网的时候先停止WiFi运行,然后配置新的WiFi信息后重新运行WiFi,运行事件触发后执行连接函数连接,完整代码如下:
#include "esp_wifi.h"
#include "esp_mac.h"
#include "esp_event.h"
#include "esp_log.h"
#include <string.h>
#include "bit.h"
#define TAG "wifi_config"
static uint8_t s_retry_num=0; //WiFi重连计数器
typedef enum{
BIT_WIFI_INIT, /* WiFi初始化标志位 */
BIT_MESH_INIT, /* Mesh初始化标志 bit 1初始化,0 未初始化*/
BIT_MESH_CONNECTED , /* Mesh 连接状态标志位 bit 1 连接,0 未连接*/
BIT_CONFIG_DISCONNECT, /* 配置WiFi断开连接标志位(仅用于处理断开后释放重复连接几次的逻辑) */
BIT_WIFI_CONNECT, /* WiFi连接状态标志位 */
BIT_WIFI_RUNNING, /* WiFi 运行状态标志位 */
BIT_CONFIG_NETWORK, /* 配网状态标志位 */
BIT_MESH_MQTT_TASK, /* Mesh Mqtt 运行任务标志位 */
}state_flag_bit;
static uint8_t state_flag=0; /*存放state_flag_bit枚举的各个位状态标志 */
void ip_event_handler(void* arg, esp_event_base_t event_base,int32_t event_id, void* event_data){
if(event_base==WIFI_EVENT){
switch(event_id){
case WIFI_EVENT_STA_START:
if(esp_wifi_connect()==ESP_OK){
ESP_LOGI(TAG, "Success start connecting to WiFi");
}else{
ESP_LOGE(TAG, "Failed to start connecting to WiFi");
}
break;
case WIFI_EVENT_STA_CONNECTED:
//在这里可以进行DNS域名解析,获取IP地址这些信息
wifi_event_sta_connected_t *connect_event=(wifi_event_sta_connected_t *)event_data;
ESP_LOGI(TAG, "Connect to WiFi。SSID:%s,aid:%d,Channel:%d,BSSID:"MACSTR"",
connect_event->ssid,connect_event->aid,connect_event->channel,MAC2STR(connect_event->bssid));
break;
case WIFI_EVENT_STA_DISCONNECTED:
if(!bitRead(state_flag,BIT_CONFIG_DISCONNECT)){
if (s_retry_num < 10) {
esp_wifi_connect();
s_retry_num++;
ESP_LOGE(TAG, "Retrying connection to WiFi %d times",s_retry_num);
}else{
ESP_LOGE(TAG,"Connection to WiFi failed");
ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, &ip_event_handler));
}
}else{
bitClear(state_flag,BIT_CONFIG_DISCONNECT); //清除配网断开标志
}
break;
default:
ESP_LOGI(TAG, "Unknown event ID:%ld", event_id);
}
}else if (event_base == IP_EVENT){
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
ESP_LOGI(TAG, "IP Address:" IPSTR, IP2STR(&event->ip_info.ip));
s_retry_num = 0; //清除重连计数
}
}
/**
* @brief 配置WiFi网络信息
* @param ssid WiFi SSID缓冲区指针
* @param pwd WiFi密码缓冲区指针
* @param bssid WiFi BSSID 数据缓存
*/
void config_wifi(char *ssid,char *pwd,uint8_t bssid[6]){
bitSet(state_flag,BIT_CONFIG_DISCONNECT); //设置配网断开标志
// 停止Wi-Fi(如果它正在运行)
esp_wifi_stop();
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &ip_event_handler, NULL)); //注册WiFi事件
// 清除之前的配置(可选,但推荐)
wifi_config_t wifi_config = {
.sta.threshold.authmode = WIFI_AUTH_OPEN,
.sta.pmf_cfg = {
.capable = false,
.required = false
},
};
if (ESP_OK != esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)) {
ESP_LOGE(TAG, "Failed to clear WiFi STA configuration");
return;
}
// 设置新的Wi-Fi配置
strcpy((char *)wifi_config.sta.ssid, ssid);
strcpy((char *)wifi_config.sta.password, pwd);
// 设置STA模式并应用配置
if (ESP_OK != esp_wifi_set_mode(WIFI_MODE_STA) ||
ESP_OK != esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)) {
ESP_LOGE(TAG, "Failed to set WiFi configuration");
return;
}
// 启动Wi-Fi
if (ESP_OK != esp_wifi_start()) {
ESP_LOGE(TAG, "Failed to start WiFi");
return;
}
}
/* 初始化并运行WiFI */
void init_wifi(){
ESP_ERROR_CHECK(esp_netif_init());
//事件初始化
ESP_ERROR_CHECK(esp_event_loop_create_default());
//注册 IP 事件处理程序
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &ip_event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &ip_event_handler, NULL));
wifi_init_config_t config = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&config));
wifi_config_t wifi_config;
esp_err_t err=esp_wifi_get_config(ESP_IF_WIFI_STA, &wifi_config);
if(err==ESP_OK){
ESP_LOGE(TAG,"SSID:%s,PWD:%s",(char *)wifi_config.sta.ssid,(char *)wifi_config.sta.password);
}else{
ESP_LOGE(TAG,"Failed to obtain configuration WiFi information, reason:%s",esp_err_to_name(err));
}
esp_wifi_set_storage(WIFI_STORAGE_FLASH);
esp_wifi_set_mode(WIFI_MODE_STA);
ESP_ERROR_CHECK(esp_wifi_start());
}
2、在执行重新配网的时候先停止WiFi连接,等待连接标志被清除后,配置新的WiFi信息后重新运行WiFi,重新连接,完整代码如下:
#include "esp_wifi.h"
#include "esp_mac.h"
#include "esp_event.h"
#include "esp_log.h"
#include <string.h>
#include "bit.h"
#define TAG "wifi_config"
typedef struct {
uint8_t ssid[32];
uint8_t password[64];
uint8_t bssid[6];
} sta_config_info_t;
static uint8_t s_retry_num=0; //WiFi重连计数器
typedef enum{
BIT_WIFI_INIT, /* WiFi初始化标志位 */
BIT_MESH_INIT, /* Mesh初始化标志 bit 1初始化,0 未初始化*/
BIT_MESH_CONNECTED , /* Mesh 连接状态标志位 bit 1 连接,0 未连接*/
BIT_CONFIG_DISCONNECT, /* 配置WiFi断开连接标志位(仅用于处理断开后释放重复连接几次的逻辑) */
BIT_WIFI_CONNECT, /* WiFi连接状态标志位 */
BIT_WIFI_RUNNING, /* WiFi 运行状态标志位 */
BIT_CONFIG_NETWORK, /* 配网状态标志位 */
BIT_MESH_MQTT_TASK, /* Mesh Mqtt 运行任务标志位 */
}state_flag_bit;
static uint8_t state_flag=0; /*存放state_flag_bit枚举的各个位状态标志 */
void ip_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data){
if(event_base==WIFI_EVENT){
switch(event_id){
case WIFI_EVENT_STA_START:{
s_retry_num=0;
if(esp_wifi_connect()==ESP_OK){
ESP_LOGI(TAG, "Success start connecting to WiFi");
}else{
ESP_LOGE(TAG, "Failed to start connecting to WiFi");
}
break;
}
case WIFI_EVENT_STA_DISCONNECTED:{
if(!bitRead(state_flag,BIT_CONFIG_DISCONNECT)){ //非配网断开
if (s_retry_num < 10) {
esp_wifi_connect();
s_retry_num++;
ESP_LOGE(TAG, "Retrying connection to WiFi %d times",s_retry_num);
}else{
ESP_LOGE(TAG,"Connection to WiFi failed");
ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, &ip_event_handler));
}
}else{
ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, &ip_event_handler));
bitClear(state_flag,BIT_CONFIG_DISCONNECT); //清除配网断开标志
ESP_LOGE(TAG,"Configure network disconnection");
}
bitClear(state_flag,BIT_WIFI_CONNECT); //清除连接标志
break;
}
case WIFI_EVENT_STA_CONNECTED:{
bitSet(state_flag,BIT_WIFI_CONNECT); //设置连接标志
wifi_event_sta_connected_t *connect_event=(wifi_event_sta_connected_t *)event_data;
ESP_LOGI(TAG, "Connect to WiFi。SSID:%s,aid:%d,Channel:%d,BSSID:"MACSTR"",connect_event->ssid,connect_event->aid,connect_event->channel,MAC2STR(connect_event->bssid));
break;
}
default:
ESP_LOGI(TAG, "Unknown event ID:%ld", event_id);
break;
}
}else if (event_base == IP_EVENT){
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
ESP_LOGI(TAG, "IP Address:" IPSTR, IP2STR(&event->ip_info.ip));
s_retry_num = 0; //清除重连计数
}
}
void init_wifi(){
ESP_ERROR_CHECK(esp_netif_init());
//事件初始化
ESP_ERROR_CHECK(esp_event_loop_create_default());
//注册 IP 事件处理程序
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &ip_event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &ip_event_handler, NULL));
wifi_init_config_t config = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&config));
wifi_config_t wifi_config;
esp_err_t err=esp_wifi_get_config(ESP_IF_WIFI_STA, &wifi_config);
if(err==ESP_OK){
ESP_LOGE(TAG,"SSID:%s,PWD:%s",(char *)wifi_config.sta.ssid,(char *)wifi_config.sta.password);
}else{
ESP_LOGE(TAG,"Failed to obtain configuration WiFi information, reason:%s",esp_err_to_name(err));
}
esp_wifi_set_storage(WIFI_STORAGE_FLASH);
esp_wifi_set_mode(WIFI_MODE_STA);
ESP_ERROR_CHECK(esp_wifi_start());
}
/*配网运行任务*/
void config_wifi_tisk(void * age){
sta_config_info_t *sta_config=(sta_config_info_t *)age;
if(sta_config!=NULL){ //配置结构体指针必须部位空才能继续任务
wifi_config_t wifi_config={
.sta={
.pmf_cfg={
.capable = true,
.required = false,
},
},
};
memcpy((uint8_t *) &wifi_config.sta.ssid, &sta_config->ssid,32);
memcpy((uint8_t *) &wifi_config.sta.password, &sta_config->password,sizeof(sta_config->password));
memcpy((uint8_t *) &wifi_config.sta.bssid, &sta_config->bssid,6);
ESP_LOGI(TAG,"WiFi configure info,SSID=:%s,PWD=:%s,BSSID="MACSTR"",(char *)wifi_config.sta.ssid,
(char *)wifi_config.sta.password,MAC2STR(wifi_config.sta.bssid));
if(bitRead(state_flag,BIT_WIFI_CONNECT)){ //判断WiFi连接标志是否为真(连接状态)
bitSet(state_flag,BIT_CONFIG_DISCONNECT); //设置为配网断开连接标志位
esp_wifi_disconnect();
}
s_retry_num=0; //清除重连计数
while(true){ //循环任务线程,等待连接标志被清除
if(!bitRead(state_flag,BIT_WIFI_CONNECT)){ //判断WiFi连接标志是否为假(连接断开状态)
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &ip_event_handler, NULL)); //注册WiFi事件
esp_wifi_set_mode(WIFI_MODE_STA);
//如果在配网时正在执行esp_wifi_connect()过程,通常会触发ESP_ERR_WIFI_CONN错误,不会执行调用下面的esp_wifi_connect()函数,内部会自动完成当前配置的连接
esp_err_t err = esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to configure WiFi,reason:%s", esp_err_to_name(err));
}else{
err= esp_wifi_connect();
if(err==ESP_OK){
ESP_LOGI(TAG, "Success to configure WiFi reconnection");
}else{
ESP_LOGE(TAG, "Failed to configure WiFi reconnection,reason:%s",esp_err_to_name(err));
}
}
break;
}
vTaskDelay(50 / portTICK_PERIOD_MS);
}
free(sta_config); //释放动态内存
}
vTaskDelete(NULL);
}
/**
* @brief 配置WiFi网络信息
* @param ssid WiFi SSID数据指针
* @param pwd WiFi密码数据指针
* @param bssid WiFi BSSID 数据缓存
*/
void config_wifi(char *ssid,char *pwd,uint8_t bssid[6]){
sta_config_info_t *config_info= (sta_config_info_t *)malloc(sizeof(sta_config_info_t));
if(config_info==NULL){
return; // 处理内存分配失败的情况
}
strcpy((char*)config_info->ssid,ssid);
strcpy((char*)config_info->password, pwd);
if(bssid!=NULL){
memcpy((uint8_t *) config_info->bssid, bssid, 6);
}
// 将需要发送的数据结构体指针传递到任务
if(xTaskCreate(config_wifi_tisk, "c_w_t", 3072,config_info, 5, NULL)!=pdPASS){
free(config_info); // 如果任务创建失败,释放内存
}
}