Files
radar_system/python_app/webui/app.py
T

44 lines
1.5 KiB
Python

"""FastAPI application factory for the embedded radar web UI.
The controller (the Qt bridge that forwards to the AppWindow) is created and
owned by the host process and injected here. The app's only owned resource is the
:class:`RingBroadcaster` polling task, created and torn down by the lifespan. The
static single-page frontend is mounted at ``/`` and the JSON/WS API under
``/api`` and ``/ws``.
"""
from __future__ import annotations
from contextlib import asynccontextmanager
from pathlib import Path
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from python_app.webui.controller import WebController
from python_app.webui.routes import router
from python_app.webui.streaming import RingBroadcaster
_STATIC_DIR = Path(__file__).resolve().parent / "static"
def create_app(controller: WebController) -> FastAPI:
"""Build the FastAPI app that serves and streams for ``controller``."""
@asynccontextmanager
async def lifespan(app: FastAPI):
broadcaster = RingBroadcaster(controller)
app.state.controller = controller
app.state.broadcaster = broadcaster
broadcaster.start()
try:
yield
finally:
await broadcaster.stop()
app = FastAPI(title="Radar Web UI", lifespan=lifespan)
app.include_router(router)
# Mount the SPA last so the API routes above always take precedence.
app.mount("/", StaticFiles(directory=_STATIC_DIR, html=True), name="static")
return app