背景

我的一个工程中,有使用扫描附近wifi这个feature,借鉴了ESP32官方的示例程序,在原esp-idf v5.0.1 上可以运行,esp-idf v5.2.1 中却扫描不到。
核心流程:就是在STA模式或STA+AP模式下,启动wifi(不连接)后,可以使用esp_wifi_scan_start()函数进行扫描,扫描后,使用 esp_wifi_scan_get_ap_num 和 esp_wifi_scan_get_ap_records 进行获取扫描的结果。

ESP32 使用 esp_wifi_scan_start 的一点小tips - 图1

问题解决方法

一顿“控制变量法”不断实验,以及深入阅读官方文档后,有了解决方案。

实验中发现

实验中发现,先 esp_wifi_scan_get_ap_num 后,再 esp_wifi_scan_get_ap_records 可以解决。

文档中发现

文档中发现:

ESP32 使用 esp_wifi_scan_start 的一点小tips - 图2


esp_wifi_scan_get_ap_records的一个个参数竟然是inout类型的,并且有Attention说调用后 will free all memory occupied by scanned AP list. 也就是再读取后会清除缓存?
所以再esp_wifi_scan_get_ap_num就读出的是0? 这是个人猜测。

最终解决办法

所以,最后的解决办法是,干脆只用esp_wifi_scan_get_ap_records 函数,不用 esp_wifi_scan_get_ap_num ,这样就OK了。

放一个代码片段:

#define DEFAULT_SCAN_LIST_SIZE     16
my_ap_wifi_info my_aps_info[DEFAULT_SCAN_LIST_SIZE];
uint16_t my_aps_num = 0;

    typedef struct 
{
    uint8_t ssid[33];
    int8_t  rssi;
    uint8_t rssi_level;
    uint8_t rssi_percent;
    uint8_t channel;
    bool needpsw;
} my_ap_wifi_info;

//不能在AP模式下扫描,需要启动wifi,但不能连接。
void wifi_scan(void){
    wifi_country_t country_config  = {
    .cc = "01",
    .schan = 1,
    .nchan = 11,
    .policy = WIFI_COUNTRY_POLICY_AUTO,
    };
    esp_wifi_set_country(&country_config);

    uint16_t ap_num = DEFAULT_SCAN_LIST_SIZE;
    wifi_ap_record_t ap_info[DEFAULT_SCAN_LIST_SIZE];
    uint16_t ap_count = 0;
    memset(ap_info, 0, sizeof(ap_info));

    static wifi_scan_config_t scanConf  = {
      .ssid = NULL,
      .bssid = NULL,
      .channel = 0,
      .show_hidden = 0,
      .scan_type = WIFI_SCAN_TYPE_ACTIVE,
      .scan_time.active.min = 0,
      .scan_time.active.max = 0,
    };//定义scanConf结构体,供函数esp_wifi_scan_start调用
    ESP_ERROR_CHECK(esp_wifi_scan_start(&scanConf, true));
    // ESP_ERROR_CHECK(esp_wifi_scan_get_ap_num(&ap_count));
    ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&ap_num, ap_info));
    // ESP_LOGI("[INFO]", "scan: %d", ap_num);
    my_aps_num = ap_num;
    if(my_aps_num > DEFAULT_SCAN_LIST_SIZE) 
        my_aps_num = DEFAULT_SCAN_LIST_SIZE; //只能装下这么多

    ESP_LOGI(TAG, "[Info] Total APs scanned = %u", my_aps_num);
    for (int i = 0; (i < DEFAULT_SCAN_LIST_SIZE) && (i < my_aps_num); i++) {
        strcpy(&my_aps_info[i].ssid, &ap_info[i].ssid);
        my_aps_info[i].rssi = ap_info[i].rssi;
        my_aps_info[i].rssi_level = rssi_to_5_level(ap_info[i].rssi);
        my_aps_info[i].rssi_percent = rssi_to_percent(ap_info[i].rssi);
        my_aps_info[i].channel = ap_info[i].primary;
        my_aps_info[i].needpsw = ap_info[i].authmode != WIFI_AUTH_OPEN;

        ESP_LOGI(TAG, "WIFI index \t\t%d", i+1);
        ESP_LOGI(TAG, "SSID \t\t\t%s----%s", my_aps_info[i].ssid, my_aps_info[i].needpsw?"有密码":"无密码");
        ESP_LOGI(TAG, "RSSI \t\t\t%d--%d--%d%%", my_aps_info[i].rssi, my_aps_info[i].rssi_level, my_aps_info[i].rssi_percent);
        ESP_LOGI(TAG, "Channel \t\t%d\n", my_aps_info[i].channel);
    }
}

一些小点

配置扫描的国家地区

    wifi_country_t country_config  = {
    .cc = "01",
    .schan = 1,
    .nchan = 11,
    .policy = WIFI_COUNTRY_POLICY_AUTO,
    };
    esp_wifi_set_country(&country_config);

参考官方api手册:https://docs.espressif.com/projects/esp-idf/zh_CN/v5.2.1/esp32c3/api-reference/network/esp_wifi.html?highlight=esp_wifi_scan_start#_CPPv420esp_wifi_set_countryPK14wifi_country_t

配置扫描的方式

    static wifi_scan_config_t scanConf  = {
      .ssid = NULL,
      .bssid = NULL,
      .channel = 0,
      .show_hidden = 0,
      .scan_type = WIFI_SCAN_TYPE_ACTIVE,
      .scan_time.active.min = 0,
      .scan_time.active.max = 0,
    };//定义scanConf结构体,供函数esp_wifi_scan_start调用
    ESP_ERROR_CHECK(esp_wifi_scan_start(&scanConf, true));

参数含义,具体详见官方api手册:https://docs.espressif.com/projects/esp-idf/zh_CN/v5.2.1/esp32c3/api-reference/network/esp_wifi.html?highlight=esp_wifi_scan_start#_CPPv419esp_wifi_scan_startPK18wifi_scan_config_tb
也可以用NULL,表示使用默认配置。

    ESP_ERROR_CHECK(esp_wifi_scan_start(NULL, true));

信号等级的转换

定义了2个小函数,将rssi变得可读性更高:

//将rssi转换成信号等级
uint8_t rssi_to_5_level(int8_t rssi){
    if(rssi <= -100)
        return 0;
    else if (rssi <= -88)
        return 1;
    else if (rssi <= -77)
        return 2;
    else if (rssi <= -55)
        return 3;
    else
        return 4;  
}
//将rssi转换成百分数
uint8_t rssi_to_percent(int8_t rssi){
    //-100:0    -50:100
    int8_t rssi_percent = 200 + rssi*2;
    if(rssi_percent > 100)
        rssi_percent = 100;
    else if(rssi_percent < 0)
        rssi_percent = 0;
    return rssi_percent;
}

来源:
链接:https://blog.csdn.net/weixin_43550576/article/details/137374231