更新wifi连接的代码,改三角形的连接为1秒超时
This commit is contained in:
140
network.py
140
network.py
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user