Referencia de la API

Esta sección documenta todas las clases y métodos disponibles en el SDK de Datadis.

Cliente Principal

Cliente V1 (Recomendado)

class datadis_python.client.v1.simple_client.SimpleDatadisClientV1(username, password, timeout=120, retries=3)[fuente]

Bases: object

Cliente simplificado para la API V1 de Datadis.

Este cliente proporciona una interfaz fácil de usar para acceder a los datos de consumo eléctrico almacenados en las bases de datos de las distribuidoras eléctricas españolas a través de la plataforma Datadis.

Características principales: - Autenticación automática y renovación de tokens - Manejo robusto de timeouts y reintentos - Validación de datos con Pydantic para mayor seguridad - Soporte para tipos flexibles en parámetros de entrada - Context manager para gestión automática de recursos

Ejemplo

Uso básico del cliente:

from datadis_python.client.v1 import SimpleDatadisClientV1

# Inicializar el cliente
client = SimpleDatadisClientV1(
    username="12345678A",
    password="mi_password",
    timeout=120,
    retries=3
)

# Usar como context manager (recomendado)
with SimpleDatadisClientV1("12345678A", "mi_password") as client:
    # Obtener suministros
    supplies = client.get_supplies()

    # Obtener consumo para un suministro específico
    if supplies:
        consumption = client.get_consumption(
            cups=supplies[0].cups,
            distributor_code=supplies[0].distributorCode,
            date_from="2024/01",
            date_to="2024/12"
        )
Parámetros:
  • username (str) – NIF del usuario registrado en Datadis (ej: «12345678A»)

  • password (str) – Contraseña de acceso a la plataforma Datadis

  • timeout (int) – Timeout para requests HTTP en segundos. 120s por defecto debido a la lentitud característica de la API de Datadis

  • retries (int) – Número de reintentos automáticos en caso de fallos de red o timeouts. 3 intentos por defecto

Muestra:
__init__(username, password, timeout=120, retries=3)[fuente]

Inicializa el cliente simplificado.

Parámetros:
  • username (str) – NIF del usuario

  • password (str) – Contraseña

  • timeout (int) – Timeout en segundos (120s por defecto para Datadis)

  • retries (int) – Número de reintentos

authenticate()[fuente]

Autentica con la API de Datadis y obtiene el token de acceso.

Realiza una petición POST al endpoint /nikola-auth/tokens/login de la API de Datadis para obtener un token Bearer que será utilizado en todas las peticiones subsecuentes. El token se almacena automáticamente y se añade a los headers de la sesión HTTP.

Nota

Este método normalmente NO necesita ser llamado manualmente, ya que la autenticación se realiza automáticamente cuando se ejecuta cualquier método que requiera acceso a la API (como get_supplies(), get_consumption(), etc.).

Advertencia

Los tokens de Datadis tienen expiración, pero la renovación se maneja automáticamente cuando se detecta un error 401 (Unauthorized).

Ejemplo

Autenticación manual (opcional):

client = SimpleDatadisClientV1("12345678A", "mi_password")

# Verificar credenciales antes de hacer operaciones
if client.authenticate():
    print("Credenciales válidas")
    supplies = client.get_supplies()
else:
    print("Error en las credenciales")
Devuelve:

True si la autenticación fue exitosa, False en caso contrario

Tipo del valor devuelto:

bool

Muestra:
  • AuthenticationError – Si las credenciales (NIF/contraseña) son inválidas o el servidor devuelve un error de autenticación

  • DatadisError – Si ocurre un timeout o error de conexión con el servidor

Ver también

  • Documentación oficial: POST /nikola-auth/tokens/login

  • Los tokens son válidos por tiempo limitado y se renuevan automáticamente

get_supplies(authorized_nif=None, distributor_code=None)[fuente]

Obtiene la lista de puntos de suministro (CUPS) asociados al usuario.

Consulta el endpoint GET /api-private/api/get-supplies para obtener todos los puntos de suministro eléctrico que el usuario tiene registrados en Datadis. Los datos se validan automáticamente usando Pydantic para garantizar la integridad y consistencia de la información.

Los puntos de suministro incluyen información detallada como: - Código CUPS (identificador único del punto de suministro) - Dirección física del suministro - Código postal, provincia y municipio - Distribuidor eléctrico y su código - Fechas de validez del contrato - Tipo de punto de medida (1-5)

Códigos de distribuidor más comunes:
  • 1: Viesgo

  • 2: E-distribución (Endesa)

  • 3: E-redes

  • 4: ASEME

  • 5: UFD (Naturgy)

  • 6: EOSA

  • 7: CIDE

  • 8: IDE

Ejemplo

Obtener todos los suministros del usuario:

with SimpleDatadisClientV1("12345678A", "password") as client:
    supplies = client.get_supplies()

    for supply in supplies:
        print(f"CUPS: {supply.cups}")
        print(f"Dirección: {supply.address}")
        print(f"Distribuidor: {supply.distributor} (código: {supply.distributorCode})")
        print(f"Tipo: {supply.pointType}")
        print("---")

Filtrar por distribuidor específico:

# Solo suministros de Endesa (E-distribución)
supplies_endesa = client.get_supplies(distributor_code=2)

# También funciona con string
supplies_endesa = client.get_supplies(distributor_code="2")
Parámetros:
  • authorized_nif (Optional[str]) – NIF de una persona autorizada para consultar sus suministros. Si se especifica, se obtendrán los suministros de esa persona en lugar de los del usuario autenticado

  • distributor_code (Optional[Union[str, int]]) – Código del distribuidor para filtrar suministros. Acepta tanto enteros como strings (ej: 2 o «2»)

Devuelve:

Lista de objetos SupplyData validados con Pydantic, cada uno representando un punto de suministro con toda su información asociada

Tipo del valor devuelto:

List[SupplyData]

Muestra:
  • AuthenticationError – Si las credenciales son inválidas o el token expira

  • APIError – Si la API devuelve un error HTTP (400, 403, 404, 500, etc.)

  • DatadisError – Si ocurren errores de conexión o timeouts repetidos

  • ValidationError – Si los datos devueltos no pasan la validación Pydantic

Ver también

  • Documentación oficial: GET /api-private/api/get-supplies

  • Para obtener detalles del contrato: get_contract_detail()

  • Lista completa de códigos de distribuidor en la documentación de la API

get_distributors()[fuente]

Obtiene la lista de distribuidores eléctricos donde el usuario tiene suministros.

Consulta el endpoint GET /api-private/api/get-distributors-with-supplies para obtener información sobre las distribuidoras eléctricas donde el usuario autenticado tiene puntos de suministro activos. Esto es útil para conocer qué distribuidores están disponibles antes de realizar consultas específicas.

La respuesta incluye los códigos únicos de cada distribuidor, que son necesarios para realizar consultas posteriores como obtener consumos, contratos o potencias máximas de suministros específicos.

Distribuidores eléctricos en España:
  • Código 1: Viesgo (Cantabria, Asturias)

  • Código 2: E-distribución/Endesa (Nacional)

  • Código 3: E-redes (Galicia)

  • Código 4: ASEME (Melilla)

  • Código 5: UFD/Naturgy (Nacional)

  • Código 6: EOSA (Aragón)

  • Código 7: CIDE (Ceuta)

  • Código 8: IDE (Baleares)

Ejemplo

Listar distribuidores del usuario:

with SimpleDatadisClientV1("12345678A", "password") as client:
    distributors = client.get_distributors()

    print("Distribuidores con suministros:")
    for dist in distributors:
        print(f"- {dist.distributorName} (Código: {dist.distributorCode})")

    # Usar el primer distribuidor para consultas posteriores
    if distributors:
        first_dist_code = distributors[0].distributorCode
        supplies = client.get_supplies(distributor_code=first_dist_code)
Devuelve:

Lista de objetos DistributorData validados con Pydantic. Cada objeto contiene el código y nombre del distribuidor donde el usuario tiene suministros activos

Tipo del valor devuelto:

List[DistributorData]

Muestra:
  • AuthenticationError – Si las credenciales son inválidas o el token expira

  • APIError – Si la API devuelve un error HTTP (400, 403, 404, 500, etc.)

  • DatadisError – Si ocurren errores de conexión o timeouts repetidos

  • ValidationError – Si los datos devueltos no pasan la validación Pydantic

Ver también

Nota

Solo se devuelven distribuidores donde el usuario tiene suministros activos. Si no hay suministros registrados, la lista estará vacía.

get_contract_detail(cups, distributor_code)[fuente]

Obtiene los detalles del contrato eléctrico para un punto de suministro específico.

Consulta el endpoint GET /api-private/api/get-contract-detail para obtener información detallada del contrato asociado a un CUPS específico. Los datos incluyen información técnica, comercial y administrativa del suministro eléctrico.

Información del contrato incluida:
  • Datos básicos: CUPS, distribuidor, comercializadora

  • Características técnicas: Tensión, potencia contratada, tipo de punto

  • Datos tarifarios: Tarifa de acceso, discriminación horaria, código de tarifa

  • Ubicación: Provincia, municipio, código postal

  • Fechas: Inicio y fin de contrato, fechas de cambios

  • Autoconsumo: Tipo y características (si aplica)

  • Control de potencia: ICP o Maxímetro

  • CAU: Código de Autoconsumo Único (si es aplicable)

Types de punto de medida:
  • Tipo 1: > 450 kW (alta tensión)

  • Tipo 2: 50-450 kW (media tensión)

  • Tipo 3: 15-50 kW (baja tensión)

  • Tipo 4: < 15 kW con discriminación horaria

  • Tipo 5: < 15 kW sin discriminación horaria

Ejemplo

Obtener detalles de contrato:

with SimpleDatadisClientV1("12345678A", "password") as client:
    # Primero obtener suministros
    supplies = client.get_supplies()

    if supplies:
        supply = supplies[0]

        # Obtener detalles del contrato
        contracts = client.get_contract_detail(
            cups=supply.cups,
            distributor_code=supply.distributorCode
        )

        for contract in contracts:
            print(f"CUPS: {contract.cups}")
            print(f"Distribuidor: {contract.distributor}")
            print(f"Potencia contratada: {contract.contractedPowerkW} kW")
            print(f"Tarifa: {contract.accessFare}")
            print(f"Tipo de punto: {contract.pointType}")
            if contract.marketer:
                print(f"Comercializadora: {contract.marketer}")

Usando tipos flexibles de parámetros:

# Ambos formatos son válidos
contracts1 = client.get_contract_detail("ES001234567890123456AB", 2)
contracts2 = client.get_contract_detail("ES001234567890123456AB", "2")
Parámetros:
  • cups (str) – Código CUPS del punto de suministro (22 caracteres alfanuméricos que identifican únicamente el punto de suministro eléctrico)

  • distributor_code (Union[str, int]) – Código numérico del distribuidor eléctrico. Acepta tanto enteros como strings para mayor flexibilidad

Devuelve:

Lista de objetos ContractData validados con Pydantic. Normalmente contiene un solo contrato, pero pueden ser varios si ha habido cambios históricos en el suministro

Tipo del valor devuelto:

List[ContractData]

Muestra:
  • AuthenticationError – Si las credenciales son inválidas o el token expira

  • APIError – Si la API devuelve un error HTTP (400, 403, 404, 500, etc.)

  • DatadisError – Si ocurren errores de conexión o timeouts repetidos

  • ValidationError – Si los datos devueltos no pasan la validación Pydantic

  • ValueError – Si el CUPS no tiene el formato correcto (22 caracteres)

Ver también

  • Documentación oficial: GET /api-private/api/get-contract-detail

  • Para obtener la lista de CUPS: get_supplies()

  • Para datos de consumo del contrato: get_consumption()

Nota

El CUPS debe ser exactamente de 22 caracteres alfanuméricos. Si el formato es incorrecto, la API devolverá un error.

get_consumption(cups, distributor_code, date_from, date_to, measurement_type=0, point_type=None)[fuente]

Obtiene los datos de consumo eléctrico para un punto de suministro específico.

Consulta el endpoint GET /api-private/api/get-consumption-data para obtener la curva de carga (datos de consumo) de un CUPS en un período determinado. Los datos incluyen consumo, excedentes, generación y autoconsumo cuando aplique.

IMPORTANTE - Limitación de fechas:

La API de Datadis SOLO acepta fechas en formato mensual (YYYY/MM). NO se permiten fechas con días específicos. El SDK convierte automáticamente fechas datetime/date al formato requerido.

IMPORTANTE - Disponibilidad de datos cuarto-horarios:

Los datos cada 15 minutos (measurement_type=1) solo están disponibles para: - Tipos de punto 1 y 2 (alta y media tensión) - Tipo de punto 3 en E-distribución únicamente - Para el resto de casos, solo están disponibles datos horarios (measurement_type=0)

Tipos de medición:
  • 0: Datos horarios (disponible para todos los tipos de punto)

  • 1: Datos cuarto-horarios/15 min (limitado según tipo de punto)

Tipos de punto de medida:
  • 1: > 450 kW - Datos horarios y cuarto-horarios

  • 2: 50-450 kW - Datos horarios y cuarto-horarios

  • 3: 15-50 kW - Cuarto-horarios solo en E-distribución

  • 4: < 15 kW con DH - Solo datos horarios

  • 5: < 15 kW sin DH - Solo datos horarios

Datos incluidos en la respuesta:
  • Consumo: Energía consumida de la red (kWh)

  • Excedentes: Energía vertida a la red (kWh)

  • Generación: Energía generada por autoconsumo (kWh)

  • Autoconsumo: Energía autoconsumida directamente (kWh)

  • Método de obtención: Real (medido) o Estimada (calculada)

Ejemplo

Obtener consumo horario para todo un año:

with SimpleDatadisClientV1("12345678A", "password") as client:
    supplies = client.get_supplies()

    if supplies:
        supply = supplies[0]

        # Consumo horario del año 2024
        consumption = client.get_consumption(
            cups=supply.cups,
            distributor_code=supply.distributorCode,
            date_from="2024/01",  # Enero 2024
            date_to="2024/12",    # Diciembre 2024
            measurement_type=0    # Datos horarios
        )

        # Analizar los datos
        total_kwh = sum(c.consumptionKWh for c in consumption if c.consumptionKWh)
        print(f"Consumo total 2024: {total_kwh:.2f} kWh")

        # Filtrar datos reales vs estimados
        real_data = [c for c in consumption if c.obtainMethod == "Real"]
        print(f"Datos reales: {len(real_data)}/{len(consumption)}")

Obtener datos cuarto-horarios (solo para tipos 1, 2, y 3 en E-distribución):

# Solo si el tipo de punto lo permite
consumption_15min = client.get_consumption(
    cups="ES001234567890123456AB",
    distributor_code=2,  # E-distribución
    date_from="2024/06",
    date_to="2024/06",
    measurement_type=1,  # Cuarto-horarios
    point_type=3         # Tipo de punto
)

Usando diferentes tipos de fecha:

from datetime import date, datetime

# Con strings (recomendado)
consumption1 = client.get_consumption(cups, dist_code, "2024/01", "2024/03")

# Con objetos datetime (se convertirán automáticamente)
start_date = datetime(2024, 1, 1)
end_date = datetime(2024, 3, 31)
consumption2 = client.get_consumption(cups, dist_code, start_date, end_date)
Parámetros:
  • cups (str) – Código CUPS del punto de suministro (22 caracteres alfanuméricos)

  • distributor_code (Union[str, int]) – Código del distribuidor eléctrico (acepta int o str)

  • date_from (Union[str, datetime, date]) – Fecha de inicio en formato YYYY/MM. También acepta objetos datetime/date que se convertirán automáticamente

  • date_to (Union[str, datetime, date]) – Fecha de fin en formato YYYY/MM. También acepta objetos datetime/date que se convertirán automáticamente

  • measurement_type (Union[int, float, str]) – Tipo de medición - 0: horarios (defecto), 1: cuarto-horarios. Acepta int, float o str

  • point_type (Optional[Union[int, float, str]]) – Tipo de punto de medida (1-5). Requerido para datos cuarto-horarios. Acepta int, float o str

Devuelve:

Lista de objetos ConsumptionData validados con Pydantic. Cada objeto representa una lectura de consumo con timestamp

Tipo del valor devuelto:

List[ConsumptionData]

Muestra:
  • AuthenticationError – Si las credenciales son inválidas o el token expira

  • APIError – Si la API devuelve un error HTTP (400, 403, 404, 500, etc.)

  • DatadisError – Si ocurren errores de conexión o timeouts repetidos

  • ValidationError – Si las fechas no están en formato mensual válido o los datos no pasan la validación Pydantic

  • ValueError – Si se solicitan datos cuarto-horarios para un tipo de punto no compatible

Ver también

  • Documentación oficial: GET /api-private/api/get-consumption-data

  • Para obtener CUPS: get_supplies()

  • Para datos de potencia máxima: get_max_power()

Advertencia

Los datos cuarto-horarios no están disponibles para todos los tipos de punto. Verifique la compatibilidad antes de solicitar measurement_type=1.

get_max_power(cups, distributor_code, date_from, date_to)[fuente]

Obtiene los datos de potencia máxima demandada para un punto de suministro.

Consulta el endpoint GET /api-private/api/get-max-power para obtener las potencias máximas registradas en cada período tarifario durante el rango de fechas especificado. Esta información es crucial para optimizar la potencia contratada y evitar penalizaciones por excesos.

IMPORTANTE - Limitación de fechas:

Al igual que los datos de consumo, la API SOLO acepta fechas en formato mensual (YYYY/MM). El SDK convierte automáticamente fechas datetime/date al primer día del mes correspondiente.

Períodos tarifarios incluidos:
  • VALLE: Período de menor coste energético (madrugada)

  • LLANO: Período de coste intermedio (mañana/tarde)

  • PUNTA: Período de mayor coste energético (mediodía/noche)

  • P1, P2, P3, P4, P5, P6: Períodos específicos según tarifa

La potencia se mide en Vatios (W) y representa la demanda máxima registrada en cada período durante el mes consultado. Esta información es especialmente útil para:

  • Optimizar la potencia contratada

  • Identificar picos de consumo

  • Evaluar la eficiencia energética

  • Planificar instalaciones de autoconsumo

Ejemplo

Obtener potencias máximas del último año:

with SimpleDatadisClientV1("12345678A", "password") as client:
    supplies = client.get_supplies()

    if supplies:
        supply = supplies[0]

        # Potencias máximas de 2024
        max_powers = client.get_max_power(
            cups=supply.cups,
            distributor_code=supply.distributorCode,
            date_from="2024/01",
            date_to="2024/12"
        )

        # Analizar potencias por período
        periods = {}
        for power in max_powers:
            period = power.period
            if period not in periods:
                periods[period] = []
            periods[period].append(power.maxPower)

        # Mostrar potencia máxima por período
        for period, powers in periods.items():
            max_power_w = max(powers)
            max_power_kw = max_power_w / 1000
            print(f"Período {period}: {max_power_kw:.2f} kW")

Identificar el mes con mayor demanda:

# Agrupar por mes
monthly_max = {}
for power in max_powers:
    month = power.date[:7]  # YYYY/MM
    if month not in monthly_max:
        monthly_max[month] = 0
    monthly_max[month] = max(monthly_max[month], power.maxPower)

# Encontrar el mes de mayor demanda
peak_month = max(monthly_max, key=monthly_max.get)
peak_power_kw = monthly_max[peak_month] / 1000
print(f"Mayor demanda: {peak_power_kw:.2f} kW en {peak_month}")
Parámetros:
  • cups (str) – Código CUPS del punto de suministro (22 caracteres alfanuméricos)

  • distributor_code (Union[str, int]) – Código del distribuidor eléctrico (acepta int o str)

  • date_from (Union[str, datetime, date]) – Fecha de inicio en formato YYYY/MM. También acepta objetos datetime/date que se convertirán automáticamente

  • date_to (Union[str, datetime, date]) – Fecha de fin en formato YYYY/MM. También acepta objetos datetime/date que se convertirán automáticamente

Devuelve:

Lista de objetos MaxPowerData validados con Pydantic. Cada objeto representa la potencia máxima registrada en un período específico con fecha, hora y período tarifario

Tipo del valor devuelto:

List[MaxPowerData]

Muestra:
  • AuthenticationError – Si las credenciales son inválidas o el token expira

  • APIError – Si la API devuelve un error HTTP (400, 403, 404, 500, etc.)

  • DatadisError – Si ocurren errores de conexión o timeouts repetidos

  • ValidationError – Si las fechas no están en formato mensual válido o los datos no pasan la validación Pydantic

  • ValueError – Si el CUPS no tiene el formato correcto

Ver también

Nota

Las potencias se devuelven en Vatios (W). Para obtener kilovatios (kW) divida el valor entre 1000.

close()[fuente]

Cierra la sesión HTTP y libera recursos del cliente.

Este método limpia los recursos utilizados por el cliente: - Cierra la sesión HTTP de requests - Elimina el token de autenticación almacenado - Libera las conexiones de red activas

Es una buena práctica llamar a este método cuando termine de usar el cliente, aunque se recomienda usar el cliente como context manager con with para gestión automática de recursos.

Ejemplo

Uso manual (no recomendado):

client = SimpleDatadisClientV1("12345678A", "password")
try:
    supplies = client.get_supplies()
    # ... más operaciones
finally:
    client.close()  # Limpiar recursos

Uso recomendado con context manager:

with SimpleDatadisClientV1("12345678A", "password") as client:
    supplies = client.get_supplies()
    # ... más operaciones
# close() se llama automáticamente

Nota

Si usa el cliente como context manager (con with), este método se llama automáticamente al salir del bloque.

__enter__()[fuente]

Entrada del context manager para gestión automática de recursos.

Este método se llama automáticamente cuando se usa el cliente con la declaración with. Permite usar el patrón context manager para garantizar la limpieza automática de recursos.

Ejemplo

Uso como context manager (recomendado):

with SimpleDatadisClientV1("12345678A", "password") as client:
    # El método __enter__ se llama aquí automáticamente
    supplies = client.get_supplies()
    consumption = client.get_consumption(...)
    # ... más operaciones
# El método __exit__ se llama automáticamente al salir
Devuelve:

La propia instancia del cliente para usar en el bloque with

