diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 23d048a..c8c4583 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -4,14 +4,10 @@
-
-
-
+
-
-
+
-
@@ -70,7 +66,7 @@
"git-widget-placeholder": "main",
"javascript.nodejs.core.library.configured.version": "20.17.0",
"javascript.nodejs.core.library.typings.version": "20.17.58",
- "last_opened_file_path": "C:/Users/zhangkai/Desktop/20250915 iosao-随机点击坐标/iOSAI",
+ "last_opened_file_path": "F:/company code/AI item/20250820/iOSAI",
"node.js.detected.package.eslint": "true",
"node.js.detected.package.tslint": "true",
"node.js.selected.package.eslint": "(autodetect)",
@@ -190,8 +186,7 @@
-
-
+
@@ -257,8 +252,6 @@
-
-
@@ -330,8 +323,8 @@
-
+
@@ -339,7 +332,7 @@
-
-
+
+
\ No newline at end of file
diff --git a/Entity/DeviceModel.py b/Entity/DeviceModel.py
index d0108bf..cddf3c0 100644
--- a/Entity/DeviceModel.py
+++ b/Entity/DeviceModel.py
@@ -1,3 +1,5 @@
+from getpass import fallback_getpass
+
# 设备模型
class DeviceModel(object):
@@ -16,6 +18,7 @@ class DeviceModel(object):
# 1 添加 2删除
self.type = type
self.ready = False
+ self.deleting = False
# 转字典
def toDict(self):
diff --git a/Module/DeviceInfo.py b/Module/DeviceInfo.py
index d4f8d74..abf031f 100644
--- a/Module/DeviceInfo.py
+++ b/Module/DeviceInfo.py
@@ -97,15 +97,20 @@ class Deviceinfo(object):
now_udids = {d.udid for d in lists if d.conn_type == ConnectionType.USB}
# 1. 失踪登记 & 累加
+ need_remove = None # ← 新增:放锁外记录
with self._lock:
for udid in list(self._model_index.keys()):
if udid not in now_udids:
self._miss_count[udid] = self._miss_count.get(udid, 0) + 1
if self._miss_count[udid] >= 3:
- self._remove_model(udid)
self._miss_count.pop(udid, None)
+ need_remove = udid # ← 只记录,不调用
else:
- self._miss_count.pop(udid, None) # 设备又出现,清零
+ self._miss_count.pop(udid, None)
+
+ # 🔓 锁已释放,再删设备(不会重入)
+ if need_remove:
+ self._remove_model(need_remove)
# 2. 全新插入(只处理未在线且信任且未满)
for d in lists:
@@ -114,13 +119,13 @@ class Deviceinfo(object):
udid = d.udid
with self._lock:
if udid in self._model_index:
- continue # 已存在,跳过
+ continue
if not self.is_device_trusted(udid):
continue
if len(self.deviceModelList) >= self.maxDeviceCount:
continue
try:
- self.connectDevice(udid) # 内部会 _add_model
+ self.connectDevice(udid)
except Exception as e:
LogManager.error(f"连接设备失败 {udid}: {e}", udid)
@@ -175,50 +180,80 @@ class Deviceinfo(object):
self.manager.send(model.toDict())
except Exception as e:
LogManager.warning(f"{model.deviceId} 发送上线事件失败:{e}")
- LogManager.info(f"{model.deviceId} 设备上线,当前在线数:{len(self.deviceModelList)}")
+ LogManager.method_info(f"{model.deviceId} 加入设备成功,当前在线数:{len(self.deviceModelList)}",method="device_count")
+
# 删除设备
def _remove_model(self, udid: str):
- """线程安全:把设备从内存、端口、iproxy 完全抹掉"""
- model = self._model_index.pop(udid, None)
- if not model:
- LogManager.error(f"没有找到需要删除的设备 {udid}")
- return
- model.type = 2
+ print(f"【删】进入删除方法 udid={udid}")
+ LogManager.method_info(f"【删】进入删除方法 udid={udid}", method="device_count")
+ # 1. 纯内存临界区——毫秒级
+ with self._lock:
+ print(f"【删】拿到锁 udid={udid}")
+ LogManager.method_info(f"【删】拿到锁 udid={udid}",
+ method="device_count")
+ model = self._model_index.pop(udid, None)
+ if not model:
+ print(f"【删】模型已空,直接返回 udid={udid}")
+ LogManager.method_info(f"【删】模型已空,直接返回 udid={udid}",method="device_count")
+ return
+ if model.deleting:
+ print(f"【删】正在删除中,幂等返回 udid={udid}")
+ LogManager.method_info(method="device_count", text=f"【删】正在删除中,幂等返回 udid={udid}")
+ return
+ model.deleting = True
+ # 标记维删除设备
+ model.type = 2
+ print(f"【删】标记 deleting=True udid={udid}")
+ LogManager.method_info("【删】标记 deleting=True udid={udid}","device_count")
+ # 过滤列表
+ before = len(self.deviceModelList)
+ self.deviceModelList = [m for m in self.deviceModelList if m.deviceId != udid]
+ after = len(self.deviceModelList)
+ print(f"【删】列表过滤 before={before} → after={after} udid={udid}")
+ LogManager.method_info(f"【删】列表过滤 before={before} → after={after} udid={udid}","device_count")
- # 1. 内存列表删除
- try:
- self.deviceModelList.remove(model)
- except ValueError:
- pass
+ # 端口
+ self._port_in_use.discard(model.screenPort)
+ self._port_pool.append(model.screenPort)
+ print(f"【删】回收端口 port={model.screenPort} udid={udid}")
+ LogManager.method_info(f"【删】回收端口 port={model.screenPort} udid={udid}", method="device_count")
- # 2. 端口回收
- self._free_port(model.screenPort)
+ # 进程
+ to_kill = [item for item in self.pidList if item.get("id") == udid]
+ self.pidList = [item for item in self.pidList if item.get("id") != udid]
+ print(f"【删】待杀进程数 count={len(to_kill)} udid={udid}")
+ LogManager.method_info(f"【删】待杀进程数 count={len(to_kill)} udid={udid}", method="device_count")
- # 3. 原子化清理 iproxy(确保进程彻底死)
- to_kill, survivors = [], []
- for item in self.pidList:
- (to_kill if item.get("id") == udid else survivors).append(item)
+ # 2. IO 区无锁
+ for idx, item in enumerate(to_kill, 1):
+ print(f"【删】杀进程 {idx}/{len(to_kill)} pid={item.get('target').pid} udid={udid}")
+ LogManager.method_error(f"【删】杀进程 {idx}/{len(to_kill)} pid={item.get('target').pid} udid={udid}", method="device_count")
+ self._terminate_proc(item.get("target"))
+ print(f"【删】进程清理完成 udid={udid}")
+ LogManager.method_info(f"【删】进程清理完成 udid={udid}", method="device_count")
- for item in to_kill:
- self._terminate_proc(item.get("target")) # 下面也给了加强版实现
-
- self.pidList = survivors
- LogManager.info(f"设备下线 {udid},当前在线数:{len(self.deviceModelList)}")
-
- # 4. 发 Socket
+ # 3. 网络 IO
retry = 3
while retry:
try:
self.manager.send(model.toDict())
+ print(f"【删】下线事件已发送 udid={udid}")
+ LogManager.method_info(f"【删】下线事件已发送 udid={udid}", method="device_count")
break
except Exception as e:
retry -= 1
- LogManager.error(f"发送下线事件失败,{udid} 剩余重试 {retry}:{e}")
+ print(f"【删】发送事件失败 retry={retry} err={e} udid={udid}")
+ LogManager.method_error(f"【删】发送事件失败 retry={retry} err={e} udid={udid}", method="device_count")
time.sleep(0.2)
else:
- LogManager.error(f"发送下线事件彻底失败,{udid} 主动崩溃防止状态不一致")
- os._exit(1)
+ print(f"【删】发送事件彻底失败,主动退出 udid={udid}")
+ LogManager.method_error(f"【删】发送事件彻底失败,主动退出 udid={udid}", method="device_count")
+
+ print(f"【删】===== 设备 {udid} 删除全流程结束 =====")
+ LogManager.method_info(f"【删】===== 设备 {udid} 删除全流程结束 =====", method="device_count")
+ print(len(self.deviceModelList))
+ LogManager.method_info(f"当前剩余设备数量:{len(self.deviceModelList)}", method="device_count")
# region ===================== 端口分配与回收 =====================
def _alloc_port(self) -> int:
@@ -274,8 +309,6 @@ class Deviceinfo(object):
if target:
self.pidList.append({"target": target, "id": udid})
- # endregion
-
# region ===================== 工具方法 =====================
def is_device_trusted(self, udid: str) -> bool:
try:
diff --git a/Utils/ControlUtils.py b/Utils/ControlUtils.py
index d695646..d540c51 100644
--- a/Utils/ControlUtils.py
+++ b/Utils/ControlUtils.py
@@ -211,22 +211,8 @@ class ControlUtils(object):
# 点击一个随机范围
@classmethod
def tap_mini_cluster(cls, center_x: int, center_y: int, session, points=5, duration_ms=60):
- """
- 以 (center_x, center_y) 为中心,在 3×3 像素范围内摆 `points` 个邻近坐标,
- 一次性同时按下,持续 `duration_ms` 后抬起。
- """
- # 1. 生成邻像素坐标(±1 像素内)
- cluster = []
- for i in range(points):
- dx = random.randint(-1, 1)
- dy = random.randint(-1, 1)
- cluster.append((center_x + dx, center_y + dy))
+ pass
- # 2. 随机持续时间 50–100 ms
- duration_s = random.randint(50, 100) / 1000.0
-
- # 3. 下发多点触控
- session.tap_hold_coords(cluster, duration=duration_s)
# 检测五分钟前和当前的状态是否相同
# @classmethod
# def compareCurrentWithPreviousState(cls,xml):
diff --git a/Utils/LogManager.py b/Utils/LogManager.py
index a39050c..67e8a24 100644
--- a/Utils/LogManager.py
+++ b/Utils/LogManager.py
@@ -240,7 +240,7 @@ def _force_utf8_everywhere():
except Exception:
pass
-_force_utf8_everywhere()
+# _force_utf8_everywhere()
# ========= 全局:强制 UTF-8 + 关闭缓冲(运行期立刻生效) =========