Inicio Rápido
Esta guía te ayudará a empezar a usar el SDK de Datadis en pocos minutos. El SDK incluye dos versiones del cliente: V1 (básico) y V2 (recomendado con manejo avanzado de errores).
Configuración inicial
Antes de comenzar, necesitas tener:
Una cuenta activa en Datadis
Tu NIF como nombre de usuario
Tu contraseña de acceso
Nota
Importante: La API de Datadis solo acepta fechas en formato mensual (YYYY/MM). No es posible especificar días específicos.
Instalación
pip install ctr-datadis
Elección de Cliente: V1 vs V2
- Cliente V1 (Básico)
Respuestas simples (listas directas)
Manejo básico de errores
Compatible con versiones anteriores
Ideal para scripts simples
- Cliente V2 (Recomendado)
Respuestas estructuradas con información de errores por distribuidor
Manejo robusto de errores
Funcionalidad exclusiva: energía reactiva
Ideal para aplicaciones de producción
Primer ejemplo - Cliente V1
Ejemplo básico con el cliente V1:
from datadis_python.client.v1.simple_client import SimpleDatadisClientV1
# Crear cliente V1
client = SimpleDatadisClientV1(
username="tu_nif",
password="tu_contraseña"
)
# Obtener puntos de suministro
supplies = client.get_supplies()
for supply in supplies:
print(f"CUPS: {supply.cups}")
print(f"Dirección: {supply.address}")
print(f"Distribuidor: {supply.distributor}")
print("---")
# Cerrar cliente
client.close()
Primer ejemplo - Cliente V2 (Recomendado)
Ejemplo con manejo mejorado de errores usando V2:
from datadis_python.client.v2.simple_client import SimpleDatadisClientV2
# Crear cliente V2
with SimpleDatadisClientV2("tu_nif", "tu_contraseña") as client:
# Obtener puntos de suministro con manejo de errores
supplies_response = client.get_supplies()
print(f"Suministros obtenidos: {len(supplies_response.supplies)}")
# Verificar errores por distribuidor
if supplies_response.distributor_error:
print("Errores encontrados:")
for error in supplies_response.distributor_error:
print(f"- {error.distributorName}: {error.errorDescription}")
# Procesar suministros válidos
for supply in supplies_response.supplies:
print(f"CUPS: {supply.cups}")
print(f"Dirección: {supply.address}")
print(f"Distribuidor: {supply.distributor}")
print("---")
Obtener datos de consumo
Cliente V1 - Obtener consumo anual
from datadis_python.client.v1.simple_client import SimpleDatadisClientV1
with SimpleDatadisClientV1("tu_nif", "tu_contraseña") as client:
# Obtener suministros
supplies = client.get_supplies()
if supplies:
supply = supplies[0] # Primer suministro
# Obtener consumo de todo 2024 (formato mensual)
consumption = client.get_consumption(
cups=supply.cups,
distributor_code=supply.distributorCode,
date_from="2024/01", # Enero 2024
date_to="2024/12" # Diciembre 2024
)
print(f"Registros de consumo: {len(consumption)}")
# Calcular consumo total
total_kwh = sum(c.consumptionKWh for c in consumption if c.consumptionKWh)
print(f"Consumo total 2024: {total_kwh:.2f} kWh")
Cliente V2 - Obtener consumo con manejo de errores
from datadis_python.client.v2.simple_client import SimpleDatadisClientV2
with SimpleDatadisClientV2("tu_nif", "tu_contraseña") as client:
# Obtener suministros
supplies_response = client.get_supplies()
if supplies_response.supplies:
supply = supplies_response.supplies[0]
# Obtener consumo con manejo robusto de errores
consumption_response = client.get_consumption(
cups=supply.cups,
distributor_code=supply.distributorCode,
date_from="2024/01",
date_to="2024/12"
)
# Verificar errores específicos
if consumption_response.distributor_error:
print("Errores al obtener consumo:")
for error in consumption_response.distributor_error:
print(f"- {error.distributorName}: {error.errorDescription}")
# Procesar datos válidos
consumption = consumption_response.time_curve
if consumption:
total_kwh = sum(c.consumptionKWh for c in consumption if c.consumptionKWh)
real_data = len([c for c in consumption if c.obtainMethod == "Real"])
print(f"Consumo total 2024: {total_kwh:.2f} kWh")
print(f"Datos reales: {real_data}/{len(consumption)} registros")
Ejemplo completo - Análisis de datos
Este ejemplo muestra cómo obtener y analizar todos los tipos de datos disponibles:
from datadis_python.client.v2.simple_client import SimpleDatadisClientV2
from datadis_python.exceptions import AuthenticationError, APIError, DatadisError
def analizar_datos_completos(username, password, year="2024"):
"""Análisis completo de datos de un año específico"""
try:
with SimpleDatadisClientV2(username, password) as client:
print(f"Analizando datos del año {year}...")
# 1. Obtener distribuidores disponibles
distributors_response = client.get_distributors()
distributor_codes = distributors_response.dist_existence_user.get("distributorCodes", [])
print(f"Distribuidores disponibles: {len(distributor_codes)}")
# 2. Obtener todos los puntos de suministro
supplies_response = client.get_supplies()
supplies = supplies_response.supplies
print(f"Puntos de suministro: {len(supplies)}")
if not supplies:
print("No se encontraron puntos de suministro")
return
# Analizar cada suministro
for i, supply in enumerate(supplies, 1):
print(f"\n--- Analizando suministro {i}/{len(supplies)} ---")
print(f"CUPS: {supply.cups}")
print(f"Dirección: {supply.address}")
print(f"Distribuidor: {supply.distributor}")
try:
# 3. Obtener detalles del contrato
contract_response = client.get_contract_detail(
cups=supply.cups,
distributor_code=supply.distributorCode
)
if contract_response.contract:
contract = contract_response.contract[0]
print(f"Potencia contratada: {contract.contractedPowerkW} kW")
print(f"Tarifa: {contract.accessFare}")
# 4. Obtener datos de consumo del año
consumption_response = client.get_consumption(
cups=supply.cups,
distributor_code=supply.distributorCode,
date_from=f"{year}/01",
date_to=f"{year}/12"
)
consumption = consumption_response.time_curve
if consumption:
total_consumo = sum(c.consumptionKWh for c in consumption if c.consumptionKWh)
total_excedentes = sum(c.surplusEnergyKWh for c in consumption if c.surplusEnergyKWh)
print(f"Consumo total {year}: {total_consumo:.2f} kWh")
print(f"Excedentes generados: {total_excedentes:.2f} kWh")
print(f"Registros: {len(consumption)}")
# Verificar si tiene autoconsumo
tiene_autoconsumo = any(c.selfConsumptionKWh for c in consumption)
if tiene_autoconsumo:
total_autoconsumo = sum(c.selfConsumptionKWh for c in consumption if c.selfConsumptionKWh)
print(f"Autoconsumo: {total_autoconsumo:.2f} kWh")
# 5. Obtener potencias máximas
max_power_response = client.get_max_power(
cups=supply.cups,
distributor_code=supply.distributorCode,
date_from=f"{year}/01",
date_to=f"{year}/12"
)
if max_power_response.max_power:
potencias = [p.maxPower for p in max_power_response.max_power]
potencia_maxima_kw = max(potencias) / 1000
print(f"Potencia máxima registrada: {potencia_maxima_kw:.2f} kW")
# 6. Intentar obtener energía reactiva (solo V2)
try:
reactive_data = client.get_reactive_data(
cups=supply.cups,
distributor_code=supply.distributorCode,
date_from=f"{year}/01",
date_to=f"{year}/12"
)
if reactive_data:
print(f"Datos de energía reactiva: {len(reactive_data)} registros")
else:
print("Sin datos de energía reactiva")
except Exception as e:
print(f"Energía reactiva no disponible: {e}")
except Exception as e:
print(f"Error procesando {supply.cups}: {e}")
print(f"\nAnálisis completado para {len(supplies)} suministros")
except AuthenticationError as e:
print(f"Error de autenticación: {e}")
print("Verifica tu NIF y contraseña")
except APIError as e:
print(f"Error de API: {e}")
except DatadisError as e:
print(f"Error de conexión: {e}")
except Exception as e:
print(f"Error inesperado: {e}")
# Ejecutar análisis
if __name__ == "__main__":
analizar_datos_completos(
username="tu_nif",
password="tu_contraseña",
year="2024"
)
Manejo de errores específicos
El cliente V2 proporciona información detallada sobre errores por distribuidor:
from datadis_python.client.v2.simple_client import SimpleDatadisClientV2
from datadis_python.exceptions import AuthenticationError, APIError, DatadisError
def manejar_errores_avanzado():
try:
with SimpleDatadisClientV2("tu_nif", "tu_contraseña") as client:
# Intentar obtener suministros
supplies_response = client.get_supplies()
# Analizar errores específicos por distribuidor
if supplies_response.distributor_error:
print("Errores por distribuidor:")
for error in supplies_response.distributor_error:
print(f"Distribuidor: {error.distributorName}")
print(f"Código de error: {error.errorCode}")
print(f"Descripción: {error.errorDescription}")
print("---")
# Procesar solo los suministros que se obtuvieron correctamente
if supplies_response.supplies:
print(f"Suministros válidos: {len(supplies_response.supplies)}")
for supply in supplies_response.supplies:
print(f"- {supply.cups} ({supply.distributor})")
else:
print("No se pudieron obtener suministros de ningún distribuidor")
except AuthenticationError:
print("Credenciales inválidas. Verifica tu NIF y contraseña.")
except APIError as e:
print(f"Error de la API de Datadis: {e}")
except DatadisError as e:
print(f"Error de conexión o timeout: {e}")
Configuración avanzada
Puedes personalizar el comportamiento del cliente:
from datadis_python.client.v2.simple_client import SimpleDatadisClientV2
# Configuración para conexiones lentas o inestables
client = SimpleDatadisClientV2(
username="tu_nif",
password="tu_contraseña",
timeout=240, # Timeout extendido (default: 120 segundos)
retries=5 # Más reintentos (default: 3)
)
# También funciona con context manager
with SimpleDatadisClientV2("tu_nif", "tu_contraseña", timeout=180, retries=4) as client:
supplies_response = client.get_supplies()
Comparación V1 vs V2
Ejemplo que muestra las diferencias principales:
from datadis_python.client.v1.simple_client import SimpleDatadisClientV1
from datadis_python.client.v2.simple_client import SimpleDatadisClientV2
def comparar_versiones(username, password):
print("=== Cliente V1 ===")
try:
with SimpleDatadisClientV1(username, password) as client_v1:
# V1 devuelve una lista directa
supplies_v1 = client_v1.get_supplies()
print(f"Suministros V1: {len(supplies_v1)} (lista simple)")
if supplies_v1:
consumption_v1 = client_v1.get_consumption(
cups=supplies_v1[0].cups,
distributor_code=supplies_v1[0].distributorCode,
date_from="2024/01",
date_to="2024/03"
)
print(f"Consumo V1: {len(consumption_v1)} registros (lista simple)")
except Exception as e:
print(f"Error en V1: {e}")
print("\n=== Cliente V2 ===")
try:
with SimpleDatadisClientV2(username, password) as client_v2:
# V2 devuelve objetos de respuesta estructurados
supplies_response_v2 = client_v2.get_supplies()
print(f"Suministros V2: {len(supplies_response_v2.supplies)} (respuesta estructurada)")
if supplies_response_v2.distributor_error:
print(f"Errores detectados: {len(supplies_response_v2.distributor_error)}")
if supplies_response_v2.supplies:
consumption_response_v2 = client_v2.get_consumption(
cups=supplies_response_v2.supplies[0].cups,
distributor_code=supplies_response_v2.supplies[0].distributorCode,
date_from="2024/01",
date_to="2024/03"
)
print(f"Consumo V2: {len(consumption_response_v2.time_curve)} registros (respuesta estructurada)")
# Funcionalidad exclusiva de V2
try:
reactive_data = client_v2.get_reactive_data(
cups=supplies_response_v2.supplies[0].cups,
distributor_code=supplies_response_v2.supplies[0].distributorCode,
date_from="2024/01",
date_to="2024/03"
)
print(f"Energía reactiva V2: {len(reactive_data)} registros (solo en V2)")
except Exception as e:
print(f"Energía reactiva no disponible: {e}")
except Exception as e:
print(f"Error en V2: {e}")
Casos de uso recomendados
Usa Cliente V1 cuando: - Necesites compatibilidad con código existente - Implementes scripts simples o prototipos rápidos - No requieras manejo avanzado de errores - Trabajes con un solo distribuidor conocido
Usa Cliente V2 cuando: - Desarrolles aplicaciones de producción - Necesites manejo robusto de errores por distribuidor - Quieras acceso a energía reactiva - Trabajes con múltiples distribuidores - Requieras información detallada de fallos
Próximos pasos
Consulta los Ejemplos de Uso para casos de uso específicos y scripts completos
Revisa la Referencia de la API para ver todas las funciones disponibles
Lee sobre Modelos de Datos para entender los modelos de datos
Consulta Solución de Problemas si encuentras problemas