Tipo del valor devuelto:

SimpleDatadisClientV1

Ver también

__exit__() - Método de salida del context manager close() - Limpieza manual de recursos

__exit__(exc_type, exc_val, exc_tb)[fuente]

Salida del context manager con limpieza automática de recursos.

Este método se llama automáticamente al salir del bloque with, garantizando que los recursos se liberen correctamente incluso si ocurre una excepción durante la ejecución.

La limpieza incluye: - Cierre de la sesión HTTP - Eliminación del token de autenticación - Liberación de conexiones de red

Ejemplo

El context manager maneja automáticamente las excepciones:

try:
    with SimpleDatadisClientV1("12345678A", "password") as client:
        supplies = client.get_supplies()
        # Si ocurre una excepción aquí...
        raise Exception("Algo salió mal")
except Exception as e:
    # ... los recursos se limpian automáticamente
    print(f"Error: {e}")
# El cliente ya está cerrado y los recursos liberados
Parámetros:
  • exc_type (Optional[type]) – Tipo de excepción que causó la salida (None si no hay excepción)

  • exc_val (Optional[BaseException]) – Instancia de la excepción (None si no hay excepción)

  • exc_tb (Optional[TracebackType]) – Traceback de la excepción (None si no hay excepción)

Devuelve:

None (no suprime excepciones)

Tipo del valor devuelto:

None

Ver también

__enter__() - Método de entrada del context manager close() - Método de limpieza llamado internamente

Nota

Este método no suprime excepciones - si ocurre un error en el bloque with, la excepción se propagará normalmente después de la limpieza.

Cliente V2 (Experimental)

class datadis_python.client.v2.simple_client.SimpleDatadisClientV2(username, password, timeout=120, retries=3)[fuente]

Bases: object

Cliente simplificado para la API V2 de Datadis con manejo mejorado de errores.

Este cliente implementa la versión 2 de la API de Datadis, que incluye mejoras significativas sobre la V1, especialmente en el manejo de errores por distribuidor y estructuras de respuesta más robustas. La V2 es la versión recomendada para nuevas implementaciones.

Principales diferencias con V1:
  • Manejo de errores por distribuidor: Respuestas incluyen distributorError

  • Estructuras de respuesta mejoradas: Objetos tipados (SuppliesResponse, etc.)

  • Nueva funcionalidad: Datos de energía reactiva (get_reactive_data())

  • Validación mejorada: Validaciones específicas para types y rangos

  • Compatibilidad: Mantiene la misma interfaz simple que V1

Características principales:
  • Autenticación automática y renovación de tokens

  • Manejo robusto de timeouts y reintentos con backoff exponencial

  • Validación de datos con Pydantic para máxima seguridad

  • Soporte para tipos flexibles en parámetros de entrada

  • Context manager para gestión automática de recursos

  • Manejo de errores por distribuidor (exclusivo de V2)

  • Respuestas estructuradas con información de errores detallada

Ventajas de la API V2:
  • Robustez: Mejor manejo de fallos de distribuidores específicos

  • Información detallada: Códigos y descripciones de errores por distribuidor

  • Funcionalidad extendida: Acceso a datos de energía reactiva

  • Compatibilidad futura: Preparada para nuevas funcionalidades

Nota

La API V2 acepta las mismas limitaciones que V1: solo fechas en formato mensual (YYYY/MM) y disponibilidad limitada de datos cuarto-horarios.

Ejemplo

Uso básico con manejo de errores V2:

from datadis_python.client.v2 import SimpleDatadisClientV2

with SimpleDatadisClientV2("12345678A", "mi_password") as client:
    # Obtener suministros con información de errores
    supplies_response = client.get_supplies()

    print(f"Suministros obtenidos: {len(supplies_response.supplies)}")

    # Verificar errores por distribuidor
    if supplies_response.distributor_error:
        for error in supplies_response.distributor_error:
            print(f"Error en {error.distributorName}: {error.errorDescription}")

    # Trabajar con los suministros válidos
    for supply in supplies_response.supplies:
        print(f"CUPS: {supply.cups} - Distribuidor: {supply.distributor}")

Comparación con V1:

# V1 - Lista simple
supplies_v1 = client_v1.get_supplies()  # List[SupplyData]

# V2 - Respuesta estructurada con manejo de errores
supplies_v2 = client_v2.get_supplies()  # SuppliesResponse
actual_supplies = supplies_v2.supplies  # List[SupplyData]
errors = supplies_v2.distributor_error   # List[DistributorError]

Funcionalidad exclusiva de V2 - Energía reactiva:

reactive_data = client.get_reactive_data(
    cups="ES001234567890123456AB",
    distributor_code="2",
    date_from="2024/01",
    date_to="2024/12"
)
Parámetros:
  • username (str) – NIF del usuario registrado en Datadis (ej: «12345678A»)

  • password (str) – Contraseña de acceso a la plataforma Datadis

  • timeout (int) – Timeout para requests HTTP en segundos. 120s por defecto debido a la lentitud característica de la API de Datadis

  • retries (int) – Número de reintentos automáticos en caso de fallos de red o timeouts. 3 intentos por defecto

Muestra:

Added in version 2.0: Soporte para estructuras de respuesta mejoradas y manejo de errores por distribuidor

Ver también

  • SimpleDatadisClientV1 - Versión anterior con respuestas simples

  • Para migración de V1 a V2: Las interfaces son compatibles, solo cambian los tipos de retorno

__init__(username, password, timeout=120, retries=3)[fuente]

Inicializa el cliente simplificado V2.

Parámetros:
  • username (str) – NIF del usuario

  • password (str) – Contraseña

  • timeout (int) – Timeout en segundos (120s por defecto para Datadis)

  • retries (int) – Número de reintentos

authenticate()[fuente]

Autentica con la API de Datadis y obtiene el token de acceso para V2.

Realiza una petición POST al endpoint /nikola-auth/tokens/login para obtener un token Bearer válido para la API V2. El proceso de autenticación es idéntico entre V1 y V2, pero el token obtenido es compatible con ambas versiones de endpoints.

Nota

Este método normalmente NO necesita ser llamado manualmente. La autenticación se realiza automáticamente en la primera petición que requiera acceso a la API. La V2 utiliza el mismo sistema de autenticación que V1.

Advertencia

Los tokens tienen expiración limitada, pero la renovación automática está implementada para todos los endpoints V2 cuando se detecta un error 401.

Ejemplo

Verificación manual de credenciales (opcional):

client = SimpleDatadisClientV2("12345678A", "mi_password")

try:
    if client.authenticate():
        print("✓ Credenciales válidas para API V2")

        # Ahora se pueden hacer peticiones autenticadas
        supplies_response = client.get_supplies()
        print(f"Suministros encontrados: {len(supplies_response.supplies)}")
    else:
        print("✗ Error en autenticación")

except AuthenticationError as e:
    print(f"Error de credenciales: {e}")
except DatadisError as e:
    print(f"Error de conexión: {e}")
Devuelve:

True si la autenticación fue exitosa, False en caso contrario

Tipo del valor devuelto:

bool

Muestra:
  • AuthenticationError – Si las credenciales (NIF/contraseña) son inválidas, el servidor devuelve un error de autenticación, o la respuesta del servidor está vacía

  • DatadisError – Si ocurre un timeout durante la autenticación o error de conexión

Ver también

  • Documentación oficial: POST /nikola-auth/tokens/login

  • Los tokens son válidos para ambas versiones V1 y V2 de la API

  • Renovación automática implementada en _make_authenticated_request()

Nota

El token obtenido se almacena automáticamente en self.token y se añade a los headers de la sesión HTTP como Authorization: Bearer <token>.

get_supplies(authorized_nif=None, distributor_code=None)[fuente]

Obtiene la lista de puntos de suministro con manejo mejorado de errores (V2).

Consulta el endpoint GET /api-private/api/get-supplies-v2 para obtener todos los puntos de suministro eléctrico con manejo mejorado de errores por distribuidor. A diferencia de V1, la V2 devuelve una respuesta estructurada que incluye tanto los suministros válidos como información detallada de errores por cada distribuidor.

Ventajas de V2 sobre V1:
  • Manejo de errores por distribuidor: Información detallada de fallos específicos

  • Respuesta estructurada: SuppliesResponse con supplies y distributor_error

  • Mayor robustez: Operación exitosa aunque algunos distribuidores fallen

  • Información diagnóstica: Códigos y descripciones de errores específicos

La respuesta incluye:
  • supplies: Lista de puntos de suministro válidos (idénticos a V1)

  • distributor_error: Lista de errores específicos por distribuidor
    • distributorCode: Código del distribuidor con problemas

    • distributorName: Nombre del distribuidor

    • errorCode: Código específico del error

    • errorDescription: Descripción detallada del problema

Ejemplo

Uso básico con manejo de errores V2:

with SimpleDatadisClientV2("12345678A", "password") as client:
    response = client.get_supplies()

    print(f"✓ Suministros obtenidos: {len(response.supplies)}")

    # Mostrar información de suministros
    for supply in response.supplies:
        print(f"CUPS: {supply.cups}")
        print(f"Distribuidor: {supply.distributor} (código: {supply.distributorCode})")
        print(f"Dirección: {supply.address}")
        print("---")

    # Verificar y manejar errores por distribuidor
    if response.distributor_error:
        print(f"⚠️  Errores encontrados en {len(response.distributor_error)} distribuidores:")
        for error in response.distributor_error:
            print(f"- {error.distributorName} ({error.distributorCode}): {error.errorDescription}")
    else:
        print("✓ Todos los distribuidores respondieron correctamente")

Comparación V1 vs V2:

# V1 - Lista simple, fallo total si hay errores
supplies_v1 = client_v1.get_supplies()  # List[SupplyData] or Exception

# V2 - Respuesta robusta con información de errores
response_v2 = client_v2.get_supplies()   # SuppliesResponse
supplies_v2 = response_v2.supplies       # List[SupplyData]
errors_v2 = response_v2.distributor_error # List[DistributorError]

Filtrar por distribuidor específico:

# Solo suministros de E-distribución
response = client.get_supplies(distributor_code="2")

if response.supplies:
    print("Suministros de E-distribución encontrados")
elif response.distributor_error:
    for error in response.distributor_error:
        if error.distributorCode == "2":
            print(f"Error en E-distribución: {error.errorDescription}")
Parámetros:
  • authorized_nif (Optional[str]) – NIF de una persona autorizada para consultar sus suministros. Si se especifica, se obtendrán los suministros de esa persona autorizada en lugar de los del usuario autenticado

  • distributor_code (Optional[str]) – Código del distribuidor para filtrar suministros. Solo acepta strings en V2 (ej: «2» para E-distribución)

Devuelve:

Objeto SuppliesResponse que contiene: - supplies: Lista de objetos SupplyData validados - distributor_error: Lista de errores por distribuidor si los hay

Tipo del valor devuelto:

SuppliesResponse

Muestra:
  • AuthenticationError – Si las credenciales son inválidas o el token expira

  • APIError – Si la API devuelve un error HTTP crítico (400, 403, 404, 500, etc.)

  • DatadisError – Si ocurren errores de conexión o timeouts repetidos

  • ValidationError – Si los datos devueltos no pasan la validación Pydantic

Ver también

  • Documentación oficial: GET /api-private/api/get-supplies-v2

  • Comparar con SimpleDatadisClientV1.get_supplies() para diferencias

  • Para obtener detalles del contrato: get_contract_detail()

Added in version 2.0: Manejo de errores por distribuidor y respuesta estructurada

Nota

A diferencia de V1, esta operación puede tener éxito parcial: obtener suministros de algunos distribuidores aunque otros fallen.

get_distributors(authorized_nif=None)[fuente]

Obtiene la lista de distribuidores con estructura mejorada (V2).

Consulta el endpoint GET /api-private/api/get-distributors-with-supplies-v2 para obtener información sobre las distribuidoras eléctricas donde el usuario tiene suministros activos. La V2 incluye manejo mejorado de errores y estructura de respuesta más detallada que proporciona mejor información diagnóstica.

Mejoras de V2 sobre V1:
  • Estructura de respuesta mejorada: DistributorsResponse con metadatos

  • Información de errores: Detalles específicos de fallos por distribuidor

  • Soporte para NIFs autorizados: Consultar distribuidores de terceros

  • Manejo robusto: Operación exitosa aunque algunos distribuidores fallen

La respuesta incluye:
  • dist_existence_user: Objeto con distributorCodes (lista de códigos)

  • distributor_error: Lista de errores específicos por distribuidor si los hay
    • Información detallada de qué distribuidores no respondieron correctamente

    • Códigos de error específicos y descripciones

Ejemplo

Obtener distribuidores del usuario autenticado:

with SimpleDatadisClientV2("12345678A", "password") as client:
    response = client.get_distributors()

    # Obtener códigos de distribuidores
    distributor_codes = response.dist_existence_user.get("distributorCodes", [])

    print(f"✓ Distribuidores encontrados: {len(distributor_codes)}")

    # Mapear códigos a nombres (referencia)
    distributor_names = {
        "1": "Viesgo", "2": "E-distribución", "3": "E-redes",
        "4": "ASEME", "5": "UFD", "6": "EOSA", "7": "CIDE", "8": "IDE"
    }

    for code in distributor_codes:
        name = distributor_names.get(code, f"Distribuidor {code}")
        print(f"- {name} (código: {code})")

    # Verificar errores
    if response.distributor_error:
        print(f"⚠️  Errores en {len(response.distributor_error)} distribuidores:")
        for error in response.distributor_error:
            print(f"- {error.distributorName}: {error.errorDescription}")

    # Usar códigos para consultas posteriores
    if distributor_codes:
        first_code = distributor_codes[0]
        supplies_response = client.get_supplies(distributor_code=first_code)
        print(f"Suministros en {distributor_names.get(first_code)}: {len(supplies_response.supplies)}")

Consultar distribuidores de una persona autorizada:

# Obtener distribuidores de un NIF autorizado
response = client.get_distributors(authorized_nif="87654321B")

auth_distributors = response.dist_existence_user.get("distributorCodes", [])
print(f"Distribuidores del NIF autorizado: {auth_distributors}")

Comparación V1 vs V2:

# V1 - Lista simple de objetos DistributorData
distributors_v1 = client_v1.get_distributors()  # List[DistributorData]
codes_v1 = [d.distributorCode for d in distributors_v1]

# V2 - Respuesta estructurada con manejo de errores
response_v2 = client_v2.get_distributors()     # DistributorsResponse
codes_v2 = response_v2.dist_existence_user.get("distributorCodes", [])
errors_v2 = response_v2.distributor_error       # Lista de errores si los hay
Parámetros:

authorized_nif (Optional[str]) – NIF de una persona autorizada para consultar sus distribuidores. Si se especifica, se obtendrán los distribuidores donde esa persona tiene suministros en lugar del usuario autenticado

Devuelve:

Objeto DistributorsResponse que contiene: - dist_existence_user: Dict con distributorCodes (lista de códigos de distribuidor) - distributor_error: Lista de errores por distribuidor si los hay

Tipo del valor devuelto:

DistributorsResponse

Muestra:
  • AuthenticationError – Si las credenciales son inválidas o el token expira

  • APIError – Si la API devuelve un error HTTP crítico (400, 403, 404, 500, etc.)

  • DatadisError – Si ocurren errores de conexión o timeouts repetidos

  • ValidationError – Si los datos devueltos no pasan la validación Pydantic

Ver también

  • Documentación oficial: GET /api-private/api/get-distributors-with-supplies-v2

  • Comparar con SimpleDatadisClientV1.get_distributors() para diferencias

  • Los códigos obtenidos se usan en get_supplies(), get_consumption(), etc.

Added in version 2.0: Soporte para NIFs autorizados y estructura de respuesta mejorada

Nota

Solo se devuelven códigos de distribuidores donde el usuario (o NIF autorizado) tiene suministros activos. La lista puede estar vacía si no hay suministros.

get_contract_detail(cups, distributor_code, authorized_nif=None)[fuente]

Obtiene los detalles del contrato eléctrico con manejo mejorado de errores (V2).

Consulta el endpoint GET /api-private/api/get-contract-detail-v2 para obtener información detallada del contrato asociado a un CUPS específico. La V2 incluye manejo mejorado de errores por distribuidor y soporte nativo para consultas con NIFs autorizados, proporcionando mayor robustez y flexibilidad.

Ventajas de V2 sobre V1:
  • Manejo de errores por distribuidor: Información detallada de fallos específicos

  • Soporte nativo para NIFs autorizados: Parámetro authorized_nif integrado

  • Respuesta estructurada: ContractResponse con contratos y errores separados

  • Mayor robustez: Operación exitosa aunque haya problemas con algunos distribuidores

Información del contrato incluida (idéntica a V1):
  • Datos básicos: CUPS, distribuidor, comercializadora

  • Características técnicas: Tensión, potencia contratada, tipo de punto

  • Datos tarifarios: Tarifa de acceso, discriminación horaria

  • Ubicación: Provincia, municipio, código postal

  • Fechas: Inicio y fin de contrato, historial de cambios

  • Autoconsumo: Tipo, características y CAU si aplica

  • Control de potencia: ICP o Maxímetro

Ejemplo

Obtener detalles de contrato con manejo de errores V2:

with SimpleDatadisClientV2("12345678A", "password") as client:
    # Primero obtener suministros
    supplies_response = client.get_supplies()

    if supplies_response.supplies:
        supply = supplies_response.supplies[0]

        # Obtener detalles del contrato
        contract_response = client.get_contract_detail(
            cups=supply.cups,
            distributor_code=supply.distributorCode
        )

        print(f"✓ Contratos obtenidos: {len(contract_response.contract)}")

        # Mostrar información de contratos
        for contract in contract_response.contract:
            print(f"CUPS: {contract.cups}")
            print(f"Distribuidor: {contract.distributor}")
            print(f"Potencia contratada: {contract.contractedPowerkW} kW")
            print(f"Tarifa de acceso: {contract.accessFare}")
            if contract.marketer:
                print(f"Comercializadora: {contract.marketer}")
            print("---")

        # Verificar errores específicos del distribuidor
        if contract_response.distributor_error:
            print("⚠️  Errores en la consulta:")
            for error in contract_response.distributor_error:
                print(f"- {error.distributorName}: {error.errorDescription}")
        else:
            print("✓ Consulta exitosa sin errores")

Consultar contrato con NIF autorizado:

# Obtener contrato de un suministro autorizado por tercero
contract_response = client.get_contract_detail(
    cups="ES001234567890123456AB",
    distributor_code="2",
    authorized_nif="87654321B"  # NIF que nos autorizó
)

if contract_response.contract:
    contract = contract_response.contract[0]
    print(f"Contrato autorizado - Potencia: {contract.contractedPowerkW} kW")
elif contract_response.distributor_error:
    for error in contract_response.distributor_error:
        print(f"Error en autorización: {error.errorDescription}")

Comparación V1 vs V2:

# V1 - Lista simple, fallo total si hay errores
contracts_v1 = client_v1.get_contract_detail(cups, dist_code)  # List[ContractData]

# V2 - Respuesta robusta con manejo de errores
response_v2 = client_v2.get_contract_detail(cups, dist_code)    # ContractResponse
contracts_v2 = response_v2.contract                            # List[ContractData]
errors_v2 = response_v2.distributor_error                      # List[DistributorError]
Parámetros:
  • cups (str) – Código CUPS del punto de suministro (22 caracteres alfanuméricos que identifican únicamente el punto de suministro eléctrico)

  • distributor_code (str) – Código del distribuidor eléctrico como string (ej: «2» para E-distribución). V2 requiere string

  • authorized_nif (Optional[str]) – NIF de la persona que autorizó la consulta de sus datos. Si se especifica, se consultará el contrato de esa persona en lugar del usuario autenticado

Devuelve:

Objeto ContractResponse que contiene: - contract: Lista de objetos ContractData validados - distributor_error: Lista de errores por distribuidor si los hay

Tipo del valor devuelto:

ContractResponse

Muestra:
  • AuthenticationError – Si las credenciales son inválidas o el token expira

  • APIError – Si la API devuelve un error HTTP crítico (400, 403, 404, 500, etc.)

  • DatadisError – Si ocurren errores de conexión o timeouts repetidos

  • ValidationError – Si los datos devueltos no pasan la validación Pydantic

  • ValueError – Si el CUPS no tiene el formato correcto (22 caracteres)

Ver también

  • Documentación oficial: GET /api-private/api/get-contract-detail-v2

  • Comparar con SimpleDatadisClientV1.get_contract_detail() para diferencias

  • Para obtener la lista de CUPS: get_supplies()

  • Para datos de consumo del contrato: get_consumption()

Added in version 2.0: Soporte nativo para authorized_nif y manejo de errores por distribuidor

Nota

El CUPS debe ser exactamente de 22 caracteres alfanuméricos. La V2 incluye validación mejorada y mensajes de error más descriptivos.

get_consumption(cups, distributor_code, date_from, date_to, measurement_type=0, point_type=None, authorized_nif=None)[fuente]

Obtiene los datos de consumo eléctrico con validaciones mejoradas (V2).

Consulta el endpoint GET /api-private/api/get-consumption-data-v2 para obtener la curva de carga con manejo mejorado de errores y validaciones específicas V2. Incluye todas las funcionalidades de V1 más validaciones automáticas de rangos, manejo robusto de errores por distribuidor y soporte nativo para NIFs autorizados.

IMPORTANTE - Limitaciones idénticas a V1:
  • Solo fechas en formato mensual (YYYY/MM)

  • Datos cuarto-horarios limitados según tipo de punto

  • Conversión automática de fechas datetime/date

Mejoras de V2 sobre V1:
  • Validación automática: measurement_type y point_type se validan automáticamente

  • Manejo de errores por distribuidor: Operación exitosa aunque algunos distribuidores fallen

  • Soporte nativo para NIFs autorizados: Parámetro authorized_nif integrado

  • Respuesta estructurada: ConsumptionResponse con curva de tiempo y errores separados

  • Mejor diagnóstico: Información detallada de problemas específicos por distribuidor

Validaciones automáticas V2:
  • measurement_type: Se valida que esté en rango [0, 1]

  • point_type: Se valida que esté en rango [1, 5] si se proporciona

  • Compatibilidad cuarto-horaria: Se verifica automáticamente según tipo de punto

