feat: add ue_scene websocket integration

This commit is contained in:
opencode
2026-05-09 11:32:07 +08:00
parent 61baee00f6
commit 8f67d8d108
12 changed files with 2684 additions and 49 deletions

View File

@@ -1,7 +1,6 @@
"""WebSocket API endpoints"""
import asyncio
import json
import logging
from datetime import UTC, datetime
from typing import Optional
@@ -12,9 +11,20 @@ from jose import jwt, JWTError
from app.core.config import settings
from app.core.time import to_iso8601_utc
from app.core.websocket.manager import manager
from app.core.websocket.ue_scene import expand_scene_payload_for_transport, ue_scene_state_store
from app.db.session import async_session_factory
logger = logging.getLogger(__name__)
router = APIRouter()
SUPPORTED_CHANNELS = [
"gpu_clusters",
"submarine_cables",
"ixp_nodes",
"alerts",
"dashboard",
"datasource_tasks",
"ue_scene",
]
async def authenticate_token(token: str) -> Optional[dict]:
@@ -50,18 +60,12 @@ async def websocket_endpoint(
await websocket.send_json(
{
"type": "connection_established",
"timestamp": to_iso8601_utc(datetime.now(UTC)),
"data": {
"connection_id": f"conn_{user_id}",
"server_version": settings.VERSION,
"heartbeat_interval": 30,
"supported_channels": [
"gpu_clusters",
"submarine_cables",
"ixp_nodes",
"alerts",
"dashboard",
"datasource_tasks",
],
"supported_channels": SUPPORTED_CHANNELS,
},
}
)
@@ -74,26 +78,79 @@ async def websocket_endpoint(
await websocket.send_json(
{
"type": "heartbeat",
"timestamp": to_iso8601_utc(datetime.now(UTC)),
"data": {"action": "pong", "timestamp": to_iso8601_utc(datetime.now(UTC))},
}
)
elif data.get("type") == "subscribe":
channels = data.get("data", {}).get("channels", [])
requested_channels = data.get("data", {}).get("channels", [])
channels = manager.subscribe(websocket, requested_channels)
await websocket.send_json(
{
"type": "subscription_confirmed",
"timestamp": to_iso8601_utc(datetime.now(UTC)),
"data": {"action": "subscribe", "channels": channels},
}
)
elif data.get("type") == "sync_request":
sync_data = data.get("data", {})
channel = sync_data.get("channel")
if channel == "ue_scene":
async with async_session_factory() as session:
scene_payloads = await ue_scene_state_store.get_sync_payloads(
session,
last_sequence=sync_data.get("last_sequence"),
reason=sync_data.get("reason"),
)
for scene_payload in scene_payloads:
for transport_payload in expand_scene_payload_for_transport(scene_payload):
await websocket.send_json(
{
"type": "data_frame",
"channel": "ue_scene",
"timestamp": to_iso8601_utc(datetime.now(UTC)),
"data": transport_payload,
}
)
else:
await websocket.send_json(
{
"type": "error",
"timestamp": to_iso8601_utc(datetime.now(UTC)),
"data": {
"message": f"Unsupported sync channel: {channel}",
},
}
)
elif data.get("type") == "control_frame":
await websocket.send_json(
{"type": "control_acknowledged", "data": {"received": True}}
{
"type": "control_acknowledged",
"timestamp": to_iso8601_utc(datetime.now(UTC)),
"data": {
"target": data.get("data", {}).get("target"),
"command": data.get("data", {}).get("command"),
"accepted": True,
},
}
)
else:
await websocket.send_json({"type": "ack", "data": {"received": True}})
await websocket.send_json(
{
"type": "ack",
"timestamp": to_iso8601_utc(datetime.now(UTC)),
"data": {"received": True},
}
)
except asyncio.TimeoutError:
await websocket.send_json({"type": "heartbeat", "data": {"action": "ping"}})
await websocket.send_json(
{
"type": "heartbeat",
"timestamp": to_iso8601_utc(datetime.now(UTC)),
"data": {"action": "ping"},
}
)
except WebSocketDisconnect:
pass