3. WiFi 6 特性检测与报告

WiFi 6 特性检测与报告 学习卡片

任务目标

在 ESP32-S3 上检测当前 Wi-Fi 连接协商的协议版本,判断是否为 WiFi 6(802.11ax),并通过串口输出检测报告。本案例聚焦于利用 ESP-IDF 的事件回调机制获取 AP 侧实际协商的协议模式,不涉及吞吐量或信号质量测量。

环境依赖

  • 硬件:ESP32-S3-DevKitC 开发板(或兼容模组)
  • 软件:ESP-IDF v5.2 及以上版本(需启用 802.11ax 支持)
  • 路由器:支持 WiFi 6(802.11ax)且已开启该模式

实现原理

ESP-IDF 在 WIFI_EVENT_STA_CONNECTED 事件中通过 wifi_event_sta_connected_t 结构体提供 phy_mode 字段,该字段直接反映与 AP 协商成功的物理层协议模式。通过比较该枚举值与 WIFI_PHY_MODE_11AX 即可判定是否为 WiFi 6 连接。此方法比主动探测更可靠,因为它是芯片与 AP 完成握手后的真实协商结果。

完整代码

#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"

static const char *TAG = "wifi6_detect";
static EventGroupHandle_t s_wifi_event_group;
#define WIFI_CONNECTED_BIT BIT0

// 将 PHY 模式枚举转换为可读字符串
static const char* phy_mode_to_str(wifi_phy_mode_t mode) {
    switch(mode) {
        case WIFI_PHY_MODE_11B:     return "802.11b";
        case WIFI_PHY_MODE_11G:     return "802.11g";
        case WIFI_PHY_MODE_11N:     return "802.11n (WiFi 4)";
        case WIFI_PHY_MODE_LR:      return "LR mode";
        case WIFI_PHY_MODE_11A:     return "802.11a";
        case WIFI_PHY_MODE_11AC:    return "802.11ac (WiFi 5)";
        case WIFI_PHY_MODE_11AX:    return "802.11ax (WiFi 6)";
        default:                    return "UNKNOWN";
    }
}

static void event_handler(void* arg, esp_event_base_t event_base,
                          int32_t event_id, void* event_data) {
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
        esp_wifi_connect();
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
        esp_wifi_connect();
        ESP_LOGI(TAG, "重连中...");
    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
    }
}

// 连接事件中提取 PHY 模式并报告
static void wifi_connected_handler(void* arg, esp_event_base_t event_base,
                                   int32_t event_id, void* event_data) {
    wifi_event_sta_connected_t* data = (wifi_event_sta_connected_t*)event_data;
    ESP_LOGI(TAG, "已连接 AP: %s, 信道: %d",
             (char*)data->ssid, data->channel);
    ESP_LOGI(TAG, "协商 PHY 模式: %s", phy_mode_to_str(data->phy_mode));

    if (data->phy_mode == WIFI_PHY_MODE_11AX) {
        ESP_LOGI(TAG, ">>> 检测结果: 当前连接支持 WiFi 6 (802.11ax)");
    } else {
        ESP_LOGI(TAG, ">>> 检测结果: 当前连接不支持 WiFi 6");
    }
}

void app_main(void) {
    ESP_ERROR_CHECK(nvs_flash_init());
    s_wifi_event_group = xEventGroupCreate();

    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    esp_netif_create_default_wifi_sta();

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));

    // 注册事件回调
    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));
    // 关键:单独注册连接事件以获取 phy_mode
    ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED,
                                               &wifi_connected_handler, NULL));

    wifi_config_t wifi_config = {0};
    strcpy((char*)wifi_config.sta.ssid, CONFIG_ESP_WIFI_SSID);
    strcpy((char*)wifi_config.sta.password, CONFIG_ESP_WIFI_PASSWORD);
    wifi_config.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK;

    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
    ESP_ERROR_CHECK(esp_wifi_start());

    // 等待连接成功(带超时)
    EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
            WIFI_CONNECTED_BIT, pdFALSE, pdTRUE, pdMS_TO_TICKS(15000));
    if (bits & WIFI_CONNECTED_BIT) {
        ESP_LOGI(TAG, "WiFi 连接成功,PHY 模式报告完成");
    } else {
        ESP_LOGE(TAG, "连接超时,请检查 SSID/密码");
    }
}

运行配置

使用 menuconfig 配置 Wi-Fi 凭据:

idf.py menuconfig
# 进入 Example Connection Configuration
# 设置 WiFi SSID 和 Password
# 保存退出

编译并烧录:

idf.py build flash monitor

验证方法

观察串口监视器输出,判定标准如下:

  • 通过条件:日志中出现 协商 PHY 模式: 802.11ax (WiFi 6) 且检测结果为支持 WiFi 6。若路由器为 WiFi 5 或更早标准,应显示对应模式且报告不支持。
  • 功能验证:分别连接 WiFi 6 路由器(2.4GHz/5GHz 均开启 ax 模式)和旧标准路由器,对比输出差异。
  • 注意事项:部分路由器默认开启“WiFi 6 兼容模式”,此时可能协商为 802.11ax;若路由器关闭 ax 功能,则 ESP32-S3 会回退到 802.11n/ac,属正常现象。

常见问题

  • 编译错误:若提示 phy_mode 字段不存在,请确认 IDF 版本 ≥ v5.2 且未禁用 802.11ax 支持。
  • 始终显示 802.11n:检查路由器管理界面是否启用了“WiFi 6/802.11ax”模式,部分路由器需在 5GHz 频段单独开启。
  • 连接不稳定:若路由器开启 WPA3 且 ESP32-S3 固件不支持,可能导致连接失败,建议先使用 WPA2 测试。