FlotillasGPS - Sistema completo de monitoreo de flotillas GPS
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.
This commit is contained in:
125
backend/app/api/websocket/alertas.py
Normal file
125
backend/app/api/websocket/alertas.py
Normal file
@@ -0,0 +1,125 @@
|
||||
"""
|
||||
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)
|
||||
Reference in New Issue
Block a user