## Backend Changes - Add new API endpoints: combustible, pois, mantenimiento, video, configuracion - Fix vehiculos endpoint to return paginated response with items array - Add /vehiculos/all endpoint for non-paginated list - Add /geocercas/all endpoint - Add /alertas/configuracion GET/PUT endpoints - Add /viajes/activos and /viajes/iniciar endpoints - Add /reportes/stats, /reportes/templates, /reportes/preview endpoints - Add /conductores/all and /conductores/disponibles endpoints - Update router.py to include all new modules ## Frontend Changes - Fix authentication token handling (snake_case vs camelCase) - Update vehiculosApi.listAll to use /vehiculos/all - Fix FuelGauge component usage in Combustible page - Fix chart component exports (named + default exports) - Update API client for proper token refresh ## Infrastructure - Rename services from ADAN to ATLAS - Configure Cloudflare tunnel for atlas.consultoria-as.com - Update systemd service files - Configure PostgreSQL with TimescaleDB - Configure Redis, Mosquitto, Traccar, MediaMTX ## Documentation - Update installation guides - Update API reference - Rename all ADAN references to ATLAS Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
269 lines
7.5 KiB
Python
269 lines
7.5 KiB
Python
"""
|
|
Aplicación principal FastAPI para Atlas Fleet Monitor.
|
|
|
|
Sistema de monitoreo de atlas GPS con soporte para:
|
|
- Tracking en tiempo real
|
|
- Gestión de vehículos y conductores
|
|
- Alertas y geocercas
|
|
- Video vigilancia
|
|
- Reportes y análisis
|
|
"""
|
|
|
|
from contextlib import asynccontextmanager
|
|
from datetime import datetime, timezone
|
|
|
|
from fastapi import FastAPI, Request
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
from fastapi.middleware.gzip import GZipMiddleware
|
|
from fastapi.responses import JSONResponse
|
|
|
|
from app.core.config import settings
|
|
from app.core.database import close_db, init_db
|
|
from app.core.exceptions import register_exception_handlers
|
|
from app.api.v1 import api_router
|
|
from app.api.websocket import ubicaciones_router, alertas_router
|
|
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(app: FastAPI):
|
|
"""
|
|
Manejador del ciclo de vida de la aplicación.
|
|
|
|
Ejecuta código de inicialización al arrancar y
|
|
limpieza al cerrar la aplicación.
|
|
"""
|
|
# Startup
|
|
print(f"Starting {settings.APP_NAME} v{settings.APP_VERSION}")
|
|
print(f"Environment: {settings.ENVIRONMENT}")
|
|
print(f"Debug mode: {settings.DEBUG}")
|
|
|
|
# Inicializar base de datos (crear tablas si no existen)
|
|
if settings.ENVIRONMENT == "development":
|
|
try:
|
|
await init_db()
|
|
print("Database initialized")
|
|
except Exception as e:
|
|
print(f"Warning: Could not initialize database: {e}")
|
|
|
|
yield # La aplicación se ejecuta aquí
|
|
|
|
# Shutdown
|
|
print("Shutting down...")
|
|
await close_db()
|
|
print("Database connections closed")
|
|
|
|
|
|
# Crear aplicación FastAPI
|
|
app = FastAPI(
|
|
title=settings.APP_NAME,
|
|
description="""
|
|
## Atlas Fleet Monitor API
|
|
|
|
Sistema de monitoreo de atlas GPS.
|
|
|
|
### Funcionalidades principales:
|
|
- **Tracking en tiempo real** de vehículos
|
|
- **Gestión de flota**: vehículos, conductores, dispositivos
|
|
- **Alertas inteligentes**: velocidad, geocercas, batería
|
|
- **Viajes automáticos**: detección de inicio/fin
|
|
- **Geocercas**: zonas circulares y poligonales
|
|
- **Video vigilancia**: integración con cámaras
|
|
- **Reportes**: PDF, Excel, dashboards
|
|
|
|
### WebSocket endpoints:
|
|
- `/ws/ubicaciones` - Ubicaciones en tiempo real
|
|
- `/ws/alertas` - Alertas en tiempo real
|
|
- `/ws/vehiculo/{id}` - Seguimiento de un vehículo
|
|
- `/ws/flota` - Monitoreo de toda la flota
|
|
""",
|
|
version=settings.APP_VERSION,
|
|
docs_url="/docs" if settings.DEBUG else None,
|
|
redoc_url="/redoc" if settings.DEBUG else None,
|
|
openapi_url="/openapi.json" if settings.DEBUG else None,
|
|
lifespan=lifespan,
|
|
)
|
|
|
|
# ============================================================================
|
|
# Middlewares
|
|
# ============================================================================
|
|
|
|
# CORS
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=settings.CORS_ORIGINS,
|
|
allow_credentials=settings.CORS_ALLOW_CREDENTIALS,
|
|
allow_methods=settings.CORS_ALLOW_METHODS,
|
|
allow_headers=settings.CORS_ALLOW_HEADERS,
|
|
)
|
|
|
|
# Compresión GZip
|
|
app.add_middleware(GZipMiddleware, minimum_size=1000)
|
|
|
|
|
|
# Middleware de logging de requests
|
|
@app.middleware("http")
|
|
async def log_requests(request: Request, call_next):
|
|
"""
|
|
Middleware para logging de requests.
|
|
|
|
Registra el tiempo de respuesta de cada request.
|
|
"""
|
|
start_time = datetime.now(timezone.utc)
|
|
|
|
response = await call_next(request)
|
|
|
|
# Calcular tiempo de procesamiento
|
|
process_time = (datetime.now(timezone.utc) - start_time).total_seconds()
|
|
response.headers["X-Process-Time"] = str(process_time)
|
|
|
|
# Log en modo debug
|
|
if settings.DEBUG:
|
|
print(
|
|
f"{request.method} {request.url.path} "
|
|
f"- {response.status_code} "
|
|
f"- {process_time:.3f}s"
|
|
)
|
|
|
|
return response
|
|
|
|
|
|
# Middleware de seguridad
|
|
@app.middleware("http")
|
|
async def security_headers(request: Request, call_next):
|
|
"""
|
|
Middleware para agregar headers de seguridad.
|
|
"""
|
|
response = await call_next(request)
|
|
|
|
# Headers de seguridad
|
|
response.headers["X-Content-Type-Options"] = "nosniff"
|
|
response.headers["X-Frame-Options"] = "DENY"
|
|
response.headers["X-XSS-Protection"] = "1; mode=block"
|
|
|
|
if not settings.DEBUG:
|
|
response.headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains"
|
|
|
|
return response
|
|
|
|
|
|
# ============================================================================
|
|
# Registrar exception handlers
|
|
# ============================================================================
|
|
|
|
register_exception_handlers(app)
|
|
|
|
|
|
# ============================================================================
|
|
# Routers
|
|
# ============================================================================
|
|
|
|
# API REST v1
|
|
app.include_router(api_router, prefix=settings.API_V1_PREFIX)
|
|
|
|
# WebSocket endpoints
|
|
app.include_router(ubicaciones_router)
|
|
app.include_router(alertas_router)
|
|
|
|
|
|
# ============================================================================
|
|
# Endpoints base
|
|
# ============================================================================
|
|
|
|
|
|
@app.get("/", tags=["Root"])
|
|
async def root():
|
|
"""
|
|
Endpoint raíz de la API.
|
|
|
|
Returns:
|
|
Información básica de la API.
|
|
"""
|
|
return {
|
|
"name": settings.APP_NAME,
|
|
"version": settings.APP_VERSION,
|
|
"status": "online",
|
|
"environment": settings.ENVIRONMENT,
|
|
"docs": "/docs" if settings.DEBUG else "disabled",
|
|
}
|
|
|
|
|
|
@app.get("/health", tags=["Health"])
|
|
async def health_check():
|
|
"""
|
|
Health check endpoint.
|
|
|
|
Verifica el estado de la aplicación y sus dependencias.
|
|
|
|
Returns:
|
|
Estado de salud de la aplicación.
|
|
"""
|
|
health = {
|
|
"status": "healthy",
|
|
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
"version": settings.APP_VERSION,
|
|
"checks": {
|
|
"api": "ok",
|
|
},
|
|
}
|
|
|
|
# Verificar base de datos
|
|
try:
|
|
from app.core.database import check_db_connection
|
|
await check_db_connection()
|
|
health["checks"]["database"] = "ok"
|
|
except Exception as e:
|
|
health["checks"]["database"] = f"error: {str(e)}"
|
|
health["status"] = "degraded"
|
|
|
|
# Verificar Redis (si está configurado)
|
|
if settings.REDIS_URL:
|
|
try:
|
|
import aioredis
|
|
redis = await aioredis.from_url(settings.REDIS_URL)
|
|
await redis.ping()
|
|
await redis.close()
|
|
health["checks"]["redis"] = "ok"
|
|
except Exception as e:
|
|
health["checks"]["redis"] = f"error: {str(e)}"
|
|
health["status"] = "degraded"
|
|
|
|
return health
|
|
|
|
|
|
@app.get("/ready", tags=["Health"])
|
|
async def readiness_check():
|
|
"""
|
|
Readiness check para Kubernetes.
|
|
|
|
Verifica si la aplicación está lista para recibir tráfico.
|
|
|
|
Returns:
|
|
Estado de preparación.
|
|
"""
|
|
try:
|
|
from app.core.database import check_db_connection
|
|
await check_db_connection()
|
|
return {"ready": True}
|
|
except Exception:
|
|
return JSONResponse(
|
|
status_code=503,
|
|
content={"ready": False, "reason": "Database not ready"},
|
|
)
|
|
|
|
|
|
# ============================================================================
|
|
# Entry point para desarrollo
|
|
# ============================================================================
|
|
|
|
if __name__ == "__main__":
|
|
import uvicorn
|
|
|
|
uvicorn.run(
|
|
"app.main:app",
|
|
host=settings.HOST,
|
|
port=settings.PORT,
|
|
reload=settings.DEBUG,
|
|
workers=1 if settings.DEBUG else settings.WORKERS,
|
|
log_level="debug" if settings.DEBUG else "info",
|
|
)
|