MVP en Python para monitorizar el entorno del Puente del Centenario con fuentes publicas de la DGT. El proyecto recoge:
- paneles VMS activos en la zona de la SE-30
- incidencias DATEX2 v3.6 cercanas al puente
- inventario de camaras y snapshots de las camaras cercanas
- intensidades y velocidad media de detectores DGT cercanos al puente
- un estado agregado del puente con una inferencia inicial de
trafico_puenteyreversible_probable
La salida del proyecto es una estimacion operativa, no una fuente oficial del estado del carril reversible.
- Paneles DGT tiempo real:
https://infocar.dgt.es/datex2/dgt/SituationPublication/paneles/content.xml - Inventario de paneles:
https://infocar.dgt.es/datex2/dgt/PredefinedLocationsPublication/paneles/content.xml - Incidencias DGT DATEX2 v3.6:
https://nap.dgt.es/datex2/v3/dgt/SituationPublication/datex2_v36.xml - Inventario de camaras:
https://nap.dgt.es/datex2/v3/dgt/DevicePublication/camaras_datex2_v36.xml - Detectores DGT tiempo real:
https://infocar.dgt.es/datex2/dgt/MeasuredDataPublication/detectores/content.xml - Inventario de detectores:
https://infocar.dgt.es/datex2/dgt/PredefinedLocationsPublication/detectores/content.xml
- Python 3.9+
python3 -m venv .venv
source .venv/bin/activate
pip install -e .Extras opcionales:
pip install -e .[dev]
pip install -e .[vision]Si no quieres instalarlo en editable, tambien puedes ejecutar con PYTHONPATH=src.
Inicializar la base SQLite:
PYTHONPATH=src python3 -m vcentenario.cli init-dbRecoger una tanda de datos y calcular el estado:
PYTHONPATH=src python3 -m vcentenario.cli run-once --jsonVer el ultimo estado guardado:
PYTHONPATH=src python3 -m vcentenario.cli latest-stateLimpiar historico antiguo:
PYTHONPATH=src python3 -m vcentenario.cli cleanup --vacuumLevantar la app web:
PYTHONPATH=src python3 -m vcentenario.cli serve --host 0.0.0.0 --port 8080Luego abre http://localhost:8080 o la IP del servidor si lo ejecutas en remoto.
Antes de publicar el repositorio:
- revisa que
var/,.venv/, logs y snapshots no se hayan versionado - no subas tokens ni secretos de despliegue
- el modelo
yolov8n.ptse trata como artefacto local y no se versiona por defecto - corrige cualquier dato operativo local antes de hacer el primer commit
Ejemplo de salida JSON:
{
"traffic_level": "denso",
"traffic_score": 42.0,
"reversible_probable": "negative",
"confidence": 0.41,
"official": false
}El sistema combina varias senales:
- mensajes VMS activos alrededor del km 13-15 de la SE-30
- incidencias en la SE-30 dentro del entorno del puente
- disponibilidad de camaras y cambios entre snapshots
- detectores de la zona con velocidad media, flujo y ocupacion cuando hay datos
La inferencia del reversible es deliberadamente conservadora:
positive/negativecorresponden a la direccion DATEX2directionRelative- si no hay evidencia suficiente, el sistema devuelve
indeterminado - la confianza solo sube cuando coinciden varias senales en el mismo sentido
- existe persistencia temporal para evitar saltos bruscos entre sentidos consecutivos
- existe un sesgo horario configurable para patrones recurrentes del puente
El motor ajusta parte del score con el historico reciente persistido en SQLite:
- compara la contribucion actual de cada fuente con su baseline historico local
- aplica una correccion limitada para no sobrerreaccionar cuando una fuente se sale de su patron reciente
- registra ese ajuste en
breakdown.historical_calibration
- Las peticiones HTTP tienen reintentos con backoff para errores temporales.
run-onceahora tolera fallos parciales: si cae una fuente, el resto sigue procesandose.- Cada ejecucion guarda un resumen de fuentes, contadores y avisos en SQLite.
- El servicio limpia historico antiguo automaticamente para evitar crecimiento indefinido de la base y de
var/snapshots.
Variables utiles:
VCENTENARIO_DB_PATHVCENTENARIO_SNAPSHOTS_DIRVCENTENARIO_REQUEST_TIMEOUTVCENTENARIO_HTTP_MAX_RETRIESVCENTENARIO_HTTP_RETRY_BACKOFF_SECONDSVCENTENARIO_ENABLE_REFRESH_ENDPOINTVCENTENARIO_REFRESH_TOKENVCENTENARIO_REFRESH_MIN_INTERVAL_SECONDSVCENTENARIO_REVERSIBLE_PERSISTENCE_WINDOWVCENTENARIO_REVERSIBLE_SCHEDULEVCENTENARIO_KEEP_STATESVCENTENARIO_KEEP_COLLECTION_RUNSVCENTENARIO_KEEP_BATCHESVCENTENARIO_KEEP_SNAPSHOTS_PER_CAMERAVCENTENARIO_ENABLE_VISIONVCENTENARIO_YOLO_MODEL_PATHVCENTENARIO_YOLO_CONFIDENCEVCENTENARIO_YOLO_IMAGE_SIZEVCENTENARIO_YOLO_ENABLE_TILINGVCENTENARIO_YOLO_TILE_OVERLAPVCENTENARIO_USER_AGENT
Por defecto el proyecto usa yolov8m.pt como modelo de vision si el archivo existe en la raiz del proyecto.
Ejemplo:
export VCENTENARIO_HTTP_MAX_RETRIES=3
export VCENTENARIO_KEEP_SNAPSHOTS_PER_CAMERA=48
PYTHONPATH=src python3 -m vcentenario.cli run-once --json- No existe una fuente publica oficial con el estado del carril reversible.
- Los detectores DGT se integran como segunda fuente, pero algunos siguen llegando con retraso o sin datos.
- La metrica visual de camaras mejora con OpenCV, pero sigue siendo una estimacion ligera, no tracking completo.
- La equivalencia de
positiveynegativecon los sentidos fisicos del puente puede ajustarse mas adelante en configuracion. - La calibracion historica usa el historico local del servicio, no etiquetas oficiales externas.
- La UI sigue siendo una app server-side muy compacta; la API y el frontend aun viven en el mismo modulo.
El dashboard puede exponerse detras de Nginx, pero la recogida manual queda desactivada por defecto. Si necesitas habilitarla:
export VCENTENARIO_ENABLE_REFRESH_ENDPOINT=true
export VCENTENARIO_REFRESH_TOKEN='token-largo-y-aleatorio'Las peticiones a POST /api/refresh deben enviar:
Authorization: Bearer <token>
Ademas, el endpoint aplica un intervalo minimo configurable entre refrescos para reducir abuso.
El script deploy.sh ahora:
- crea
.venvsi no existe - instala el proyecto y extras opcionales
- genera un
EnvironmentFilepara systemd en/etc/default/vcentenario - crea una unidad
systemdpara la web y untimerque ejecutarun-onceautomaticamente - refresca datos, estado y predicciones cada 5 minutos por defecto
- endurece las unidades
systemdcon restricciones basicas - configura Nginx como proxy inverso
Ejemplo:
sudo APP_HOST=127.0.0.1 APP_PORT=5000 PUBLIC_PORT=8088 ./deploy.shSi quieres cambiar la cadencia del refresco automatico:
sudo REFRESH_INTERVAL_MINUTES=5 ./deploy.shSi quieres instalar dependencias de desarrollo o vision durante el bootstrap:
sudo INSTALL_DEV_DEPS=1 INSTALL_VISION_DEPS=1 ./deploy.shsrc/vcentenario/cli.pysrc/vcentenario/service.pysrc/vcentenario/inference.pysrc/vcentenario/storage.pysrc/vcentenario/collectors/panels.pysrc/vcentenario/collectors/incidents.pysrc/vcentenario/collectors/cameras.py
- incorporar etiquetas externas u observacion manual para calibracion supervisada real
- reforzar la metrica visual con tracking o segmentacion si YOLO se queda corto
- afinar las reglas horarias del reversible con operacion real del puente
- exponer autenticacion o rate limiting si el dashboard se publica en Internet
- separar frontend/API en modulos distintos si la interfaz sigue creciendo