如何在Lua应用与Shell脚本中高效使用wpa_supplicant管理WiFi连接
基于wpa_supplicant的WiFi连接管理优化方案
1. 用wpa_supplicant控制接口替代ping轮询,实时获取连接状态
原来靠定时ping公共DNS判断连接状态,不仅延迟高,还浪费系统资源。直接利用wpa_supplicant自带的wpa_cli工具,通过控制接口实时获取连接状态:
- 启动wpa_supplicant时指定控制接口:
wpa_supplicant -B -D nl80211 -i wlan0 -c /etc/wpa_supplicant.conf -C /var/run/wpa_supplicant - 执行
wpa_cli -i wlan0 status,解析输出中的wpa_state核心字段:COMPLETED:已成功连接WiFi并获取IPDISCONNECTED:未处于连接状态ASSOCIATING/AUTHENTICATING:正在连接过程中
- Lua代码直接调用该命令解析结果,无需依赖Shell脚本写文件,示例:
function get_wifi_connection_state() local handle = io.popen("wpa_cli -i wlan0 status 2>/dev/null") if not handle then return "DISCONNECTED" end local output = handle:read("*a") handle:close() local wpa_state = output:match("wpa_state=(%w+)") return wpa_state or "DISCONNECTED" end
2. 合并WiFi配置文件,让wpa_supplicant自动管理连接优先级
原来每个SSID单独一个配置文件,管理繁琐且无法利用wpa_supplicant的自动选网能力:
- 把所有已保存的WiFi配置合并到一个
/etc/wpa_supplicant.conf文件,每个网络用network块定义:
ctrl_interface=/var/run/wpa_supplicant ap_scan=1 network={ ssid="YourWiFi1" psk="yourpassword1" priority=10 # 数值越高,连接优先级越高 } network={ ssid="YourWiFi2" psk="yourpassword2" priority=5 }
- 配置完成后,wpa_supplicant会自动扫描并尝试连接优先级最高的可用已知网络,无需Lua手动遍历选择
3. 优化重连逻辑,避免频繁重启wpa_supplicant
原来每次重连都kill并重启wpa_supplicant,会导致不必要的服务中断,改用wpa_cli的控制命令实现平滑切换:
- 当需要切换网络时,先通过
wpa_cli -i wlan0 list_networks获取所有已配置网络的ID - 用
wpa_cli -i wlan0 select_network <network_id>指定连接目标网络 - 仅当wpa_supplicant进程异常时,才执行重启操作
- 修改原
First_Connection_Wifi函数,去掉killall逻辑,改为调用wpa_cli命令:
function First_Connection_Wifi(mapargs) local current_state = get_wifi_connection_state() if current_state == "COMPLETED" then return end -- 获取扫描结果 local scan_handle = io.popen("wpa_cli -i wlan0 scan_results 2>/dev/null") if not scan_handle then return end local scan_output = scan_handle:read("*a") scan_handle:close() -- 获取已配置网络列表 local networks_handle = io.popen("wpa_cli -i wlan0 list_networks 2>/dev/null") if not networks_handle then return end local networks_output = networks_handle:read("*a") networks_handle:close() -- 匹配可用的已配置网络并触发连接 for line in networks_output:gmatch("[^\n]+") do local id, ssid = line:match("(%d+)%s+([^%s]+)%s+.*") if id and ssid and scan_output:find(ssid, 1, true) then os.execute("wpa_cli -i wlan0 select_network " .. id .. " &") Tempo_Last_Check_Connection = gre.mstime() / 1000 return end end end
4. 优化WiFi扫描逻辑,减少资源消耗
原来固定10秒扫描一次,改为按需扫描降低资源占用:
- 仅当连接断开时触发扫描,或者当当前连接信号强度低于阈值时(通过
iwconfig wlan0获取信号强度)触发扫描 - 用
wpa_cli -i wlan0 scan触发扫描,扫描完成后用scan_results获取结果,避免直接调用iwlist
5. 简化连接状态判断逻辑
去掉原Lua代码中依赖/tmp/connesso文件的轮询逻辑,改用定时调用状态获取函数:
-- 替换原有的counter_500ms相关逻辑 if counter_500ms % 10 == 0 then local wpa_state = get_wifi_connection_state() if wpa_state == "COMPLETED" then print("connesso") Connesso_A_Internet = true Tempo_Last_Check_Connection = gre.mstime() / 1000 else if Connesso_A_Internet then -- 之前已连接,现在断开,等待20秒后尝试重连 if math.abs(Tempo_Last_Check_Connection - gre.mstime() / 1000) >= 20 then Connesso_A_Internet = false First_Connection_Wifi(mapargs) end else -- 未连接,间隔20秒尝试重连 if math.abs(Tempo_Last_Check_Connection - gre.mstime() / 1000) >= 20 then First_Connection_Wifi(mapargs) end end end end
内容的提问来源于stack exchange,提问作者Merlin
相关产品推荐
相关产品推荐

