Files
Remote-Terminal-for-MeshCore/app/routers/ws.py
2026-01-13 12:49:27 -08:00

73 lines
2.2 KiB
Python

"""WebSocket router for real-time updates."""
import logging
import os
from fastapi import APIRouter, WebSocket, WebSocketDisconnect
from app.config import settings
from app.radio import radio_manager
from app.repository import ChannelRepository, ContactRepository
from app.websocket import ws_manager
logger = logging.getLogger(__name__)
router = APIRouter()
@router.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket) -> None:
"""WebSocket endpoint for real-time updates."""
await ws_manager.connect(websocket)
# Send initial state
try:
# Health status
db_size_mb = 0.0
try:
db_size_bytes = os.path.getsize(settings.database_path)
db_size_mb = round(db_size_bytes / (1024 * 1024), 2)
except OSError:
pass
health_data = {
"status": "ok" if radio_manager.is_connected else "degraded",
"radio_connected": radio_manager.is_connected,
"serial_port": radio_manager.port,
"database_size_mb": db_size_mb,
}
await ws_manager.send_personal(websocket, "health", health_data)
# Contacts
contacts = await ContactRepository.get_all(limit=500)
await ws_manager.send_personal(
websocket,
"contacts",
[c.model_dump() for c in contacts],
)
# Channels
channels = await ChannelRepository.get_all()
await ws_manager.send_personal(
websocket,
"channels",
[c.model_dump() for c in channels],
)
except Exception as e:
logger.error("Error sending initial state: %s", e)
# Keep connection alive and handle incoming messages
try:
while True:
# We don't expect messages from client, but need to keep connection open
# and handle pings/pongs
data = await websocket.receive_text()
# Client can send "ping" to keep alive
if data == "ping":
await websocket.send_text('{"type":"pong"}')
except WebSocketDisconnect:
await ws_manager.disconnect(websocket)
except Exception as e:
logger.debug("WebSocket error: %s", e)
await ws_manager.disconnect(websocket)