fix(provision): treat WiFi join success by STA state, not internet ping
This commit is contained in:
@@ -124,7 +124,9 @@ class CaptiveServer {
|
|||||||
// 延迟执行,确保 HTTP 响应送达
|
// 延迟执行,确保 HTTP 响应送达
|
||||||
if (this._onConnect) {
|
if (this._onConnect) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this._onConnect(ssid, password || '');
|
Promise.resolve(this._onConnect(ssid, password || '')).catch((e) => {
|
||||||
|
log.error('http', '配网回调异常:', e.message);
|
||||||
|
});
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 }}
|
* @returns {{ success: boolean, error?: string }}
|
||||||
*/
|
*/
|
||||||
function connectWifi(ssid, password) {
|
function connectWifi(ssid, password) {
|
||||||
@@ -205,15 +209,24 @@ function connectWifi(ssid, password) {
|
|||||||
try { run(`nmcli connection delete "${ssid}"`); } catch (_) {}
|
try { run(`nmcli connection delete "${ssid}"`); } catch (_) {}
|
||||||
|
|
||||||
const pwdArg = password ? `password "${password}"` : '';
|
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);
|
||||||
|
|
||||||
// 验证连通性
|
const deadline = Date.now() + CONNECT_WIFI_STA_WAIT_MS;
|
||||||
sleep(3000);
|
while (Date.now() < deadline) {
|
||||||
|
if (isWifiStaConnected()) {
|
||||||
if (hasInternet()) {
|
if (hasInternet()) {
|
||||||
log.info('network', `WiFi 已连接: ${ssid}`);
|
log.info('network', `WiFi 已连接且有外网: ${ssid}`);
|
||||||
|
} else {
|
||||||
|
log.warn(
|
||||||
|
'network',
|
||||||
|
`WiFi STA 已连接(${ssid}),暂未检测到外网;配网仍视为成功(内网/防火墙/国内 DNS 常见)`,
|
||||||
|
);
|
||||||
|
}
|
||||||
return { success: true };
|
return { success: true };
|
||||||
}
|
}
|
||||||
return { success: false, error: '已连接但无法访问互联网' };
|
sleep(CONNECT_WIFI_STA_POLL_MS);
|
||||||
|
}
|
||||||
|
return { success: false, error: '超时:网卡未进入已连接状态' };
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log.error('network', `WiFi 连接失败: ${e.message}`);
|
log.error('network', `WiFi 连接失败: ${e.message}`);
|
||||||
return { success: false, error: 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');
|
const out = run('nmcli -t -f DEVICE,TYPE,STATE,CONNECTION device');
|
||||||
for (const line of out.split('\n')) {
|
for (const line of out.split('\n')) {
|
||||||
const parts = line.split(':');
|
const parts = line.split(':');
|
||||||
if (parts[0] === iface && parts[1] === 'wifi' && parts[2] === 'connected') {
|
const dev = (parts[0] || '').trim();
|
||||||
return parts[3] !== CON_NAME;
|
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 (_) {}
|
} catch (_) {}
|
||||||
|
|||||||
@@ -163,6 +163,9 @@ class ProvisionManager extends EventEmitter {
|
|||||||
|
|
||||||
this._stopAPServices();
|
this._stopAPServices();
|
||||||
|
|
||||||
|
// 关热点后射频/模式切换需要时间,立刻 connect 在部分板子上会失败
|
||||||
|
await new Promise((r) => setTimeout(r, 2500));
|
||||||
|
|
||||||
const result = connectWifi(ssid, password);
|
const result = connectWifi(ssid, password);
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
|
|||||||
Reference in New Issue
Block a user