4d4d38fe0f
迁自 park-desktop/backend/app:config(数据目录→serverdata/park)/storage/sim_engine/ mqtt/event_bus + 精简 routers(health/settings/config/dashboard/park/companies/display/ events) + app.py 子应用(lifespan 起 MQTT hub+tick 线程, include_router prefix=/park)。 dispatcher.py 增 ROUTE_PARK_PREFIX + _prefix_app,与 app.training(/api)、app.main 分流。 pyproject 增 paho-mqtt(MQTT 必需)。AI/知识库/语音/视觉重模块延后全量迁入。
68 lines
2.0 KiB
Python
68 lines
2.0 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""园区子应用(app/park)—— FastAPI 子应用组装。
|
||
|
||
由 server-core/dispatcher.py 以 `/park` 前缀路由对外;独立 lifespan:
|
||
启动 MQTT hub、数据 tick 线程(sim_engine → publish_tick);s2s 实时语音栈延后。
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
import asyncio
|
||
import logging
|
||
import threading
|
||
from contextlib import asynccontextmanager
|
||
from pathlib import Path
|
||
|
||
from fastapi import FastAPI
|
||
from fastapi.staticfiles import StaticFiles
|
||
|
||
from .config import settings
|
||
from .event_bus import bus
|
||
from .mqtt import hub
|
||
from .routers import router
|
||
from .sim_engine import sim_engine
|
||
|
||
log = logging.getLogger("dpm.park")
|
||
|
||
settings.MEDIA_DIR.mkdir(parents=True, exist_ok=True)
|
||
|
||
|
||
@asynccontextmanager
|
||
async def lifespan(app: FastAPI):
|
||
bus.set_loop(asyncio.get_running_loop())
|
||
hub.start()
|
||
|
||
stop = threading.Event()
|
||
|
||
def tick_loop():
|
||
while not stop.is_set():
|
||
try:
|
||
snap = sim_engine.tick()
|
||
hub.publish_tick(snap)
|
||
except Exception as e: # noqa: BLE001
|
||
log.warning("园区数据 tick 异常: %s", e)
|
||
stop.wait(settings.MQTT_TICK_INTERVAL)
|
||
|
||
threading.Thread(target=tick_loop, daemon=True).start()
|
||
log.info("园区子应用 /park 启动(MQTT %s:%s 系 %s)",
|
||
settings.MQTT_HOST, settings.MQTT_PORT,
|
||
"已启用" if settings.MQTT_ENABLED else "已禁用")
|
||
try:
|
||
yield
|
||
finally:
|
||
stop.set()
|
||
hub.stop()
|
||
|
||
|
||
app = FastAPI(title="OPC 智能园区子应用", version="1.0.0", lifespan=lifespan)
|
||
|
||
# 关键:内部路由本为 /api/*,挂载到 /park 下 → 外部地址 /park/api/*
|
||
app.include_router(router, prefix="/park")
|
||
|
||
# 媒体静态服务(上传/播放文件)
|
||
app.mount("/park/file", StaticFiles(directory=str(settings.MEDIA_DIR)), name="park-media")
|
||
|
||
# 管理后台静态资源(如有)
|
||
_static_dir = Path(__file__).resolve().parent / "static"
|
||
if _static_dir.exists():
|
||
app.mount("/park/static", StaticFiles(directory=str(_static_dir)), name="park-static")
|