Ejemplo

Obtener consumo con manejo de errores V2:

with SimpleDatadisClientV2("12345678A", "password") as client:
    supplies_response = client.get_supplies()

    if supplies_response.supplies:
        supply = supplies_response.supplies[0]

        # Consumo horario del año 2024
        consumption_response = client.get_consumption(
            cups=supply.cups,
            distributor_code=supply.distributorCode,
            date_from="2024/01",
            date_to="2024/12",
            measurement_type=0  # Horarios - se valida automáticamente
        )

        print(f"✓ Registros obtenidos: {len(consumption_response.time_curve)}")

        # Analizar consumo
        total_kwh = sum(c.consumptionKWh for c in consumption_response.time_curve
                      if c.consumptionKWh)
        print(f"Consumo total 2024: {total_kwh:.2f} kWh")

        # Verificar errores específicos
        if consumption_response.distributor_error:
            print("⚠️  Errores encontrados:")
            for error in consumption_response.distributor_error:
                print(f"- {error.distributorName}: {error.errorDescription}")
        else:
            print("✓ Datos obtenidos sin errores")

Obtener datos cuarto-horarios con validación automática:

# V2 valida automáticamente la compatibilidad
try:
    consumption_response = client.get_consumption(
        cups="ES001234567890123456AB",
        distributor_code="2",  # E-distribución
        date_from="2024/06",
        date_to="2024/06",
        measurement_type=1,    # Cuarto-horarios - se valida automáticamente
        point_type=3           # Tipo 3 - se valida que esté en [1-5]
    )

    print(f"Datos cada 15 min: {len(consumption_response.time_curve)} registros")

except ValidationError as e:
    print(f"Error de validación V2: {e}")
except APIError as e:
    print(f"API rechazó la petición: {e}")

Consultar consumo con NIF autorizado:

consumption_response = client.get_consumption(
    cups="ES001234567890123456AB",
    distributor_code="2",
    date_from="2024/01",
    date_to="2024/03",
    authorized_nif="87654321B"  # NIF que nos autorizó
)

if consumption_response.time_curve:
    print(f"Datos autorizados obtenidos: {len(consumption_response.time_curve)}")

Comparación V1 vs V2:

# V1 - Lista simple, validación manual
consumption_v1 = client_v1.get_consumption(cups, dist, date_from, date_to)  # List[ConsumptionData]

# V2 - Respuesta estructurada, validación automática
response_v2 = client_v2.get_consumption(cups, dist, date_from, date_to)     # ConsumptionResponse
consumption_v2 = response_v2.time_curve                                     # List[ConsumptionData]
errors_v2 = response_v2.distributor_error                                   # List[DistributorError]
Parámetros:
  • cups (str) – Código CUPS del punto de suministro (22 caracteres alfanuméricos)

  • distributor_code (Union[str, int]) – Código del distribuidor eléctrico (acepta int o str, se convierte automáticamente)

  • date_from (Union[str, datetime, date]) – Fecha de inicio en formato YYYY/MM. También acepta objetos datetime/date que se convertirán automáticamente

  • date_to (Union[str, datetime, date]) – Fecha de fin en formato YYYY/MM. También acepta objetos datetime/date que se convertirán automáticamente

  • measurement_type (Union[int, float, str]) – Tipo de medición - 0: horarios (defecto), 1: cuarto-horarios. Se valida automáticamente en V2 que esté en rango [0, 1]

  • point_type (Optional[Union[int, float, str]]) – Tipo de punto de medida (1-5). Requerido para datos cuarto-horarios. Se valida automáticamente en V2 que esté en rango [1, 5]

  • authorized_nif (Optional[str]) – NIF de la persona que autorizó la consulta de sus datos. Si se especifica, se consultarán los datos de esa persona

Devuelve:

Objeto ConsumptionResponse que contiene: - time_curve: Lista de objetos ConsumptionData validados - distributor_error: Lista de errores por distribuidor si los hay

Tipo del valor devuelto:

ConsumptionResponse

Muestra:
  • AuthenticationError – Si las credenciales son inválidas o el token expira

  • APIError – Si la API devuelve un error HTTP crítico (400, 403, 404, 500, etc.)

  • DatadisError – Si ocurren errores de conexión o timeouts repetidos

  • ValidationError – Si las fechas no están en formato mensual válido, los tipos de medición/punto están fuera de rango, o los datos no pasan la validación Pydantic mejorada de V2

  • ValueError – Si se solicitan datos cuarto-horarios para un tipo de punto no compatible

Ver también

  • Documentación oficial: GET /api-private/api/get-consumption-data-v2

  • Comparar con SimpleDatadisClientV1.get_consumption() para diferencias

  • Para obtener CUPS: get_supplies()

  • Para datos de potencia máxima: get_max_power()

Added in version 2.0: Validaciones automáticas de rangos, soporte para authorized_nif y manejo de errores por distribuidor

Advertencia

Los datos cuarto-horarios siguen teniendo las mismas limitaciones que en V1: solo disponibles para tipos de punto 1, 2, y 3 en E-distribución.

get_max_power(cups, distributor_code, date_from, date_to, authorized_nif=None)[fuente]

Obtiene los datos de potencia máxima demandada con manejo mejorado de errores (V2).

Consulta el endpoint GET /api-private/api/get-max-power-v2 para obtener las potencias máximas registradas en cada período tarifario con manejo mejorado de errores por distribuidor y soporte nativo para NIFs autorizados. Mantiene toda la funcionalidad de V1 con mayor robustez y mejor información diagnóstica.

IMPORTANTE - Limitación idéntica a V1:

Solo acepta fechas en formato mensual (YYYY/MM). El SDK convierte automáticamente fechas datetime/date al formato requerido.

Mejoras de V2 sobre V1:
  • Manejo de errores por distribuidor: Información detallada de fallos específicos

  • Soporte nativo para NIFs autorizados: Parámetro authorized_nif integrado

  • Respuesta estructurada: MaxPowerResponse con potencias y errores separados

  • Mayor robustez: Operación exitosa aunque algunos distribuidores fallen

  • Mejor diagnóstico: Códigos y descripciones de errores específicos

Información de potencia máxima (idéntica a V1):
  • Potencia en Vatios (W): Demanda máxima registrada en cada período

  • Períodos tarifarios: VALLE, LLANO, PUNTA, P1-P6

  • Timestamp completo: Fecha y hora exacta del pico de potencia

  • Aplicaciones: Optimización de potencia contratada, identificación de picos

Ejemplo

Obtener potencias máximas con manejo de errores V2:

with SimpleDatadisClientV2("12345678A", "password") as client:
    supplies_response = client.get_supplies()

    if supplies_response.supplies:
        supply = supplies_response.supplies[0]

        # Potencias máximas de 2024
        max_power_response = client.get_max_power(
            cups=supply.cups,
            distributor_code=supply.distributorCode,
            date_from="2024/01",
            date_to="2024/12"
        )

        print(f"✓ Registros de potencia: {len(max_power_response.max_power)}")

        # Analizar potencias por período
        periods = {}
        for power in max_power_response.max_power:
            period = power.period
            if period not in periods:
                periods[period] = []
            periods[period].append(power.maxPower)

        # Mostrar potencia máxima por período
        for period, powers in periods.items():
            max_power_w = max(powers)
            max_power_kw = max_power_w / 1000
            print(f"Período {period}: {max_power_kw:.2f} kW")

        # Verificar errores específicos
        if max_power_response.distributor_error:
            print("⚠️  Errores encontrados:")
            for error in max_power_response.distributor_error:
                print(f"- {error.distributorName}: {error.errorDescription}")
        else:
            print("✓ Datos obtenidos sin errores")

Consultar potencias con NIF autorizado:

max_power_response = client.get_max_power(
    cups="ES001234567890123456AB",
    distributor_code="2",
    date_from="2024/01",
    date_to="2024/12",
    authorized_nif="87654321B"  # NIF que nos autorizó
)

if max_power_response.max_power:
    # Encontrar la potencia máxima absoluta del período
    all_powers = [p.maxPower for p in max_power_response.max_power]
    peak_power_w = max(all_powers)
    peak_power_kw = peak_power_w / 1000
    print(f"Pico máximo autorizado: {peak_power_kw:.2f} kW")

Identificar mes con mayor demanda:

# Agrupar por mes (idéntico a V1)
monthly_max = {}
for power in max_power_response.max_power:
    month = power.date[:7]  # YYYY/MM
    if month not in monthly_max:
        monthly_max[month] = 0
    monthly_max[month] = max(monthly_max[month], power.maxPower)

if monthly_max:
    peak_month = max(monthly_max, key=monthly_max.get)
    peak_power_kw = monthly_max[peak_month] / 1000
    print(f"Mayor demanda: {peak_power_kw:.2f} kW en {peak_month}")

Comparación V1 vs V2:

# V1 - Lista simple, fallo total si hay errores
max_power_v1 = client_v1.get_max_power(cups, dist, date_from, date_to)  # List[MaxPowerData]

# V2 - Respuesta robusta con manejo de errores
response_v2 = client_v2.get_max_power(cups, dist, date_from, date_to)    # MaxPowerResponse
max_power_v2 = response_v2.max_power                                     # List[MaxPowerData]
errors_v2 = response_v2.distributor_error                               # List[DistributorError]
Parámetros:
  • cups (str) – Código CUPS del punto de suministro (22 caracteres alfanuméricos)

  • distributor_code (str) – Código del distribuidor eléctrico como string (ej: «2» para E-distribución). V2 requiere string

  • date_from (str) – Fecha de inicio en formato YYYY/MM. Se convierte automáticamente si se pasa como datetime/date

  • date_to (str) – Fecha de fin en formato YYYY/MM. Se convierte automáticamente si se pasa como datetime/date

  • authorized_nif (Optional[str]) – NIF de la persona que autorizó la consulta de sus datos. Si se especifica, se consultarán los datos de esa persona

Devuelve:

Objeto MaxPowerResponse que contiene: - max_power: Lista de objetos MaxPowerData validados - distributor_error: Lista de errores por distribuidor si los hay

Tipo del valor devuelto:

MaxPowerResponse

Muestra:
  • AuthenticationError – Si las credenciales son inválidas o el token expira

  • APIError – Si la API devuelve un error HTTP crítico (400, 403, 404, 500, etc.)

  • DatadisError – Si ocurren errores de conexión o timeouts repetidos

  • ValidationError – Si las fechas no están en formato mensual válido o los datos no pasan la validación Pydantic

  • ValueError – Si el CUPS no tiene el formato correcto

Ver también

Added in version 2.0: Soporte nativo para authorized_nif y manejo de errores por distribuidor

Nota

Las potencias se devuelven en Vatios (W) como en V1. Para obtener kilovatios (kW) divida el valor entre 1000.

get_reactive_data(cups, distributor_code, date_from, date_to, authorized_nif=None)[fuente]

Obtiene datos de energía reactiva - Funcionalidad EXCLUSIVA de la API V2.

Consulta el endpoint GET /api-private/api/get-reactive-data-v2 para obtener información sobre la energía reactiva consumida por el punto de suministro. Esta funcionalidad es completamente nueva en V2 y no está disponible en V1.

¿Qué es la energía reactiva?

La energía reactiva es la energía eléctrica que no realiza trabajo útil pero es necesaria para el funcionamiento de equipos inductivos (motores, transformadores, etc.). Se mide en kVARh y puede generar penalizaciones en la factura eléctrica.

IMPORTANTE - Limitación de fechas:

Al igual que otros endpoints, solo acepta fechas en formato mensual (YYYY/MM). No se permiten fechas con días específicos.

Información incluida en los datos reactivos:
  • Energía reactiva por período: P1, P2, P3, P4, P5, P6

  • Código y descripción: Información del tipo de medición

  • Períodos mensuales: Datos agregados por mes

  • CUPS asociado: Identificación del punto de suministro

Períodos tarifarios de energía reactiva:
  • P1-P6: Períodos tarifarios según discriminación horaria

  • Valores en kVARh: Energía reactiva consumida en cada período

  • Agregación mensual: Datos totalizados por mes del período consultado

Applications:
  • Análisis de eficiencia energética: Identificar equipos ineficientes

  • Optimización de costes: Reducir penalizaciones por energía reactiva

  • Gestión técnica: Mejorar el factor de potencia de la instalación

  • Auditorías energéticas: Análisis completo del comportamiento eléctrico

Ejemplo

Obtener datos de energía reactiva (exclusivo V2):

with SimpleDatadisClientV2("12345678A", "password") as client:
    supplies_response = client.get_supplies()

    if supplies_response.supplies:
        supply = supplies_response.supplies[0]

        # Energía reactiva del año 2024
        reactive_data = client.get_reactive_data(
            cups=supply.cups,
            distributor_code=supply.distributorCode,
            date_from="2024/01",
            date_to="2024/12"
        )

        print(f"✓ Datos de energía reactiva: {len(reactive_data)} registros")

        for data in reactive_data:
            print(f"CUPS: {data.reactive_energy.cups}")
            print(f"Código: {data.reactive_energy.code}")
            print(f"Descripción: {data.reactive_energy.code_desc}")

            # Analizar energía por períodos
            for energy_record in data.reactive_energy.energy:
                date = energy_record.date
                total_reactive = sum([
                    energy_record.energy_p1 or 0,
                    energy_record.energy_p2 or 0,
                    energy_record.energy_p3 or 0,
                    energy_record.energy_p4 or 0,
                    energy_record.energy_p5 or 0,
                    energy_record.energy_p6 or 0
                ])
                print(f"{date}: {total_reactive:.2f} kVARh total")

            print("---")

Analizar penalizaciones potenciales:

# Buscar meses con alta energía reactiva
for data in reactive_data:
    for energy_record in data.reactive_energy.energy:
        # Calcular energía reactiva total del mes
        monthly_reactive = sum([
            energy_record.energy_p1 or 0,
            energy_record.energy_p2 or 0,
            energy_record.energy_p3 or 0,
            energy_record.energy_p4 or 0,
            energy_record.energy_p5 or 0,
            energy_record.energy_p6 or 0
        ])

        if monthly_reactive > 1000:  # Umbral de ejemplo
            print(f"⚠️  {energy_record.date}: Alta energía reactiva ({monthly_reactive:.2f} kVARh)")
            print("   → Revisar equipos inductivos para optimizar factor de potencia")

Consultar con NIF autorizado:

reactive_data = client.get_reactive_data(
    cups="ES001234567890123456AB",
    distributor_code="2",
    date_from="2024/01",
    date_to="2024/06",
    authorized_nif="87654321B"
)

if reactive_data:
    print("Datos de energía reactiva obtenidos con autorización")

¿Por qué no está disponible en V1?:

# V1 - Esta funcionalidad NO EXISTE
# client_v1.get_reactive_data()  # ← AttributeError: no existe

# V2 - Funcionalidad completamente nueva
reactive_data = client_v2.get_reactive_data(...)  # ✓ Disponible
Parámetros:
  • cups (str) – Código CUPS del punto de suministro (22 caracteres alfanuméricos)

  • distributor_code (str) – Código del distribuidor eléctrico como string (ej: «2» para E-distribución)

  • date_from (str) – Fecha de inicio en formato YYYY/MM

  • date_to (str) – Fecha de fin en formato YYYY/MM

  • authorized_nif (Optional[str]) – NIF de la persona que autorizó la consulta de sus datos. Si se especifica, se consultarán los datos de esa persona

Devuelve:

Lista de objetos ReactiveData validados con Pydantic. Cada objeto contiene información detallada de energía reactiva por períodos tarifarios y fechas

Tipo del valor devuelto:

List[ReactiveData]

Muestra:
  • AuthenticationError – Si las credenciales son inválidas o el token expira

  • APIError – Si la API devuelve un error HTTP (400, 403, 404, 500, etc.)

  • DatadisError – Si ocurren errores de conexión o timeouts repetidos

  • ValidationError – Si las fechas no están en formato mensual válido o los datos no pasan la validación Pydantic

  • ValueError – Si el CUPS no tiene el formato correcto

Ver también

  • Documentación oficial: GET /api-private/api/get-reactive-data-v2

  • Para datos de energía activa: get_consumption()

  • Para datos de potencia máxima: get_max_power()

  • Información sobre factor de potencia y energía reactiva en documentación técnica

Added in version 2.0: Funcionalidad completamente nueva, no disponible en V1

Nota

Esta funcionalidad puede no estar disponible para todos los tipos de punto o distribuidores. Consulte con su distribuidor la disponibilidad de estos datos.

Advertencia

La energía reactiva puede generar penalizaciones en la factura eléctrica. Use estos datos para optimizar el factor de potencia de su instalación.

close()[fuente]

Cierra explícitamente la sesión HTTP y limpia los recursos del cliente V2.

Realiza las siguientes operaciones de limpieza:
  • Cierra la sesión HTTP: Libera conexiones TCP activas

  • Invalida el token: Establece el token a None por seguridad

  • Libera recursos: Evita memory leaks en aplicaciones de larga duración

¿Cuándo llamar manualmente?

Normalmente NO es necesario llamar este método explícitamente cuando se usa el patrón with (context manager), ya que __exit__ lo llama automáticamente.

Sin embargo, puede ser útil en estos casos:
  • Aplicaciones de larga duración: Cuando el cliente se mantiene activo mucho tiempo

  • Gestión manual de recursos: Cuando no se usa context manager

  • Problemas de conectividad: Para forzar reconexión después de errores

  • Testing y debugging: Para controlar explícitamente el ciclo de vida

V1 vs V2 - Diferencias en gestión de recursos:
  • V1: Gestión de recursos más simple, principalmente HTTP sessions

  • V2: Gestión más robusta con mejor manejo de tokens y sesiones

Ejemplo

Uso con context manager (recomendado):

# El método close() se llama automáticamente
with SimpleDatadisClientV2("12345678A", "password") as client:
    supplies = client.get_supplies()
    # Al salir del bloque 'with', close() se ejecuta automáticamente

print("✓ Sesión cerrada automáticamente")

Uso manual (casos especiales):

client = SimpleDatadisClientV2("12345678A", "password")
try:
    supplies = client.get_supplies()
    consumption = client.get_consumption(
        cups=supplies.supplies[0].cups,
        distributor_code=supplies.supplies[0].distributorCode,
        date_from="2024/01",
        date_to="2024/03"
    )

    # Procesar muchos datos...

finally:
    client.close()  # ← Llamada manual obligatoria
    print("✓ Recursos liberados manualmente")

Aplicación de larga duración:

class DatadisService:
    def __init__(self):
        self.client = None

    def connect(self):
        self.client = SimpleDatadisClientV2("12345678A", "password")

    def disconnect(self):
        if self.client:
            self.client.close()  # ← Limpieza explícita
            self.client = None

    def get_recent_consumption(self):
        if not self.client:
            self.connect()
        return self.client.get_consumption(...)

Debugging y reconexión:

client = SimpleDatadisClientV2("12345678A", "password")

# Primer intento
try:
    supplies = client.get_supplies()
except Exception as e:
    print(f"Error: {e}")
    client.close()  # ← Limpiar estado

    # Reintentar con nueva sesión
    client = SimpleDatadisClientV2("12345678A", "password")
    supplies = client.get_supplies()

Nota

Este método es idempotente: se puede llamar múltiples veces sin efectos secundarios. Si la sesión ya está cerrada, no hace nada.

Advertencia

Después de llamar a close(), el cliente queda inutilizable. Cualquier intento de hacer requests fallará. Cree una nueva instancia si necesita continuar usando la API.

Ver también

  • __enter__() y __exit__() para el patrón context manager

  • Documentación de requests.Session.close() para detalles técnicos

__enter__()[fuente]

Método de entrada del context manager - Permite usar with statement.

Implementa el protocolo de context manager de Python, permitiendo que el cliente se use con la declaración with para gestión automática de recursos.

¿Qué hace este método?
  • Retorna la instancia actual: Permite acceso a todos los métodos del cliente

  • Inicialización implícita: La autenticación se realiza de forma lazy en el primer request

  • Establece el contexto: Prepara el cliente para uso dentro del bloque with

Ventajas del patrón context manager:
  1. Gestión automática: Los recursos se liberan automáticamente al salir

  2. Robustez ante errores: Cleanup garantizado incluso si ocurren excepciones

  3. Código más limpio: No necesidad de llamadas manuales a close()

  4. Mejores prácticas: Patrón estándar en Python para gestión de recursos

V1 vs V2 - Context manager:
  • V1: Implementación básica del patrón

  • V2: Implementación mejorada con mejor gestión de excepciones y recursos

Ejemplo

Uso estándar con context manager:

# __enter__() se llama automáticamente aquí ↓
with SimpleDatadisClientV2("12345678A", "password") as client:
    # 'client' es lo que retorna __enter__()
    supplies = client.get_supplies()

    for supply in supplies.supplies:
        consumption = client.get_consumption(
            cups=supply.cups,
            distributor_code=supply.distributorCode,
            date_from="2024/01",
            date_to="2024/03"
        )
        print(f"Consumo: {len(consumption)} registros")
# __exit__() se llama automáticamente aquí ↑

print("✓ Recursos liberados automáticamente")

Context manager anidado:

with SimpleDatadisClientV2("12345678A", "password") as client:
    supplies = client.get_supplies()

    # Múltiples operaciones en el mismo contexto
    for supply in supplies.supplies[:3]:  # Primeros 3 suministros
        distributors = client.get_distributors()
        contracts = client.get_contract_detail(
            cups=supply.cups,
            distributor_code=supply.distributorCode
        )

        # V2 exclusive: Energía reactiva
        reactive_data = client.get_reactive_data(
            cups=supply.cups,
            distributor_code=supply.distributorCode,
            date_from="2024/01",
            date_to="2024/03"
        )

        print(f"CUPS: {supply.cups}")
        print(f"- Contratos: {len(contracts)}")
        print(f"- Energía reactiva: {len(reactive_data)} registros")

Comparación con uso manual:

# ❌ Uso manual (más propenso a errores)
client = SimpleDatadisClientV2("12345678A", "password")
try:
    supplies = client.get_supplies()
    # ... hacer trabajo ...
finally:
    client.close()  # ← Fácil de olvidar

