import asyncio # ===== Main.py 顶部放置(所有 import 之前)===== import os import sys from pathlib import Path from asgiref.wsgi import WsgiToAsgi from Utils.AiUtils import AiUtils from Utils.LogManager import LogManager from hypercorn.asyncio import serve from hypercorn.config import Config import sys from pathlib import Path from Module.DeviceInfo import DeviceInfo from Module.FlaskSubprocessManager import FlaskSubprocessManager from Utils.DevDiskImageDeployer import DevDiskImageDeployer if "IOSAI_PYTHON" not in os.environ: base_path = Path(sys.argv[0]).resolve() base_dir = base_path.parent if base_path.is_file() else base_path sidecar = base_dir / "python-rt" / ("python.exe" if os.name == "nt" else "python") if sidecar.exists(): os.environ["IOSAI_PYTHON"] = str(sidecar) # ============================================== # 确定 exe 或 py 文件所在目录 BASE = Path(getattr(sys, 'frozen', False) and sys.executable or __file__).resolve().parent LOG_DIR = BASE / "log" LOG_DIR.mkdir(exist_ok=True) # 确保 log 目录存在 print(f"日志目录: {LOG_DIR}") def _run_flask_role(): from Module.FlaskService import get_app, bootstrap_server_side_effects print("Flask Pid:", os.getpid()) port = int(os.getenv("FLASK_COMM_PORT", "34566")) # 固定端口的兜底仍是 34567 app = get_app() flaskPort = port + 1 AiUtils.flask_port_free(flaskPort) bootstrap_server_side_effects() # 把 WSGI Flask app 包成 ASGI app asgi_app = WsgiToAsgi(app) # Hypercorn 配置 # 自动定位 resources 目录 base_dir = os.path.dirname(os.path.abspath(__file__)) # 当前 py 的目录(Module/) project_root = os.path.dirname(base_dir) # 回到项目根目录(iOSAi/) resource_dir = os.path.join(project_root, "resources") # 拼到 resources config = Config() config.bind = [f"0.0.0.0:{flaskPort}"] config.alpn_protocols = ["h2"] # 开 HTTP/2 config.certfile = os.path.join(resource_dir, "cert.pem") config.keyfile = os.path.join(resource_dir, "key.pem") print(f"Starting Hypercorn on port {flaskPort} (HTTP/2 enabled)") # 开启 HTTP/2 config.alpn_protocols = ["h2"] print(f"Starting Hypercorn on https://localhost:{flaskPort} (HTTP/2 enabled)") asyncio.run(serve(asgi_app, config)) if "--role=flask" in sys.argv: _run_flask_role() sys.exit(0) # 启动锁 def main(arg): if len(arg) != 2 or arg[1] != "iosai": sys.exit(0) # 项目入口 if __name__ == "__main__": # 清空日志 LogManager.clearLogs() main(sys.argv) # 添加iOS开发包到电脑上 deployer = DevDiskImageDeployer(verbose=True) deployer.deploy_all() # 启动 Flask 子进程 manager = FlaskSubprocessManager.get_instance() manager.start() # 设备监听(即使失败/很快返回,也不会导致主进程退出) try: info = DeviceInfo() info.listen() except Exception as e: print("[WARN] Device listener not running:", e) # === 保活:阻塞主线程,直到收到 Ctrl+C/关闭 === import threading, time, signal stop = threading.Event() def _handle(_sig, _frm): stop.set() # Windows 上 SIGINT/SIGTERM 都可以拦到 try: signal.signal(signal.SIGINT, _handle) signal.signal(signal.SIGTERM, _handle) except Exception: pass # 某些环境可能不支持,忽略 try: while not stop.is_set(): time.sleep(1) finally: # 进程退出前记得把子进程关掉 manager.stop()