esp8266+RTOS+ESP-IDF扫描附近WiFi并优选WiFi连接

esp8266+RTOS+ESP-IDF扫描附近WiFi并优选WiFi连接

前言

找了很多网站,浏览了很多资料都找不到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;
    }
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值