# ✅ Context manager (recomendado)
with SimpleDatadisClientV2("12345678A", "password") as client:
    supplies = client.get_supplies()
    # ... hacer trabajo ...
# ← Cleanup automático garantizado

Manejo de excepciones transparente:

try:
    with SimpleDatadisClientV2("invalid_nif", "wrong_pass") as client:
        supplies = client.get_supplies()  # ← AuthenticationError
except AuthenticationError as e:
    print(f"Error de autenticación: {e}")
# ← close() se ejecuta incluso con excepción
Devuelve:

La propia instancia del cliente, permitiendo acceso a todos sus métodos

Tipo del valor devuelto:

SimpleDatadisClientV2

Nota

Este método NO realiza la autenticación. La autenticación se hace de forma lazy en el primer request que requiera token.

Ver también

  • __exit__() para el método de salida del context manager

  • close() para limpieza manual de recursos

  • PEP 343 - Especificación del protocolo context manager

Added in version 2.0: Implementación mejorada del context manager con mejor gestión de recursos

__exit__(exc_type, exc_val, exc_tb)[fuente]

Método de salida del context manager - Garantiza limpieza automática de recursos.

Se ejecuta automáticamente al salir del bloque with, independientemente de si el código terminó normalmente o con una excepción. Garantiza que los recursos se liberen correctamente en todos los casos.

¿Qué hace este método?
  • Llamada automática a close(): Libera sesiones HTTP y tokens

  • Cleanup garantizado: Se ejecuta incluso si ocurren excepciones

  • No suprime excepciones: Permite que las excepciones se propaguen normalmente

  • Gestión robusta: Implementación defensiva ante posibles errores

Flujo de ejecución:
  1. Entrada: __enter__() retorna la instancia del cliente

  2. Trabajo: Se ejecuta el código dentro del bloque with

  3. Salida: __exit__() se llama automáticamente (incluso con excepciones)

  4. Cleanup: close() libera todos los recursos

  5. Propagación: Las excepciones originales se mantienen

V1 vs V2 - Gestión de excepciones:
  • V1: Implementación básica de cleanup

  • V2: Gestión más robusta, mejor logging de errores durante cleanup

Ejemplo

Flujo normal (sin excepciones):

with SimpleDatadisClientV2("12345678A", "password") as client:
    # __enter__() ejecutado ↑

    supplies = client.get_supplies()
    print(f"Suministros: {len(supplies.supplies)}")

    # Código se ejecuta normalmente
    consumption = client.get_consumption(
        cups=supplies.supplies[0].cups,
        distributor_code=supplies.supplies[0].distributorCode,
        date_from="2024/01",
        date_to="2024/03"
    )

# __exit__(None, None, None) ejecutado aquí ↑
# Recursos liberados automáticamente
print("✓ Operación completada, recursos liberados")

Flujo con excepción controlada:

try:
    with SimpleDatadisClientV2("12345678A", "wrong_password") as client:
        # __enter__() ejecutado ↑

        supplies = client.get_supplies()  # ← AuthenticationError

except AuthenticationError as e:
    # __exit__(AuthenticationError, e, traceback) ya ejecutado ↑
    print(f"Error de autenticación: {e}")
    print("✓ Recursos liberados automáticamente (con excepción)")

Flujo con excepción inesperada:

with SimpleDatadisClientV2("12345678A", "password") as client:
    # __enter__() ejecutado ↑

    supplies = client.get_supplies()

    # Error inesperado en el código del usuario
    result = 1 / 0  # ← ZeroDivisionError

# __exit__(ZeroDivisionError, exception, traceback) ejecutado ↑
# Recursos liberados automáticamente
# ZeroDivisionError se propaga normalmente

Múltiples context managers:

# Cada context manager gestiona sus propios recursos
with SimpleDatadisClientV2("user1_nif", "pass1") as client1:
    with SimpleDatadisClientV2("user2_nif", "pass2") as client2:
        # Ambos clientes activos
        supplies1 = client1.get_supplies()
        supplies2 = client2.get_supplies()

        # Comparar datos entre usuarios
        print(f"Usuario 1: {len(supplies1.supplies)} suministros")
        print(f"Usuario 2: {len(supplies2.supplies)} suministros")
    # client2.__exit__() ejecutado aquí
# client1.__exit__() ejecutado aquí

print("✓ Ambos clientes cerrados correctamente")

Debugging del context manager:

class DebuggingDatadisClient(SimpleDatadisClientV2):
    def __exit__(self, exc_type, exc_val, exc_tb):
        print(f"Saliendo del context manager...")
        if exc_type:
            print(f"- Con excepción: {exc_type.__name__}: {exc_val}")
        else:
            print("- Terminación normal")

        # Llamar al método padre para cleanup real
        super().__exit__(exc_type, exc_val, exc_tb)
        print("✓ Recursos liberados")

with DebuggingDatadisClient("12345678A", "password") as client:
    supplies = client.get_supplies()
    # raise ValueError("Error de prueba")  # ← Descomentar para probar
Parámetros:
  • exc_type (Optional[Type[BaseException]]) – Tipo de excepción que causó la salida, o None si terminó normalmente

  • exc_val (Optional[BaseException]) – Instancia de la excepción que causó la salida, o None si terminó normalmente

  • exc_tb (Optional[TracebackType]) – Traceback de la excepción, o None si terminó normalmente

Devuelve:

None (no suprime excepciones, permite propagación normal)

Tipo del valor devuelto:

None

Nota

Este método NUNCA suprime excepciones (siempre retorna None/False). Las excepciones se propagan normalmente después del cleanup.

Advertencia

NO llame este método manualmente. Es invocado automáticamente por Python al salir del bloque with. La llamada manual puede causar doble cleanup.

Ver también

Added in version 2.0: Implementación mejorada con mejor gestión de excepciones durante cleanup

Modelos de Datos

Datos de Consumo

class datadis_python.models.consumption.ConsumptionData(*, cups, date, time, consumptionKWh, obtainMethod, surplusEnergyKWh=None, generationEnergyKWh=None, selfConsumptionEnergyKWh=None)[fuente]

Bases: BaseModel

Modelo Pydantic para datos de consumo energético de Datadis.

Representa una medición de consumo eléctrico proveniente de los contadores inteligentes de las distribuidoras eléctricas españolas. Los datos incluyen tanto consumo tradicional como información de autoconsumo y generación para instalaciones con paneles solares u otras fuentes de energía renovable.

Características principales:
  • Validación automática: Todos los campos se validan con Pydantic

  • Compatibilidad de alias: Soporta tanto nombres Python como nombres API

  • Datos de autoconsumo: Información completa para instalaciones fotovoltaicas

  • Granularidad temporal: Mediciones horarias o cuarto-horarias según disponibilidad

  • Métodos de obtención: Distingue entre mediciones reales y estimadas

Tipos de mediciones soportadas:
  • Consumo tradicional: Energía consumida de la red eléctrica

  • Autoconsumo: Energía generada y consumida localmente (sin pasar por la red)

  • Excedentes/Vertidos: Energía generada y vendida a la red eléctrica

  • Generación total: Energía total producida por la instalación renovable

Métodos de obtención de datos:
  • «Real»: Medición directa del contador inteligente

  • «Estimada»: Estimación basada en patrones históricos o interpolación

  • «Provisional»: Datos preliminares pendientes de validación final

Ejemplo

Uso básico del modelo:

from datadis_python.models.consumption import ConsumptionData

# Datos típicos de consumo sin autoconsumo
consumption_basic = ConsumptionData(
    cups="ES001234567890123456AB",
    date="2024/12/15",
    time="14:00",
    consumptionKWh=2.45,
    obtainMethod="Real"
)

print(f"Consumo: {consumption_basic.consumption_kwh} kWh")
print(f"Método: {consumption_basic.obtain_method}")

Datos de instalación con autoconsumo fotovoltaico:

# Instalación con paneles solares
consumption_solar = ConsumptionData(
    cups="ES001234567890123456AB",
    date="2024/07/20",
    time="13:00",  # Hora de máxima producción solar
    consumptionKWh=0.25,      # Poca energía de la red
    obtainMethod="Real",
    surplusEnergyKWh=3.20,    # Excedente vendido a la red
    generationEnergyKWh=5.80, # Generación total de paneles
    selfConsumptionEnergyKWh=2.60  # Autoconsumo directo
)

# Verificar balance energético
total_consumption = (consumption_solar.consumption_kwh +
                   consumption_solar.self_consumption_energy_kwh)
print(f"Consumo total real: {total_consumption} kWh")
print(f"Excedente vendido: {consumption_solar.surplus_energy_kwh} kWh")

Validación automática con alias:

# Usando nombres de la API (camelCase)
data_api = {
    "cups": "ES001234567890123456AB",
    "date": "2024/12/15",
    "time": "10:30",
    "consumptionKWh": 1.85,  # Nombre API
    "obtainMethod": "Estimada"
}

consumption = ConsumptionData(**data_api)
print(f"Consumo: {consumption.consumption_kwh}")  # Acceso Python
Parámetros:
  • cups (str) – Código CUPS del punto de suministro. Identificador único de 22 caracteres que identifica de forma inequívoca el punto de conexión a la red eléctrica

  • date (str) – Fecha de la medición en formato YYYY/MM/DD. Corresponde al día de la lectura del contador, en zona horaria española (CET/CEST)

  • time (str) – Hora de la medición en formato HH:MM (24h). Para mediciones horarias normalmente :00, para cuarto-horarias :00, :15, :30, :45

  • consumption_kwh (float) – Energía activa consumida desde la red eléctrica en kWh. Representa la energía que el usuario ha tomado de la red durante el período de medición

  • obtain_method (str) – Método de obtención de los datos. Valores posibles: «Real» (medición directa), «Estimada» (cálculo), «Provisional»

  • surplus_energy_kwh (Optional[float]) – Energía excedentaria vertida a la red en kWh. Solo aplica para instalaciones de autoconsumo con excedentes. Representa la energía generada localmente y vendida/cedida a la red

  • generation_energy_kwh (Optional[float]) – Energía total generada por la instalación renovable en kWh. Suma del autoconsumo directo más los excedentes vertidos. Solo aplica para instalaciones con generación propia

  • self_consumption_energy_kwh (Optional[float]) – Energía autoconsumida directamente en kWh. Energía generada localmente y consumida sin pasar por la red. Solo aplica para instalaciones de autoconsumo

  • consumptionKWh (float)

  • obtainMethod (str)

  • surplusEnergyKWh (float | None)

  • generationEnergyKWh (float | None)

  • selfConsumptionEnergyKWh (float | None)

Muestra:

ValidationError – Si algún campo no cumple las validaciones de Pydantic (tipos incorrectos, valores nulos en campos obligatorios, etc.)

Nota

Para instalaciones con autoconsumo, se cumple la ecuación: generation_energy_kwh = self_consumption_energy_kwh + surplus_energy_kwh

Ver también

  • ConsumptionResponse - Respuesta estructurada de la API V2

  • SimpleDatadisClientV1.get_consumption() - Obtener datos V1

  • SimpleDatadisClientV2.get_consumption() - Obtener datos V2

cups: str
date: str
time: str
consumption_kwh: float
obtain_method: str
surplus_energy_kwh: float | None
generation_energy_kwh: float | None
self_consumption_energy_kwh: float | None
model_config: ClassVar[ConfigDict] = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

Datos de Suministro

class datadis_python.models.supply.SupplyData(*, address, cups, postalCode, province, municipality, distributor, validDateFrom, validDateTo=None, pointType, distributorCode)[fuente]

Bases: BaseModel

Modelo Pydantic para datos de puntos de suministro eléctrico españoles.

Representa la información completa de un punto de suministro (CUPS) registrado en el sistema eléctrico español. Cada objeto contiene todos los datos técnicos, geográficos y contractuales necesarios para identificar y trabajar con un punto de conexión específico a la red eléctrica nacional.

Información del punto de suministro:
  • Identificación única: Código CUPS de 20-22 caracteres

  • Ubicación física: Dirección completa, código postal, provincia y municipio

  • Información técnica: Tipo de punto de medida y clasificación

  • Datos del distribuidor: Empresa responsable de la red en la zona

  • Período contractual: Fechas de validez del contrato actual

Tipos de punto de medida (point_type):
  • Tipo 1: Potencia contratada > 450 kW (grandes industrias)

  • Tipo 2: 50 kW < Potencia ≤ 450 kW (medianas industrias)

  • Tipo 3: 15 kW < Potencia ≤ 50 kW (pequeñas industrias, grandes comercios)

  • Tipo 4: 10 kW < Potencia ≤ 15 kW (pequeños comercios, grandes viviendas)

  • Tipo 5: Potencia ≤ 10 kW (viviendas domésticas típicas)

Estructura del código CUPS:
  • Formato: ESXXXXXXXXXXXXXXXXXXX

  • Longitud: 20-22 caracteres alfanuméricos

  • Prefijo: Siempre «ES» para España

  • Identificador: Único a nivel nacional

  • Verificación: Dígitos de control incluidos

Distribuidores por zona geográfica:
  • Viesgo (1): Cantabria, Asturias

  • E-distribución (2): Cobertura nacional, mayor distribuidor

  • E-redes (3): Galicia

  • ASEME (4): Melilla (ciudad autónoma)

  • UFD (5): Nacional, especialmente Cataluña y Madrid

  • EOSA (6): Aragón

  • CIDE (7): Ceuta (ciudad autónoma)

  • IDE (8): Islas Baleares

Ejemplo

Análisis básico de un punto de suministro:

from datadis_python.models.supply import SupplyData

# Punto de suministro doméstico típico
supply_home = SupplyData(
    address="Calle Mayor 123, 1º A",
    cups="ES001234567890123456AB",
    postalCode="28001",
    province="Madrid",
    municipality="Madrid",
    distributor="E-distribución",
    validDateFrom="2023/01/15",
    validDateTo=None,  # Contrato activo
    pointType=5,  # Doméstico
    distributorCode="2"  # E-distribución
)

print(f"CUPS: {supply_home.cups}")
print(f"Ubicación: {supply_home.address}")
print(f"Zona: {supply_home.municipality}, {supply_home.province}")
print(f"Distribuidor: {supply_home.distributor}")

# Determinar tipo de instalación
point_types = {
    1: "Gran industria (>450 kW)",
    2: "Mediana industria (50-450 kW)",
    3: "Pequeña industria (15-50 kW)",
    4: "Comercio/gran vivienda (10-15 kW)",
    5: "Vivienda doméstica (≤10 kW)"
}

print(f"Tipo: {point_types.get(supply_home.point_type, 'Desconocido')}")

Análisis de vigencia contractual:

from datetime import datetime

def analyze_contract_validity(supply: SupplyData) -> str:
    \"\"\"Analiza el estado del contrato del suministro.\"\"\"

    if supply.valid_date_to is None:
        return "✅ Contrato activo (sin fecha de fin)"

    # Parsear fecha de fin (formato YYYY/MM/DD)
    try:
        end_date = datetime.strptime(supply.valid_date_to, "%Y/%m/%d")
        current_date = datetime.now()

        if end_date > current_date:
            days_remaining = (end_date - current_date).days
            return f"✅ Contrato activo ({days_remaining} días restantes)"
        else:
            return "❌ Contrato expirado"
    except ValueError:
        return "⚠️ Fecha de fin inválida"

# Usar la función
status = analyze_contract_validity(supply_home)
print(f"Estado contractual: {status}")

Agrupación por distribuidor:

# Lista de suministros de un usuario
supplies = [
    SupplyData(
        address="Calle A", cups="ES0012...", postalCode="28001",
        province="Madrid", municipality="Madrid", distributor="E-distribución",
        validDateFrom="2023/01/01", pointType=5, distributorCode="2"
    ),
    SupplyData(
        address="Calle B", cups="ES0034...", postalCode="08001",
        province="Barcelona", municipality="Barcelona", distributor="UFD",
        validDateFrom="2022/06/15", pointType=4, distributorCode="5"
    )
]

# Agrupar por distribuidor
by_distributor = {}
for supply in supplies:
    dist_name = supply.distributor
    if dist_name not in by_distributor:
        by_distributor[dist_name] = []
    by_distributor[dist_name].append(supply)

print("Suministros por distribuidor:")
for distributor, supply_list in by_distributor.items():
    print(f"- {distributor}: {len(supply_list)} suministros")
    for supply in supply_list:
        print(f"  * {supply.municipality} ({supply.cups[:8]}...)")

Validación de código CUPS:

def validate_cups_format(cups: str) -> bool:
    \"\"\"Valida formato básico del código CUPS español.\"\"\"

    # Verificaciones básicas
    if not cups.startswith("ES"):
        return False
    if len(cups) < 20 or len(cups) > 22:
        return False
    if not cups[2:].isalnum():
        return False

    return True

# Validar CUPS
if validate_cups_format(supply_home.cups):
    print("✅ Formato CUPS válido")
else:
    print("❌ Formato CUPS inválido")

Análisis geográfico:

# Identificar región por distribuidor
regions = {
    "1": "Norte (Cantabria/Asturias)",
    "2": "Nacional (E-distribución)",
    "3": "Galicia",
    "4": "Melilla",
    "5": "Nacional (UFD)",
    "6": "Aragón",
    "7": "Ceuta",
    "8": "Baleares"
}

region = regions.get(supply_home.distributor_code, "Región desconocida")
print(f"Región de distribución: {region}")
Parámetros:
  • address (str) – Dirección física completa del punto de suministro. Incluye calle, número, piso/puerta si aplica. Corresponde a la ubicación real donde se encuentra la instalación eléctrica

  • cups (str) – Código CUPS (Código Único del Punto de Suministro). Identificador alfanumérico único de 20-22 caracteres que identifica inequívocamente el punto de conexión a la red eléctrica española

  • postal_code (str) – Código postal de la dirección del suministro. Código numérico de 5 dígitos que identifica la zona postal española

  • province (str) – Provincia española donde se ubica el punto de suministro. Corresponde a la división administrativa de primer nivel

  • municipality (str) – Municipio donde se encuentra el suministro eléctrico. División administrativa local dentro de la provincia

  • distributor (str) – Nombre comercial de la empresa distribuidora responsable de la red eléctrica en la zona geográfica del suministro

  • valid_date_from (str) – Fecha de inicio de validez del contrato actual en formato YYYY/MM/DD. Marca el comienzo del período contractual vigente

  • valid_date_to (Optional[str]) – Fecha de finalización del contrato en formato YYYY/MM/DD. None para contratos sin fecha de fin definida (más común)

  • point_type (int) – Tipo de punto de medida según clasificación técnica española. Entero del 1 al 5 que determina el tipo de instalación y medición

  • distributor_code (str) – Código numérico del distribuidor (1-8). Identificador único usado en las consultas API para el distribuidor específico

  • postalCode (str)

  • validDateFrom (str)

  • validDateTo (str | None)

  • pointType (int)

  • distributorCode (str)

Muestra:

ValidationError – Si algún campo obligatorio falta o tiene formato incorrecto

Nota

El point_type determina el tipo de contador y sistema de medición. Los tipos 1-3 suelen tener medición cuarto-horaria, los tipos 4-5 horaria.

Truco

Use el distributor_code para consultas posteriores de consumo, contratos y otros datos específicos del punto de suministro.

Ver también

  • SuppliesResponse - Respuesta estructurada de la API V2 que contiene estos datos

  • SimpleDatadisClientV1.get_supplies() - Obtener puntos de suministro V1

  • SimpleDatadisClientV2.get_supplies() - Obtener puntos de suministro V2

  • Códigos CUPS oficiales en la documentación del sistema eléctrico español

Added in version 1.0: Modelo base para puntos de suministro del sistema eléctrico español

address: str
cups: str
postal_code: str
province: str
municipality: str
distributor: str
valid_date_from: str
valid_date_to: str | None
point_type: int
distributor_code: str
model_config: ClassVar[ConfigDict] = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

Datos de Contrato

class datadis_python.models.contract.ContractData(*, cups, distributor, marketer=None, tension, accessFare, province, municipality, postalCode, contractedPowerkW, timeDiscrimination=None, modePowerControl, startDate, endDate=None, codeFare, selfConsumptionTypeCode=None, selfConsumptionTypeDesc=None, section=None, subsection=None, partitionCoefficient=None, cau=None, installedCapacityKW=None, dateOwner=None, lastMarketerDate=None, maxPowerInstall=None)[fuente]

Bases: BaseModel

Modelo Pydantic completo para datos contractuales de suministros eléctricos.

Representa la información contractual completa de un punto de suministro (CUPS), incluyendo datos técnicos, comerciales, tarifarios y de autoconsumo. Este modelo contiene toda la información relevante sobre el contrato eléctrico asociado a una instalación, desde datos básicos hasta configuraciones avanzadas de autoconsumo.

Información contractual incluida:
  • Datos básicos: CUPS, distribuidor, comercializadora, ubicación

  • Información técnica: Tensión, potencias contratadas, control de potencia

  • Datos tarifarios: Tarifa de acceso, discriminación horaria, códigos CNMC

  • Autoconsumo: Tipo, configuración, coeficientes, CAU

  • Histórico: Períodos de propiedad, cambios de comercializadora

Tipos de instalaciones soportadas:
  • Consumo tradicional: Sin generación propia

  • Autoconsumo individual: Instalación fotovoltaica privada

  • Autoconsumo colectivo: Instalaciones compartidas entre varios usuarios

  • Autoconsumo con excedentes: Venta de energía sobrante a la red

  • Autoconsumo sin excedentes: Generación solo para consumo propio

Códigos de tarifa de acceso (CNMC):
  • 2.0TD: Baja tensión ≤ 15 kW (doméstico típico)

  • 3.0TD: Baja tensión > 15 kW ≤ 100 kW (comercios, pequeña industria)

  • 6.1TD: Alta tensión 1-36 kV (gran industria)

  • 6.2TD: Alta tensión 36-72.5 kV

  • 6.3TD: Alta tensión 72.5-145 kV

  • 6.4TD: Alta tensión ≥ 145 kV

Ejemplo

Contrato doméstico básico sin autoconsumo:

from datadis_python.models.contract import ContractData

