web UI added and refactoring done
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
"""HTTP and WebSocket routes for the embedded radar web UI.
|
||||
|
||||
Every handler is a thin shell over the :class:`WebController` (which forwards to
|
||||
the AppWindow's existing buttons) and the :class:`RingBroadcaster` (the single
|
||||
frame source). There is no ownership gating: the web UI lives inside the process
|
||||
that already owns the hardware, so its controls are simply that process's buttons.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import contextlib
|
||||
|
||||
from fastapi import APIRouter, Body, HTTPException, Request, WebSocket, WebSocketDisconnect
|
||||
|
||||
from python_app.webui.controller import WebController
|
||||
from python_app.webui.streaming import RingBroadcaster
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
def _controller(request: Request) -> WebController:
|
||||
return request.app.state.controller
|
||||
|
||||
|
||||
@router.get("/api/status")
|
||||
async def get_status(request: Request) -> dict:
|
||||
return _controller(request).status()
|
||||
|
||||
|
||||
@router.post("/api/start")
|
||||
async def post_start(request: Request) -> dict:
|
||||
controller = _controller(request)
|
||||
controller.start()
|
||||
return controller.status()
|
||||
|
||||
|
||||
@router.post("/api/single_capture")
|
||||
async def post_single_capture(request: Request) -> dict:
|
||||
controller = _controller(request)
|
||||
controller.single_capture()
|
||||
return controller.status()
|
||||
|
||||
|
||||
@router.post("/api/stop")
|
||||
async def post_stop(request: Request) -> dict:
|
||||
controller = _controller(request)
|
||||
controller.stop()
|
||||
return controller.status()
|
||||
|
||||
|
||||
@router.post("/api/tmp_reference")
|
||||
async def post_tmp_reference(request: Request) -> dict:
|
||||
controller = _controller(request)
|
||||
controller.capture_tmp_reference()
|
||||
return controller.status()
|
||||
|
||||
|
||||
@router.get("/api/live_settings")
|
||||
async def get_live_settings(request: Request) -> list:
|
||||
return _controller(request).current_live_settings()
|
||||
|
||||
|
||||
@router.post("/api/live_settings")
|
||||
async def post_live_settings(request: Request, fields: dict = Body(default={})) -> list:
|
||||
try:
|
||||
return _controller(request).apply_live_settings(fields)
|
||||
except ValueError as exc:
|
||||
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
||||
|
||||
|
||||
@router.websocket("/ws")
|
||||
async def ws(websocket: WebSocket) -> None:
|
||||
"""Stream frames and status to one client until it disconnects."""
|
||||
await websocket.accept()
|
||||
broadcaster: RingBroadcaster = websocket.app.state.broadcaster
|
||||
queue: asyncio.Queue[dict] = asyncio.Queue(maxsize=1)
|
||||
broadcaster.register(queue)
|
||||
try:
|
||||
while True:
|
||||
await websocket.send_json(await queue.get())
|
||||
except WebSocketDisconnect:
|
||||
pass
|
||||
finally:
|
||||
broadcaster.unregister(queue)
|
||||
with contextlib.suppress(Exception):
|
||||
await websocket.close()
|
||||
Reference in New Issue
Block a user