Añadir 03-debug-simulador.md
451
03-debug-simulador.md.-.md
Normal file
451
03-debug-simulador.md.-.md
Normal file
@@ -0,0 +1,451 @@
|
||||
# Debug del Simulador
|
||||
|
||||
Herramientas y comandos para verificar el estado del simulador y troubleshooting avanzado.
|
||||
|
||||
---
|
||||
|
||||
## Verificar que el simulador está corriendo
|
||||
|
||||
### Método 1: Endpoint de status
|
||||
|
||||
```bash
|
||||
curl http://localhost:8000/admin/route/RUTA-01/status
|
||||
```
|
||||
|
||||
**Si está corriendo:**
|
||||
```json
|
||||
{
|
||||
"route_id": "RUTA-01",
|
||||
"current_position_id": 3,
|
||||
"current_position_name": "Parque Xochipilli",
|
||||
"status": "EN_RUTA",
|
||||
"last_update": "2026-05-22T19:35:12.123456"
|
||||
}
|
||||
```
|
||||
|
||||
**Si NO está corriendo:**
|
||||
```json
|
||||
{
|
||||
"detail": "Ruta no encontrada o simulador detenido"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Método 2: Logs del servidor
|
||||
|
||||
En la terminal donde corre `uvicorn`, deberías ver:
|
||||
|
||||
```
|
||||
INFO: Tick simulador: RUTA-01 -> posición 3
|
||||
INFO: Broadcast WebSocket a address_id 1: aproximandose
|
||||
INFO: Tick simulador: RUTA-01 -> posición 4
|
||||
```
|
||||
|
||||
**Si NO ves logs cada 10s** → el simulador está detenido.
|
||||
|
||||
---
|
||||
|
||||
## Arrancar el simulador
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/admin/route/RUTA-01/start
|
||||
```
|
||||
|
||||
**Response esperada:**
|
||||
```json
|
||||
{
|
||||
"message": "Ruta RUTA-01 iniciada",
|
||||
"route_id": "RUTA-01",
|
||||
"status": "EN_RUTA"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Detener el simulador
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/admin/route/RUTA-01/stop
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"message": "Ruta RUTA-01 detenida",
|
||||
"route_id": "RUTA-01"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Inspeccionar la base de datos
|
||||
|
||||
### Abrir con sqlite3
|
||||
|
||||
```bash
|
||||
cd basura_backend
|
||||
sqlite3 basura.db
|
||||
|
||||
# Comandos útiles:
|
||||
.tables # Listar tablas
|
||||
.schema truck_status # Ver estructura de tabla
|
||||
|
||||
SELECT * FROM truck_status; # Ver estado actual
|
||||
SELECT * FROM rutas; # Ver rutas disponibles
|
||||
SELECT * FROM puntos_ruta WHERE ruta_id = 'RUTA-01' ORDER BY orden; # Waypoints
|
||||
SELECT * FROM notificaciones ORDER BY creada_en DESC LIMIT 10; # Últimas 10 notificaciones
|
||||
|
||||
.quit
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Verificar datos del seed
|
||||
|
||||
```sql
|
||||
-- Debe haber 1 ruta
|
||||
SELECT COUNT(*) FROM rutas;
|
||||
-- Resultado: 1
|
||||
|
||||
-- Debe haber 5 puntos de ruta
|
||||
SELECT COUNT(*) FROM puntos_ruta WHERE ruta_id = 'RUTA-01';
|
||||
-- Resultado: 5
|
||||
|
||||
-- Debe haber 1 usuario demo
|
||||
SELECT * FROM users;
|
||||
-- Resultado: id=1, email='demo@ejemplo.com'
|
||||
|
||||
-- Debe haber 1 domicilio
|
||||
SELECT * FROM addresses;
|
||||
-- Resultado: id=1, user_id=1, route_id='RUTA-01'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Problemas comunes del simulador
|
||||
|
||||
### El camión no avanza
|
||||
|
||||
**Síntoma:** `current_position_id` no cambia.
|
||||
|
||||
**Diagnóstico:**
|
||||
```bash
|
||||
# 1. Verificar que el simulador está corriendo
|
||||
curl http://localhost:8000/admin/route/RUTA-01/status
|
||||
|
||||
# 2. Verificar logs del servidor
|
||||
# Deberías ver "Tick simulador" cada 10s
|
||||
```
|
||||
|
||||
**Causa 1:** El simulador nunca se arrancó.
|
||||
|
||||
**Solución:**
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/admin/route/RUTA-01/start
|
||||
```
|
||||
|
||||
**Causa 2:** El camión ya llegó al último punto.
|
||||
|
||||
**Solución:**
|
||||
```sql
|
||||
-- Reiniciar posición a 1
|
||||
sqlite3 basura.db "UPDATE truck_status SET current_position_id = 1 WHERE route_id = 'RUTA-01';"
|
||||
|
||||
-- Arrancar de nuevo
|
||||
curl -X POST http://localhost:8000/admin/route/RUTA-01/start
|
||||
```
|
||||
|
||||
**Causa 3:** El status es `AVERIADA`.
|
||||
|
||||
**Solución:**
|
||||
```sql
|
||||
-- Cambiar status a EN_RUTA
|
||||
sqlite3 basura.db "UPDATE truck_status SET status = 'EN_RUTA' WHERE route_id = 'RUTA-01';"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### No llegan notificaciones WebSocket
|
||||
|
||||
**Síntoma:** Flutter conecta pero no recibe eventos.
|
||||
|
||||
**Diagnóstico:**
|
||||
```bash
|
||||
# 1. Conectar con wscat
|
||||
wscat -c ws://localhost:8000/ws/1
|
||||
|
||||
# 2. Arrancar simulador
|
||||
curl -X POST http://localhost:8000/admin/route/RUTA-01/start
|
||||
|
||||
# 3. Esperar 10 segundos
|
||||
# ¿Recibes eventos?
|
||||
```
|
||||
|
||||
**Causa 1:** El ETA es muy grande (>10 min).
|
||||
|
||||
**Solución:** Esperar o forzar proximidad:
|
||||
```sql
|
||||
-- Poner el camión cerca del domicilio
|
||||
sqlite3 basura.db "UPDATE truck_status SET current_position_id = 4 WHERE route_id = 'RUTA-01';"
|
||||
```
|
||||
|
||||
**Causa 2:** Las preferencias de notificación están desactivadas.
|
||||
|
||||
**Solución:**
|
||||
```sql
|
||||
SELECT * FROM notification_preferences WHERE user_id = 1;
|
||||
-- Si notify_proximity = False:
|
||||
UPDATE notification_preferences SET notify_proximity = 1 WHERE user_id = 1;
|
||||
```
|
||||
|
||||
**Causa 3:** El `address_id` no pertenece a `RUTA-01`.
|
||||
|
||||
**Solución:**
|
||||
```sql
|
||||
SELECT route_id FROM addresses WHERE id = 1;
|
||||
-- Si es NULL o diferente a 'RUTA-01':
|
||||
UPDATE addresses SET route_id = 'RUTA-01' WHERE id = 1;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### El simulador se detiene solo
|
||||
|
||||
**Síntoma:** El simulador arranca pero se detiene después de unos segundos.
|
||||
|
||||
**Diagnóstico:**
|
||||
```bash
|
||||
# Revisar logs del servidor
|
||||
# Busca errores como:
|
||||
# ERROR: Exception in simulator
|
||||
```
|
||||
|
||||
**Causa 1:** Error en el código del simulador.
|
||||
|
||||
**Solución:**
|
||||
```bash
|
||||
# Revisar logs completos
|
||||
uvicorn app.main:app --reload --log-level debug
|
||||
```
|
||||
|
||||
**Causa 2:** El camión llegó al último punto.
|
||||
|
||||
**Solución:**
|
||||
```bash
|
||||
# El simulador se detiene automáticamente al final
|
||||
# Esto es comportamiento esperado
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Ajustar velocidad del simulador
|
||||
|
||||
### Acelerar para demos
|
||||
|
||||
```bash
|
||||
# En .env
|
||||
SIM_TICK_SECONDS=5 # Tick cada 5s (más rápido)
|
||||
SIM_SPEED_MULTIPLIER=2.0 # Doble velocidad
|
||||
```
|
||||
|
||||
Reinicia el backend:
|
||||
```bash
|
||||
uvicorn app.main:app --reload
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Ralentizar para debug
|
||||
|
||||
```bash
|
||||
# En .env
|
||||
SIM_TICK_SECONDS=30 # Tick cada 30s
|
||||
SIM_SPEED_MULTIPLIER=0.5 # Mitad de velocidad
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Forzar eventos manualmente
|
||||
|
||||
### Forzar avería
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/alerts/breakdown \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"route_id": "RUTA-01"}'
|
||||
```
|
||||
|
||||
**Efecto:**
|
||||
- Detiene el simulador
|
||||
- Cambia status a `AVERIADA`
|
||||
- Broadcast WebSocket `falla_mecanica` a todos los domicilios
|
||||
|
||||
---
|
||||
|
||||
### Forzar retraso
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/admin/route/RUTA-01/delay \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"delay_minutes": 15}'
|
||||
```
|
||||
|
||||
**Efecto:**
|
||||
- Cambia status a `RETRASADA`
|
||||
- Broadcast WebSocket `ruta_tarde`
|
||||
|
||||
---
|
||||
|
||||
### Forzar proximidad (para testing)
|
||||
|
||||
```sql
|
||||
-- Mover el camión al penúltimo punto
|
||||
sqlite3 basura.db "UPDATE truck_status SET current_position_id = 4 WHERE route_id = 'RUTA-01';"
|
||||
|
||||
-- Arrancar simulador
|
||||
curl -X POST http://localhost:8000/admin/route/RUTA-01/start
|
||||
|
||||
-- En 10s, recibirás evento "aproximandose"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Monitorear en tiempo real
|
||||
|
||||
### Ver logs del simulador
|
||||
|
||||
```bash
|
||||
# En la terminal del backend
|
||||
tail -f <archivo-de-logs>
|
||||
|
||||
# O con uvicorn:
|
||||
uvicorn app.main:app --reload --log-level info
|
||||
```
|
||||
|
||||
**Logs esperados cada 10s:**
|
||||
```
|
||||
INFO: Tick simulador: RUTA-01 -> posición 2
|
||||
INFO: ETA calculado para address_id 1: 18 minutos
|
||||
INFO: Tick simulador: RUTA-01 -> posición 3
|
||||
INFO: ETA calculado para address_id 1: 12 minutos
|
||||
INFO: Tick simulador: RUTA-01 -> posición 4
|
||||
INFO: ETA calculado para address_id 1: 6 minutos
|
||||
INFO: Broadcast WebSocket a address_id 1: aproximandose
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Ver tabla de notificaciones
|
||||
|
||||
```sql
|
||||
-- Ver últimas 20 notificaciones enviadas
|
||||
SELECT
|
||||
tipo,
|
||||
address_id,
|
||||
eta_minutos,
|
||||
mensaje,
|
||||
creada_en
|
||||
FROM notificaciones
|
||||
ORDER BY creada_en DESC
|
||||
LIMIT 20;
|
||||
```
|
||||
|
||||
**Ejemplo de salida:**
|
||||
```
|
||||
aproximandose|1|8|El camión llega en ~8 minutos|2026-05-22 19:35:00
|
||||
aproximandose|1|9|El camión llega en ~9 minutos|2026-05-22 19:34:50
|
||||
ruta_iniciada|1|NULL|El camión comenzó su recorrido|2026-05-22 19:00:00
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Resetear el simulador completamente
|
||||
|
||||
```bash
|
||||
# 1. Detener el backend (Ctrl+C)
|
||||
|
||||
# 2. Borrar la BD
|
||||
rm basura.db
|
||||
|
||||
# 3. Arrancar de nuevo (recrea BD + seed)
|
||||
uvicorn app.main:app --reload
|
||||
|
||||
# 4. Verificar que el seed fue creado
|
||||
curl http://localhost:8000/admin/route/RUTA-01/status
|
||||
|
||||
# 5. Arrancar simulador
|
||||
curl -X POST http://localhost:8000/admin/route/RUTA-01/start
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting avanzado
|
||||
|
||||
### Ver el código del simulador
|
||||
|
||||
```python
|
||||
# app/services/simulador.py
|
||||
|
||||
def tick_simulador(self):
|
||||
# Este método se ejecuta cada SIM_TICK_SECONDS
|
||||
# 1. Avanza current_position_id
|
||||
# 2. Calcula ETA para cada address
|
||||
# 3. Si ETA <= umbral, broadcast WebSocket
|
||||
|
||||
# Agregar prints para debug:
|
||||
print(f"DEBUG: current_position = {current_position_id}")
|
||||
print(f"DEBUG: ETA calculado = {eta_minutos}")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Ver el broadcast WebSocket
|
||||
|
||||
```python
|
||||
# app/services/ws_manager.py
|
||||
|
||||
async def broadcast_zona(self, zona_key: str, payload: dict):
|
||||
# Agregar log:
|
||||
print(f"DEBUG: Broadcasting a zona {zona_key}: {payload}")
|
||||
# ...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Verificar APScheduler
|
||||
|
||||
```python
|
||||
# app/services/simulador.py
|
||||
|
||||
# Ver jobs activos
|
||||
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
||||
|
||||
scheduler = AsyncIOScheduler()
|
||||
jobs = scheduler.get_jobs()
|
||||
print(f"DEBUG: Jobs activos: {len(jobs)}")
|
||||
for job in jobs:
|
||||
print(f" - {job.id}: {job.next_run_time}")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Checklist de debug
|
||||
|
||||
- [ ] Backend está corriendo (`curl /health`)
|
||||
- [ ] Simulador está arrancado (`GET /admin/route/.../status`)
|
||||
- [ ] Logs muestran "Tick simulador" cada 10s
|
||||
- [ ] `truck_status.current_position_id` incrementa
|
||||
- [ ] ETA se calcula correctamente (`GET /eta/1`)
|
||||
- [ ] WebSocket conecta (`wscat -c ws://...`)
|
||||
- [ ] Eventos llegan a Flutter
|
||||
- [ ] Preferencias de notificación activadas
|
||||
- [ ] `address_id` pertenece a la ruta correcta
|
||||
|
||||
---
|
||||
|
||||
## Siguiente paso
|
||||
|
||||
- [Errores comunes](01-errores-comunes.md) — soluciones rápidas
|
||||
- [Problemas de versiones](02-versiones.md) — Dart, Java, Python
|
||||
- [Documentación de API](../api/01-endpoints.md) — endpoints disponibles
|
||||
Reference in New Issue
Block a user