# Vivienda típica con tarifa 2.0TD
contract_home = ContractData(
    cups="ES001234567890123456AB",
    distributor="E-distribución",
    marketer="Iberdrola",
    tension="BT",
    accessFare="2.0TD (Peaje de acceso 2.0TD)",
    province="Madrid",
    municipality="Madrid",
    postalCode="28001",
    contractedPowerkW=[5.75],  # 5.75 kW contratados
    timeDiscrimination="DHA",   # Discriminación horaria
    modePowerControl="ICP",     # Interruptor Control Potencia
    startDate="2023/01/15",
    codeFare="2.0TD"
)

print(f"Potencia contratada: {contract_home.contracted_power_kw[0]} kW")
print(f"Tarifa: {contract_home.code_fare}")

Instalación con autoconsumo fotovoltaico:

from datadis_python.models.contract import ContractData, DateOwner

# Casa con paneles solares y autoconsumo
contract_solar = ContractData(
    cups="ES001234567890123456AB",
    distributor="UFD",
    marketer="Naturgy",
    tension="BT",
    accessFare="2.0TD con autoconsumo",
    province="Valencia",
    municipality="Valencia",
    postalCode="46001",
    contractedPowerkW=[4.60],
    modePowerControl="ICP",
    startDate="2022/03/01",
    codeFare="2.0TD",
    # Configuración de autoconsumo
    selfConsumptionTypeCode="41",
    selfConsumptionTypeDesc="Autoconsumo con excedentes acogido a compensación",
    installedCapacityKW=5.0,  # 5 kW de paneles solares
    cau="ES00123456789",      # Código de Autoconsumo Único
    dateOwner=[
        DateOwner(startDate="2022/03/01", endDate="2024/12/31")
    ]
)

print(f"Tipo autoconsumo: {contract_solar.self_consumption_type_desc}")
print(f"Potencia instalada: {contract_solar.installed_capacity_kw} kW")

Autoconsumo colectivo con coeficiente de reparto:

# Instalación compartida en comunidad de vecinos
contract_collective = ContractData(
    cups="ES001234567890123456AB",
    distributor="E-distribución",
    tension="BT",
    accessFare="2.0TD autoconsumo colectivo",
    province="Barcelona",
    municipality="Barcelona",
    postalCode="08001",
    contractedPowerkW=[3.45],
    codeFare="2.0TD",
    selfConsumptionTypeCode="43",
    selfConsumptionTypeDesc="Autoconsumo colectivo con excedentes",
    partitionCoefficient=0.15,  # 15% del total generado
    cau="ES00987654321",
    installedCapacityKW=20.0,    # Instalación total compartida
    startDate="2023/06/01"
)

print(f"Coeficiente de reparto: {contract_collective.partition_coefficient}")
Parámetros:
  • cups (str) – Código CUPS del punto de suministro. Identificador único nacional de 20-22 caracteres que identifica inequívocamente el punto de conexión

  • distributor (str) – Nombre de la empresa distribuidora responsable de la red en la zona geográfica del suministro

  • marketer (Optional[str]) – Empresa comercializadora que factura la energía. Solo visible si el usuario autenticado es propietario del CUPS

  • tension (str) – Nivel de tensión del suministro. Valores típicos: «BT» (Baja Tensión), «AT» (Alta Tensión), «MT» (Media Tensión)

  • access_fare (str) – Descripción completa de la tarifa de acceso aplicable. Incluye el código y descripción extendida

  • province (str) – Provincia donde se ubica físicamente el punto de suministro

  • municipality (str) – Municipio de ubicación del suministro eléctrico

  • postal_code (str) – Código postal de la dirección del punto de suministro

  • contracted_power_kw (List[float]) – Lista de potencias contratadas en kW por período tarifario. Para tarifas simples: un valor. Para discriminación horaria: múltiples valores

  • time_discrimination (Optional[str]) – Tipo de discriminación horaria aplicada. Valores típicos: «DHA» (Discriminación Horaria), «DHS» (Supervalle), None (tarifa simple)

  • mode_power_control (str) – Sistema de control de la potencia contratada. «ICP» (Interruptor Control Potencia) o «Maxímetro»

  • start_date (str) – Fecha de inicio de vigencia del contrato en formato YYYY/MM/DD

  • end_date (Optional[str]) – Fecha de finalización del contrato. None para contratos activos

  • code_fare (str) – Código oficial de la tarifa de acceso según clasificación CNMC. Define la estructura tarifaria aplicable

  • self_consumption_type_code (Optional[str]) – Código numérico del tipo de autoconsumo según RD 244/2019. Códigos 4X para diferentes modalidades de autoconsumo

  • self_consumption_type_desc (Optional[str]) – Descripción detallada del tipo de autoconsumo configurado. Especifica modalidad, excedentes y acogimiento a compensación

  • section (Optional[str]) – Clasificación de sección para autoconsumo según normativa vigente

  • subsection (Optional[str]) – Subclasificación específica dentro de la sección de autoconsumo

  • partition_coefficient (Optional[float]) – Coeficiente de reparto para autoconsumo colectivo. Porcentaje de la energía generada asignado a este CUPS (0.0-1.0)

  • cau (Optional[str]) – Código de Autoconsumo Único. Identificador oficial de la instalación de autoconsumo asignado por la administración competente

  • installed_capacity_kw (Optional[float]) – Potencia pico instalada de generación renovable en kW. Suma de toda la capacidad de generación asociada al autoconsumo

  • date_owner (Optional[List[DateOwner]]) – Lista de períodos durante los cuales el usuario autenticado ha sido propietario del punto de suministro

  • last_marketer_date (Optional[str]) – Fecha del último cambio de empresa comercializadora en formato YYYY/MM/DD

  • max_power_install (Optional[str]) – Potencia máxima de la instalación eléctrica en formato texto. Puede incluir información adicional sobre limitaciones técnicas

  • accessFare (str)

  • postalCode (str)

  • contractedPowerkW (List[float])

  • timeDiscrimination (str | None)

  • modePowerControl (str)

  • startDate (str)

  • endDate (str | None)

  • codeFare (str)

  • selfConsumptionTypeCode (str | None)

  • selfConsumptionTypeDesc (str | None)

  • partitionCoefficient (float | None)

  • installedCapacityKW (float | None)

  • dateOwner (List[DateOwner] | None)

  • lastMarketerDate (str | None)

  • maxPowerInstall (str | None)

Muestra:

ValidationError – Si algún campo obligatorio está ausente o tiene formato incorrecto

Nota

Para autoconsumo colectivo, el partition_coefficient debe sumar 1.0 entre todos los participantes de la instalación compartida.

Ver también

  • DateOwner - Modelo para períodos de propiedad

  • ContractResponse - Respuesta estructurada de la API V2

  • SimpleDatadisClientV2.get_contract_detail() - Obtener datos contractuales

  • RD 244/2019 para códigos de autoconsumo oficiales

Added in version 2.0: Soporte completo para autoconsumo y datos contractuales extendidos

cups: str
distributor: str
marketer: str | None
tension: str
access_fare: str
province: str
municipality: str
postal_code: str
contracted_power_kw: List[float]
time_discrimination: str | None
mode_power_control: str
start_date: str
end_date: str | None
code_fare: str
self_consumption_type_code: str | None
self_consumption_type_desc: str | None
section: str | None
subsection: str | None
partition_coefficient: float | None
cau: str | None
installed_capacity_kw: float | None
date_owner: List[DateOwner] | None
last_marketer_date: str | None
max_power_install: str | None
model_config: ClassVar[ConfigDict] = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

Datos de Distribuidor

class datadis_python.models.distributor.DistributorData(*, distributorCodes)[fuente]

Bases: BaseModel

Modelo Pydantic para datos de distribuidoras eléctricas españolas.

Representa la información de las empresas distribuidoras de energía eléctrica donde el usuario tiene puntos de suministro activos. Las distribuidoras son las empresas responsables del mantenimiento y operación de las redes eléctricas en España, y cada zona geográfica está asignada a una distribuidora específica.

Sistema eléctrico español:

Las distribuidoras están reguladas por la CNMC (Comisión Nacional de los Mercados y la Competencia) y tienen asignadas zonas geográficas exclusivas donde son responsables de la red de distribución eléctrica.

Distribuidoras principales en España:
  • Código «1»: Viesgo - Cantabria, Asturias

  • Código «2»: E-distribución (Endesa) - Nacional (mayor cobertura)

  • Código «3»: E-redes - Galicia

  • Código «4»: ASEME - Melilla

  • Código «5»: UFD (Naturgy) - Nacional, especialmente Cataluña, Madrid

  • Código «6»: EOSA - Aragón

  • Código «7»: CIDE - Ceuta

  • Código «8»: IDE (Redeia) - Islas Baleares

Diferencia con comercializadoras:
  • Distribuidoras: Mantienen y operan la red física (cables, transformadores)

  • Comercializadoras: Venden la energía y emiten facturas al usuario final

Ejemplo

Uso básico del modelo:

from datadis_python.models.distributor import DistributorData

# Datos típicos de respuesta V1
distributor_data = DistributorData(
    distributorCodes=["2", "5"]  # E-distribución y UFD
)

print("Distribuidoras donde tienes suministros:")
for code in distributor_data.distributor_codes:
    distributor_name = {
        "1": "Viesgo",
        "2": "E-distribución (Endesa)",
        "3": "E-redes",
        "4": "ASEME",
        "5": "UFD (Naturgy)",
        "6": "EOSA",
        "7": "CIDE",
        "8": "IDE (Redeia)"
    }.get(code, f"Distribuidor {code}")

    print(f"- Código {code}: {distributor_name}")

Uso con clientes V1:

from datadis_python.client.v1 import SimpleDatadisClientV1

with SimpleDatadisClientV1("12345678A", "password") as client:
    # Obtener distribuidoras donde el usuario tiene suministros
    distributors = client.get_distributors()

    print(f"Distribuidoras encontradas: {len(distributors)}")
    for dist in distributors:
        print(f"Códigos: {dist.distributor_codes}")

    # Usar el primer código para consultas posteriores
    if distributors and distributors[0].distributor_codes:
        first_code = distributors[0].distributor_codes[0]
        supplies = client.get_supplies(distributor_code=first_code)

Filtrado por zona geográfica:

# Ejemplo: usuario con suministros en múltiples zonas
multi_zone_data = DistributorData(
    distributorCodes=["2", "5", "8"]  # Endesa, Naturgy, Baleares
)

# Identificar regiones
regions = {
    "2": "Península (Endesa)",
    "5": "Cataluña/Madrid (Naturgy)",
    "8": "Islas Baleares (IDE)"
}

for code in multi_zone_data.distributor_codes:
    print(f"Suministros en: {regions.get(code, 'Región desconocida')}")
Parámetros:
  • distributor_codes (List[str]) – Lista de códigos de distribuidoras donde el usuario tiene puntos de suministro activos. Cada código identifica una empresa distribuidora específica del sistema eléctrico español

  • distributorCodes (List[str])

Muestra:

ValidationError – Si la lista está vacía o contiene valores no válidos

Nota

Este modelo representa la respuesta simplificada de la API V1. La API V2 utiliza modelos más complejos con información extendida de cada distribuidor.

Ver también

  • DistributorsResponse - Respuesta estructurada de la API V2

  • SimpleDatadisClientV1.get_distributors() - Obtener distribuidoras V1

  • SimpleDatadisClientV2.get_distributors() - Obtener distribuidoras V2

  • Los códigos obtenidos se usan en métodos de consulta específicos

Added in version 1.0: Soporte para códigos de distribuidor en API V1

distributor_codes: List[str]
model_config: ClassVar[ConfigDict] = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

Datos de Potencia Máxima

class datadis_python.models.max_power.MaxPowerData(*, cups, date, time, maxPower, period)[fuente]

Bases: BaseModel

Modelo Pydantic para datos de potencia máxima demandada en suministros eléctricos.

Representa el registro de potencia eléctrica máxima demandada en un punto de suministro durante un período determinado. Esta información es crucial para la facturación eléctrica, optimización de contratos y análisis de consumo, especialmente en instalaciones comerciales e industriales con control por maxímetro.

Conceptos fundamentales:
  • Potencia máxima: Pico de demanda eléctrica registrado en un período

  • Control por maxímetro: Sistema que registra automáticamente los picos de potencia

  • Períodos tarifarios: Franjas horarias con diferentes precios de energía

  • Penalizaciones: Excesos sobre la potencia contratada pueden generar recargos

Sistemas de control de potencia en España:
  • ICP (Interruptor Control Potencia): Corta el suministro si se excede la potencia

  • Maxímetro: Registra los picos pero permite el consumo (con posible recargo)

Períodos tarifarios comunes:
  • PUNTA: Horas de mayor demanda nacional (18:00-22:00 invierno)

  • LLANO: Horas intermedias de demanda

  • VALLE: Horas de menor demanda (01:00-08:00)

  • P1-P6: Períodos numerados según discriminación horaria específica

Ejemplo

Análisis de potencia máxima doméstica:

from datadis_python.models.max_power import MaxPowerData

# Pico de potencia en hora punta
max_power_home = MaxPowerData(
    cups="ES001234567890123456AB",
    date="2024/12/15",
    time="19:30",  # Hora punta de invierno
    maxPower=4250.0,  # 4.25 kW
    period="PUNTA"
)

print(f"Potencia máxima: {max_power_home.max_power / 1000:.2f} kW")
print(f"Momento pico: {max_power_home.date} a las {max_power_home.time}")
print(f"Período tarifario: {max_power_home.period}")

# Verificar si excede potencia contratada
potencia_contratada = 5750  # 5.75 kW en W
if max_power_home.max_power > potencia_contratada:
    exceso = max_power_home.max_power - potencia_contratada
    print(f"⚠️ Exceso: {exceso:.0f} W sobre lo contratado")
else:
    print("✅ Dentro de la potencia contratada")

Instalación comercial con múltiples períodos:

# Ejemplo de pequeño comercio
power_records = [
    MaxPowerData(
        cups="ES009876543210987654AB",
        date="2024/11/20",
        time="09:15",
        maxPower=12500.0,  # 12.5 kW
        period="LLANO"
    ),
    MaxPowerData(
        cups="ES009876543210987654AB",
        date="2024/11/20",
        time="20:45",
        maxPower=15200.0,  # 15.2 kW
        period="PUNTA"
    )
]

# Analizar picos por período
for record in power_records:
    kw_power = record.max_power / 1000
    print(f"Período {record.period}: {kw_power:.1f} kW a las {record.time}")

Optimización de contrato basada en datos históricos:

from datadis_python.client.v2 import SimpleDatadisClientV2

with SimpleDatadisClientV2("12345678A", "password") as client:
    # Obtener datos de potencia máxima del último año
    max_power_response = client.get_max_power(
        cups="ES001234567890123456AB",
        distributor_code="2",
        date_from="2024/01",
        date_to="2024/12"
    )

    # Analizar patrones para optimizar contrato
    monthly_peaks = {}
    for power_data in max_power_response.max_power_data:
        month = power_data.date[:7]  # YYYY/MM
        current_peak = monthly_peaks.get(month, 0)
        monthly_peaks[month] = max(current_peak, power_data.max_power)

    avg_peak = sum(monthly_peaks.values()) / len(monthly_peaks)
    print(f"Potencia promedio máxima: {avg_peak/1000:.2f} kW")
Parámetros:
  • cups (str) – Código CUPS del punto de suministro. Identificador único del punto de conexión donde se registró la potencia máxima

  • date (str) – Fecha en que se registró la potencia máxima en formato YYYY/MM/DD. Corresponde al día específico en que ocurrió el pico de demanda

  • time (str) – Hora exacta del pico de potencia en formato HH:MM (24h). Momento preciso en que se registró la demanda máxima del período

  • max_power (float) – Potencia máxima demandada expresada en vatios (W). Representa el pico de consumo eléctrico registrado en el momento especificado

  • period (str) – Período tarifario en el que ocurrió el pico. Valores típicos: «PUNTA», «LLANO», «VALLE» o códigos numéricos «P1»-«P6» según discriminación horaria

  • maxPower (float)

Muestra:

ValidationError – Si algún campo obligatorio falta o tiene formato incorrecto

Nota

La potencia se expresa en vatios (W). Para convertir a kilovatios: max_power / 1000

Truco

Para instalaciones con ICP, los picos registrados normalmente no excederán la potencia contratada ya que el interruptor cortaría el suministro.

Ver también

  • MaxPowerResponse - Respuesta estructurada de la API V2

  • SimpleDatadisClientV1.get_max_power() - Obtener datos V1

  • SimpleDatadisClientV2.get_max_power() - Obtener datos V2

  • ContractData - Información sobre potencias contratadas

Added in version 1.0: Soporte para datos de potencia máxima de contadores inteligentes

cups: str
date: str
time: str
max_power: float
period: str
model_config: ClassVar[ConfigDict] = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

Datos de Energía Reactiva

class datadis_python.models.reactive.ReactiveData(*, reactiveEnergy)[fuente]

Bases: BaseModel

Modelo Pydantic simplificado para respuesta de energía reactiva.

Wrapper o contenedor simple para datos de energía reactiva que encapsula la información principal en un objeto ReactiveEnergyData. Este modelo representa la estructura de respuesta básica de algunos endpoints de energía reactiva, proporcionando acceso directo a los datos principales.

Casos de uso:
  • Respuestas simples: Cuando solo se necesitan los datos principales

  • Compatibilidad: Para mantener consistencia con otras APIs

  • Encapsulación: Estructura que puede extenderse en futuras versiones

Ejemplo

Uso básico del modelo wrapper:

from datadis_python.models.reactive import ReactiveData, ReactiveEnergyData

# Datos encapsulados en el wrapper
reactive_wrapper = ReactiveData(
    reactiveEnergy=ReactiveEnergyData(
        cups="ES001234567890123456AB",
        energy=[],  # Lista de períodos
        code=None,
        code_desc=None
    )
)

# Acceso a los datos principales
main_data = reactive_wrapper.reactive_energy
print(f"CUPS: {main_data.cups}")
print(f"Períodos disponibles: {len(main_data.energy)}")

Procesamiento directo:

# Trabajar directamente con los datos encapsulados
if reactive_wrapper.reactive_energy.code is None:
    # Procesar datos de energía reactiva
    for period in reactive_wrapper.reactive_energy.energy:
        print(f"Mes {period.date}: datos disponibles")
else:
    print(f"Error: {reactive_wrapper.reactive_energy.code_desc}")
Parámetros:
  • reactive_energy (ReactiveEnergyData) – Objeto ReactiveEnergyData que contiene toda la información de energía reactiva para el punto de suministro consultado

  • reactiveEnergy (ReactiveEnergyData)

Muestra:

ValidationError – Si el objeto ReactiveEnergyData no es válido

Nota

Este modelo es principalmente un wrapper. Para acceso a datos detallados, utilice directamente el atributo reactive_energy.

Ver también

reactive_energy: ReactiveEnergyData
model_config: ClassVar[ConfigDict] = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

Respuestas de la API

Excepciones

Excepciones personalizadas para el SDK de Datadis.

author:

TacoronteRiveroCristian

exception datadis_python.exceptions.DatadisError[fuente]

Bases: Exception

Base exception for Datadis SDK.

Esta es la excepción base de la cual heredan todas las demás excepciones del SDK.

exception datadis_python.exceptions.AuthenticationError[fuente]

Bases: DatadisError

Authentication related errors.

Se lanza cuando hay problemas con la autenticación del usuario.

exception datadis_python.exceptions.APIError(message, status_code=None)[fuente]

Bases: DatadisError

API response errors.

Se lanza cuando la API de Datadis devuelve errores HTTP.

Parámetros:
  • message (str) – Mensaje de error

  • status_code (int) – Código de estado HTTP (opcional)

__init__(message, status_code=None)[fuente]

Inicializa una excepción de error de API.

Parámetros:
  • message (str) – Mensaje de error

  • status_code (int) – Código de estado HTTP (opcional)

exception datadis_python.exceptions.ValidationError[fuente]

Bases: DatadisError

Parameter validation errors.

Se lanza cuando los parámetros proporcionados no son válidos.

Utilidades

Validadores

Validadores especializados para parámetros de la API de Datadis.

Este módulo proporciona funciones de validación específicas para los diferentes tipos de parámetros que acepta la API de Datadis. Cada validador implementa las reglas de negocio y restricciones técnicas específicas de la plataforma.

Los validadores están diseñados para detectar y prevenir errores comunes antes de realizar peticiones a la API, proporcionando mensajes de error claros y específicos que guían al usuario hacia la solución correcta.

Categorías de validación:
  • Identificadores: CUPS, códigos de distribuidor

  • Fechas y rangos: Validación temporal con restricciones de Datadis

  • Tipos de datos: Tipos de medida, tipos de punto

  • Formatos: Patrones específicos requeridos por la API

Características principales:
  • Validación temprana: Detecta errores antes de peticiones HTTP

  • Mensajes específicos: Guía clara sobre cómo corregir problemas

  • Reglas de negocio: Implementa restricciones específicas de Datadis

  • Robustez: Manejo de casos edge y entradas malformadas

Restricciones específicas de Datadis:
  • Rango temporal: Solo últimos 2 años de datos disponibles

  • Formato de fechas: Principalmente YYYY/MM (mensual)

  • Códigos limitados: Solo 8 distribuidores oficiales válidos

  • CUPS españoles: Formato específico ES + 20-22 caracteres

Ejemplo

Validaciones independientes:

from datadis_python.utils.validators import (
    validate_cups,
    validate_distributor_code,
    validate_date_range
)

# Validar CUPS
valid_cups = validate_cups("ES0031607515707001RC0F")

# Validar distribuidor
valid_code = validate_distributor_code("2")  # E-distribución

# Validar rango de fechas
from_date, to_date = validate_date_range("2024/01", "2024/12", "monthly")

Integración con conversores:

# Los validadores se llaman automáticamente desde los conversores
from datadis_python.utils.type_converters import (
    convert_cups_parameter,
    convert_distributor_code_parameter
)

# Conversión + validación automática
cups = convert_cups_parameter("ES0031607515707001RC0F")
code = convert_distributor_code_parameter(2)  # int → "2" + validación

Nota

Todos los validadores lanzan ValidationError con mensajes descriptivos cuando encuentran problemas. Esto permite manejo de errores consistente en todo el SDK.

