fix(provision): treat WiFi join success by STA state, not internet ping

This commit is contained in:
stswangzhiping
2026-03-29 07:10:43 +08:00
parent 2ec02d71bb
commit 012ad90335
3 changed files with 33 additions and 11 deletions

View File

@@ -124,7 +124,9 @@ class CaptiveServer {
// 延迟执行,确保 HTTP 响应送达
if (this._onConnect) {
setTimeout(() => {
this._onConnect(ssid, password || '');
Promise.resolve(this._onConnect(ssid, password || '')).catch((e) => {
log.error('http', '配网回调异常:', e.message);
});
}, 1000);
}
}

View File

@@ -193,8 +193,12 @@ function scanWifi() {
}
}
/** AP 切 STA 后等待网卡进入 connected 的最长时间(不依赖外网探测) */
const CONNECT_WIFI_STA_WAIT_MS = 25_000;
const CONNECT_WIFI_STA_POLL_MS = 1_000;
/**
* 连接指定 WiFi
* 连接指定 WiFi(配网场景:成功 = NM 显示 STA 已连上目标网,不要求一定能 ping 通 8.8.8.8
* @returns {{ success: boolean, error?: string }}
*/
function connectWifi(ssid, password) {
@@ -205,15 +209,24 @@ function connectWifi(ssid, password) {
try { run(`nmcli connection delete "${ssid}"`); } catch (_) {}
const pwdArg = password ? `password "${password}"` : '';
run(`nmcli device wifi connect "${ssid}" ${pwdArg} ifname ${iface}`, 30000);
run(`nmcli device wifi connect "${ssid}" ${pwdArg} ifname ${iface}`, 60000);
// 验证连通性
sleep(3000);
if (hasInternet()) {
log.info('network', `WiFi 已连接: ${ssid}`);
return { success: true };
const deadline = Date.now() + CONNECT_WIFI_STA_WAIT_MS;
while (Date.now() < deadline) {
if (isWifiStaConnected()) {
if (hasInternet()) {
log.info('network', `WiFi 已连接且有外网: ${ssid}`);
} else {
log.warn(
'network',
`WiFi STA 已连接(${ssid}),暂未检测到外网;配网仍视为成功(内网/防火墙/国内 DNS 常见)`,
);
}
return { success: true };
}
sleep(CONNECT_WIFI_STA_POLL_MS);
}
return { success: false, error: '已连接但无法访问互联网' };
return { success: false, error: '超时:网卡未进入已连接状态' };
} catch (e) {
log.error('network', `WiFi 连接失败: ${e.message}`);
return { success: false, error: e.message };
@@ -308,8 +321,12 @@ function isWifiStaConnected() {
const out = run('nmcli -t -f DEVICE,TYPE,STATE,CONNECTION device');
for (const line of out.split('\n')) {
const parts = line.split(':');
if (parts[0] === iface && parts[1] === 'wifi' && parts[2] === 'connected') {
return parts[3] !== CON_NAME;
const dev = (parts[0] || '').trim();
const type = (parts[1] || '').trim();
const state = (parts[2] || '').trim();
const conn = (parts[3] || '').trim();
if (dev === iface && type === 'wifi' && state === 'connected') {
return conn !== CON_NAME;
}
}
} catch (_) {}

View File

@@ -163,6 +163,9 @@ class ProvisionManager extends EventEmitter {
this._stopAPServices();
// 关热点后射频/模式切换需要时间,立刻 connect 在部分板子上会失败
await new Promise((r) => setTimeout(r, 2500));
const result = connectWifi(ssid, password);
if (result.success) {