API de Rutas para Transporte: Guía para Desarrolladores Python
API de Rutas para Transporte: Guía para Desarrolladores Python
Introducción
La integración de APIs de optimización de rutas en aplicaciones de transporte se ha convertido en un diferenciador competitivo. Esta guía técnica muestra cómo implementar una API de rutas en Python para optimizar operaciones logísticas.
> Nota: Esta guía está orientada a desarrolladores que necesitan integrar servicios de rutas en sus aplicaciones.
---
Fundamentos de APIs de Rutas
Conceptos Básicos
Una API de rutas para transporte permite:
- Cálculo de rutas óptimas considerando múltiples factores - Optimización de trayectos con restricciones específicas - Estimación de tiempos y costes de combustible - Predicción de tráfico basada en datos históricos
Componentes de una Solicitud
```python import requests import json
def calcular_ruta(origen, destino, parametros): """ Calcula ruta óptima entre dos puntos """ url = "https://api.cargoffer.com/v1/rutas"
payload = { "origen": { "latitud": origen["lat"], "longitud": origen["lon"], "direccion": origen["direccion"] }, "destino": { "latitud": destino["lat"], "longitud": destino["lon"], "direccion": destino["direccion"] }, "vehiculo": { "tipo": "camion", "peso_kg": parametros.get("peso", 20000), "altura_m": parametros.get("altura", 4.5), "consumo_100km": parametros.get("consumo", 35) }, "preferencias": { "evitar_peajes": parametros.get("evitar_peajes", False), "evitar_carreteras_lentas": parametros.get("evitar_carreteras", False), "prioridad": parametros.get("prioridad", "tiempo") # tiempo | distancia | coste } }
headers = { "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json" }
response = requests.post(url, json=payload, headers=headers) return response.json() ```
---
Autenticación
Obtener API Key
```python
Guardar credenciales de forma segura
import os
API_KEY = os.environ.get("CARGOFFER_API_KEY") API_SECRET = os.environ.get("CARGOFFER_API_SECRET") ```
Autenticación JWT
```python import jwt import time
def crear_token_jwt(): """ Genera token JWT para autenticación """ now = int(time.time())
payload = { "iat": now, "exp": now + 3600, # 1 hora "aud": "/admin/" }
header = { "alg": "HS256", "typ": "JWT", "kid": API_KEY.split(":")[0] }
secret = API_KEY.split(":")[1] token = jwt.encode(payload, secret, algorithm="HS256", headers=header)
return token ```
---
Endpoints Principales
1. Calcular Ruta Simple
```python def ruta_simple(origen, destino): """Calcula ruta básica entre dos puntos"""
response = requests.get( f"{BASE_URL}/rutas", params={ "origen": f"{origen['lat']},{origen['lon']}", "destino": f"{destino['lat']},{destino['lon']}", "vehiculo": "camion" }, headers={"Authorization": f"Bearer {token}"} )
return response.json() ```
2. Optimizar Múltiples Paradas
```python def optimizar_multiples_paradas(paradas, optimizar_orden=True): """ Optimiza ruta con múltiples paradas El parámetro optimizar_orden determina si la API calcula el orden óptimo """
payload = { "paradas": [ {"lat": p["lat"], "lon": p["lon"], "tipo": p.get("tipo", "entrega")} for p in paradas ], "configuracion": { "optimizar_orden": optimizar_orden, "vehiculo": {"tipo": "camion_articulado"}, "restricciones": { "tiempo_maximo_ruta": 480, # minutos "paradas_maximas": 15 } } }
response = requests.post( f"{BASE_URL}/rutas/optimizar", json=payload, headers={"Authorization": f"Bearer {token}"} )
return response.json() ```
3. Calcular Costes
```python def calcular_coste_ruta(ruta_id, precio_gasolina=1.65, precio_diesel=1.45): """ Calcula coste estimado de una ruta existente """
payload = { "ruta_id": ruta_id, "costes": { "combustible": { "tipo": "diesel", "precio_por_litro": precio_diesel, "consumo_real": True # Considera peso y terrain }, "peajes": True, "tiempo_conductor": 15.50, # €/hora "amortizacion_km": 0.12 # €/km } }
response = requests.post( f"{BASE_URL}/rutas/{ruta_id}/costes", json=payload, headers={"Authorization": f"Bearer {token}"} )
return response.json() ```
4. Predicción de Tráfico
```python def predecir_trafico(ruta_id, fecha_hora): """ Predice condiciones de tráfico para una ruta y hora específicas Útil para planificación de tiempos de llegada """
params = { "ruta_id": ruta_id, "fecha_hora": fecha_hora.isoformat(), # datetime "incluir_alternativas": True }
response = requests.get( f"{BASE_URL}/trafico/prediccion", params=params, headers={"Authorization": f"Bearer {token}"} )
return response.json() ```
---
Ejemplo Completo: Optimizador de Rutas
```python import requests from datetime import datetime, timedelta import json
class OptimizadorRutas: """ Cliente completo para optimización de rutas de transporte """
def __init__(self, api_key, base_url="https://api.cargoffer.com/v1"): self.api_key = api_key self.base_url = base_url self.headers = { "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" }
def optimizar_entregas(self, entregas, restricciones=None): """ Optimiza ruta para múltiples entregas
Args: entregas: List[dict] con claves 'lat', 'lon', 'ventana_horaria' restricciones: dict con restricciones opcionales """
payload = { "paradas": [ { "lat": e["lat"], "lon": e["lon"], "ventana_inicio": e.get("ventana_inicio"), "ventana_fin": e.get("ventana_fin"), "duracion_minutos": e.get("duracion", 30) } for e in entregas ], "vehiculo": { "tipo": "camion", "capacidad_kg": restricciones.get("capacidad", 20000), "altura_m": restricciones.get("altura", 4.2) }, "optimizar": { "objetivo": restricciones.get("objetivo", "coste"), # tiempo | distancia | coste "evitar": restricciones.get("evitar", []) } }
response = requests.post( f"{self.base_url}/rutas/optimizar", json=payload, headers=self.headers )
if response.status_code == 200: return response.json() else: raise Exception(f"Error: {response.text}")
def obtener_ruta(self, ruta_id): """Obtiene detalles de una ruta"""
response = requests.get( f"{self.base_url}/rutas/{ruta_id}", headers=self.headers ) return response.json()
def estimar_coste(self, ruta_id, parametros_coste): """ Estima coste detallado de una ruta """
response = requests.post( f"{self.base_url}/rutas/{ruta_id}/coste", json=parametros_coste, headers=self.headers ) return response.json()
Uso ejemplo
if __name__ == "__main__":
# Inicializar cliente cliente = OptimizadorRutas(API_KEY)
# Definir entregas entregas = [ {"lat": 40.4168, "lon": -3.7038, "ventana_inicio": "09:00", "ventana_fin": "11:00", "duracion": 30}, {"lat": 41.3851, "lon": 2.1734, "ventana_inicio": "14:00", "ventana_fin": "17:00", "duracion": 45}, {"lat": 39.4699, "lon": -0.3763, "ventana_inicio": "09:00", "ventana_fin": "11:00", "duracion": 30}, ]
# Optimizar resultado = cliente.optimizar_entregas(entregas, {"objetivo": "coste"})
print(f"Ruta óptima: {resultado['ruta']['distancia_km']} km") print(f"Tiempo total: {resultado['ruta']['tiempo_minutos']} min") print(f"Coste estimado: {resultado['coste']['total']}€") ```
---
Mejores Prácticas
Manejo de Errores
```python import logging from requests.exceptions import RequestException
class RutaAPIError(Exception): pass
def safe_request(func): """Decorador para manejo de errores""" def wrapper(args, kwargs): try: return func(args, kwargs) except RequestException as e: logging.error(f"Error de conexión: {e}") raise RutaAPIError("Problema de conexión con API de rutas") except Exception as e: logging.error(f"Error inesperado: {e}") raise return wrapper ```
Retry Logic
```python from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry
session = requests.Session() retry = Retry( total=3, backoff_factor=0.5, status_forcelist=[500, 502, 503, 504] ) adapter = HTTPAdapter(max_retries=retry) session.mount('https://', adapter) ```
Rate Limiting
```python import time from collections import deque
class RateLimiter: """Limita peticiones a la API"""
def __init__(self, max_peticiones=100, ventana_segundos=60): self.max = max_peticiones self.ventana = ventana_segundos self.cola = deque()
def wait(self): ahora = time.time() # Limpiar peticiones antiguas while self.cola and ahora - self.cola[0] > self.ventana: self.cola.popleft()
# Esperar si llegamos al límite if len(self.cola) >= self.max: tiempo_espera = self.ventana - (ahora - self.cola[0]) time.sleep(tiempo_espera)
self.cola.append(ahora) ```
---
FAQ: Preguntas Técnicas
¿Qué formato de coordenadas acepta la API?
Aceptamos tanto latitud/longitud como direcciones. La API geocodifica automáticamente.
```python
Con coordenadas
{"lat": 40.4168, "lon": -3.7038}
O con dirección
{"direccion": "Calle Gran Vía 1, Madrid, España"} ```
¿Puedo usar la API offline?
No, requiere conectividad. Para modo offline, contacta soporte para opciones enterprise.
¿Cómo calculamos el consumo de combustible?
Usamos algoritmos que consideran peso del vehículo, tipo de ruta, pendiente y condiciones de tráfico reales.
---
Conclusión
La integración de APIs de rutas en Python permite optimizar operaciones logísticas significativamente. Los ejemplos mostrados cubren los casos de uso principales.
Pasos siguientes:
1. Solicitar API key de desarrollo 2. Probar endpoints en sandbox 3. Implementar en producción con rate limiting 4. Monitorizar métricas de uso
---