Advertencia

Las validaciones están sincronizadas con las limitaciones actuales de la API de Datadis (2025). Si la API cambia sus restricciones, estos validadores necesitarán actualizarse.

author:

TacoronteRiveroCristian

datadis_python.utils.validators.validate_cups(cups)[fuente]

Valida el formato del código CUPS (Código Universal del Punto de Suministro).

Los códigos CUPS son identificadores únicos obligatorios para todos los puntos de suministro eléctrico en España. Esta función valida que el código cumple con el formato oficial establecido por el sistema eléctrico español.

Especificaciones del formato CUPS:
  • Prefijo obligatorio: «ES» (código ISO del país)

  • Longitud variable: 20-22 caracteres alfanuméricos después del prefijo

  • Total: 22-24 caracteres (incluyendo «ES»)

  • Caracteres válidos: Solo letras mayúsculas (A-Z) y números (0-9)

  • Sin separadores: No se permiten espacios, guiones u otros caracteres

Ejemplos de códigos CUPS reales:
  • Formato 20: ES0031607515707001RC0F (22 caracteres totales)

  • Formato 22: ES1234567890123456789012 (24 caracteres totales)

Proceso de validación:
  1. Verificación de vacío: El CUPS no puede estar vacío o ser None

  2. Normalización: Conversión a mayúsculas y eliminación de espacios

  3. Validación de patrón: Verificación contra regex oficial

  4. Verificación de longitud: Confirmar longitud dentro del rango válido

Parámetros:

cups (str) – Código CUPS a validar. Debe ser un string con formato válido

Devuelve:

Código CUPS validado, normalizado (mayúsculas, sin espacios)

Tipo del valor devuelto:

str

Muestra:

ValidationError – Si el CUPS no cumple con el formato esperado

Ejemplo

Códigos CUPS válidos:

# Formato estándar (20 caracteres después de ES)
validate_cups("ES0031607515707001RC0F")
# → "ES0031607515707001RC0F"

# Formato extendido (22 caracteres después de ES)
validate_cups("ES1234567890123456789012")
# → "ES1234567890123456789012"

# Con espacios (se limpian automáticamente)
validate_cups(" ES0031607515707001RC0F ")
# → "ES0031607515707001RC0F"

# Minúsculas (se convierten automáticamente)
validate_cups("es0031607515707001rc0f")
# → "ES0031607515707001RC0F"

Casos que fallan (errores esperados):

# ❌ Código vacío
validate_cups("")
# → ValidationError: "CUPS no puede estar vacío"

# ❌ Sin prefijo ES
validate_cups("0031607515707001RC0F")
# → ValidationError: "Formato CUPS inválido. Debe ser: ES + 20-22 caracteres alfanuméricos"

# ❌ Demasiado corto
validate_cups("ES123456")
# → ValidationError: "Formato CUPS inválido..."

# ❌ Caracteres inválidos
validate_cups("ES003160751570700@RC0F")
# → ValidationError: "Formato CUPS inválido..."

# ❌ Prefijo incorrecto
validate_cups("FR0031607515707001RC0F")
# → ValidationError: "Formato CUPS inválido..."

Uso en validación de entrada:

def get_consumption(self, cups: str, ...):
    # Validar antes de usar en petición
    validated_cups = validate_cups(cups)
    # validated_cups está garantizado como válido
    params = {"cups": validated_cups}

Nota

Esta función valida únicamente el formato del CUPS, no verifica que el código exista realmente o esté asociado a un usuario específico. Esa validación la realiza el servidor de Datadis.

Technical Details:
  • Regex utilizado: ^ES[A-Z0-9]{20,22}$

  • Normalización: .upper().strip() automática

  • Performance: Validación muy rápida usando regex compilado

  • Memoria: No guarda estado entre llamadas

Referencias

  • CNE (Comisión Nacional de Energía): Especificaciones oficiales CUPS

  • BOE: Normativa sobre identificación de puntos de suministro

  • Datadis: Documentación técnica de la API

Ver también

  • convert_cups_parameter() para conversión automática con validación

  • Documentación oficial sobre códigos CUPS en España

Added in version 1.0: Validación básica de formato CUPS

Distinto en la versión 2.0: Mejorado soporte para formatos CUPS extendidos (22 caracteres)

datadis_python.utils.validators.validate_date_range(date_from, date_to, format_type='monthly')[fuente]

Valida un rango de fechas según las restricciones específicas de Datadis.

Esta función implementa todas las reglas de validación temporal específicas de la API de Datadis, incluyendo formatos aceptados, rangos permitidos y limitaciones de acceso a datos históricos.

Restricciones de Datadis implementadas:
  • Rango temporal: Solo últimos 2 años desde la fecha actual

  • No fechas futuras: Las fechas no pueden ser posteriores al día actual

  • Orden lógico: date_from debe ser anterior o igual a date_to

  • Formatos específicos: YYYY/MM para mensual, YYYY/MM/DD para diario

Formatos soportados:
  • Mensual: «YYYY/MM» (ej: «2024/01») - Recomendado para Datadis

  • Diario: «YYYY/MM/DD» (ej: «2024/01/15») - Limitado en algunos endpoints

Validaciones aplicadas:
  1. Formato de entrada: Verificación contra patrones regex específicos

  2. Parseabilidad: Verificación de fechas válidas (no 30 de febrero)

  3. Orden lógico: date_from ≤ date_to

  4. Límite histórico: No más de 2 años hacia atrás

  5. Límite futuro: No fechas posteriores a hoy

Parámetros:
  • date_from (str) – Fecha de inicio del rango en formato string

  • date_to (str) – Fecha de fin del rango en formato string

  • format_type (str) – Tipo de formato («monthly» para YYYY/MM).

Devuelve:

Tupla con las fechas validadas (date_from, date_to)

Tipo del valor devuelto:

Tuple[str, str]

Muestra:

ValidationError – Si cualquier validación falla

Ejemplo

Validaciones exitosas:

# Rango mensual válido
validate_date_range("2024/01", "2024/12", "monthly")
# → ("2024/01", "2024/12")

# Rango diario válido
validate_date_range("2024/01/01", "2024/01/31", "daily")
# → ("2024/01/01", "2024/01/31")

# Rango de un mes
validate_date_range("2024/06", "2024/06", "monthly")
# → ("2024/06", "2024/06")

Casos que fallan (errores esperados):

# ❌ Formato incorrecto
validate_date_range("2024-01", "2024-12", "monthly")
# → ValidationError: "Formato de fecha_desde inválido: 2024-01. Use 2024/01"

# ❌ Rango invertido
validate_date_range("2024/12", "2024/01", "monthly")
# → ValidationError: "fecha_desde no puede ser posterior a fecha_hasta"

# ❌ Demasiado antigua (más de 2 años)
validate_date_range("2020/01", "2020/12", "monthly")
# → ValidationError: "fecha_desde no puede ser anterior a hace 2 años"

# ❌ Fecha futura
validate_date_range("2030/01", "2030/12", "monthly")
# → ValidationError: "fecha_hasta no puede ser futura"

# ❌ Fecha inválida
validate_date_range("2024/02/30", "2024/02/30", "daily")
# → ValidationError: "Fecha inválida: day is out of range for month"

Uso típico en métodos del SDK:

def get_consumption(self, date_from, date_to):
    # Validación robusta antes de petición API
    validated_from, validated_to = validate_date_range(
        date_from, date_to, "monthly"
    )
    # Las fechas están garantizadas como válidas
    params = {"dateFrom": validated_from, "dateTo": validated_to}

Nota

El límite de 2 años se basa en las limitaciones actuales de Datadis para acceso a datos históricos. Este límite puede cambiar en el futuro según las políticas de la plataforma.

Performance:

La validación incluye cálculos de fecha para verificar límites temporales. Para uso intensivo, considere cachear los límites calculados.

Technical Details:
  • Regex patterns: Específicos para cada formato (daily/monthly)

  • Parsing: Usa datetime.strptime() para validación completa

  • Límites dinámicos: Calculados en tiempo real basados en datetime.now()

  • Timezone: Usa timezone local del sistema

Ver también

  • convert_date_range_to_api_format() para conversión + validación

  • convert_date_to_api_format() para fechas individuales

  • Documentación de Datadis sobre disponibilidad de datos históricos

Added in version 1.0: Validación básica de rangos de fechas

Distinto en la versión 2.0: Añadidas validaciones específicas para limitaciones de Datadis

datadis_python.utils.validators.validate_distributor_code(distributor_code)[fuente]

Valida códigos de distribuidor eléctrico españoles oficiales.

Parámetros:

distributor_code (str) – Código de distribuidor a validar

Devuelve:

Código de distribuidor validado

Tipo del valor devuelto:

str

Muestra:

ValidationError – Si el código no corresponde a un distribuidor válido

Ejemplo

Códigos válidos:

# Distribuidores nacionales principales
validate_distributor_code("2")  # → "2" (E-distribución/Endesa)
validate_distributor_code("5")  # → "5" (UFD/Naturgy)

# Distribuidores regionales
validate_distributor_code("1")  # → "1" (Viesgo - Norte)
validate_distributor_code("3")  # → "3" (E-redes - Galicia)
validate_distributor_code("6")  # → "6" (EOSA - Aragón)

# Distribuidores insulares/locales
validate_distributor_code("8")  # → "8" (IDE - Baleares)
validate_distributor_code("4")  # → "4" (ASEME - Melilla)
validate_distributor_code("7")  # → "7" (CIDE - Ceuta)

Casos que fallan (errores esperados):

# ❌ Código inexistente
validate_distributor_code("9")
# → ValidationError: "Código de distribuidor inválido: 9. Válidos: 1, 2, 3, 4, 5, 6, 7, 8"

# ❌ Código múltiple
validate_distributor_code("12")
# → ValidationError: "Código de distribuidor inválido: 12..."

# ❌ Código negativo
validate_distributor_code("-1")
# → ValidationError: "Código de distribuidor inválido: -1..."

Uso con constantes descriptivas:

from datadis_python.utils.constants import DISTRIBUTOR_CODES

# Usar nombres descriptivos en lugar de números
endesa_code = DISTRIBUTOR_CODES["E_DISTRIBUCION"]  # "2"
validated = validate_distributor_code(endesa_code)  # "2"

# Iterar sobre todos los distribuidores válidos
for name, code in DISTRIBUTOR_CODES.items():
    validated_code = validate_distributor_code(code)
    print(f"{name}: {validated_code}")

Nota

Los códigos de distribuidor son siempre strings en la API de Datadis, aunque representen números. Use convert_distributor_code_parameter() si necesita conversión automática desde enteros.

Technical Details:
  • Lista estática: Los 8 códigos están hardcodeados (no cambian frecuentemente)

  • Validación rápida: Lookup en lista pequeña, muy eficiente

  • Case sensitive: Los códigos deben ser exactamente como se especifican

  • No conversión: Esta función no convierte tipos, solo valida

Referencias

  • CNE: Comisión Nacional de Energía - Listado oficial de distribuidores

  • CNMC: Comisión Nacional de los Mercados y la Competencia

  • Datadis: Documentación oficial de códigos soportados

Ver también

Added in version 1.0: Validación de códigos de distribuidor

Distinto en la versión 2.0: Actualizada lista con información geográfica detallada

datadis_python.utils.validators.validate_measurement_type(measurement_type)[fuente]

Valida y normaliza tipos de medida eléctrica para la API de Datadis.

Los tipos de medida distinguen entre consumo de energía (tomada de la red) y generación de energía (inyectada a la red). Esta distinción es importante para usuarios con instalaciones de autoconsumo que pueden tanto consumir como generar electricidad.

Tipos de medida oficiales:
  • 0 - CONSUMO: Energía consumida desde la red eléctrica (por defecto)

  • 1 - GENERACIÓN: Energía generada e inyectada a la red

Casos de uso:
  • Consumo doméstico: Siempre tipo 0 (viviendas sin generación)

  • Autoconsumo con inyección: Tipo 0 para consumo, tipo 1 para excedentes

  • Plantas de generación: Principalmente tipo 1

  • Instalaciones mixtas: Ambos tipos según el flujo de energía

Manejo de valores por defecto:
  • None: Se convierte automáticamente a 0 (consumo)

  • Valor explícito: Se valida que esté en el rango permitido

Parámetros:

measurement_type (Optional[int]) –

Tipo de medida a validar:

  • 0 o None: Consumo (energía tomada de la red)

  • 1: Generación (energía inyectada a la red)

Devuelve:

Tipo de medida validado (siempre 0 o 1)

Tipo del valor devuelto:

int

Muestra:

ValidationError – Si el tipo no está en el rango válido (0-1)

Ejemplo

Valores válidos:

# Consumo explícito
validate_measurement_type(0)     # → 0 (consumo)

# Generación explícita
validate_measurement_type(1)     # → 1 (generación)

# Valor por defecto (None → consumo)
validate_measurement_type(None)  # → 0 (consumo por defecto)

Casos que fallan (errores esperados):

# ❌ Tipo inválido
validate_measurement_type(2)
# → ValidationError: "measurement_type debe ser 0 (consumo) o 1 (generación)"

# ❌ Tipo negativo
validate_measurement_type(-1)
# → ValidationError: "measurement_type debe ser 0 (consumo) o 1 (generación)"

Uso típico en consultas:

# Consulta de consumo doméstico (por defecto)
consumption_data = client.get_consumption(
    cups="ES001234567890123456AB",
    distributor_code="2",
    date_from="2024/01",
    date_to="2024/12",
    measurement_type=validate_measurement_type(None)  # → 0
)

# Consulta de generación solar
generation_data = client.get_consumption(
    cups="ES001234567890123456AB",
    distributor_code="2",
    date_from="2024/01",
    date_to="2024/12",
    measurement_type=validate_measurement_type(1)  # → 1
)

Uso con constantes:

from datadis_python.utils.constants import MEASUREMENT_TYPES

# Usar constantes descriptivas
consumption_type = validate_measurement_type(MEASUREMENT_TYPES["CONSUMPTION"])  # 0
generation_type = validate_measurement_type(MEASUREMENT_TYPES["GENERATION"])    # 1

Nota

La mayoría de usuarios domésticos solo necesitarán el tipo 0 (consumo). El tipo 1 (generación) es relevante principalmente para instalaciones con paneles solares u otras fuentes de generación distribuida.

Technical Details:
  • Rango válido: Solo 0 y 1 según especificación de Datadis

  • Default seguro: None se convierte a 0 (caso más común)

  • Validación estricta: No se permiten otros valores enteros

  • Performance: Validación muy rápida (comparación simple)

Ver también

Added in version 1.0: Validación de tipos de medida

Distinto en la versión 2.0: Mejorada documentación con casos de uso específicos

datadis_python.utils.validators.validate_point_type(point_type)[fuente]

Valida y normaliza tipos de punto de medida según normativa eléctrica española.

Parámetros:

point_type (Optional[int]) – Tipo de punto, None para usar por defecto (1)

Devuelve:

Tipo de punto validado (siempre 1-5)

Tipo del valor devuelto:

int

Muestra:

ValidationError – Si el tipo no está en el rango válido (1-5)

Ejemplo

Valores válidos:

# Frontera (por defecto)
validate_point_type(None)  # → 1 (frontera por defecto)
validate_point_type(1)     # → 1 (frontera explícito)

# Consumo doméstico/comercial
validate_point_type(2)     # → 2 (consumo)

# Generación eléctrica
validate_point_type(3)     # → 3 (generación)

# Servicios del sistema
validate_point_type(4)     # → 4 (servicios auxiliares)
validate_point_type(5)     # → 5 (servicios auxiliares alt)

Casos que fallan (errores esperados):

# ❌ Tipo fuera de rango
validate_point_type(6)
# → ValidationError: "point_type debe ser 1 (frontera), 2 (consumo), 3 (generación) o 4 (servicios auxiliares)"

# ❌ Tipo cero o negativo
validate_point_type(0)
# → ValidationError: "point_type debe ser 1 (frontera)..."

Uso típico por contexto:

# Consulta de consumo doméstico típico
domestic_data = client.get_consumption(
    cups="ES001234567890123456AB",
    distributor_code="2",
    date_from="2024/01",
    date_to="2024/12",
    point_type=validate_point_type(2)  # Consumo doméstico
)

# Consulta de generación renovable
generation_data = client.get_consumption(
    cups="ES001234567890123456AB",
    distributor_code="2",
    date_from="2024/01",
    date_to="2024/12",
    point_type=validate_point_type(3)  # Generación
)

Uso con constantes descriptivas:

from datadis_python.utils.constants import POINT_TYPES

# Usar nombres descriptivos en lugar de números
consumption_type = validate_point_type(POINT_TYPES["CONSUMPTION"])  # 2
generation_type = validate_point_type(POINT_TYPES["GENERATION"])    # 3
border_type = validate_point_type(POINT_TYPES["BORDER"])            # 1

Nota

Para la mayoría de usuarios domésticos y comerciales, el tipo 2 (CONSUMO) será el más relevante. Los tipos 3-5 son principalmente para instalaciones industriales y de servicios eléctricos.

Technical Details:
  • Rango válido: 1-5 según normativa del sistema eléctrico español

  • Default conservador: None → 1 (frontera, valor neutro)

  • Validación estricta: Solo enteros en el rango específico

  • Mapeo normativo: Basado en clasificación oficial CNE/CNMC

Referencias

  • CNE: Comisión Nacional de Energía - Clasificación de puntos de medida

  • CNMC: Comisión Nacional de los Mercados y la Competencia

  • BOE: Normativa sobre tipos de punto en el sistema eléctrico

Ver también

Added in version 1.0: Validación de tipos de punto

Distinto en la versión 2.0: Añadido soporte para tipo 5 y documentación extendida

Utilidades HTTP

Cliente HTTP robusto y reutilizable para el SDK de Datadis.

Este módulo proporciona una clase HTTPClient especializada para realizar peticiones HTTP a la API de Datadis con funcionalidades avanzadas como reintentos automáticos, manejo de timeouts, gestión de headers y procesamiento de respuestas.

La clase está optimizada específicamente para las características de la API de Datadis: - Timeouts largos debido a la lentitud característica del servicio - Reintentos automáticos con backoff exponencial para manejar inestabilidad - Soporte para autenticación Bearer Token - Manejo especial de diferentes tipos de contenido (JSON, form-data, texto plano) - Procesamiento de respuestas con normalización de texto para caracteres especiales

Características principales:
  • Gestión automática de reintentos: Backoff exponencial para timeouts y errores de red

  • Flexibilidad de contenido: Soporte para JSON y form-data según el endpoint

  • Manejo robusto de errores: Clasificación inteligente de errores HTTP

  • Integración con Pydantic: Preparado para validación de datos

  • Rate limiting integrado: Delays automáticos para evitar sobrecarga del servidor

Ejemplo

Uso básico del cliente HTTP:

from datadis_python.utils.http import HTTPClient

# Inicializar con configuración personalizada
client = HTTPClient(timeout=120, retries=5)

# Petición GET simple
response = client.make_request(
    method="GET",
    url="https://api.example.com/data",
    params={"param1": "value1"}
)

# Petición POST con autenticación
client.set_auth_header("bearer_token_here")
response = client.make_request(
    method="POST",
    url="https://api.example.com/auth",
    data={"username": "user", "password": "pass"},
    use_form_data=True
)

# Cerrar recursos
client.close()

Uso como context manager (recomendado):

with HTTPClient(timeout=90, retries=3) as client:
    client.set_auth_header("token")
    response = client.make_request("GET", "https://api.example.com/data")
    # El cliente se cierra automáticamente

Advertencia

Este cliente está específicamente optimizado para la API de Datadis. Para uso general, considere usar directamente la biblioteca requests o un cliente HTTP más genérico.

author:

TacoronteRiveroCristian

class datadis_python.utils.http.HTTPClient(timeout=60, retries=3)[fuente]

Bases: object

Cliente HTTP robusto especializado para la API de Datadis.

Esta clase proporciona una interfaz de alto nivel para realizar peticiones HTTP con características específicamente optimizadas para interactuar con la API de Datadis. Incluye manejo automático de reintentos, timeouts largos, gestión de autenticación y procesamiento especializado de respuestas.

Optimizaciones para Datadis:
  • Timeouts largos: Por defecto 60s, recomendado 90-120s para Datadis

  • Reintentos robustos: Backoff exponencial con hasta 5 reintentos

  • Rate limiting: Delays automáticos para evitar sobrecarga del servidor

  • Manejo de encoding: Desactiva compresión gzip para evitar problemas

  • Procesamiento de texto: Normalización automática de caracteres especiales

Estrategia de reintentos:
  • Errores de red y timeouts: Se reintentan automáticamente

  • Errores HTTP 4xx/5xx: Se propagan inmediatamente (no reintentos)

  • Backoff exponencial: 2s → 4s → 8s → 16s → 32s (máximo 10s para timeouts)

  • Error 401: Se propaga para permitir renovación de token

Ejemplo

Configuración típica para Datadis:

# Configuración robusta para API lenta de Datadis
client = HTTPClient(timeout=120, retries=5)

# Autenticación Bearer Token
client.set_auth_header("jwt_token_from_datadis")

# Petición con gestión automática de errores
response = client.make_request(
    method="GET",
    url="https://datadis.es/api-private/api/get-supplies",
    params={"distributor_code": "2"}
)

Diferentes tipos de contenido:

# Para autenticación (form-data)
auth_response = client.make_request(
    method="POST",
    url="https://datadis.es/nikola-auth/tokens/login",
    data={"username": "12345678A", "password": "password"},
    use_form_data=True
)

# Para endpoints de datos (JSON, por defecto)
data_response = client.make_request(
    method="GET",
    url="https://datadis.es/api-private/api/get-consumption-data",
    params={"cups": "ES001234567890123456AB"}
)
Parámetros:
  • timeout (int) – Timeout para peticiones HTTP en segundos. Recomendado: 90-120s para Datadis

  • retries (int) – Número máximo de reintentos automáticos para errores de red/timeouts

Nota

La API de Datadis puede ser muy lenta (60-90 segundos) al procesar consultas complejas que requieren agregar datos de múltiples distribuidoras eléctricas.

