Files
trenes/README.md

681 lines
17 KiB
Markdown
Raw Permalink Normal View History

# Sistema de Tracking de Trenes en Tiempo Real
Sistema web para visualizar en tiempo real la posición de todos los trenes operados por Renfe en España, con capacidad de consultar histórico mediante un timeline slider.
## Características
- 🚄 **Visualización en tiempo real** de posiciones de trenes en mapa OpenStreetMap
- 📊 **Información detallada** de cada tren (velocidad, dirección, estado, ruta)
- ⏱️ **Timeline slider** para navegar por el histórico de posiciones
- 🗺️ **Datos geoespaciales** usando PostGIS
- 🔄 **Actualización automática** cada 30 segundos desde feed GTFS-RT
- 📡 **WebSocket** para actualizaciones en tiempo real sin polling
- 🎨 **Interfaz moderna** con React + Leaflet.js
## Stack Tecnológico
### Frontend
- React + JavaScript (JSX)
- Leaflet.js para mapas (OpenStreetMap)
- Socket.io client para WebSocket
- Vite como bundler
### Backend
- Node.js + Express/Fastify
- Socket.io para WebSocket server
- Parser GTFS-RT (gtfs-realtime-bindings)
### Infraestructura
- PostgreSQL 15 + PostGIS (datos geoespaciales)
- Redis (caché de posiciones actuales)
- Nginx (reverse proxy)
- Flyway (migraciones de base de datos)
- Docker + Docker Compose
## Requisitos Previos
- Docker >= 20.10
- Docker Compose >= 2.0
- Make (opcional, pero recomendado)
- Git
## Instalación Rápida
### Usando Make (Recomendado)
```bash
# 1. Clonar el repositorio
git clone <repository-url>
cd trenes
# 2. Ver comandos disponibles
make help
# 3. Configurar variables de entorno
cp .env.example .env
# Editar .env con tus credenciales
# 4. Ejecutar migraciones
make migrate
# 5. Iniciar servicios
make start
```
### Instalación Manual (sin Make)
#### 1. Clonar el repositorio
```bash
git clone <repository-url>
cd trenes
```
#### 2. Configurar variables de entorno
```bash
cp .env.example .env
```
Editar `.env` y configurar las contraseñas y secretos:
```env
POSTGRES_PASSWORD=tu_password_seguro
REDIS_PASSWORD=tu_redis_password
JWT_SECRET=tu_jwt_secret_minimo_32_caracteres
```
#### 3. Ejecutar migraciones de base de datos
```bash
# Primera vez: ejecutar migraciones
docker-compose --profile migration up flyway
# Verificar que las migraciones se aplicaron correctamente
docker-compose logs flyway
```
#### 4. Iniciar todos los servicios
```bash
docker-compose up -d
```
#### 5. Verificar que todo está funcionando
```bash
# Ver logs de todos los servicios
docker-compose logs -f
# Verificar estado de los servicios
docker-compose ps
```
## Acceso a los Servicios
Una vez iniciado, el sistema estará disponible en:
- **Aplicación Web**: http://localhost
- **API REST**: http://localhost/api
- **WebSocket**: ws://localhost/ws
- **Adminer** (DB admin): http://localhost:8080 (solo en modo debug)
- **Redis Commander**: http://localhost:8081 (solo en modo debug)
## Uso
### Comandos Make Disponibles
```bash
# Ver todos los comandos disponibles
make help
# Comandos de Producción
make start # Iniciar servicios
make stop # Detener servicios
make restart # Reiniciar servicios
make logs # Ver logs
make status # Ver estado de servicios
make migrate # Ejecutar migraciones
make debug-start # Iniciar con herramientas de debug
# Comandos de Testing
make test-start # Iniciar entorno de testing
make test-stop # Detener entorno de testing
make test-logs # Ver logs de testing
make test-clean # Limpiar datos de testing
make test-reset # Reset completo de testing
# Utilidades
make psql # Conectar a PostgreSQL
make redis-cli # Conectar a Redis
make backup-db # Crear backup de BD
make cleanup-old-data # Limpiar datos antiguos
```
### Modo Normal (Producción)
```bash
# Usando Make
make start # Iniciar todos los servicios
make logs # Ver logs
make stop # Detener servicios
# O manualmente con docker-compose
docker-compose up -d
docker-compose logs -f
docker-compose down
```
### Modo Testing
El entorno de testing usa el archivo `.env.testing` que incluye configuraciones específicas para pruebas:
```bash
# Iniciar entorno de testing
make test-start
# Ver logs
make test-logs
# Detener y limpiar
make test-clean
```
El entorno de testing incluye:
- Configuración de desarrollo con logs detallados
- Polling más frecuente (15 segundos)
- Debug endpoints habilitados
- Rate limiting deshabilitado
- Herramientas de administración (Adminer, Redis Commander) activadas por defecto
### Modo Debug (con herramientas de administración)
```bash
# Usando Make
make debug-start
# O manualmente
docker-compose --profile debug up -d
# Acceder a Adminer: http://localhost:8080
# - Sistema: PostgreSQL
# - Servidor: postgres
# - Usuario: trenes_user
# - Contraseña: [tu POSTGRES_PASSWORD]
# - Base de datos: trenes_db
```
### Ejecutar Migraciones
```bash
# Usando Make
make migrate # Aplicar migraciones
make migrate-info # Ver información
make migrate-validate # Validar migraciones
# O manualmente
docker-compose --profile migration up flyway
docker-compose --profile migration run --rm flyway info
docker-compose --profile migration run --rm flyway validate
```
## Estructura del Proyecto
```
trenes/
├── backend/ # Backend Node.js
│ ├── src/
│ │ ├── api/ # API REST
│ │ │ └── server.js
│ │ └── worker/ # Worker GTFS-RT polling
│ │ └── gtfs-poller.js
│ ├── Dockerfile
│ └── package.json
├── frontend/ # Frontend React
│ ├── src/
│ │ ├── components/
│ │ ├── hooks/
│ │ └── App.jsx
│ ├── Dockerfile
│ ├── nginx.conf # Configuración nginx del contenedor
│ └── package.json
├── database/
│ ├── init/ # Scripts de inicialización (solo primera vez)
│ │ ├── 01-init-extensions.sql
│ │ ├── 02-create-schema.sql
│ │ └── 03-seed-data.sql
│ └── migrations/ # Migraciones versionadas (Flyway)
│ ├── V1__initial_schema.sql
│ ├── V2__create_partitions.sql
│ ├── V3__create_views_and_functions.sql
│ └── V4__seed_initial_data.sql
├── nginx/ # Configuración Nginx (reverse proxy)
│ ├── nginx.conf
│ └── conf.d/
│ └── default.conf
├── docker-compose.yml
├── .env.example
└── README.md
```
## API Endpoints
### Posiciones de Trenes
```bash
# Obtener posiciones actuales de todos los trenes
GET /api/trains/current
# Obtener histórico de un tren
GET /api/trains/history?train_id=XXX&from=TIMESTAMP&to=TIMESTAMP
# Obtener información de un tren específico
GET /api/trains/:id
# Obtener rutas disponibles
GET /api/routes
# Obtener estaciones
GET /api/stations
```
### WebSocket Events
```javascript
// Conectar al WebSocket
const socket = io('ws://localhost/ws');
// Escuchar actualizaciones de posiciones
socket.on('train:update', (position) => {
console.log('Nueva posición:', position);
});
// Suscribirse a un tren específico
socket.emit('subscribe', { train_id: 'AVE-03041' });
```
## Base de Datos
### Tablas Principales
- **trains**: Catálogo de trenes
- **train_positions**: Histórico de posiciones (particionada por mes)
- **routes**: Rutas y líneas
- **stations**: Estaciones
- **alerts**: Alertas e incidencias
### Vistas
- **current_train_positions**: Última posición de cada tren
- **active_trains**: Trenes activos en las últimas 24 horas
### Funciones Útiles
```sql
-- Limpiar posiciones antiguas (mayores a 90 días)
SELECT cleanup_old_positions(90);
-- Crear siguiente partición mensual
SELECT create_next_partition();
-- Obtener trayectoria de un tren
SELECT * FROM get_train_path('AVE-03041', '2025-01-01', '2025-01-02');
-- Obtener trenes en un área
SELECT * FROM get_trains_in_area(40.0, -4.0, 41.0, -3.0);
-- Calcular estadísticas de un tren
SELECT * FROM calculate_train_statistics('AVE-03041', '2025-01-01', '2025-01-02');
```
## Gestión de Migraciones
Este proyecto usa **Flyway** para gestionar las migraciones de base de datos de forma versionada y reproducible.
### Convención de Nombres
Las migraciones siguen el formato: `V{version}__{description}.sql`
- `V1__initial_schema.sql` - Versión 1: Schema inicial
- `V2__create_partitions.sql` - Versión 2: Crear particiones
- etc.
### Crear Nueva Migración
1. Crear archivo en `database/migrations/` siguiendo la convención:
```
V5__add_train_operators.sql
```
2. Aplicar migración:
```bash
docker-compose --profile migration up flyway
```
### Comandos de Flyway
```bash
# Ver estado de migraciones
docker-compose --profile migration run --rm flyway info
# Validar migraciones
docker-compose --profile migration run --rm flyway validate
# Limpiar base de datos (¡CUIDADO! Borra todo)
docker-compose --profile migration run --rm flyway clean
# Reparar tabla de migraciones
docker-compose --profile migration run --rm flyway repair
```
## Mantenimiento
### Backup de Base de Datos
```bash
# Crear backup
docker-compose exec postgres pg_dump -U trenes_user trenes_db > backup.sql
# Restaurar backup
docker-compose exec -T postgres psql -U trenes_user trenes_db < backup.sql
```
### Limpiar Datos Antiguos
```bash
# Conectar a PostgreSQL
docker-compose exec postgres psql -U trenes_user -d trenes_db
# Ejecutar función de limpieza (elimina datos > 90 días)
SELECT cleanup_old_positions(90);
```
### Crear Nuevas Particiones
```bash
# Conectar a PostgreSQL
docker-compose exec postgres psql -U trenes_user -d trenes_db
# Crear próxima partición
SELECT create_next_partition();
```
## Desarrollo
### Modo Desarrollo
Para desarrollo local con hot-reload:
```bash
# Backend
cd backend
npm install
npm run dev
# Frontend
cd frontend
npm install
npm run dev
```
### Estructura de Logs
```bash
# Ver logs de un servicio específico
docker-compose logs -f api
docker-compose logs -f worker
docker-compose logs -f frontend
# Ver logs de todos los servicios
docker-compose logs -f
```
## Troubleshooting
### El worker no puede conectar con GTFS-RT
```bash
# Verificar que el worker está corriendo
docker-compose logs worker
# Probar manualmente el endpoint
curl -I https://gtfsrt.renfe.com/vehicle_positions.pb
```
### La base de datos no inicia
```bash
# Ver logs de PostgreSQL
docker-compose logs postgres
# Verificar permisos de volúmenes
ls -la postgres_data/
# Reiniciar contenedor
docker-compose restart postgres
```
### No se ven los trenes en el mapa
1. Verificar que el worker está recolectando datos:
```bash
docker-compose logs worker
```
2. Verificar que hay datos en la base de datos:
```bash
docker-compose exec postgres psql -U trenes_user -d trenes_db -c "SELECT COUNT(*) FROM train_positions;"
```
3. Verificar que el API responde:
```bash
curl http://localhost/api/trains/current
```
## Despliegue en Producción
### Requisitos del Servidor
- Linux (Debian/Ubuntu recomendado)
- Docker >= 20.10
- Docker Compose >= 2.0
- Mínimo 2GB RAM, 20GB disco
- Puerto 80 y 443 abiertos
- Dominio apuntando al servidor
### Despliegue Rápido
```bash
# 1. Copiar proyecto al servidor
rsync -avz --exclude 'node_modules' --exclude '.git' --exclude 'postgres_data' \
./ root@tu-servidor:/opt/trenes/
# 2. En el servidor, crear archivo .env de producción
cat > /opt/trenes/.env << 'EOF'
POSTGRES_USER=trenes
POSTGRES_PASSWORD=TU_PASSWORD_SEGURO_GENERADO
POSTGRES_DB=trenes
DATABASE_URL=postgres://trenes:${POSTGRES_PASSWORD}@postgres:5432/trenes
REDIS_URL=redis://redis:6379
NODE_ENV=production
PORT=3000
CORS_ORIGINS=https://tu-dominio.com
EOF
# 3. Iniciar servicios
cd /opt/trenes
docker compose -f docker-compose.prod.yml up -d
```
### Configuración SSL con Let's Encrypt
```bash
# 1. Iniciar nginx temporal para obtener certificado
docker run -d --name temp-nginx -p 80:80 \
-v /opt/trenes/nginx/prod.conf:/etc/nginx/conf.d/default.conf:ro \
-v certbot_webroot:/var/www/certbot nginx:alpine
# 2. Obtener certificado
docker run --rm \
-v trenes_certbot_certs:/etc/letsencrypt \
-v certbot_webroot:/var/www/certbot \
certbot/certbot certonly --webroot \
--webroot-path=/var/www/certbot \
--email tu-email@dominio.com \
--agree-tos --no-eff-email \
-d tu-dominio.com
# 3. Detener nginx temporal
docker stop temp-nginx && docker rm temp-nginx
# 4. Iniciar servicios completos
docker compose -f docker-compose.prod.yml up -d
```
### Lecciones Aprendidas del Despliegue
#### 1. PostgreSQL/PostGIS - Compatibilidad de Versiones
**Problema**: Error `FATAL: database files are incompatible with server` al usar datos existentes.
**Solución**: Asegurar que la versión de PostgreSQL en producción coincida con la de desarrollo. Si los datos fueron creados con PostgreSQL 16, usar `postgis/postgis:16-3.4-alpine` en producción.
#### 2. Socket.io - Configuración de URL
**Problema**: Error "Invalid namespace" al conectar WebSocket.
**Causa**: Socket.io añade automáticamente `/socket.io/` al path. Si `VITE_WS_URL=wss://dominio.com/ws`, intentará conectar a `/ws/socket.io/`.
**Solución**: Configurar `VITE_WS_URL=https://dominio.com` (sin path adicional) para que Socket.io conecte correctamente a `/socket.io/`.
#### 3. Nginx - Variables y Proxy Pass
**Problema**: Cuando se usan variables en `proxy_pass`, nginx NO hace sustitución automática de URI.
**Solución**: Usar `rewrite` explícito:
```nginx
location /api/ {
set $backend api:3000;
rewrite ^/api/(.*)$ /$1 break;
proxy_pass http://$backend;
}
```
#### 4. Nginx - Resolución DNS de Contenedores
**Problema**: Error `host not found in upstream` al iniciar nginx antes que otros servicios.
**Solución**: Usar el resolver DNS de Docker:
```nginx
resolver 127.0.0.11 valid=30s;
```
#### 5. Nginx - Directiva HTTP/2
**Problema**: Warning `the "listen ... http2" directive is deprecated`.
**Solución**: Cambiar de `listen 443 ssl http2;` a:
```nginx
listen 443 ssl;
http2 on;
```
#### 6. Variables VITE en Docker
**Problema**: Las variables `VITE_*` del `.env` no se aplican en el build de Docker.
**Solución**: Pasar las variables como build args en docker-compose:
```yaml
frontend:
build:
args:
VITE_API_URL: https://tu-dominio.com/api
VITE_WS_URL: https://tu-dominio.com
```
Y en el Dockerfile del frontend:
```dockerfile
ARG VITE_API_URL
ARG VITE_WS_URL
ENV VITE_API_URL=${VITE_API_URL}
ENV VITE_WS_URL=${VITE_WS_URL}
```
#### 7. Migración de Datos
**Comando para exportar e importar datos históricos**:
```bash
# Exportar desde desarrollo
docker compose exec -T postgres pg_dump -U trenes_user -d trenes_db \
--data-only --exclude-table='flyway_schema_history' | gzip > backup.sql.gz
# Copiar al servidor
scp backup.sql.gz root@servidor:/tmp/
# Importar en producción
gunzip -c /tmp/backup.sql.gz | docker exec -i trenes-postgres \
psql -U trenes -d trenes
```
### Verificación del Despliegue
```bash
# Verificar servicios
docker ps --format "table {{.Names}}\t{{.Status}}"
# Test API
curl https://tu-dominio.com/api/health
# Test Dashboard
curl https://tu-dominio.com/api/dashboard/current
# Test WebSocket (debe devolver sid)
curl "https://tu-dominio.com/socket.io/?EIO=4&transport=polling"
```
## Roadmap
- [x] **Fase 1: MVP** ✅ COMPLETADA
- [x] Arquitectura y Docker Compose
- [x] Backend API y Worker GTFS-RT
- [x] Frontend con mapa Leaflet
- [x] WebSocket en tiempo real
- [x] Timeline slider (UI básica)
- [x] **Fase 2: Enriquecimiento** ✅ BACKEND COMPLETADO
- [x] GTFS Static Syncer (sync diario)
- [x] Trip Updates Poller (retrasos)
- [x] Service Alerts Poller (alertas)
- [x] API de Alertas y Trips
- [ ] Frontend: componentes de alertas y puntualidad
- [x] **Fase 3: Analytics** ✅ BACKEND COMPLETADO
- [x] Analytics API (heatmaps, estadísticas)
- [x] Explorer API (planificador de viajes)
- [x] Exportación de datos (CSV, JSON, GeoJSON)
- [ ] Frontend: dashboard de analytics
- [ ] **Fase 4: ML y Predicciones** (Futuro)
- [ ] Predicción de retrasos
- [ ] Detección de anomalías
- [ ] Correlación con meteorología
## Licencia
MIT
## Contribuir
Las contribuciones son bienvenidas. Por favor:
1. Fork el proyecto
2. Crea una rama para tu feature (`git checkout -b feature/AmazingFeature`)
3. Commit tus cambios (`git commit -m 'Add some AmazingFeature'`)
4. Push a la rama (`git push origin feature/AmazingFeature`)
5. Abre un Pull Request
## Recursos
- [GTFS Realtime Specification](https://gtfs.org/documentation/realtime/)
- [Renfe Data Portal](https://data.renfe.com/)
- [PostGIS Documentation](https://postgis.net/)
- [Leaflet.js](https://leafletjs.com/)
- [Flyway Documentation](https://flywaydb.org/documentation/)