21cfab58fa
导入 .s2s_bridge.start_s2s_backend 并以 stop 事件控制;依赖 speech_to_speech (vendor/s2s-cloud),启用前需 uv pip install -e app/park/vendor/s2s-cloud。
77 lines
2.5 KiB
Python
77 lines
2.5 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()
|
||
|
||
# s2s 实时语音栈(可选):后台线程起 RealtimeServer(:8765),仅 S2S_ENABLED=1
|
||
# 依赖 speech_to_speech(vendor/s2s-cloud,需先 `uv pip install -e app/park/vendor/s2s-cloud`)
|
||
if settings.S2S_ENABLED:
|
||
try:
|
||
from .s2s_bridge import start_s2s_backend
|
||
start_s2s_backend(stop)
|
||
except Exception as e: # noqa: BLE001
|
||
log.warning("s2s 语音栈启动失败(S2S_ENABLED=1 但依赖未装?): %s", e)
|
||
|
||
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")
|