ESP‑IDF 默认的连接流程是
确实,按官方文档,ESP‑IDF 默认的连接流程是:
-
按信号强度排序
在执行esp_wifi_connect()
时,底层会对「所有匹配目标 SSID 的 AP 列表」应用策略WIFI_CONNECT_AP_BY_SIGNAL
,即按照 RSSI 从大到小降序排列,并优先尝试连接信号最强的那台 AP (espressif-docs.readthedocs-hosted.com)。 -
扫描结果本身也是按 RSSI 排序
通过esp_wifi_scan_get_ap_records()
拿到的扫描列表,API 保证返回的记录已经按 RSSI 降序排列 (Espressif 文档)。
为什么有时会连到弱信号 AP?
-
没做「新一轮扫描」就连了
如果你直接调用esp_wifi_connect()
而没有先手动esp_wifi_scan_start()
+ 等待WIFI_EVENT_SCAN_DONE
,驱动会用「上次扫描」的缓存结果,可能那时信号最强的 AP 现在反而变弱了,但列表没更新,就依旧选它。 -
扫描-连接时序冲突
在WIFI_EVENT_STA_START
或其它地方触发了扫描,又立刻调用了esp_wifi_connect()
,有可能扫描还没完成就开始连接,于是使用了旧的或部分扫描结果中的第一个匹配项。 -
断线重连优先上次 BSSID
默认断线后重连,驱动会先尝试上次成功连接的 BSSID,再才按策略(信号或安全)去重选。 -
策略被改成「按安全优先」
在 menuconfig 里可切换策略为WIFI_CONNECT_AP_BY_SECURITY
(按安全性排序),这时即使信号弱,如果安全性更高也会被先尝试。
如何确保连到「当前」最强信号?
最稳妥的做法是 手动全流程:
-
调用
esp_wifi_scan_start(NULL, false);
并在事件回调里等待
WIFI_EVENT_SCAN_DONE
。 -
取最新列表:
uint16_t n = 0; esp_wifi_scan_get_ap_num(&n); wifi_ap_record_t *records = malloc(n * sizeof(*records)); esp_wifi_scan_get_ap_records(&n, records); // 由于 API 已经按 RSSI 降序,records[0] 即信号最强
-
强制指定 BSSID 连接:
wifi_config_t cfg = { 0 }; strcpy((char*)cfg.sta.ssid, TARGET_SSID); cfg.sta.bssid_set = true; memcpy(cfg.sta.bssid, records[0].bssid, 6); esp_wifi_set_config(WIFI_IF_STA, &cfg); esp_wifi_connect();
-
释放内存并处理连接事件。
通过这种方式,就能保证每次都拿到「实时扫描」里信号最强的那台 AP。