125 lines
3.7 KiB
Python
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()
|
|
|