Ver también

  • SimpleDatadisClientV1 y SimpleDatadisClientV2 para uso de alto nivel

  • Documentación oficial de Datadis para límites de rate limiting

__init__(timeout=60, retries=3)[fuente]

Inicializa el cliente HTTP con configuración optimizada para Datadis.

Configura una sesión HTTP persistente con headers optimizados y timeouts apropiados para la API de Datadis. La configuración por defecto está pensada para un uso general, pero se recomienda ajustar los valores para Datadis.

Configuración recomendada para Datadis:
  • timeout: 90-120 segundos (la API puede ser muy lenta)

  • retries: 3-5 reintentos (para manejar inestabilidad ocasional)

Parámetros:
  • timeout (int) – Timeout para peticiones HTTP en segundos. Para Datadis se recomienda 90-120s debido a la lentitud del servicio

  • retries (int) – Número máximo de reintentos automáticos para errores de red. 3-5 reintentos recomendados para Datadis por su inestabilidad ocasional

Ejemplo

Configuraciones típicas:

# Configuración conservadora (rápida, pocos reintentos)
client = HTTPClient(timeout=60, retries=2)

# Configuración robusta para Datadis (recomendada)
client = HTTPClient(timeout=120, retries=5)

# Configuración para desarrollo/testing (muy paciente)
client = HTTPClient(timeout=180, retries=3)
make_request(method, url, data=None, params=None, headers=None, use_form_data=False)[fuente]

Realiza una petición HTTP robusta con reintentos automáticos y manejo de errores.

Este método es el núcleo del cliente HTTP y maneja toda la lógica de peticiones incluyendo reintentos con backoff exponencial, manejo de diferentes tipos de contenido, rate limiting automático y procesamiento especializado de respuestas.

Flujo de operación:
  1. Rate limiting: Delay automático de 0.1s (excepto para autenticación)

  2. Configuración de headers: Combina headers por defecto con personalizados

  3. Selección de formato: JSON o form-data según use_form_data

  4. Ejecución con reintentos: Hasta self.retries intentos con backoff exponencial

  5. Procesamiento de respuesta: Manejo especializado según tipo de contenido

Estrategia de reintentos:
  • Errores de red/timeout: Reintentos con backoff: 2s → 4s → 8s → 16s…

  • Errores HTTP: Propagación inmediata sin reintentos

  • Máximo wait: 10 segundos entre reintentos para evitar timeouts excesivos

Tipos de contenido soportados:
  • JSON (por defecto): Para la mayoría de endpoints de datos

  • Form-data: Para autenticación y algunos endpoints legacy

  • Detección automática: Basada en el parámetro use_form_data

Parámetros:
  • method (str) – Método HTTP a usar (GET, POST, PUT, DELETE, etc.)

  • url (str) – URL completa del endpoint a consultar

  • data (Optional[Dict[str, Any]]) – Datos a enviar en el cuerpo de la petición. Para GET se ignora, para POST se usa según use_form_data

  • params (Optional[Dict[str, Any]]) – Parámetros de query string a añadir a la URL

  • headers (Optional[Dict[str, str]]) – Headers HTTP adicionales a combinar con los por defecto. Los headers personalizados tienen prioridad sobre los por defecto

  • use_form_data (bool) – Si True, envía datos como application/x-www-form-urlencoded. Si False (por defecto), envía como application/json

Devuelve:

Respuesta procesada del servidor. El tipo depende del endpoint:

  • JWT tokens: str (para endpoints de autenticación)

  • Datos JSON: Dict[str, Any] o List[Any] (para endpoints de datos)

  • Respuestas de texto: str (para endpoints que no devuelven JSON)

Tipo del valor devuelto:

Union[Dict[str, Any], str, list]

Muestra:
  • DatadisError – Si se agotan todos los reintentos por errores de red/timeouts

  • AuthenticationError – Si hay errores de autenticación (401)

  • APIError – Si la API devuelve errores HTTP (400, 403, 404, 500, etc.)

Ejemplo

Diferentes tipos de peticiones:

# GET con parámetros de query
response = client.make_request(
    method="GET",
    url="https://datadis.es/api-private/api/get-supplies",
    params={"distributor_code": "2", "authorized_nif": "12345678A"}
)

# POST con autenticación (form-data)
token = client.make_request(
    method="POST",
    url="https://datadis.es/nikola-auth/tokens/login",
    data={"username": "12345678A", "password": "mi_password"},
    use_form_data=True
)

# GET con headers personalizados
response = client.make_request(
    method="GET",
    url="https://datadis.es/api-private/api/get-consumption-data",
    params={"cups": "ES001234567890123456AB"},
    headers={"Authorization": f"Bearer {token}"}
)

Nota

El rate limiting automático (delay de 0.1s) se aplica a todas las peticiones excepto las de autenticación para evitar sobrecargar los servidores de Datadis que pueden tener límites de rate restrictivos.

Ver también

  • _handle_response() para detalles del procesamiento de respuestas

  • La normalización de texto se realiza automáticamente en respuestas JSON

close()[fuente]

Cierra la sesión HTTP y libera recursos asociados.

Cierra explícitamente la sesión HTTP subyacente, liberando conexiones de red y otros recursos. Es una buena práctica llamar este método cuando se termina de usar el cliente, especialmente en aplicaciones de larga duración.

Este método es seguro de llamar múltiples veces y no genera errores si la sesión ya está cerrada.

Ejemplo

Uso manual de cierre:

client = HTTPClient(timeout=120, retries=5)
try:
    # Usar cliente para peticiones...
    response = client.make_request("GET", "https://example.com")
finally:
    # Asegurar limpieza de recursos
    client.close()

Uso como context manager (recomendado):

with HTTPClient(timeout=120, retries=5) as client:
    # Usar cliente...
    response = client.make_request("GET", "https://example.com")
    # client.close() se llama automáticamente

Nota

Cuando se usa el cliente como context manager (with statement), este método se llama automáticamente al salir del bloque, por lo que no es necesario llamarlo manualmente.

Tipo del valor devuelto:

None

set_auth_header(token)[fuente]

Establece el header de autorización Bearer Token para todas las peticiones futuras.

Configura el token de autenticación que se añadirá automáticamente a todas las peticiones HTTP subsecuentes. Este método es típicamente llamado después de una autenticación exitosa para configurar el cliente para peticiones autenticadas.

El token se almacena en los headers de la sesión persistent, por lo que se aplicará automáticamente a todas las peticiones realizadas con este cliente hasta que se reemplace con un nuevo token o se elimine.

Parámetros:

token (str) – Token JWT obtenido del endpoint de autenticación de Datadis. Debe ser un token válido sin el prefijo «Bearer « (se añade automáticamente)

Tipo del valor devuelto:

None

Ejemplo

Configurar autenticación después del login:

client = HTTPClient(timeout=120, retries=5)

# Autenticar y obtener token
token = client.make_request(
    method="POST",
    url="https://datadis.es/nikola-auth/tokens/login",
    data={"username": "12345678A", "password": "mi_password"},
    use_form_data=True
)

# Configurar token para peticiones futuras
client.set_auth_header(token)

# Ahora todas las peticiones incluirán el header Authorization
response = client.make_request(
    method="GET",
    url="https://datadis.es/api-private/api/get-supplies"
)

Nota

El token se prefija automáticamente con «Bearer « según el estándar RFC 6750. No incluya este prefijo en el parámetro token.

Ver también

  • remove_auth_header() para eliminar la autenticación

  • RFC 6750 para especificación completa de Bearer Token

remove_auth_header()[fuente]

Elimina el header de autorización de todas las peticiones futuras.

Remueve el token de autenticación de los headers de la sesión, haciendo que las peticiones subsecuentes se realicen sin autenticación. Esto es útil para limpiar credenciales cuando se cambia de usuario o cuando se quiere realizar peticiones no autenticadas.

Esta operación es segura y no genera errores si no existe un header de autorización configurado.

Ejemplo

Limpiar autenticación para cambio de usuario:

# Usuario 1 autenticado
client.set_auth_header(token_user1)
data_user1 = client.make_request("GET", "/get-supplies")

# Cambiar a usuario 2
client.remove_auth_header()  # Limpiar credenciales anteriores
token_user2 = client.make_request(
    "POST", "/nikola-auth/tokens/login",
    data={"username": "87654321B", "password": "other_password"},
    use_form_data=True
)
client.set_auth_header(token_user2)
data_user2 = client.make_request("GET", "/get-supplies")

Peticiones sin autenticación:

client.remove_auth_header()
# Ahora las peticiones no incluirán Authorization header
public_data = client.make_request("GET", "/public-endpoint")

Nota

Después de llamar este método, las peticiones a endpoints que requieren autenticación fallarán con error 401 hasta que se establezca un nuevo token con set_auth_header().

Ver también

Tipo del valor devuelto:

None

__enter__()[fuente]

Método de entrada para context manager.

Permite usar el HTTPClient con la declaración with de Python para gestión automática de recursos. Al entrar en el bloque with, retorna la instancia del cliente lista para usar.

Devuelve:

La instancia del cliente HTTP configurada

Tipo del valor devuelto:

HTTPClient

Ejemplo

Uso como context manager:

with HTTPClient(timeout=120, retries=5) as client:
    # Configurar autenticación
    token = client.make_request(
        "POST", "/auth",
        data={"user": "12345678A", "pass": "password"},
        use_form_data=True
    )
    client.set_auth_header(token)

    # Realizar peticiones
    data = client.make_request("GET", "/api/data")

# client.close() se llama automáticamente aquí

Nota

El uso como context manager es la forma recomendada de usar HTTPClient ya que garantiza la liberación adecuada de recursos de red.

__exit__(exc_type, exc_val, exc_tb)[fuente]

Método de salida para context manager.

Se llama automáticamente al salir del bloque with, garantizando que los recursos del cliente HTTP se liberen adecuadamente, independientemente de si el bloque se completó exitosamente o se produjo una excepción.

Parámetros:
  • exc_type – Tipo de excepción si ocurrió una excepción, None en caso contrario

  • exc_val – Valor de la excepción si ocurrió una excepción, None en caso contrario

  • exc_tb – Traceback de la excepción si ocurrió una excepción, None en caso contrario

Nota

Este método siempre retorna None, lo que significa que no suprime ninguna excepción que pueda haber ocurrido dentro del bloque with. Las excepciones se propagan normalmente después de la limpieza de recursos.

Utilidades de Texto

Utilidades para normalización y procesamiento de texto de respuestas de Datadis.

Este módulo proporciona funciones especializadas para procesar y normalizar texto recibido de la API de Datadis, solucionando problemas comunes de encoding y caracteres especiales que pueden aparecer en las respuestas del servicio.

La API de Datadis frecuentemente devuelve texto con problemas de encoding, especialmente con caracteres españoles como tildes (á, é, í, ó, ú), eñes (ñ), cedillas (ç) y otros caracteres especiales. Este módulo proporciona herramientas robustas para detectar y corregir estos problemas automáticamente.

Problemas comunes solucionados:
  • Doble codificación UTF-8: Secuencias como «Ãx93» en lugar de «Ó»

  • Caracteres especiales mal codificados: «EDISTRIBUCIÃx93N» → «EDISTRIBUCION»

  • Inconsistencias de encoding: Mezcla de encodings en una misma respuesta

  • Caracteres no ASCII: Normalización a ASCII para compatibilidad

Funciones principales:

Ejemplo

Uso típico para procesar respuestas de Datadis:

from datadis_python.utils.text_utils import normalize_api_response

# Respuesta raw de Datadis con problemas de encoding
raw_response = {
    "distributor": "EDISTRIBUCIÃ\x93N",
    "address": "CALLE JOSÃπ MARTÃ\xadNEZ"
}

# Normalizar respuesta completa
clean_response = normalize_api_response(raw_response)
# Resultado: {"distributor": "EDISTRIBUCION", "address": "CALLE JOSE MARTINEZ"}

Normalización de texto individual:

from datadis_python.utils.text_utils import normalize_text

# Texto con problemas típicos de Datadis
problematic_text = "Málaga"
clean_text = normalize_text(problematic_text)
# Resultado: "Malaga"

Nota

Todas las funciones de este módulo son seguras de usar con datos None o de tipos incorrectos - retornan el valor original sin modificar si no pueden procesarlo.

Advertencia

La normalización elimina permanentemente caracteres especiales y acentos. Si necesita preservar el texto original, haga una copia antes de aplicar estas funciones.

author:

TacoronteRiveroCristian

datadis_python.utils.text_utils.normalize_text(text)[fuente]

Normaliza texto removiendo tildes, caracteres especiales y corrigiendo problemas de encoding.

Esta función es el núcleo del sistema de normalización de texto del SDK. Aplica múltiples estrategias para corregir problemas comunes de encoding que aparecen frecuentemente en las respuestas de la API de Datadis, especialmente con caracteres españoles.

Proceso de normalización:
  1. Detección de doble codificación: Identifica secuencias como «Ãx93» (debe ser «Ó»)

  2. Corrección de encoding: Recodifica usando latin-1 → UTF-8 cuando es necesario

  3. Normalización Unicode: Aplica descomposición NFD para separar caracteres base de acentos

  4. Eliminación de acentos: Convierte caracteres acentuados a su equivalente ASCII

  5. Reemplazos específicos: Maneja caracteres especiales españoles (ñ, ç, etc.)

Casos de uso típicos:
  • Nombres de distribuidores: «EDISTRIBUCIÃx93N» → «EDISTRIBUCION»

  • Direcciones: «CALLE JOSÃπ MARTÃxadNEZ» → «CALLE JOSE MARTINEZ»

  • Nombres de municipios: «Málaga», «Cádiz» → «Malaga», «Cadiz»

  • Códigos postales: Normalmente no necesitan normalización pero se procesan igual

Parámetros:

text (str) – Texto a normalizar. Puede contener caracteres especiales, acentos, o problemas de doble codificación típicos de Datadis

Devuelve:

Texto normalizado sin tildes, acentos ni caracteres especiales. Convertido completamente a caracteres ASCII seguros

Tipo del valor devuelto:

str

Ejemplo

Problemas típicos de encoding de Datadis:

# Doble codificación UTF-8
normalize_text("EDISTRIBUCIÃ\x93N")     # → "EDISTRIBUCION"
normalize_text("Málaga")               # → "Malaga"

# Caracteres españoles normales
normalize_text("Málaga")                # → "Malaga"
normalize_text("Coruña")                # → "Coruna"
normalize_text("Cáceres")               # → "Caceres"

# Caracteres especiales
normalize_text("Peñíscola")             # → "Peniscola"
normalize_text("François")              # → "Francois"

Casos extremos manejados:

# Texto ya normalizado - sin cambios
normalize_text("MADRID")                # → "MADRID"

# Mezcla de problemas
normalize_text("Cádiz - AndalucÃ\xada") # → "Cadiz - Andalucia"

Nota

La función es segura con datos de entrada inválidos - si recibe algo que no es string, retorna el valor original sin modificar. Esto evita errores en cadenas de procesamiento de datos.

Advertencia

La normalización es irreversible. Si necesita preservar el texto original con acentos, haga una copia antes de llamar esta función.

Technical details:
  • Usa unicodedata.normalize('NFD', text) para descomposición Unicode

  • Aplica encode('ascii', 'ignore') para eliminar caracteres no-ASCII

  • Maneja específicamente problemas de doble codificación latin-1/UTF-8

  • Incluye tabla de reemplazos para caracteres que unicodedata no maneja

Ver también

datadis_python.utils.text_utils.normalize_dict_strings(data)[fuente]

Normaliza recursivamente todas las cadenas de texto en un diccionario.

Esta función recorre un diccionario de forma recursiva aplicando normalización de texto a todas las cadenas encontradas, manteniendo la estructura original del diccionario pero limpiando el contenido textual.

Procesamiento recursivo:

Esta función es especialmente útil para procesar respuestas JSON estructuradas de la API de Datadis donde los problemas de encoding pueden aparecer en cualquier campo de texto dentro de estructuras complejas.

Parámetros:

data (Dict[str, Any]) – Diccionario con datos a normalizar. Puede contener estructuras anidadas complejas con strings que necesiten limpieza de caracteres especiales

Devuelve:

Nuevo diccionario con la misma estructura pero con todos los strings normalizados. Los valores no-string se mantienen exactamente igual

Tipo del valor devuelto:

Dict[str, Any]

Ejemplo

Normalizar respuesta estructurada de Datadis:

raw_supply_data = {
    "cups": "ES001234567890123456AB",
    "address": "CALLE JOSÃπ MARTÃ\xadNEZ",
    "distributor": "EDISTRIBUCIÃ\x93N",
    "postalCode": "28001",
    "province": "Mádrid",
    "details": {
        "city": "Málaga",
        "municipality": "AndalucÃ\xada"
    },
    "contracts": [
        {"startDate": "2024/01/01", "type": "Normal"}
    ],
    "active": True,
    "pointType": 2
}

normalized_data = normalize_dict_strings(raw_supply_data)
# Resultado:
# {
#     "cups": "ES001234567890123456AB",          # Sin cambio
#     "address": "CALLE JOSE MARTINEZ",          # Normalizado
#     "distributor": "EDISTRIBUCION",            # Normalizado
#     "postalCode": "28001",                     # Sin cambio
#     "province": "Madrid",                      # Normalizado
#     "details": {
#         "city": "Malaga",                      # Normalizado (recursivo)
#         "municipality": "Andalucia"            # Normalizado (recursivo)
#     },
#     "contracts": [
#         {"startDate": "2024/01/01", "type": "Normal"}  # Procesado recursivamente
#     ],
#     "active": True,                            # Sin cambio (boolean)
#     "pointType": 2                             # Sin cambio (int)
# }

Casos extremos manejados:

# Diccionario vacío
normalize_dict_strings({})  # → {}

# Diccionario con valores None
normalize_dict_strings({"key": None})  # → {"key": None}

# Anidación profunda
deep_dict = {"level1": {"level2": {"text": "Málaga"}}}
normalize_dict_strings(deep_dict)  # → {"level1": {"level2": {"text": "Malaga"}}}

Nota

La función es segura con datos de entrada inválidos - si recibe algo que no es diccionario, retorna el valor original sin modificar. Esto permite su uso seguro en cadenas de procesamiento donde el tipo de dato puede ser incierto.

Performance:

La función crea un nuevo diccionario en lugar de modificar el original, lo que la hace segura para uso concurrente pero puede consumir más memoria con estructuras muy grandes.

Ver también

datadis_python.utils.text_utils.normalize_list_strings(data)[fuente]

Normaliza recursivamente todas las cadenas de texto en una lista.

Esta función procesa listas de forma recursiva aplicando normalización de texto a todos los elementos string encontrados, mientras mantiene la estructura y orden original de la lista. Es especialmente útil para procesar arrays de datos de Datadis.

Procesamiento recursivo por tipo:
Casos de uso típicos en Datadis:
  • Arrays de suministros: Lista de objetos SupplyData con addresses problemáticas

  • Arrays de consumo: Lista de ConsumptionData con distributors mal codificados

  • Arrays mixtos: Listas que combinan strings, números y objetos

Parámetros:

data (List[Any]) – Lista con datos a normalizar. Puede contener elementos de cualquier tipo, incluidas estructuras anidadas complejas

Devuelve:

Nueva lista con la misma estructura y orden, pero con todos los strings normalizados. Los elementos no-string se mantienen exactamente igual

Tipo del valor devuelto:

List[Any]

Ejemplo

Normalizar array de respuesta de Datadis:

raw_supplies_list = [
    "EDISTRIBUCIÃ\x93N",  # String simple problemático
    {
        "distributor": "Málaga Eléctrica",
        "address": "CALLE JOSÃπ MARTÃ\xadNEZ"
    },
    ["Cádiz", "Sevillá"],  # Lista anidada
    42,  # Número
    None,  # Valor nulo
    True  # Booleano
]

normalized_list = normalize_list_strings(raw_supplies_list)
# Resultado:
# [
#     "EDISTRIBUCION",                    # String normalizado
#     {
#         "distributor": "Malaga Electrica",  # Dict normalizado recursivamente
#         "address": "CALLE JOSE MARTINEZ"
#     },
#     ["Cadiz", "Sevilla"],               # Lista normalizada recursivamente
#     42,                                 # Sin cambio (int)
#     None,                               # Sin cambio (None)
#     True                                # Sin cambio (bool)
# ]

Array de objetos de consumo:

consumption_data = [
    {
        "date": "2024/01/01",
        "consumptionKWh": 5.2,
        "distributor": "EDISTRIBUCIÃ\x93N"
    },
    {
        "date": "2024/01/02",
        "consumptionKWh": 4.8,
        "distributor": "Málaga Eléctrica"
    }
]

normalized_consumption = normalize_list_strings(consumption_data)
# Solo los campos "distributor" se normalizan, fechas y números quedan igual

Casos extremos:

# Lista vacía
normalize_list_strings([])  # → []

# Lista con solo valores no-string
normalize_list_strings([1, 2, 3, True, None])  # → [1, 2, 3, True, None]

# Anidación profunda
deep_list = [[[["Málaga"]]]]
normalize_list_strings(deep_list)  # → [[[["Malaga"]]]]

Nota

La función es segura con datos de entrada inválidos - si recibe algo que no es lista, retorna el valor original sin modificar. Esto permite su uso seguro en cadenas de procesamiento de datos heterogéneos.

Performance:

Crea una nueva lista en lugar de modificar la original, garantizando inmutabilidad pero puede consumir más memoria con listas muy grandes.

Ver también

datadis_python.utils.text_utils.normalize_api_response(response)[fuente]

Función principal para normalizar respuestas completas de la API de Datadis.

Esta es la función de entrada principal del sistema de normalización del SDK. Detecta automáticamente el tipo de respuesta (diccionario o lista) y aplica la estrategia de normalización correspondiente para limpiar todos los strings de problemas de encoding y caracteres especiales.

Función de router inteligente:

Esta función es llamada automáticamente por el HTTPClient del SDK, por lo que los usuarios normalmente no necesitan llamarla manualmente. Sin embargo, puede ser útil para procesar datos cacheados o respuestas guardadas localmente.

