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:
FlotillasGPS Developer
2026-01-21 08:18:00 +00:00
commit 51d78bacf4
248 changed files with 50171 additions and 0 deletions

View 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)