下面给出一份基于 ESP32‑C3 + ESP‑IDF 的示例代码,演示如何在存在多个同名 SSID 的环境中,选取信号最强的那个 AP(通过 BSSID 做唯一标识)并连接。
思路:
发起一次扫描,扫描所有信道;
在扫描结果中筛选出与目标 SSID 名称相同的条目,比较它们的 RSSI,选出最强信号对应的 BSSID;
使用
wifi_config_t.sta.bssid_set = true
+ 填入选中的 BSSID,再调用esp_wifi_connect()
。
#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 = "c3_best_ap";
static const char *TARGET_SSID = "YOUR_SSID"; // ← 替换为你要连接的 SSID 名称
// 事件组,用于等待扫描完成和连接成功
static EventGroupHandle_t s_wifi_event_group;
#define SCAN_DONE_BIT BIT0
#define CONNECTED_BIT BIT1
// 最佳 AP 信息
static wifi_ap_record_t best_ap;
// Wi‑Fi 事件回调
static void
wifi_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_SCAN_DONE) {
ESP_LOGI(TAG, "Scan done, selecting strongest AP...");
uint16_t ap_count = 0;
esp_wifi_scan_get_ap_num(&ap_count);
wifi_ap_record_t *ap_list =
calloc(ap_count, sizeof(wifi_ap_record_t));
esp_wifi_scan_get_ap_records(&ap_count, ap_list);
bool found = false;
for (int i = 0; i < ap_count; i++) {
if (strcmp((char*)ap_list[i].ssid, TARGET_SSID) == 0) {
ESP_LOGD(TAG, "Found SSID %s, BSSID " MACSTR ", RSSI %d",
ap_list[i].ssid,
MAC2STR(ap_list[i].bssid),
ap_list[i].rssi);
if (!found || ap_list[i].rssi > best_ap.rssi) {
best_ap = ap_list[i];
found = true;
}
}
}
free(ap_list);
if (found) {
ESP_LOGI(TAG,
"Will connect to BSSID " MACSTR " with RSSI %d",
MAC2STR(best_ap.bssid), best_ap.rssi);
xEventGroupSetBits(s_wifi_event_group, SCAN_DONE_BIT);
} else {
ESP_LOGW(TAG, "No AP with SSID \"%s\" found!", TARGET_SSID);
// 也可以重试 scan:esp_wifi_scan_start(...)
}
}
else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
ESP_LOGI(TAG, "WiFi inited, start scan");
esp_wifi_scan_start(NULL, false);
}
else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_CONNECTED) {
ESP_LOGI(TAG, "Connected to AP");
xEventGroupSetBits(s_wifi_event_group, CONNECTED_BIT);
}
else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
ip_event_got_ip_t* evt = (ip_event_got_ip_t*)event_data;
ESP_LOGI(TAG, "Got IP:" IPSTR, IP2STR(&evt->ip_info.ip));
}
}
// 初始化 Wi‑Fi 并启动 STA
static void wifi_init_and_start(void)
{
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES ||
ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
nvs_flash_erase();
nvs_flash_init();
}
s_wifi_event_group = xEventGroupCreate();
esp_netif_init();
esp_event_loop_create_default();
esp_netif_create_default_wifi_sta();
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
esp_wifi_init(&cfg);
// 注册事件
esp_event_handler_instance_t instance_any_id;
esp_event_handler_instance_t instance_got_ip;
esp_event_handler_instance_register(WIFI_EVENT,
ESP_EVENT_ANY_ID,
wifi_event_handler,
NULL,
&instance_any_id);
esp_event_handler_instance_register(IP_EVENT,
IP_EVENT_STA_GOT_IP,
wifi_event_handler,
NULL,
&instance_got_ip);
// STA 模式启动
esp_wifi_set_mode(WIFI_MODE_STA);
esp_wifi_start();
}
void app_main(void)
{
// 1. 初始化并启动 Wi‑Fi
wifi_init_and_start();
// 2. 等待扫描完成
EventBits_t bits = xEventGroupWaitBits(
s_wifi_event_group,
SCAN_DONE_BIT,
pdFALSE, pdFALSE,
portMAX_DELAY);
if (bits & SCAN_DONE_BIT) {
// 3. 根据 best_ap 填写连接配置
wifi_config_t sta_cfg = { 0 };
strcpy((char*)sta_cfg.sta.ssid, TARGET_SSID);
// 如果是开放网络,此处 pwd 可以留空
strcpy((char*)sta_cfg.sta.password, "YOUR_PASSWORD");
sta_cfg.sta.bssid_set = true;
memcpy(sta_cfg.sta.bssid, best_ap.bssid, 6);
sta_cfg.sta.channel = best_ap.primary; // 可选:绑定信道加速连接
ESP_LOGI(TAG, "Connecting to selected AP ...");
esp_wifi_set_config(WIFI_IF_STA, &sta_cfg);
esp_wifi_connect();
// 4. 等待连接结果
bits = xEventGroupWaitBits(
s_wifi_event_group,
CONNECTED_BIT,
pdFALSE, pdFALSE,
pdMS_TO_TICKS(10000));
if (bits & CONNECTED_BIT) {
ESP_LOGI(TAG, "Successfully connected to best AP");
} else {
ESP_LOGE(TAG, "Failed to connect to best AP");
}
}
}
关键说明
-
扫描:调用
esp_wifi_scan_start(NULL, false)
扫描所有信道 -
筛选同名 SSID:遍历
wifi_ap_record_t
数组,比较rssi
,记录最强信号对应的bssid
-
强制 BSSID 连接:在
wifi_config_t.sta
中设置.bssid_set = true
且填入bssid[6]
,还可指定channel
加速连接 -
事件同步:使用 FreeRTOS 事件组等待扫描完成及连接成功
这样就能确保 ESP32‑C3 始终连接到信号最强的同名 AP。