Casos de uso típicos:
  • Auto-procesamiento: Llamada automática por HTTPClient en todas las respuestas JSON

  • Procesamiento manual: Para limpiar datos guardados localmente o cacheados

  • Testing: Para normalizar respuestas mock en tests unitarios

  • Debugging: Para limpiar respuestas antes de análisis manual

Parámetros:

response (Union[Dict[str, Any], List[Any]]) – Respuesta completa de la API de Datadis en formato JSON deserializado. Puede ser un diccionario (respuesta de objeto) o lista (respuesta de array)

Devuelve:

Respuesta normalizada con la misma estructura pero con todos los strings limpios de problemas de encoding y caracteres especiales

Tipo del valor devuelto:

Union[Dict[str, Any], List[Any]]

Ejemplo

Respuestas típicas de diferentes endpoints:

# Respuesta de get_supplies (lista de objetos)
supplies_response = [
    {"cups": "ES001...", "distributor": "EDISTRIBUCIÃ\x93N"},
    {"cups": "ES002...", "distributor": "Málaga Eléctrica"}
]
clean_supplies = normalize_api_response(supplies_response)
# Resultado: [{"cups": "ES001...", "distributor": "EDISTRIBUCION"}, ...]

# Respuesta de get_consumption (objeto con arrays)
consumption_response = {
    "consumption": [
        {"date": "2024/01/01", "distributor": "EDISTRIBUCIÃ\x93N"}
    ],
    "distributor_error": []
}
clean_consumption = normalize_api_response(consumption_response)
# Resultado: {"consumption": [{"date": "2024/01/01", "distributor": "EDISTRIBUCION"}], ...}

Procesamiento manual de datos guardados:

# Datos cacheados que pueden tener problemas de encoding
cached_data = load_from_cache("datadis_supplies.json")
clean_data = normalize_api_response(cached_data)
# Ahora clean_data está libre de problemas de encoding

Uso en testing:

# Mock response con problemas simulados de Datadis
mock_response = {"distributor": "EDISTRIBUCIÃ\x93N"}
normalized_mock = normalize_api_response(mock_response)
# Para tests con datos normalizados

Nota

Esta función es completamente segura con cualquier tipo de entrada. Si recibe datos que no puede procesar, los retorna sin modificar, garantizando que nunca cause errores en el pipeline de datos.

Performance:

La función crea nuevas estructuras de datos en lugar de modificar las originales, lo que la hace segura para uso concurrente pero puede consumir más memoria con respuestas muy grandes (miles de registros).

Integration:

Esta función está integrada automáticamente en la cadena de procesamiento de respuestas del HTTPClient, por lo que todos los datos que llegan a los usuarios finales ya están normalizados.

Ver también

Added in version 1.0: Normalización automática integrada en todo el SDK

Distinto en la versión 2.0: Mejorada detección de problemas de doble codificación UTF-8

Constantes

Constantes y configuraciones para el SDK de Datadis.

Este módulo centraliza todas las constantes utilizadas para interactuar con la API de Datadis, incluyendo URLs base, endpoints, códigos de distribuidores y configuraciones por defecto. Proporciona soporte para ambas versiones de la API (V1 y V2) manteniendo compatibilidad hacia atrás.

La API de Datadis es la plataforma oficial del gobierno español para acceder a datos de consumo eléctrico de las distribuidoras eléctricas. Este módulo abstrae toda la configuración necesaria para facilitar el desarrollo con el SDK.

Organización de constantes:
  • URLs base: URLs principales de autenticación y API

  • Endpoints por versión: V1 (estables) y V2 (modernos con mejoras)

  • Códigos de distribuidores: Mapeo completo de todas las distribuidoras españolas

  • Configuraciones por defecto: Timeouts, reintentos y otros parámetros optimizados

  • Tipos de medida y punto: Constantes para clasificar datos eléctricos

Ejemplo

Uso básico de constantes:

from datadis_python.utils.constants import (
    DATADIS_API_BASE,
    API_V2_ENDPOINTS,
    DISTRIBUTOR_CODES,
    DEFAULT_TIMEOUT
)

# Construir URL de endpoint V2
supplies_url = f"{DATADIS_API_BASE}{API_V2_ENDPOINTS['supplies']}"

# Usar código de distribuidor por nombre
endesa_code = DISTRIBUTOR_CODES["E_DISTRIBUCION"]  # "2"

# Configurar timeout por defecto
requests.get(url, timeout=DEFAULT_TIMEOUT)

Migración de V1 a V2:

# V1 (endpoints legacy)
v1_endpoint = API_V1_ENDPOINTS["consumption"]  # "/get-consumption-data"

# V2 (endpoints modernos)
v2_endpoint = API_V2_ENDPOINTS["consumption"]  # "/get-consumption-data-v2"

Nota

Los endpoints V2 incluyen funcionalidades adicionales como manejo de errores por distribuidor y estructuras de respuesta mejoradas. Se recomienda usar V2 para nuevas implementaciones.

Advertencia

La constante API_ENDPOINTS está marcada como DEPRECATED y se mantiene solo para compatibilidad hacia atrás. Use API_V1_ENDPOINTS o API_V2_ENDPOINTS según la versión de API que necesite.

author:

TacoronteRiveroCristian

datadis_python.utils.constants.DATADIS_BASE_URL = 'https://datadis.es'

URL principal del portal web de Datadis

datadis_python.utils.constants.DATADIS_AUTH_URL = 'https://datadis.es/nikola-auth/tokens/login'

URL específica para autenticación de usuarios

datadis_python.utils.constants.DATADIS_API_BASE = 'https://datadis.es/api-private/api'

URL base para todas las peticiones a la API privada de Datadis

datadis_python.utils.constants.AUTH_ENDPOINTS = {'login': '/nikola-auth/tokens/login'}

Endpoints para operaciones de autenticación y gestión de tokens. Estos endpoints son compartidos por todas las versiones de la API.

datadis_python.utils.constants.API_V1_ENDPOINTS = {'consumption': '/get-consumption-data', 'contracts': '/get-contract-detail', 'distributors': '/get-distributors-with-supplies', 'max_power': '/get-max-power', 'supplies': '/get-supplies'}

Endpoints para la API V1 de Datadis.

La versión 1 de la API proporciona respuestas directas (listas o diccionarios simples) sin estructuras de error por distribuidor. Es la versión original y más estable de la API, pero carece de algunas funcionalidades modernas.

Características de V1:
  • Respuestas simples: List[SupplyData], List[ConsumptionData], etc.

  • Sin manejo de errores por distribuidor

  • Funcionalidad básica completa

  • Mayor compatibilidad con sistemas legacy

Ejemplo

Construir URL de endpoint V1:

from datadis_python.utils.constants import DATADIS_API_BASE, API_V1_ENDPOINTS

supplies_url = f"{DATADIS_API_BASE}{API_V1_ENDPOINTS['supplies']}"
# Resultado: "https://datadis.es/api-private/api/get-supplies"
datadis_python.utils.constants.API_V2_ENDPOINTS = {'consumption': '/get-consumption-data-v2', 'contracts': '/get-contract-detail-v2', 'distributors': '/get-distributors-with-supplies-v2', 'max_power': '/get-max-power-v2', 'reactive_data': '/get-reactive-data-v2', 'supplies': '/get-supplies-v2'}

Endpoints para la API V2 de Datadis.

La versión 2 de la API introduce mejoras significativas incluyendo manejo robusto de errores por distribuidor, estructuras de respuesta tipadas y funcionalidades adicionales como datos de energía reactiva.

Mejoras de V2 sobre V1:
  • Manejo de errores por distribuidor: Información detallada de fallos

  • Respuestas estructuradas: SuppliesResponse, ConsumptionResponse, etc.

  • Funcionalidad extendida: Acceso a datos de energía reactiva

  • Mejor compatibilidad: Preparada para futuras funcionalidades

Nota

Se recomienda usar la API V2 para nuevas implementaciones. Los endpoints V2 mantienen compatibilidad de interfaz con V1 pero devuelven estructuras de datos más robustas que incluyen información de errores detallada.

Ejemplo

Comparación de endpoints V1 vs V2:

# V1 - Respuesta simple
v1_url = f"{DATADIS_API_BASE}{API_V1_ENDPOINTS['supplies']}"
# GET /get-supplies → List[SupplyData]

# V2 - Respuesta estructurada con manejo de errores
v2_url = f"{DATADIS_API_BASE}{API_V2_ENDPOINTS['supplies']}"
# GET /get-supplies-v2 → SuppliesResponse (includes distributor_error)
datadis_python.utils.constants.AUTHORIZATION_ENDPOINTS = {'cancel_authorization': '/cancel-authorization', 'list_authorization': '/list-authorization', 'new_authorization': '/new-authorization'}

Endpoints para gestión de autorizaciones entre usuarios.

Estos endpoints permiten gestionar autorizaciones para que un usuario pueda consultar los datos de consumo de otro usuario (por ejemplo, un gestor energético consultando datos de sus clientes con autorización previa).

Flujo de autorización:
  1. new_authorization: Crear nueva autorización

  2. list_authorization: Listar autorizaciones activas

  3. cancel_authorization: Cancelar autorización existente

Nota

Esta funcionalidad requiere configuración especial en la cuenta de Datadis y está orientada a usuarios avanzados como gestores energéticos o empresas de servicios energéticos.

datadis_python.utils.constants.DEFAULT_TIMEOUT = 90

Timeout por defecto para peticiones HTTP en segundos.

El valor de 90 segundos está optimizado para la API de Datadis, que puede ser notablemente lenta debido a la necesidad de consultar múltiples sistemas de distribuidoras eléctricas en tiempo real.

Nota

La API de Datadis puede tardar hasta 60-80 segundos en responder consultas complejas, especialmente cuando debe agregar datos de múltiples distribuidores o procesar rangos de fechas extensos.

datadis_python.utils.constants.MAX_RETRIES = 5

Número máximo de reintentos automáticos para peticiones fallidas.

Se incrementa a 5 reintentos debido a la naturaleza inestable de algunos endpoints de Datadis y la dependencia de sistemas externos de las distribuidoras eléctricas. Los reintentos usan backoff exponencial para evitar sobrecargar el servidor.

datadis_python.utils.constants.TOKEN_EXPIRY_HOURS = 24

Duración estimada de validez de los tokens de autenticación en horas.

Los tokens de Datadis tienen una validez limitada. Aunque la duración exacta no está documentada oficialmente, la experiencia práctica sugiere que expiran en aproximadamente 24 horas.

Nota

El SDK maneja automáticamente la renovación de tokens cuando detecta errores 401 (Unauthorized), por lo que este valor es principalmente informativo.

datadis_python.utils.constants.MEASUREMENT_TYPES = {'CONSUMPTION': 0, 'GENERATION': 1}

Constantes para los tipos de medida eléctrica soportados por Datadis.

La API de Datadis distingue entre consumo (energía tomada de la red) y generación (energía inyectada a la red, típicamente de instalaciones fotovoltaicas u otras fuentes renovables).

Valores válidos:
  • CONSUMPTION (0): Energía consumida desde la red eléctrica

  • GENERATION (1): Energía generada e inyectada a la red

Ejemplo

Usar constantes de tipo de medida:

from datadis_python.utils.constants import MEASUREMENT_TYPES

# Obtener datos de consumo
consumption_data = client.get_consumption(
    cups="ES001234567890123456AB",
    distributor_code="2",
    date_from="2024/01",
    date_to="2024/12",
    measurement_type=MEASUREMENT_TYPES["CONSUMPTION"]  # 0
)

# Obtener datos de generación (ej: paneles solares)
generation_data = client.get_consumption(
    cups="ES001234567890123456AB",
    distributor_code="2",
    date_from="2024/01",
    date_to="2024/12",
    measurement_type=MEASUREMENT_TYPES["GENERATION"]  # 1
)
datadis_python.utils.constants.POINT_TYPES = {'AUXILIARY_SERVICES': 4, 'AUXILIARY_SERVICES_ALT': 5, 'BORDER': 1, 'CONSUMPTION': 2, 'GENERATION': 3}

Constantes para los tipos de punto de medida eléctrica según normativa española.

Los tipos de punto definen la naturaleza y propósito del punto de medida eléctrica según la normativa del sistema eléctrico español. Cada tipo tiene características específicas y se usa en diferentes contextos de la red eléctrica.

Tipos de punto válidos:
  • BORDER (1): Punto de frontera - Intercambio entre sistemas

  • CONSUMPTION (2): Punto de consumo - Usuarios finales domésticos/comerciales

  • GENERATION (3): Punto de generación - Plantas de generación eléctrica

  • AUXILIARY_SERVICES (4): Servicios auxiliares - Equipos de soporte al sistema

  • AUXILIARY_SERVICES_ALT (5): Servicios auxiliares alternativos

Nota

El tipo de punto más común para usuarios domésticos y comerciales es CONSUMPTION (2). Los tipos de generación se usan principalmente para instalaciones con autoconsumo que inyectan energía a la red.

Ejemplo

Filtrar por tipo de punto específico:

from datadis_python.utils.constants import POINT_TYPES

# Datos de consumo doméstico típico
consumption_data = client.get_consumption(
    cups="ES001234567890123456AB",
    distributor_code="2",
    date_from="2024/01",
    date_to="2024/12",
    point_type=POINT_TYPES["CONSUMPTION"]  # 2
)

# Datos de instalación de generación
generation_data = client.get_consumption(
    cups="ES001234567890123456AB",
    distributor_code="2",
    date_from="2024/01",
    date_to="2024/12",
    point_type=POINT_TYPES["GENERATION"]  # 3
)
datadis_python.utils.constants.DISTRIBUTOR_CODES = {'ASEME': '4', 'CIDE': '7', 'EOSA': '6', 'E_DISTRIBUCION': '2', 'E_REDES': '3', 'IDE': '8', 'UFD': '5', 'VIESGO': '1'}

Mapeo completo de todas las distribuidoras eléctricas españolas con sus códigos oficiales.

Este diccionario proporciona el mapeo entre nombres de distribuidoras y sus códigos numéricos oficiales utilizados por la API de Datadis. Los códigos son asignados por el sistema eléctrico español y son únicos para cada distribuidora.

Distribuidoras por código:
  • «1» - VIESGO: Cantabria, Asturias (norte de España)

  • «2» - E-DISTRIBUCIÓN: Filial de Endesa, cobertura nacional amplia

  • «3» - E-REDES: Galicia y zonas de Castilla y León

  • «4» - ASEME: Ciudad autónoma de Melilla

  • «5» - UFD (Naturgy): Cobertura nacional, especialmente este y sur

  • «6» - EOSA: Aragón y zonas del noreste

  • «7» - CIDE: Ciudad autónoma de Ceuta

  • «8» - IDE: Islas Baleares

Coverage geográfico:
  • Nacional: E-distribución (Endesa), UFD (Naturgy)

  • Regional: Viesgo (norte), E-redes (noroeste), EOSA (noreste)

  • Insular/Local: IDE (Baleares), ASEME (Melilla), CIDE (Ceuta)

Ejemplo

Usar nombres de distribuidoras en lugar de códigos:

from datadis_python.utils.constants import DISTRIBUTOR_CODES

# Buscar suministros de Endesa por nombre
endesa_code = DISTRIBUTOR_CODES["E_DISTRIBUCION"]  # "2"
supplies = client.get_supplies(distributor_code=endesa_code)

# Buscar suministros de Naturgy por nombre
naturgy_code = DISTRIBUTOR_CODES["UFD"]  # "5"
supplies = client.get_supplies(distributor_code=naturgy_code)

# Iterar sobre todas las distribuidoras
for name, code in DISTRIBUTOR_CODES.items():
    print(f"Distribuidor {name}: código {code}")

Nota

Los códigos de distribuidor son strings (no enteros) para mantener consistencia con la API de Datadis. El SDK acepta tanto strings como enteros y convierte automáticamente al tipo correcto.

datadis_python.utils.constants.API_ENDPOINTS = {'cancel_authorization': '/cancel-authorization', 'consumption': '/get-consumption-data', 'consumption_v2': '/get-consumption-data-v2', 'contracts': '/get-contract-detail', 'contracts_v2': '/get-contract-detail-v2', 'distributors': '/get-distributors-with-supplies', 'distributors_v2': '/get-distributors-with-supplies-v2', 'list_authorization': '/list-authorization', 'login': '/nikola-auth/tokens/login', 'max_power': '/get-max-power', 'max_power_v2': '/get-max-power-v2', 'new_authorization': '/new-authorization', 'reactive_data_v2': '/get-reactive-data-v2', 'supplies': '/get-supplies', 'supplies_v2': '/get-supplies-v2'}

Diccionario unificado de endpoints para compatibilidad hacia atrás.

Obsoleto desde la versión 2.0: Use API_V1_ENDPOINTS o API_V2_ENDPOINTS según la versión de API que necesite. Este diccionario se mantiene solo para compatibilidad con código legacy y será eliminado en futuras versiones.

Este diccionario combina todos los endpoints disponibles en un solo lugar, pero no proporciona la claridad de separación entre versiones que ofrecen las constantes específicas por versión.

Problemas con este enfoque:
  • Ambigüedad de versión: No queda claro qué versión de API se está usando

  • Mantenimiento complejo: Requiere sincronización manual entre versiones

  • Falta de tipado: No aprovecha las mejoras de tipos de V2

Migration path:

Reemplazar uso de API_ENDPOINTS:

# ❌ Deprecated - No usar
old_endpoint = API_ENDPOINTS["supplies"]

# ✅ Recomendado - Usar versión específica
v1_endpoint = API_V1_ENDPOINTS["supplies"]  # Para compatibilidad
v2_endpoint = API_V2_ENDPOINTS["supplies"]  # Para nuevas funcionalidades

Advertencia

Esta constante será eliminada en la versión 3.0 del SDK. Migre su código para usar las constantes específicas por versión.

Cliente Base (Avanzado)

class datadis_python.client.base.BaseDatadisClient(username, password, timeout=90, retries=5)[fuente]

Bases: ABC

Cliente base abstracto con funcionalidad común para todas las versiones.

Parámetros:
  • username (str) – NIF del usuario registrado en Datadis.

  • password (str) – Contraseña de acceso a Datadis.

  • timeout (int) – Timeout para requests en segundos.

  • retries (int) – Número de reintentos automáticos.

__init__(username, password, timeout=90, retries=5)[fuente]

Inicializa el cliente base.

Parámetros:
  • username (str) – NIF del usuario registrado en Datadis.

  • password (str) – Contraseña de acceso a Datadis.

  • timeout (int) – Timeout para requests en segundos.

  • retries (int) – Número de reintentos automáticos.

authenticate()[fuente]

Autentica con la API y obtiene token de acceso.

Muestra:
Tipo del valor devuelto:

None

ensure_authenticated()[fuente]

Asegura que el cliente está autenticado con un token válido.

Renueva automáticamente el token si ha expirado o está próximo a expirar.

Tipo del valor devuelto:

None

make_authenticated_request(method, endpoint, data=None, params=None)[fuente]

Realiza una petición autenticada a la API.

Parámetros:
  • method (str) – Método HTTP (GET, POST)

  • endpoint (str) – Endpoint de la API

  • data (Optional[Dict[str, Any]]) – Datos para el body de la petición

  • params (Optional[Dict[str, Any]]) – Parámetros de query string

Devuelve:

Respuesta de la API

Tipo del valor devuelto:

Union[Dict[str, Any], str, list]

Muestra:
close()[fuente]

Cierra la sesión y libera recursos.

Limpia el token de autenticación y cierra las conexiones HTTP.

Tipo del valor devuelto:

None

__enter__()[fuente]

Entrada del context manager.

Devuelve:

Instancia del cliente

Tipo del valor devuelto:

BaseDatadisClient

__exit__(exc_type, exc_val, exc_tb)[fuente]

Salida del context manager.

Parámetros:
  • exc_type (Optional[type]) – Tipo de excepción

  • exc_val (Optional[BaseException]) – Valor de la excepción

  • exc_tb (Optional[TracebackType]) – Traceback de la excepción

abstractmethod get_supplies(authorized_nif=None, distributor_code=None)[fuente]

Obtiene puntos de suministro.

Parámetros:
  • authorized_nif (Optional[str]) – NIF autorizado para la consulta

  • distributor_code (Optional[str]) – Código de la distribuidora

Devuelve:

Lista de puntos de suministro

Tipo del valor devuelto:

Any

abstractmethod get_distributors(authorized_nif=None)[fuente]

Obtiene distribuidores.

Parámetros:

authorized_nif (Optional[str]) – NIF autorizado para la consulta

Devuelve:

Lista de distribuidores

Tipo del valor devuelto:

Any

abstractmethod get_contract_detail(cups, distributor_code, authorized_nif=None)[fuente]

Obtiene detalle del contrato.

Parámetros:
  • cups (str) – Código CUPS del punto de suministro

  • distributor_code (str) – Código de la distribuidora

  • authorized_nif (Optional[str]) – NIF autorizado para la consulta

Devuelve:

Detalle del contrato

Tipo del valor devuelto:

Any

abstractmethod get_consumption(cups, distributor_code, date_from, date_to, measurement_type=0, point_type=None, authorized_nif=None)[fuente]

Obtiene datos de consumo.

Parámetros:
  • cups (str) – Código CUPS del punto de suministro

  • distributor_code (str) – Código de la distribuidora

  • date_from (str) – Fecha de inicio (YYYY-MM-DD)

  • date_to (str) – Fecha de fin (YYYY-MM-DD)

  • measurement_type (int) – Tipo de medida

  • point_type (Optional[int]) – Tipo de punto

  • authorized_nif (Optional[str]) – NIF autorizado para la consulta

Devuelve:

Datos de consumo

Tipo del valor devuelto:

Any

abstractmethod get_max_power(cups, distributor_code, date_from, date_to, authorized_nif=None)[fuente]

Obtiene datos de potencia máxima.

Parámetros:
  • cups (str) – Código CUPS del punto de suministro

  • distributor_code (str) – Código de la distribuidora

  • date_from (str) – Fecha de inicio (YYYY-MM-DD)

  • date_to (str) – Fecha de fin (YYYY-MM-DD)

  • authorized_nif (Optional[str]) – NIF autorizado para la consulta

Devuelve:

Datos de potencia máxima

Tipo del valor devuelto:

Any

Cliente Unificado (Futuro)