前言
找了很多网站,浏览了很多资料都找不到WiFi优选的项目,只找到一份扫描附近WiFi的例程,但是光有这样还不行,我还要优选出来,连接信号最好的预置AP。
代码部分
代码部分需要修改的内容仅为三个SSID信息,每隔一定时间系统会自动对3个SSID进行排序,然后优选最佳WiFi,如果发生改变则需重连,否则程序继续运行。
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_wifi.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_event_loop.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "string.h"
#include "math.h"
#include <stdlib.h>
#include <stdio.h>
#define EXAMPLE_ESP_WIFI_MODE_AP FALSE //TRUE:AP FALSE:STA
static EventGroupHandle_t wifi_event_group;//定义一个事件的句柄
/* FreeRTOS event group to signal when we are connected*/
int maxairssi=-200,maxssrssi=-200,maxhwrssi=-200;
const int SCAN_DONE_BIT = BIT0;//定义事件,占用事件变量的第0位,最多可以定义32个事件。
const int WIFI_CONNECTED_BIT = BIT1;//定义事件,占用事件变量的第1位,最多可以定义32个事件。
static wifi_scan_config_t scanConf = {
.ssid = NULL,
.bssid = NULL,
.channel = 0,
.show_hidden = 1
};//定义scanConf结构体,供函数esp_wifi_scan_start调用
static const char *TAG = "example";
/* 系统事件循环处理函数 */
static esp_err_t event_handler(void *ctx, system_event_t *event)
{
/* For accessing reason codes in case of disconnection */
system_event_info_t *info = &event->event_info;
switch(event->event_id) {
case SYSTEM_EVENT_STA_START:
printf("wifi_event——SYSTEM_EVENT_STA_START=%d",SYSTEM_EVENT_STA_START);
esp_wifi_connect();
vTaskDelay(100 / portTICK_PERIOD_MS);
break;
case SYSTEM_EVENT_STA_GOT_IP:
printf("wifi_event_SYSTEM_EVENT_STA_GOT_IP=%d",SYSTEM_EVENT_STA_GOT_IP);
ESP_LOGI(TAG, "got ip:%s",
ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip));
xEventGroupSetBits(wifi_event_group, WIFI_CONNECTED_BIT);
break;
case SYSTEM_EVENT_AP_STACONNECTED:
printf("wifi_event——SYSTEM_EVENT_AP_STADISCONNECTED=%d",SYSTEM_EVENT_AP_STACONNECTED);
ESP_LOGI(TAG, "station:"MACSTR" join, AID=%d",
MAC2STR(event->event_info.sta_connected.mac),
event->event_info.sta_connected.aid);
break;
case SYSTEM_EVENT_AP_STADISCONNECTED:
printf("wifi_event_SYSTEM_EVENT_AP_STADISCONNECTED=%d",SYSTEM_EVENT_AP_STADISCONNECTED);
ESP_LOGI(TAG, "station:"MACSTR"leave, AID=%d",
MAC2STR(event->event_info.sta_disconnected.mac),
event->event_info.sta_disconnected.aid);
break;
case SYSTEM_EVENT_STA_DISCONNECTED:
printf("wifi_event_SYSTEM_EVENT_STA_DISCONNECTED=%d",SYSTEM_EVENT_STA_DISCONNECTED);
ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason);
if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) {
/*Switch to 802.11 bgn mode */
esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N);
}
esp_wifi_connect();
xEventGroupClearBits(wifi_event_group, WIFI_CONNECTED_BIT);
break;
case SYSTEM_EVENT_SCAN_DONE:
printf("wifi_event_SYSTEM_EVENT_SCAN_DONE=%d",SYSTEM_EVENT_SCAN_DONE);
xEventGroupSetBits(wifi_event_group,SCAN_DONE_BIT);
break;
default:
break;
}
return ESP_OK;
}
wifi_config_t hw_wifi_config = {
.sta = {
.ssid = "A-SSID",
.password = "A-PASWD"
},
};
wifi_config_t gc_wifi_config = {
.sta = {
.ssid = "B-SSID",
.password = "B-PASWD",
.scan_method = WIFI_ALL_CHANNEL_SCAN//可以连接隐藏WiFi
},
};
wifi_config_t ai_wifi_config={
.sta = {
.ssid = "C-SSID",
.password = "C-PASWD"
},
};
wifi_config_t now_wifi_config={
.sta = {
.ssid = "",
.password = ""
},
};
void wifi_init_sta()
{
tcpip_adapter_init();//初始化i本机TCP/IP协议
wifi_event_group = xEventGroupCreate();
ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL) );
/* 使用WIFI_INIT_CONFIG_DEFAULT() 来获取一个默认的wifi配置参数结构体变量*/
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
/* 根据cfg参数初始化wifi连接所需要的资源 */
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
/* 将事件处理程序注册到系统默认事件循环,分别是WiFi事件和IP地址事件 */
//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));
/* 设置WiFi的工作模式为 STA */
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &ai_wifi_config) );
//ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
/* 启动WiFi连接 */
ESP_ERROR_CHECK(esp_wifi_start() );
ESP_LOGI(TAG, "wifi_init_sta finished.");
//ESP_LOGI(TAG, "connect to ap SSID:%s password:%s",EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);
}
void set_ssid_config(){
ESP_ERROR_CHECK(esp_wifi_get_config(ESP_IF_WIFI_STA,&now_wifi_config) );
if(maxairssi>maxhwrssi&&maxairssi>maxssrssi){
if(now_wifi_config.sta.ssid[0]=='A'&&now_wifi_config.sta.ssid[5]=='S'){
ESP_LOGI(TAG, "Now SSID is %s ,NO NEED CHANGE", now_wifi_config.sta.ssid);
}else{
ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", ai_wifi_config.sta.ssid);
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &ai_wifi_config) );
}
}else if(maxhwrssi>maxairssi&&maxhwrssi>maxssrssi){
if(now_wifi_config.sta.ssid[0]=='H'&&now_wifi_config.sta.ssid[5]=='I'){
ESP_LOGI(TAG, "Now SSID is %s ,NO NEED CHANGE", now_wifi_config.sta.ssid);
}else{
ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", hw_wifi_config.sta.ssid);
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &hw_wifi_config) );
}
}else if (maxssrssi>maxairssi&&maxssrssi>maxhwrssi)
{
if(now_wifi_config.sta.ssid[0]=='s'&&now_wifi_config.sta.ssid[5]=='c'){
ESP_LOGI(TAG, "Now SSID is %s ,NO NEED CHANGE", now_wifi_config.sta.ssid);
}else{
ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", gc_wifi_config.sta.ssid);
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &gc_wifi_config) );
}
}else{
ESP_LOGI(TAG, "airssi=%d----hwrssi=%d----gcrssi=%d\r\n",maxairssi,maxhwrssi,maxssrssi);
}
ESP_ERROR_CHECK(esp_wifi_start() );
//esp_wifi_connect();
}
static void scan_task(void *pvParameters)
{
while(1) {
xEventGroupWaitBits(wifi_event_group, SCAN_DONE_BIT, 0, 1, portMAX_DELAY); //等待事件被置位,即等待扫描完成
ESP_LOGI(TAG, "WIFI scan doen");
xEventGroupClearBits(wifi_event_group, SCAN_DONE_BIT);//清除事件标志位
uint16_t apCount = 0;
esp_wifi_scan_get_ap_num(&apCount);//Get number of APs found in last scan
printf("Number of access points found: %d\n", apCount);
if (apCount == 0) {
ESP_LOGI(TAG, "Nothing AP found");
return;
}//如果apCount没有受到数据,则说明没有路由器
wifi_ap_record_t *list = (wifi_ap_record_t *)malloc(sizeof(wifi_ap_record_t) * apCount);//定义一个wifi_ap_record_t的结构体的链表空间
ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&apCount, list));//获取上次扫描中找到的AP列表。
int i;
maxssrssi=maxairssi=maxhwrssi=-200;
printf("======================================================================\n");
printf(" SSID | RSSI | AUTH \n");
printf("======================================================================\n");
for (i=0; i<apCount; i++) {
char *authmode;
switch(list[i].authmode) {
case WIFI_AUTH_OPEN:
authmode = "WIFI_AUTH_OPEN";
break;
case WIFI_AUTH_WEP:
authmode = "WIFI_AUTH_WEP";
break;
case WIFI_AUTH_WPA_PSK:
authmode = "WIFI_AUTH_WPA_PSK";
break;
case WIFI_AUTH_WPA2_PSK:
authmode = "WIFI_AUTH_WPA2_PSK";
break;
case WIFI_AUTH_WPA_WPA2_PSK:
authmode = "WIFI_AUTH_WPA_WPA2_PSK";
break;
default:
authmode = "Unknown";
break;
}
printf("%26.26s | % 4d | %22.22s\n",list[i].ssid, list[i].rssi, authmode);
if(list[i].ssid[0]=='A'&&list[i].ssid[5]=='S'){//实验室信号
if(list[i].rssi>maxairssi){
maxairssi=list[i].rssi;
}
}
if(list[i].ssid[0]=='H'&&list[i].ssid[3]=='W'){//华为信号
if(list[i].rssi>maxhwrssi){
maxhwrssi=list[i].rssi;
}
}
if(list[i].ssid[0]=='s'&&list[i].ssid[3]=='s'){//工厂信号
if(list[i].rssi>maxssrssi){
maxssrssi=list[i].rssi;
}
}
}
ESP_LOGI(TAG, "airssi=%d----hwrssi=%d----gcrssi=%d\r\n",maxairssi,maxhwrssi,maxssrssi);
set_ssid_config();
// if(ip_addr_get_ip4_u32()==0){
// set_ssid_config();
// }
//将链表的数据信息打印出来
free(list);//释放链表
//printf("%s%d\n\n","xinhao zuihao wei",maxrssi);//换行
// scan again
vTaskDelay(2000 / portTICK_PERIOD_MS);//调用延时函数,再次扫描
//The true parameter cause the function to block until the scan is done.
ESP_ERROR_CHECK(esp_wifi_scan_start(&scanConf, 1));//扫描所有可用的AP。
}
}
int app_main(void)
{
nvs_flash_init();//初始化NVS flash storage
wifi_init_sta();
//initialise_wifi();//初始化wifi
xTaskCreate(&scan_task, "scan_task", 2048, NULL, 15, NULL);//创建扫描任务
ESP_ERROR_CHECK(esp_wifi_scan_start(&scanConf, 1)); //The true parameter cause the function to block until
//the scan is done.
//vTaskDelay(2000);
return 0;
}