Files
iOSAI/Module/Main.py
2025-11-17 19:42:27 +08:00

125 lines
3.7 KiB
Python

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)
# ==== 关键:统一获取 resources 目录 ====
if "__compiled__" in globals():
# 被 Nuitka 编译后的 exe 运行时
base_dir = os.path.dirname(sys.executable) # exe 所在目录
else:
# 开发环境,直接跑 .py
cur_file = os.path.abspath(__file__) # Module/Main.py 所在目录
base_dir = os.path.dirname(os.path.dirname(cur_file)) # 回到项目根 iOSAi
resource_dir = os.path.join(base_dir, "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()