完善tidevice逻辑
This commit is contained in:
8
.idea/workspace.xml
generated
8
.idea/workspace.xml
generated
@@ -6,9 +6,14 @@
|
|||||||
<component name="ChangeListManager">
|
<component name="ChangeListManager">
|
||||||
<list default="true" id="eceeff5e-51c1-459c-a911-d21ec090a423" name="Changes" comment="20250904-初步功能已完成">
|
<list default="true" id="eceeff5e-51c1-459c-a911-d21ec090a423" name="Changes" comment="20250904-初步功能已完成">
|
||||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/Module/DeviceInfo.py" beforeDir="false" afterPath="$PROJECT_DIR$/Module/DeviceInfo.py" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/Module/FlaskService.py" beforeDir="false" afterPath="$PROJECT_DIR$/Module/FlaskService.py" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/Module/FlaskService.py" beforeDir="false" afterPath="$PROJECT_DIR$/Module/FlaskService.py" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/Module/Main.py" beforeDir="false" afterPath="$PROJECT_DIR$/Module/Main.py" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/Utils/LogManager.py" beforeDir="false" afterPath="$PROJECT_DIR$/Utils/LogManager.py" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/Utils/LogManager.py" beforeDir="false" afterPath="$PROJECT_DIR$/Utils/LogManager.py" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/script/ScriptManager.py" beforeDir="false" afterPath="$PROJECT_DIR$/script/ScriptManager.py" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/build-tidevice.bat" beforeDir="false" afterPath="$PROJECT_DIR$/build-tidevice.bat" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/build.bat" beforeDir="false" afterPath="$PROJECT_DIR$/build.bat" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/resources/iproxy/tidevice.exe" beforeDir="false" afterPath="$PROJECT_DIR$/resources/iproxy/tidevice.exe" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/tidevice_entry.py" beforeDir="false" afterPath="$PROJECT_DIR$/tidevice_entry.py" afterDir="false" />
|
||||||
</list>
|
</list>
|
||||||
<option name="SHOW_DIALOG" value="false" />
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
@@ -86,6 +91,7 @@
|
|||||||
<recent name="C:\Users\zhangkai\Desktop\20250916ios\iOSAI\resources" />
|
<recent name="C:\Users\zhangkai\Desktop\20250916ios\iOSAI\resources" />
|
||||||
</key>
|
</key>
|
||||||
<key name="MoveFile.RECENT_KEYS">
|
<key name="MoveFile.RECENT_KEYS">
|
||||||
|
<recent name="E:\code\Python\iOSAi" />
|
||||||
<recent name="E:\Code\python\iOSAI\resources" />
|
<recent name="E:\Code\python\iOSAI\resources" />
|
||||||
<recent name="E:\Code\python\iOSAI" />
|
<recent name="E:\Code\python\iOSAI" />
|
||||||
</key>
|
</key>
|
||||||
|
|||||||
@@ -6,11 +6,9 @@ import time
|
|||||||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict, Optional, List
|
from typing import Dict, Optional, List
|
||||||
|
|
||||||
import wda
|
import wda
|
||||||
from tidevice import Usbmux, ConnectionType
|
from tidevice import Usbmux, ConnectionType
|
||||||
from tidevice._device import BaseDevice
|
from tidevice._device import BaseDevice
|
||||||
|
|
||||||
from Entity.DeviceModel import DeviceModel
|
from Entity.DeviceModel import DeviceModel
|
||||||
from Module.FlaskSubprocessManager import FlaskSubprocessManager
|
from Module.FlaskSubprocessManager import FlaskSubprocessManager
|
||||||
from Utils.LogManager import LogManager
|
from Utils.LogManager import LogManager
|
||||||
@@ -19,15 +17,12 @@ from Utils.LogManager import LogManager
|
|||||||
class DeviceInfo:
|
class DeviceInfo:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._port = 9110
|
self._port = 9110
|
||||||
self._models: Dict[str, DeviceModel] = {} # udid -> model
|
self._models: Dict[str, DeviceModel] = {}
|
||||||
self._procs: Dict[str, subprocess.Popen] = {} # udid -> iproxy proc
|
self._procs: Dict[str, subprocess.Popen] = {}
|
||||||
self._manager = FlaskSubprocessManager.get_instance()
|
self._manager = FlaskSubprocessManager.get_instance()
|
||||||
self._iproxy_path = self._find_iproxy()
|
self._iproxy_path = self._find_iproxy()
|
||||||
self._pool = ThreadPoolExecutor(max_workers=6)
|
self._pool = ThreadPoolExecutor(max_workers=6)
|
||||||
|
|
||||||
# 可选:10 秒一次扫野进程
|
|
||||||
threading.Thread(target=self._janitor, daemon=True).start()
|
|
||||||
|
|
||||||
# ---------------- 主循环 ----------------
|
# ---------------- 主循环 ----------------
|
||||||
def listen(self):
|
def listen(self):
|
||||||
while True:
|
while True:
|
||||||
@@ -89,13 +84,20 @@ class DeviceInfo:
|
|||||||
except Exception:
|
except Exception:
|
||||||
return 828, 1792, 2.0
|
return 828, 1792, 2.0
|
||||||
|
|
||||||
|
...
|
||||||
|
# ---------------- 原来代码不变,只替换下面一个函数 ----------------
|
||||||
def _start_iproxy(self, udid: str, port: int) -> Optional[subprocess.Popen]:
|
def _start_iproxy(self, udid: str, port: int) -> Optional[subprocess.Popen]:
|
||||||
try:
|
try:
|
||||||
|
# 隐藏窗口的核心参数
|
||||||
|
kw = {"creationflags": subprocess.CREATE_NO_WINDOW}
|
||||||
return subprocess.Popen(
|
return subprocess.Popen(
|
||||||
[self._iproxy_path, "-u", udid, str(port), "9100"],
|
[self._iproxy_path, "-u", udid, str(port), "9100"],
|
||||||
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
|
stdout=subprocess.DEVNULL,
|
||||||
|
stderr=subprocess.DEVNULL,
|
||||||
|
**kw
|
||||||
)
|
)
|
||||||
except Exception:
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def _kill(self, proc: Optional[subprocess.Popen]):
|
def _kill(self, proc: Optional[subprocess.Popen]):
|
||||||
@@ -124,16 +126,11 @@ class DeviceInfo:
|
|||||||
base = Path(__file__).resolve().parent.parent
|
base = Path(__file__).resolve().parent.parent
|
||||||
name = "iproxy.exe"
|
name = "iproxy.exe"
|
||||||
path = base / "resources" / "iproxy" / name
|
path = base / "resources" / "iproxy" / name
|
||||||
|
print(str(path))
|
||||||
if path.is_file():
|
if path.is_file():
|
||||||
return str(path)
|
return str(path)
|
||||||
raise FileNotFoundError(f"iproxy 不存在: {path}")
|
raise FileNotFoundError(f"iproxy 不存在: {path}")
|
||||||
|
|
||||||
# ---------------- janitor(扫野进程) ----------------
|
|
||||||
def _janitor(self):
|
|
||||||
while True:
|
|
||||||
time.sleep(10)
|
|
||||||
self._cleanup_orphan_iproxy()
|
|
||||||
|
|
||||||
# ------------ Windows 专用:列出所有 iproxy 命令行 ------------
|
# ------------ Windows 专用:列出所有 iproxy 命令行 ------------
|
||||||
def _get_all_iproxy_cmdlines(self) -> List[str]:
|
def _get_all_iproxy_cmdlines(self) -> List[str]:
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -2,12 +2,10 @@ import json
|
|||||||
import os
|
import os
|
||||||
import socket
|
import socket
|
||||||
import threading
|
import threading
|
||||||
import time
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from queue import Queue
|
from queue import Queue
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
|
|
||||||
from Entity.AnchorModel import AnchorModel
|
|
||||||
from Utils.AiUtils import AiUtils
|
from Utils.AiUtils import AiUtils
|
||||||
from Utils.IOSAIStorage import IOSAIStorage
|
from Utils.IOSAIStorage import IOSAIStorage
|
||||||
from Utils.LogManager import LogManager
|
from Utils.LogManager import LogManager
|
||||||
@@ -19,7 +17,7 @@ from Entity.ResultData import ResultData
|
|||||||
from Utils.ControlUtils import ControlUtils
|
from Utils.ControlUtils import ControlUtils
|
||||||
from Utils.ThreadManager import ThreadManager
|
from Utils.ThreadManager import ThreadManager
|
||||||
from script.ScriptManager import ScriptManager
|
from script.ScriptManager import ScriptManager
|
||||||
from Entity.Variables import anchorList, prologueList, addModelToAnchorList, removeModelFromAnchorList
|
from Entity.Variables import addModelToAnchorList
|
||||||
import Entity.Variables as ev
|
import Entity.Variables as ev
|
||||||
from Utils.JsonUtils import JsonUtils
|
from Utils.JsonUtils import JsonUtils
|
||||||
|
|
||||||
@@ -268,7 +266,7 @@ def stopScript():
|
|||||||
udid = body.get("udid")
|
udid = body.get("udid")
|
||||||
LogManager.method_info(f"接口收到 /stopScript udid={udid}", method="task")
|
LogManager.method_info(f"接口收到 /stopScript udid={udid}", method="task")
|
||||||
code, msg = ThreadManager.stop(udid)
|
code, msg = ThreadManager.stop(udid)
|
||||||
return ResultData(code=code, data="", message=msg).toJson()
|
return ResultData(code=code, data=[], message=msg).toJson()
|
||||||
|
|
||||||
|
|
||||||
# 关注打招呼
|
# 关注打招呼
|
||||||
@@ -576,7 +574,7 @@ def delete_last_message():
|
|||||||
def stopAllTask():
|
def stopAllTask():
|
||||||
idList = request.get_json()
|
idList = request.get_json()
|
||||||
code, msg = ThreadManager.batch_stop(idList)
|
code, msg = ThreadManager.batch_stop(idList)
|
||||||
return ResultData(code, "", msg).toJson()
|
return ResultData(code, [], msg).toJson()
|
||||||
|
|
||||||
|
|
||||||
# @app.route("/killWda", methods=['POST'])
|
# @app.route("/killWda", methods=['POST'])
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
import wda
|
||||||
|
|
||||||
|
import tidevice
|
||||||
from Module.DeviceInfo import DeviceInfo
|
from Module.DeviceInfo import DeviceInfo
|
||||||
from Module.FlaskSubprocessManager import FlaskSubprocessManager
|
from Module.FlaskSubprocessManager import FlaskSubprocessManager
|
||||||
from Utils.DevDiskImageDeployer import DevDiskImageDeployer
|
from Utils.DevDiskImageDeployer import DevDiskImageDeployer
|
||||||
@@ -27,6 +31,27 @@ if "--role=flask" in sys.argv:
|
|||||||
# 项目入口
|
# 项目入口
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
wda.debug = True
|
||||||
|
|
||||||
|
# 1. 拿到打包后的临时目录
|
||||||
|
base_dir = getattr(sys, '_MEIPASS', os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
|
# 2. 构造 resources/iproxy 绝对路径
|
||||||
|
iproxy_dir = os.path.join(base_dir, 'resources', 'iproxy')
|
||||||
|
|
||||||
|
# 3. 如果目录存在就追加到 PATH
|
||||||
|
if os.path.isdir(iproxy_dir):
|
||||||
|
# Windows 用 ; 分隔,Linux/Mac 用 :
|
||||||
|
sep = os.pathsep
|
||||||
|
old_path = os.environ.get('PATH', '')
|
||||||
|
# 避免重复追加
|
||||||
|
if iproxy_dir not in old_path:
|
||||||
|
os.environ['PATH'] = old_path + sep + iproxy_dir
|
||||||
|
else:
|
||||||
|
# 调试用,打包后可删掉
|
||||||
|
print(f'warning: {iproxy_dir} not found', file=sys.stderr)
|
||||||
|
|
||||||
|
|
||||||
# 添加iOS开发包到电脑上
|
# 添加iOS开发包到电脑上
|
||||||
deployer = DevDiskImageDeployer(verbose=True)
|
deployer = DevDiskImageDeployer(verbose=True)
|
||||||
deployer.deploy_all()
|
deployer.deploy_all()
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -26,7 +26,7 @@ def _force_utf8_everywhere():
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
_force_utf8_everywhere()
|
# _force_utf8_everywhere()
|
||||||
|
|
||||||
class LogManager:
|
class LogManager:
|
||||||
"""
|
"""
|
||||||
|
|||||||
Binary file not shown.
@@ -6,4 +6,8 @@ pyinstaller -F -n tidevice ^
|
|||||||
--collect-all tidevice ^
|
--collect-all tidevice ^
|
||||||
--noconsole ^
|
--noconsole ^
|
||||||
--add-data="C:\Users\milk\AppData\Local\Programs\Python\Python312\Lib\site-packages\tidevice;tidevice" ^
|
--add-data="C:\Users\milk\AppData\Local\Programs\Python\Python312\Lib\site-packages\tidevice;tidevice" ^
|
||||||
tidevice_entry.py
|
tidevice_entry.py
|
||||||
|
|
||||||
|
@REM pyinstaller -F -n tidevice -noconsole ^
|
||||||
|
@REM --collect-all tidevice ^
|
||||||
|
@REM tidevice_entry.py
|
||||||
80
build.bat
80
build.bat
@@ -1,18 +1,62 @@
|
|||||||
python -m nuitka "Module/Main.py" ^
|
@REM python -m nuitka "Module/Main.py" ^
|
||||||
--standalone ^
|
@REM --standalone ^
|
||||||
--msvc=latest ^
|
@REM --msvc=latest ^
|
||||||
--windows-console-mode=disable ^
|
@REM --windows-console-mode=disable ^
|
||||||
--output-filename=IOSAI ^
|
@REM --output-filename=IOSAI ^
|
||||||
--include-package=Module,Utils,Entity,script ^
|
@REM --include-package=Module,Utils,Entity,script ^
|
||||||
--include-module=flask ^
|
@REM --include-module=flask ^
|
||||||
--include-module=flask_cors ^
|
@REM --include-module=flask_cors ^
|
||||||
--include-module=lxml ^
|
@REM --include-module=lxml ^
|
||||||
--include-module=lxml.etree ^
|
@REM --include-module=lxml.etree ^
|
||||||
--include-module=requests ^
|
@REM --include-module=requests ^
|
||||||
--include-module=urllib3 ^
|
@REM --include-module=urllib3 ^
|
||||||
--include-module=certifi ^
|
@REM --include-module=certifi ^
|
||||||
--include-module=idna ^
|
@REM --include-module=idna ^
|
||||||
--include-data-dir="E:/code/Python/iOSAI/SupportFiles=SupportFiles" ^
|
@REM --include-data-files="E:/code/Python/iOSAI/.venv/Scripts/tidevice.exe=tidevice.exe" ^
|
||||||
--include-data-dir="E:/code/Python/iOSAI/resources=resources" ^
|
@REM --include-data-dir="E:/code/Python/iOSAI/.venv/Scripts=Scripts" ^
|
||||||
--include-data-files="E:/code/Python/iOSAI/resources/iproxy/*=resources/iproxy/" ^
|
@REM --include-data-dir="E:/code/Python/iOSAI/SupportFiles=SupportFiles" ^
|
||||||
--windows-icon-from-ico="E:/code/Python/iOSAI/resources/icon.ico"
|
@REM --include-data-dir="E:/code/Python/iOSAI/resources=resources" ^
|
||||||
|
@REM --include-data-files="E:/code/Python/iOSAI/resources/iproxy/*=resources/iproxy/" ^
|
||||||
|
@REM --windows-icon-from-ico="E:/code/Python/iOSAI/resources/icon.ico"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@REM python -m nuitka "Module/Main.py" ^
|
||||||
|
@REM --standalone ^
|
||||||
|
@REM --msvc=latest ^
|
||||||
|
@REM --windows-console-mode=force ^
|
||||||
|
@REM --output-filename=IOSAI ^
|
||||||
|
@REM --include-package=Module,Utils,Entity,script ^
|
||||||
|
@REM --include-module=flask ^
|
||||||
|
@REM --include-module=wda ^
|
||||||
|
@REM --include-module=flask_cors ^
|
||||||
|
@REM --include-module=lxml ^
|
||||||
|
@REM --include-module=lxml.etree ^
|
||||||
|
@REM --include-module=requests ^
|
||||||
|
@REM --include-module=urllib3 ^
|
||||||
|
@REM --include-module=certifi ^
|
||||||
|
@REM --include-module=idna ^
|
||||||
|
@REM --include-module=setuptools ^
|
||||||
|
@REM --include-module=tidevice ^
|
||||||
|
@REM --include-data-dir=resources=resources ^
|
||||||
|
@REM --include-data-dir=SupportFiles=SupportFiles ^
|
||||||
|
@REM --include-data-files="E:/code/Python/iOSAi/resources/iproxy/*=resources/iproxy/" ^
|
||||||
|
@REM --include-data-files=resources/icon.ico=resources/icon.ico ^
|
||||||
|
@REM --jobs=20 ^
|
||||||
|
@REM --windows-icon-from-ico=resources/icon.ico
|
||||||
|
|
||||||
|
|
||||||
|
python -m nuitka Module\Main.py ^
|
||||||
|
--standalone ^
|
||||||
|
--msvc=latest ^
|
||||||
|
--windows-console-mode=force ^
|
||||||
|
--output-filename=IOSAI ^
|
||||||
|
--include-package=Module,Utils,Entity,script ^
|
||||||
|
--include-module=flask,wda,flask_cors,lxml,lxml.etree,requests,urllib3,certifi,idna,setuptools,tidevice ^
|
||||||
|
--include-data-dir=resources=resources ^
|
||||||
|
--include-data-dir=SupportFiles=SupportFiles ^
|
||||||
|
--include-data-files="E:/code/Python/iOSAi/resources/iproxy/*=resources/iproxy/" ^
|
||||||
|
--include-data-files=resources/icon.ico=resources/icon.ico ^
|
||||||
|
--jobs=20 ^
|
||||||
|
--windows-icon-from-ico=resources/icon.ico
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
@@ -1,16 +1,37 @@
|
|||||||
|
# import sys, traceback, os
|
||||||
|
# from tidevice.__main__ import main
|
||||||
|
#
|
||||||
|
# import sys, os
|
||||||
|
# with open(os.path.join(os.path.dirname(sys.executable), '_entry_log.txt'), 'w') as f:
|
||||||
|
# f.write('entry reached\nargs=%r\n' % sys.argv)
|
||||||
|
#
|
||||||
|
# if hasattr(sys, 'frozen') and sys.executable.endswith('.exe'):
|
||||||
|
# # 打包后且无控制台时,把标准流扔掉
|
||||||
|
# sys.stdout = sys.stderr = open(os.devnull, 'w', encoding='utf-8')
|
||||||
|
#
|
||||||
|
# if __name__ == "__main__":
|
||||||
|
# try:
|
||||||
|
# main()
|
||||||
|
# except Exception:
|
||||||
|
# # 把 traceback 写到日志文件,但**不输出到控制台**
|
||||||
|
# with open(os.path.expanduser("~/tidevice_crash.log"), "a", encoding="utf-8") as f:
|
||||||
|
# traceback.print_exc(file=f)
|
||||||
|
# # 静默退出,返回码 1
|
||||||
|
# sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
import sys, traceback, os
|
import sys, traceback, os
|
||||||
from tidevice.__main__ import main
|
from tidevice.__main__ import main
|
||||||
|
|
||||||
if hasattr(sys, 'frozen') and sys.executable.endswith('.exe'):
|
|
||||||
# 打包后且无控制台时,把标准流扔掉
|
|
||||||
sys.stdout = sys.stderr = open(os.devnull, 'w', encoding='utf-8')
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
try:
|
try:
|
||||||
main()
|
main()
|
||||||
except Exception:
|
except SystemExit as se: # 允许正常 exit(code) 继续生效
|
||||||
# 把 traceback 写到日志文件,但**不输出到控制台**
|
raise
|
||||||
with open(os.path.expanduser("~/tidevice_crash.log"), "a", encoding="utf-8") as f:
|
except Exception: # 真正异常时才写日志
|
||||||
|
crash_log = os.path.expanduser("~/tidevice_crash.log")
|
||||||
|
with open(crash_log, "a", encoding="utf-8") as f:
|
||||||
|
f.write("----- tidevice exe crash -----\n")
|
||||||
traceback.print_exc(file=f)
|
traceback.print_exc(file=f)
|
||||||
# 静默退出,返回码 1
|
# 如果想让用户知道崩溃了,可以返回非 0
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
Reference in New Issue
Block a user