增加监听投屏端口

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 socket
from pathlib import Path
from typing import Dict, Optional
from typing import Dict, Optional, List, Any
import platform
import psutil
import http.client
@@ -116,45 +116,62 @@ class DeviceInfo:
self._iproxy_path = self._find_iproxy()
LogManager.info("DeviceInfo 初始化完成", udid="system")
print("[Init] DeviceInfo 初始化完成")
# 延迟执行删除设备方法
threading.Thread(target=self.readdDevice).start()
# 清空所有设备
def readdDevice(self):
print("开始自动删除设备")
second = 0
threading.Thread(target=self.check_iproxy_ports).start()
# =============== 核心:端口连通性检测 =================
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:
second += 1
if second == 3555:
with self._lock:
# 先拍一张快照,避免“边遍历边修改”
udids = list(self._models.keys())
for udid in udids:
print(f"[Remove] 正在移除设备 {udid}")
# 以 udid 为主键,逐个 pop
model = self._models.pop(udid, None)
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)
snapshot = list(self._models.items()) # [(deviceId, DeviceModel), ...]
for device_id, model in snapshot:
try:
# 只处理在线且端口合法的设备
if model.type != 1:
continue
port = int(model.screenPort)
if port <= 0 or port > 65535:
continue
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):
LogManager.method_info("进入主循环", "listen", udid="system")
@@ -242,10 +259,7 @@ class DeviceInfo:
if not self._wda_http_status_ok_once(udid):
if major > 17:
print("进入iOS17设备的分支")
print(f"[WDA] iOS>17 调用 IOSActivator (port={wdaScreenPort})")
print("准备启动隧道")
out = IOSActivator().activate(udid)
print("------------------",out)
print("wda启动完成")
else:
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}")
def _remove_device(self, udid: str):
method = "_remove_device"
"""
移除设备及其转发,通知上层。
幂等:重复调用不会出错。
"""
print(f"[Remove] 正在移除设备 {udid}")
# --- 1. 锁内执行所有轻量字典操作 ---
with self._lock:
model = self._models.pop(udid, None)
proc = self._iproxy.pop(udid, None)
@@ -302,14 +321,30 @@ class DeviceInfo:
self._first_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:
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.ready = False
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}")
def _trusted(self, udid: str) -> bool:

View File

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

View File

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