ESP32-IDF的WiFi STA配网

两种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); // 如果任务创建失败,释放内存
   }
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值