- Updated docs and inventory files - Added new architecture docs Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
114 lines
6.2 KiB
Markdown
114 lines
6.2 KiB
Markdown
# US-MAI006-013: Validar posiciones GPS
|
|
|
|
## Metadata
|
|
|
|
| Campo | Valor |
|
|
|-------|-------|
|
|
| **ID** | US-MAI006-013 |
|
|
| **Epica** | EPIC-MAI-006 - Tracking en Tiempo Real |
|
|
| **Modulo** | tracking |
|
|
| **Prioridad** | P1 |
|
|
| **Story Points** | 5 |
|
|
| **Sprint** | Por asignar |
|
|
| **Estado** | Backlog |
|
|
|
|
## Historia de Usuario
|
|
|
|
**Como** administrador del sistema de tracking,
|
|
**quiero** que el sistema filtre automaticamente las posiciones GPS invalidas o anomalas,
|
|
**para** evitar que datos erroneos afecten el calculo de rutas, distancias y la visualizacion en el mapa.
|
|
|
|
## Descripcion Detallada
|
|
|
|
Los dispositivos GPS pueden reportar posiciones invalidas por diversas razones: perdida de senal satelital, interferencia, mal funcionamiento del dispositivo, o manipulacion. Estas posiciones anomalas pueden causar problemas graves en el sistema: rutas con "saltos" imposibles en el mapa, calculos de distancia incorrectos, alertas falsas de exceso de velocidad, y ETAs erroneos.
|
|
|
|
El sistema debe implementar un servicio de validacion que analice cada posicion recibida y determine si es valida o no. Las validaciones incluyen: coordenadas dentro de rangos validos, velocidad fisicamente posible, precision GPS aceptable (HDOP), numero minimo de satelites, y deteccion de "teleportacion" (saltos de posicion imposibles dado el tiempo transcurrido).
|
|
|
|
Las posiciones invalidas se almacenan marcadas con `valida = FALSE` para fines de auditoria y debugging, pero no se consideran para calculos de ruta, distancia, o visualizacion en el mapa.
|
|
|
|
## Criterios de Aceptacion
|
|
|
|
### Escenario 1: Rechazar coordenadas fuera de rango
|
|
|
|
**Dado** que se recibe una posicion GPS con latitud 95.0 (fuera del rango -90 a 90),
|
|
**Cuando** el sistema procesa la posicion,
|
|
**Entonces** la posicion se almacena con `valida = FALSE` y razon "Latitud fuera de rango", no se emite por WebSocket, y no se considera para calculos.
|
|
|
|
### Escenario 2: Detectar velocidad imposible
|
|
|
|
**Dado** que se recibe una posicion GPS con velocidad 350 km/h (configuracion maxima: 200 km/h para transporte de carga),
|
|
**Cuando** el sistema procesa la posicion,
|
|
**Entonces** la posicion se almacena con `valida = FALSE` y razon "Velocidad excesiva", y se genera una alerta informativa de "posicion anomala detectada".
|
|
|
|
### Escenario 3: Detectar salto de posicion (teleportacion)
|
|
|
|
**Dado** que la ultima posicion valida de la Unidad T-001 fue en CDMX hace 30 segundos,
|
|
**Cuando** se recibe una nueva posicion ubicada en Monterrey (1000 km de distancia),
|
|
**Entonces** el sistema calcula que seria imposible recorrer esa distancia en 30 segundos (requeriria velocidad de 120,000 km/h), marca la posicion como invalida con razon "Salto de posicion detectado".
|
|
|
|
### Escenario 4: Rechazar posicion con baja precision GPS
|
|
|
|
**Dado** que se recibe una posicion con HDOP = 25 (configuracion maxima: 10),
|
|
**Cuando** el sistema procesa la posicion,
|
|
**Entonces** la posicion se almacena con `valida = FALSE` y razon "Precision GPS baja (HDOP > 10)", permitiendo que la siguiente posicion con buena precision sea aceptada.
|
|
|
|
### Escenario 5: Rechazar posicion con pocos satelites
|
|
|
|
**Dado** que se recibe una posicion con solo 2 satelites (configuracion minima: 4),
|
|
**Cuando** el sistema procesa la posicion,
|
|
**Entonces** la posicion se almacena con `valida = FALSE` y razon "Satelites insuficientes".
|
|
|
|
### Escenario 6: Posicion valida se procesa normalmente
|
|
|
|
**Dado** que se recibe una posicion con: latitud 19.4326, longitud -99.1332, velocidad 65 km/h, HDOP 1.2, satelites 12, y la distancia desde la ultima posicion es coherente con el tiempo transcurrido,
|
|
**Cuando** el sistema procesa la posicion,
|
|
**Entonces** la posicion se almacena con `valida = TRUE`, se emite por WebSocket, y se utiliza para calculos de ruta y distancia.
|
|
|
|
### Escenario 7: Configurar reglas de validacion por tenant
|
|
|
|
**Dado** que el tenant configura velocidad maxima de 120 km/h (transporte especial de carga delicada),
|
|
**Cuando** se recibe una posicion con velocidad 130 km/h,
|
|
**Entonces** el sistema aplica la configuracion especifica del tenant y marca la posicion como invalida.
|
|
|
|
## Tareas Tecnicas
|
|
|
|
- **Database:** Agregar campo `valida BOOLEAN DEFAULT TRUE` y `razon_invalida VARCHAR(200)` a la tabla `tracking.posiciones_gps` si no existen. Crear indice parcial: `CREATE INDEX idx_posicion_valida ON tracking.posiciones_gps(unidad_id, timestamp_gps) WHERE valida = TRUE`.
|
|
- **Backend:** Crear `PositionValidatorService` con metodo `validate(position, lastPosition): ValidationResult`. Implementar validaciones: coordenadas en rango, velocidad maxima, HDOP maximo, satelites minimos, deteccion de salto. Integrar validador en `PositionIngestionService`.
|
|
- **Configuration:** Crear tabla `tracking.validation_config` o usar tenant_settings para configurar: max_speed_kmh (default 200), max_hdop (default 10), min_satellites (default 4), max_jump_factor (default 1.5).
|
|
- **Alerting:** Generar alerta informativa cuando se detectan multiples posiciones invalidas consecutivas del mismo dispositivo (posible falla de equipo).
|
|
- **Tests:** Tests unitarios de cada validacion. Tests con posiciones edge case. Tests de configuracion por tenant.
|
|
|
|
## Dependencias
|
|
|
|
- **Depende de:** US-MAI006-012 (recibir posiciones), MAI-001 (tenant settings)
|
|
- **Bloquea:** Ninguna (es una mejora transversal)
|
|
|
|
## Notas Tecnicas
|
|
|
|
- **Validaciones implementadas:**
|
|
|
|
| Validacion | Regla | Default |
|
|
|------------|-------|---------|
|
|
| Latitud | -90 <= lat <= 90 | Fijo |
|
|
| Longitud | -180 <= lon <= 180 | Fijo |
|
|
| Velocidad | speed <= max_speed | 200 km/h |
|
|
| HDOP | hdop <= max_hdop | 10 |
|
|
| Satelites | sat >= min_sat | 4 |
|
|
| Salto | dist <= max_possible * factor | factor 1.5 |
|
|
|
|
- **Formula de distancia maxima posible:**
|
|
```
|
|
tiempo_segundos = (timestamp_nuevo - timestamp_anterior)
|
|
max_distancia_km = (max_speed_kmh / 3600) * tiempo_segundos
|
|
distancia_real = haversine(pos_anterior, pos_nueva)
|
|
es_valida = distancia_real <= max_distancia_km * factor
|
|
```
|
|
|
|
- **Cache:** Mantener ultima posicion valida en Redis para comparacion rapida: `lastpos:{unidad_id}`
|
|
- **Logs:** Registrar posiciones invalidas en log estructurado para analisis posterior
|
|
- **Metricas:** Exponer metrica `gps_positions_invalid_total` con label por razon para monitoreo
|
|
|
|
---
|
|
|
|
*US-MAI006-013 - ERP Transportistas v1.0.0*
|