feat: add realtime GNSS monitor with telemetry websocket
All checks were successful
Deploy to Production / deploy (push) Successful in 1m10s
All checks were successful
Deploy to Production / deploy (push) Successful in 1m10s
This commit is contained in:
63
backend/app/api/routes/telemetry.py
Normal file
63
backend/app/api/routes/telemetry.py
Normal file
@@ -0,0 +1,63 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter, HTTPException, Query, WebSocket, status
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
from fastapi.websockets import WebSocketDisconnect
|
||||
from sqlmodel import Session
|
||||
|
||||
from app.api.deps import CurrentUser, SessionDep, resolve_user_from_token
|
||||
from app.core.db import engine
|
||||
from app.mqtt.telemetry import build_telemetry_snapshot
|
||||
|
||||
router = APIRouter(prefix="/telemetry", tags=["telemetry"])
|
||||
STREAM_INTERVAL_SECONDS = 1.0
|
||||
|
||||
|
||||
@router.get("/latest")
|
||||
def read_telemetry_latest(
|
||||
session: SessionDep,
|
||||
_current_user: CurrentUser,
|
||||
device_id: str | None = None,
|
||||
limit: int = Query(default=50, ge=1, le=200),
|
||||
) -> dict[str, Any]:
|
||||
"""
|
||||
Return the latest parsed GNSS telemetry snapshot.
|
||||
"""
|
||||
return build_telemetry_snapshot(session=session, device_id=device_id, limit=limit)
|
||||
|
||||
|
||||
@router.websocket("/ws")
|
||||
async def telemetry_websocket(
|
||||
websocket: WebSocket,
|
||||
token: str | None = Query(default=None),
|
||||
device_id: str | None = Query(default=None),
|
||||
limit: int = Query(default=50, ge=1, le=200),
|
||||
) -> None:
|
||||
if not token:
|
||||
await websocket.close(code=status.WS_1008_POLICY_VIOLATION)
|
||||
return
|
||||
|
||||
with Session(engine) as session:
|
||||
try:
|
||||
resolve_user_from_token(session=session, token=token)
|
||||
except HTTPException:
|
||||
await websocket.close(code=status.WS_1008_POLICY_VIOLATION)
|
||||
return
|
||||
|
||||
await websocket.accept()
|
||||
|
||||
try:
|
||||
while True:
|
||||
with Session(engine) as session:
|
||||
payload = build_telemetry_snapshot(
|
||||
session=session,
|
||||
device_id=device_id,
|
||||
limit=limit,
|
||||
)
|
||||
await websocket.send_json(jsonable_encoder(payload))
|
||||
await asyncio.sleep(STREAM_INTERVAL_SECONDS)
|
||||
except (WebSocketDisconnect, RuntimeError):
|
||||
return
|
||||
Reference in New Issue
Block a user