diff --git a/.idea/iOSAI.iml b/.idea/iOSAI.iml index df5cbff..6cb8b9a 100644 --- a/.idea/iOSAI.iml +++ b/.idea/iOSAI.iml @@ -1,8 +1,10 @@ - - + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index c27b771..db8786c 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -3,5 +3,5 @@ - + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 4dd45fc..7549b82 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -5,6 +5,8 @@ + + diff --git a/Module/DeviceInfo.py b/Module/DeviceInfo.py index 95dce34..05116b7 100644 --- a/Module/DeviceInfo.py +++ b/Module/DeviceInfo.py @@ -83,7 +83,6 @@ class Deviceinfo(object): # endregion def startDeviceListener(self): - """死循环监听设备插拔;以 deviceModelList 为准""" while True: try: lists = Usbmux().device_list() @@ -94,41 +93,30 @@ class Deviceinfo(object): now_udids = {d.udid for d in lists if d.conn_type == ConnectionType.USB} - # 0. 首次失踪登记:已在线设备若突然扫不到,计数器归零 + # 1. 失踪登记 & 累加 with self._lock: for udid in list(self._model_index.keys()): - if udid not in now_udids and udid not in self._miss_count: - self._miss_count[udid] = 0 - LogManager.info(f"[DEBUG] 首次失踪登记:{udid}", udid) - - # 1. 处理已在线设备的失联计数 - with self._lock: - for udid in list(self._miss_count.keys()): if udid not in now_udids: - self._miss_count[udid] += 1 - LogManager.info(f"[DEBUG] 累加 {udid} -> {self._miss_count[udid]}", udid) + self._miss_count[udid] = self._miss_count.get(udid, 0) + 1 if self._miss_count[udid] >= 3: - print("设备下线了") - LogManager.info(f"[DEBUG] 触发下线 {udid}", udid) self._remove_model(udid) self._miss_count.pop(udid, None) else: - LogManager.info(f"[DEBUG] 设备仍在,清零 {udid}", udid) - self._miss_count.pop(udid, None) + self._miss_count.pop(udid, None) # 设备又出现,清零 - # 2. 处理新插入 + # 2. 全新插入(只处理未在线且信任且未满) for d in lists: if d.conn_type != ConnectionType.USB: continue udid = d.udid with self._lock: if udid in self._model_index: - continue # 已存在 + continue # 已存在,跳过 if not self.is_device_trusted(udid): - LogManager.warning("设备未信任,跳过", udid) continue if len(self.deviceModelList) >= self.maxDeviceCount: continue + port = self._alloc_port() try: self.connectDevice(udid) # 内部会 _add_model except Exception as e: @@ -140,34 +128,55 @@ class Deviceinfo(object): # region ===================== 增删改查唯一入口(线程安全) ===================== def _has_model(self, udid: str) -> bool: - with self._lock: - return udid in self._model_index + return udid in self._model_index def _add_model(self, model: DeviceModel): - with self._lock: - if model.deviceId in self._model_index: - return # 防重复 - self.deviceModelList.append(model) - self._model_index[model.deviceId] = model - try: - self.manager.send(model.toDict()) - except Exception as e: - LogManager.warning(f"发送上线事件失败:{e}", model.deviceId) - LogManager.info(f"设备上线,当前在线数:{len(self.deviceModelList)}", model.deviceId) + if model.deviceId in self._model_index: + return # 防重复 + self.deviceModelList.append(model) + self._model_index[model.deviceId] = model + try: + self.manager.send(model.toDict()) + except Exception as e: + LogManager.warning(f"发送上线事件失败:{e}", model.deviceId) + LogManager.info(f"设备上线,当前在线数:{len(self.deviceModelList)}", model.deviceId) def _remove_model(self, udid: str): + print("进入删除方法") model = self._model_index.pop(udid, None) + print(model) if not model: + print("没有找到model") return model.type = 2 - print(model.toDict()) - # ① 关键:重试 3 次,必须送达,否则崩溃 + + # 内存结构删除 + try: + idx = self.deviceModelList.index(model) + self.deviceModelList.pop(idx) + except ValueError: + print("有错误了") + pass + + # 端口回收(关键) + self._free_port(model.screenPort) + + # 清理 iproxy + survivors = [item for item in self.pidList if item.get("id") != udid] + for item in self.pidList: + if item.get("id") == udid: + self._terminate_proc(item.get("target")) + self.pidList = survivors + + # Socket 发送(无锁) retry = 3 while retry: try: self.manager.send(model.toDict()) + print("删除了") break except Exception as e: + print("有问题了", e) retry -= 1 LogManager.error(f"发送下线事件失败,剩余重试 {retry}:{e}", udid) time.sleep(0.2) @@ -175,48 +184,22 @@ class Deviceinfo(object): LogManager.error("发送下线事件彻底失败,主动崩溃防止状态不一致", udid) os._exit(1) - # ② 安全删除 - try: - idx = self.deviceModelList.index(model) - self.deviceModelList.pop(idx) - print(len(self.deviceModelList)) - except Exception as e: - print("22222222") - print(f"[FlaskSubprocessManager] 发送失败,异常类型:{type(e).__name__},内容:{e}") - - - # ③ 回收端口 - self._free_port(model.screenPort) - - print("继续执行了") - - # ④ 清理 iproxy - survivors = [item for item in self.pidList if item.get("id") != udid] - for item in self.pidList: - if item.get("id") == udid: - self._terminate_proc(item.get("target")) - self.pidList = survivors - print("设备下线。删除设备成功") LogManager.info(f"设备下线,当前在线数:{len(self.deviceModelList)}", udid) - LogManager.info(f"[Deviceinfo] 下线包已送进队列 -> type=2", udid) - # endregion # region ===================== 端口分配与回收 ===================== def _alloc_port(self) -> int: - with self._lock: - if self._port_pool: - port = self._port_pool.pop() - else: - self.screenProxy += 1 - port = self.screenProxy - self._port_in_use.add(port) - return port + if self._port_pool: + port = self._port_pool.pop() + else: + self.screenProxy += 1 + port = self.screenProxy + self._port_in_use.add(port) + return port def _free_port(self, port: int): - with self._lock: - if port in self._port_in_use: - self._port_in_use.remove(port) - self._port_pool.append(port) + if port in self._port_in_use: + self._port_in_use.remove(port) + self._port_pool.append(port) # endregion # region ===================== 单台设备连接 ===================== @@ -255,12 +238,10 @@ class Deviceinfo(object): time.sleep(2) # 先清旧进程再启动新进程 - with self._lock: - self.pidList = [item for item in self.pidList if item.get("id") != udid] + self.pidList = [item for item in self.pidList if item.get("id") != udid] target = self.relayDeviceScreenPort(udid, port) if target: - with self._lock: - self.pidList.append({"target": target, "id": udid}) + self.pidList.append({"target": target, "id": udid}) # endregion diff --git a/Module/FlaskService.py b/Module/FlaskService.py index 04a9882..b1fe646 100644 --- a/Module/FlaskService.py +++ b/Module/FlaskService.py @@ -92,21 +92,18 @@ listener_thread.start() def deviceList(): try: with listLock: - # 1. 一次性消费完队列 + # 1. 消费完队列 while not dataQueue.empty(): obj = dataQueue.get() if obj["type"] == 1: + # 上线:先踢掉同 deviceId 的旧记录(端口可能变) + listData[:] = [d for d in listData if d.get("deviceId") != obj.get("deviceId")] listData.append(obj) else: - # 倒序删除,安全 - for i in range(len(listData) - 1, -1, -1): - d = listData[i] - if d.get("deviceId") == obj.get("deviceId") and \ - d.get("screenPort") == obj.get("screenPort"): - listData.pop(i) - break # 同一端口同一设备只删一次 + # 下线:只要同 deviceId 就删,不管端口 + listData[:] = [d for d in listData if d.get("deviceId") != obj.get("deviceId")] - # 2. 兜底:只保留 type == 1 的在线设备 + # 2. 兜底:只保留在线 listData[:] = [d for d in listData if d.get('type') == 1] return ResultData(data=listData.copy()).toJson()