Sistema completo para monitoreo y gestion de flotas de vehiculos con: - Backend FastAPI con PostgreSQL/TimescaleDB - Frontend React con TypeScript y TailwindCSS - App movil React Native con Expo - Soporte para dispositivos GPS, Meshtastic y celulares - Video streaming en vivo con MediaMTX - Geocercas, alertas, viajes y reportes - Autenticacion JWT y WebSockets en tiempo real Documentacion completa y guias de usuario incluidas.
126 lines
3.2 KiB
Python
126 lines
3.2 KiB
Python
"""
|
|
WebSocket endpoint para alertas en tiempo real.
|
|
"""
|
|
|
|
import json
|
|
from typing import Optional
|
|
|
|
from fastapi import APIRouter, Query, WebSocket, WebSocketDisconnect
|
|
|
|
from app.api.websocket.manager import manager
|
|
from app.core.security import decode_token
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
async def get_user_from_token(token: Optional[str]) -> Optional[int]:
|
|
"""
|
|
Obtiene el ID de usuario desde un token JWT.
|
|
|
|
Args:
|
|
token: Token JWT.
|
|
|
|
Returns:
|
|
ID del usuario o None.
|
|
"""
|
|
if not token:
|
|
return None
|
|
try:
|
|
payload = decode_token(token)
|
|
return int(payload.get("sub"))
|
|
except Exception:
|
|
return None
|
|
|
|
|
|
@router.websocket("/ws/alertas")
|
|
async def websocket_alertas(
|
|
websocket: WebSocket,
|
|
token: Optional[str] = Query(None),
|
|
):
|
|
"""
|
|
WebSocket para recibir alertas en tiempo real.
|
|
|
|
Recibe todas las alertas generadas en el sistema.
|
|
|
|
Args:
|
|
websocket: Conexión WebSocket.
|
|
token: Token JWT para autenticación (opcional).
|
|
"""
|
|
user_id = await get_user_from_token(token)
|
|
|
|
await manager.connect(websocket, "alertas", user_id)
|
|
|
|
# Enviar confirmación
|
|
await websocket.send_json({
|
|
"type": "connected",
|
|
"channel": "alerts",
|
|
})
|
|
|
|
try:
|
|
while True:
|
|
data = await websocket.receive_text()
|
|
|
|
try:
|
|
message = json.loads(data)
|
|
|
|
if message.get("action") == "ping":
|
|
await websocket.send_json({"type": "pong"})
|
|
|
|
elif message.get("action") == "acknowledge":
|
|
# Cliente confirma recepción de alerta
|
|
alert_id = message.get("alert_id")
|
|
await websocket.send_json({
|
|
"type": "acknowledged",
|
|
"alert_id": alert_id,
|
|
})
|
|
|
|
except json.JSONDecodeError:
|
|
pass
|
|
|
|
except WebSocketDisconnect:
|
|
await manager.disconnect(websocket, "alertas", user_id)
|
|
|
|
|
|
@router.websocket("/ws/alertas/vehiculo/{vehiculo_id}")
|
|
async def websocket_alertas_vehiculo(
|
|
websocket: WebSocket,
|
|
vehiculo_id: int,
|
|
token: Optional[str] = Query(None),
|
|
):
|
|
"""
|
|
WebSocket para alertas de un vehículo específico.
|
|
|
|
Args:
|
|
websocket: Conexión WebSocket.
|
|
vehiculo_id: ID del vehículo.
|
|
token: Token JWT para autenticación (opcional).
|
|
"""
|
|
user_id = await get_user_from_token(token)
|
|
|
|
await manager.connect(websocket, "alertas", user_id)
|
|
await manager.subscribe_vehicle(websocket, vehiculo_id)
|
|
|
|
# Enviar confirmación
|
|
await websocket.send_json({
|
|
"type": "connected",
|
|
"channel": "vehicle_alerts",
|
|
"vehicle_id": vehiculo_id,
|
|
})
|
|
|
|
try:
|
|
while True:
|
|
data = await websocket.receive_text()
|
|
|
|
try:
|
|
message = json.loads(data)
|
|
|
|
if message.get("action") == "ping":
|
|
await websocket.send_json({"type": "pong"})
|
|
|
|
except json.JSONDecodeError:
|
|
pass
|
|
|
|
except WebSocketDisconnect:
|
|
await manager.unsubscribe_vehicle(websocket, vehiculo_id)
|
|
await manager.disconnect(websocket, "alertas", user_id)
|