更新wifi连接的代码,改三角形的连接为1秒超时

This commit is contained in:
gcw_4spBpAfv
2026-05-13 16:08:00 +08:00
parent 0a1c7cff5c
commit 4b94e03413
7 changed files with 97 additions and 165 deletions

View File

@@ -239,127 +239,28 @@ class NetworkManager:
def connect_wifi(self, ssid, password, verify_host=None, verify_port=None, persist=True, timeout_s=20):
"""
连接 Wi-Fi委托 wifi_manager
Returns:
(ip, error): IP地址和错误信息成功时error为None
连接 Wi-Fi委托 ``wifi_manager.connect_wifi``。
未指定 ``verify_host``/``verify_port`` 时,可达性校验使用本管理器配置的 ``_server_ip``/``_server_port``。
"""
# 配置文件路径定义
conf_path = "/etc/wpa_supplicant.conf"
ssid_file = "/boot/wifi.ssid"
pass_file = "/boot/wifi.pass"
def _read_text(path: str):
def _verify(ip: str):
v_host = verify_host if verify_host is not None else self._server_ip
v_port = verify_port if verify_port is not None else self._server_port
try:
if os.path.exists(path):
with open(path, "r", encoding="utf-8") as f:
return f.read()
except Exception:
return None
return None
v_port_i = int(v_port) if v_port is not None else None
except (TypeError, ValueError):
v_port_i = None
if v_host and v_port_i:
if not self.is_server_reachable(v_host, v_port_i, timeout=5):
return False, f"Target unreachable ({v_host}:{v_port_i})"
return True, ""
def _write_text(path: str, content: str):
with open(path, "w", encoding="utf-8") as f:
f.write(content)
def _restore_boot(old_ssid: str | None, old_pass: str | None):
# 还原 /boot 凭证:原来没有就删除,原来有就写回
try:
if old_ssid is None:
if os.path.exists(ssid_file):
os.remove(ssid_file)
else:
_write_text(ssid_file, old_ssid)
except Exception:
pass
try:
if old_pass is None:
if os.path.exists(pass_file):
os.remove(pass_file)
else:
_write_text(pass_file, old_pass)
except Exception:
pass
old_conf = _read_text(conf_path)
old_boot_ssid = _read_text(ssid_file)
old_boot_pass = _read_text(pass_file)
try:
# 生成 wpa_supplicant 配置(写 /etc 作为辅助,具体是否生效取决于 S30wifi 脚本)
net_conf = os.popen(f'wpa_passphrase "{ssid}" "{password}"').read()
if "network={" not in net_conf:
raise RuntimeError("Failed to generate wpa config")
try:
_write_text(
conf_path,
"ctrl_interface=/var/run/wpa_supplicant\n"
"update_config=1\n\n"
+ net_conf,
)
except Exception:
# 不强制要求写 /etc 成功(某些系统只用 /boot
pass
# ====== 临时写入 /boot 凭证,触发 WiFi 服务真正尝试连接新 SSID ======
_write_text(ssid_file, ssid.strip())
_write_text(pass_file, password.strip())
# 重启 Wi-Fi 服务
os.system("/etc/init.d/S30wifi restart")
# 等待获取 IP
import time as std_time
wait_s = int(timeout_s) if timeout_s and timeout_s > 0 else 20
wait_s = min(max(wait_s, 5), 60)
for _ in range(wait_s):
ip = os.popen("ifconfig wlan0 2>/dev/null | grep 'inet ' | awk '{print $2}'").read().strip()
if ip:
# 拿到 IP 不代表可上网/可访问目标;继续做可达性验证
self._wifi_connected = True
self._wifi_ip = ip
self.logger.info(f"[WIFI] 已连接IP: {ip},开始验证网络可用性...")
# 验证能访问指定目标(默认使用 TCP 服务器)
v_host = verify_host if verify_host is not None else self._server_ip
v_port = int(verify_port) if verify_port is not None else int(self._server_port)
if v_host and v_port:
if not self.is_server_reachable(v_host, v_port, timeout=5):
raise RuntimeError(f"Target unreachable ({v_host}:{v_port})")
# ====== 验证通过 ======
if not persist:
# 不持久化:把 /boot 恢复成旧值(不重启,当前连接保持不变)
_restore_boot(old_boot_ssid, old_boot_pass)
self.logger.info("[WIFI] 网络验证通过,但按 persist=False 回滚 /boot 凭证(不重启)")
else:
self.logger.info("[WIFI] 网络验证通过,/boot 凭证已保留(持久化)")
return ip, None
std_time.sleep(1)
raise RuntimeError("Timeout: No IP obtained")
except Exception as e:
# 失败:回滚 /boot 和 /etc重启 WiFi 恢复旧网络
_restore_boot(old_boot_ssid, old_boot_pass)
try:
if old_conf is not None:
_write_text(conf_path, old_conf)
except Exception:
pass
try:
os.system("/etc/init.d/S30wifi restart")
except Exception:
pass
self._wifi_connected = False
self._wifi_ip = None
self.logger.error(f"[WIFI] 连接/验证失败,已回滚: {e}")
return None, str(e)
return wifi_manager.connect_wifi(
ssid,
password,
verify_callback=_verify,
persist=persist,
timeout_s=timeout_s,
)
def is_server_reachable(self, host, port=80, timeout=5):
"""检查目标主机端口是否可达(用于网络检测)"""
@@ -1157,7 +1058,6 @@ class NetworkManager:
v_port = parsed.port or (443 if parsed.scheme == "https" else 80)
except Exception:
v_host, v_port = None, None
ip, error = self.connect_wifi(
wifi_ssid,
wifi_password,
@@ -2036,6 +1936,8 @@ class NetworkManager:
self.logger.error("ota wifi mode requires ssid and password")
self.safe_enqueue({"result": "missing_ssid_or_password"}, 2)
else:
self.logger.info(f"ssid: {ssid}")
self.logger.info(f"password: {password}")
ota_manager._start_update_thread()
_thread.start_new_thread(ota_manager.handle_wifi_and_update, (ssid, password, ota_url))
elif inner_cmd == 6: