增加监听投屏端口

This commit is contained in:
2025-10-31 13:19:55 +08:00
parent bde168df15
commit 54ee0f7490
7 changed files with 81 additions and 46 deletions

View File

@@ -10,7 +10,7 @@ import threading
import subprocess import subprocess
import socket import socket
from pathlib import Path from pathlib import Path
from typing import Dict, Optional from typing import Dict, Optional, List, Any
import platform import platform
import psutil import psutil
import http.client import http.client
@@ -116,45 +116,62 @@ class DeviceInfo:
self._iproxy_path = self._find_iproxy() self._iproxy_path = self._find_iproxy()
LogManager.info("DeviceInfo 初始化完成", udid="system") LogManager.info("DeviceInfo 初始化完成", udid="system")
print("[Init] DeviceInfo 初始化完成") print("[Init] DeviceInfo 初始化完成")
# 延迟执行删除设备方法
threading.Thread(target=self.readdDevice).start()
# 清空所有设备 threading.Thread(target=self.check_iproxy_ports).start()
def readdDevice(self):
print("开始自动删除设备")
second = 0 # =============== 核心:端口连通性检测 =================
def _is_local_port_open(self, port: int,udid:str, timeout: float = 5) -> bool:
print("开始监听剪口")
"""
Windows: 尝试连接 127.0.0.1:port能连上即认为端口可用iproxy 正在监听/转发)。
不抛异常,返回 True/False。
"""
if not isinstance(port, int) or port <= 0 or port > 65535:
LogManager.error("端口不可用",udid=udid)
return False
try:
print("尝试监听")
# create_connection 会在连接成功时立即返回 socket
with socket.create_connection(("127.0.0.1", int(port)), timeout=timeout):
print("端口正常")
return True
except OSError:
LogManager.error("端口不可用",udid=udid)
return False
# =============== 一轮检查:发现不通就移除 =================
def check_iproxy_ports(self, connect_timeout: float = 3) -> None:
time.sleep(60)
print("开始监听投屏端口")
while True: while True:
second += 1 snapshot = list(self._models.items()) # [(deviceId, DeviceModel), ...]
if second == 3555: for device_id, model in snapshot:
with self._lock: try:
# 先拍一张快照,避免“边遍历边修改” # 只处理在线且端口合法的设备
udids = list(self._models.keys()) if model.type != 1:
for udid in udids: continue
print(f"[Remove] 正在移除设备 {udid}") port = int(model.screenPort)
# 以 udid 为主键,逐个 pop if port <= 0 or port > 65535:
model = self._models.pop(udid, None) continue
proc = self._iproxy.pop(udid, None)
self._port_by_udid.pop(udid, None)
self._first_seen.pop(udid, None)
self._last_seen.pop(udid, None)
# 安全结束进程
self._kill(proc)
# 组一个“下线通知”的占位模型
if model is None:
model = DeviceModel(
deviceId=udid, screenPort=-1, width=0, height=0, scale=0.0, type=2
)
# 标记为“已移除/离线”
model.type = 2
model.ready = False
model.screenPort = -1
# 通知上层
self._manager_send(model)
print(f"[Remove] 已移除设备 {udid}")
second = 0
print(f"[Remove] 设备移除完成,总数: {len(udids)}")
time.sleep(1)
ok = self._is_local_port_open(port, timeout=connect_timeout, udid=device_id)
if not ok:
print(f"[iproxy-check] 端口不可连,移除设备 deviceId={device_id} port={port}")
try:
self._remove_device(device_id) # 这里面可安全地改 self._models
except Exception as e:
print(f"[iproxy-check] _remove_device 异常 deviceId={device_id}: {e}")
else:
# 心跳日志按需开启,避免刷屏
# print(f"[iproxy-check] OK deviceId={device_id} port={port}")
pass
except Exception as e:
print(f"[iproxy-check] 单设备检查异常: {e}")
# 8秒间隔
time.sleep(10)
def listen(self): def listen(self):
LogManager.method_info("进入主循环", "listen", udid="system") LogManager.method_info("进入主循环", "listen", udid="system")
@@ -242,10 +259,7 @@ class DeviceInfo:
if not self._wda_http_status_ok_once(udid): if not self._wda_http_status_ok_once(udid):
if major > 17: if major > 17:
print("进入iOS17设备的分支") print("进入iOS17设备的分支")
print(f"[WDA] iOS>17 调用 IOSActivator (port={wdaScreenPort})")
print("准备启动隧道")
out = IOSActivator().activate(udid) out = IOSActivator().activate(udid)
print("------------------",out)
print("wda启动完成") print("wda启动完成")
else: else:
print(f"[WDA] iOS<=17 启动 WDA app_start (port={wdaScreenPort})") print(f"[WDA] iOS<=17 启动 WDA app_start (port={wdaScreenPort})")
@@ -293,8 +307,13 @@ class DeviceInfo:
print(f"[Add] 设备添加成功 {udid}, port={port}, {w}x{h}@{s}") print(f"[Add] 设备添加成功 {udid}, port={port}, {w}x{h}@{s}")
def _remove_device(self, udid: str): def _remove_device(self, udid: str):
method = "_remove_device" """
移除设备及其转发,通知上层。
幂等:重复调用不会出错。
"""
print(f"[Remove] 正在移除设备 {udid}") print(f"[Remove] 正在移除设备 {udid}")
# --- 1. 锁内执行所有轻量字典操作 ---
with self._lock: with self._lock:
model = self._models.pop(udid, None) model = self._models.pop(udid, None)
proc = self._iproxy.pop(udid, None) proc = self._iproxy.pop(udid, None)
@@ -302,14 +321,30 @@ class DeviceInfo:
self._first_seen.pop(udid, None) self._first_seen.pop(udid, None)
self._last_seen.pop(udid, None) self._last_seen.pop(udid, None)
self._kill(proc) # --- 2. 锁外执行重操作 ---
# 杀进程
try:
self._kill(proc)
except Exception as e:
print(f"[Remove] 杀进程异常 {udid}: {e}")
# 准备下线模型model 可能为 None
if model is None: if model is None:
model = DeviceModel(deviceId=udid, screenPort=-1, width=0, height=0, scale=0.0, type=2) model = DeviceModel(
deviceId=udid, screenPort=-1, width=0, height=0, scale=0.0, type=2
)
# 标记状态为离线
model.type = 2 model.type = 2
model.ready = False model.ready = False
model.screenPort = -1 model.screenPort = -1
self._manager_send(model)
# 通知上层
try:
self._manager_send(model)
except Exception as e:
print(f"[Remove] 通知上层异常 {udid}: {e}")
print(f"[Remove] 设备移除完成 {udid}") print(f"[Remove] 设备移除完成 {udid}")
def _trusted(self, udid: str) -> bool: def _trusted(self, udid: str) -> bool:

View File

@@ -50,7 +50,7 @@ if __name__ == "__main__":
# 清空日志 # 清空日志
LogManager.clearLogs() LogManager.clearLogs()
main(sys.argv) # main(sys.argv)
# 添加iOS开发包到电脑上 # 添加iOS开发包到电脑上
deployer = DevDiskImageDeployer(verbose=True) deployer = DevDiskImageDeployer(verbose=True)

View File

@@ -26,7 +26,7 @@ def _force_utf8_everywhere():
except Exception: except Exception:
pass pass
_force_utf8_everywhere() # _force_utf8_everywhere()
class LogManager: class LogManager:
""" """