Automatización IoT

Monitorización de energía con enchufe inteligente MQTT: recoge datos de consumo y grafica el gasto diario

Recoge lecturas de potencia y energía de enchufes inteligentes compatibles con MQTT, guárdalas en SQLite con un pequeño suscriptor en Python y conviértelas en gráficas de kWh diarios por aparato que resisten reinicios y puestas a cero de contadores.

Enchufes inteligentes en electrodomésticos de cocina alimentando un gráfico de barras de consumo diario en un proyecto de enchufe inteligente mqtt
Pruébalo en tu propio broker MQTTConsigue un broker MQTT privado y gestionado con el plan Free y empieza con ejemplos de código listos para usar.
Pruébalo gratis Ejemplos de código Sin tarjeta

Monitorizar con enchufes inteligentes MQTT es la forma más barata de averiguar cuánto cuesta realmente el funcionamiento de cada aparato de tu casa. En este tutorial conectarás enchufes Tasmota y Shelly a un broker, normalizarás sus distintos payloads, guardarás las lecturas en SQLite con un suscriptor en Python y generarás una gráfica de kWh diarios por aparato. El método tiene en cuenta los reinicios y las puestas a cero de los contadores, que es justo donde la mayoría de los registradores de energía caseros fallan sin que nadie lo note.

Qué enchufes inteligentes hablan MQTT

Necesitas un enchufe capaz de publicar en un broker de tu elección, no solo en la nube del fabricante. Tres familias cubren la mayor parte del mercado para este fin:

Familia de enchufes Cómo se activa MQTT Campos de energía Notas
Enchufes con Tasmota (muchos modelos basados en ESP) Integrado en el firmware Tasmota ENERGY.Power (W), ENERGY.Total (kWh), Today, Yesterday Algunos modelos vienen con Tasmota; otros hay que flashearlos
Shelly Plug S Gen3 / Plus Plug Interfaz web local, Settings > MQTT apower (W), aenergy.total (Wh) API JSON-RPC de Gen2/Gen3
Enchufes basados en ESPHome Bloque mqtt: en el YAML de ESPHome Un topic por sensor Flexibles, pero con topics por entidad

Comprueba que el enchufe tenga medición de potencia antes de comprarlo; muchos enchufes baratos solo conmutan. Revisa también la corriente nominal frente a la del aparato, ya que hervidores, calefactores y secadoras están cerca del límite de la mayoría de los enchufes.

Conectar un enchufe Tasmota

Abre la interfaz web de Tasmota y ve a Configuration > Configure MQTT, o usa la consola para ir más rápido. El comando Backlog aplica varios ajustes de una vez y reinicia el enchufe:

Backlog MqttHost broker.connectmq.com; MqttPort 1883; MqttClient plug-kitchen-kettle-9f2; Topic kettle; FullTopic connectmq/demo/p4w8/%prefix%/%topic%/; TelePeriod 60

Así el enchufe publica su telemetría cada 60 segundos en connectmq/demo/p4w8/tele/kettle/SENSOR, con un payload como este:

{
  "Time": "2026-10-16T07:31:12",
  "ENERGY": {
    "TotalStartTime": "2025-11-02T18:04:51",
    "Total": 48.215,
    "Yesterday": 0.412,
    "Today": 0.197,
    "Period": 3,
    "Power": 0,
    "ApparentPower": 0,
    "ReactivePower": 0,
    "Factor": 0.00,
    "Voltage": 231,
    "Current": 0.000
  }
}

Total es la energía acumulada de por vida en kWh y Power es la potencia activa instantánea en vatios. Usa un segmento de ruta aleatorio como p4w8, porque el servidor MQTT público gratuito es compartido, cualquiera puede leerlo y está pensado solo para pruebas, no para datos de producción. Los detalles específicos de Tasmota, incluidas las compilaciones con TLS, se explican en la guía de Tasmota MQTT.

Conectar un enchufe Shelly

En un Shelly Plus Plug o Plug S Gen3, abre la interfaz web local, ve a Settings > MQTT, actívalo, establece el servidor en broker.connectmq.com:1883, el prefijo en connectmq/demo/p4w8/shelly/fridge y activa Generic status update over MQTT. El enchufe publicará entonces instantáneas completas en connectmq/demo/p4w8/shelly/fridge/status/switch:0, donde apower está en vatios y aenergy.total es la energía acumulada en vatios-hora, no en kWh. Confundir estas unidades es el error más habitual al combinar marcas. La guía de configuración de Shelly MQTT explica la estructura completa de topics y RPC.

Diseñar la canalización de datos del enchufe inteligente MQTT

Todos los enchufes ya publican en el broker; lo que falta es algo que escuche y guarde el histórico. Los brokers entregan mensajes en vivo y valores retenidos, pero no son bases de datos, así que el registrador es un cliente MQTT independiente. El plan:

  1. Suscribirse a ambos formatos de enchufe con comodines.
  2. Normalizar cada mensaje en (time, plug, power_w, total_kwh).
  3. Guardar cada muestra en SQLite.
  4. Calcular la energía diaria a partir de la diferencia entre totales acumulados consecutivos, ignorando los saltos negativos causados por puestas a cero del contador.
  5. Dibujar una serie de barras por enchufe y día.

¿Por qué calcular a partir de los totales acumulados en lugar de integrar la potencia? Porque la potencia se muestrea una vez por minuto, y un hervidor que funciona 90 segundos entre dos muestras puede aparecer como cero. El contador de energía del propio enchufe mide de forma continua, así que las diferencias del total son precisas incluso con un muestreo escaso. Si se pierde un mensaje, la siguiente diferencia simplemente abarca un periodo más largo.

El registrador en Python

pip install "paho-mqtt>=2.0" matplotlib
import json
import sqlite3
import sys
from datetime import datetime
import paho.mqtt.client as mqtt

PREFIX = "connectmq/demo/p4w8"
DB = sqlite3.connect("plugs.db", check_same_thread=False)
DB.execute("""CREATE TABLE IF NOT EXISTS samples (
    ts TEXT, plug TEXT, power_w REAL, total_kwh REAL)""")
DB.commit()


def normalize(topic, payload):
    parts = topic.split("/")
    data = json.loads(payload)
    if "/tele/" in topic and topic.endswith("/SENSOR"):
        e = data.get("ENERGY")
        if not e:
            return None
        return parts[-2], float(e["Power"]), float(e["Total"])
    if "/shelly/" in topic and topic.endswith("/status/switch:0"):
        if "aenergy" not in data:
            return None
        plug = parts[parts.index("shelly") + 1]
        return plug, float(data.get("apower", 0)), float(data["aenergy"]["total"]) / 1000.0
    return None


def on_connect(client, userdata, flags, reason_code, properties):
    print("Connected:", reason_code)
    client.subscribe(f"{PREFIX}/tele/+/SENSOR", qos=1)
    client.subscribe(f"{PREFIX}/shelly/+/status/switch:0", qos=1)


def on_message(client, userdata, msg):
    try:
        row = normalize(msg.topic, msg.payload)
    except (ValueError, KeyError) as exc:
        print("Skipping", msg.topic, exc)
        return
    if row is None:
        return
    plug, power, total = row
    DB.execute("INSERT INTO samples VALUES (?, ?, ?, ?)",
               (datetime.now().isoformat(timespec="seconds"), plug, power, total))
    DB.commit()
    print(f"{plug:12s} {power:8.1f} W  {total:10.3f} kWh")


def daily_kwh():
    rows = DB.execute("SELECT ts, plug, total_kwh FROM samples ORDER BY plug, ts").fetchall()
    result, last = {}, {}
    for ts, plug, total in rows:
        day = ts[:10]
        prev = last.get(plug)
        last[plug] = total
        if prev is None:
            continue
        delta = total - prev
        if delta < 0:          # contador a cero o enchufe sustituido: se omite este intervalo
            continue
        result.setdefault(plug, {}).setdefault(day, 0.0)
        result[plug][day] += delta
    return result


def plot():
    import matplotlib.pyplot as plt
    data = daily_kwh()
    days = sorted({d for per in data.values() for d in per})
    width = 0.8 / max(len(data), 1)
    fig, ax = plt.subplots(figsize=(10, 5))
    for i, (plug, per_day) in enumerate(sorted(data.items())):
        xs = [n + i * width for n in range(len(days))]
        ax.bar(xs, [per_day.get(d, 0) for d in days], width, label=plug)
    ax.set_xticks([n + 0.4 - width / 2 for n in range(len(days))])
    ax.set_xticklabels(days, rotation=45, ha="right")
    ax.set_ylabel("kWh per day")
    ax.legend()
    fig.tight_layout()
    fig.savefig("daily_kwh.png", dpi=120)
    for plug, per_day in sorted(data.items()):
        print(plug, {d: round(v, 3) for d, v in sorted(per_day.items())})


if __name__ == "__main__":
    if sys.argv[1:] == ["plot"]:
        plot()
    else:
        client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="plug-logger-3391")
        client.on_connect = on_connect
        client.on_message = on_message
        client.connect("broker.connectmq.com", 1883, keepalive=60)
        client.loop_forever()

Deja python plug_logger.py en ejecución y, al cabo de uno o dos días, ejecuta python plug_logger.py plot para generar daily_kwh.png y mostrar las cifras. Los días se agrupan según la hora local del registrador, que suele ser lo que interesa para los informes domésticos.

Interpretar las cifras

Con una semana de datos, normalmente destacan algunos patrones:

  • Consumos en reposo. Televisores, consolas y equipos de red que nunca bajan de unos pocos vatios suman bastante a lo largo de un año. Fíjate en el power_w mínimo de cada enchufe, no solo en el total diario.
  • Refrigeradores y congeladores muestran un ciclo de trabajo regular. Un total diario creciente con la misma temperatura ambiente puede indicar una junta en mal estado o un condensador sucio.
  • Cargas altas y breves como hervidores y cafeteras apenas aparecen en las muestras de potencia, pero el contador de energía las captura, lo que valida el método de diferencias.
  • El coste anual es el consumo diario en kWh multiplicado por 365 y por tu tarifa. Calcúlalo por enchufe para saber qué cambio merece la pena.

Para tener una visión de toda la vivienda con la que comparar, consulta el tutorial del monitor de energía doméstica con MQTT.

Convertir los datos del enchufe inteligente MQTT en alertas

El histórico te dice lo que pasó; las alertas te avisan mientras todavía está pasando. Como todas las lecturas ya pasan por el broker, puedes añadir alertas sin tocar los enchufes:

  • Congelador parado. Un enchufe de congelador que informa de menos de unos pocos vatios durante más de una hora suele indicar un termostato disparado o una puerta abierta. Las reglas de alerta por umbral del portal de ConnectMQ pueden vigilar un campo numérico de un topic, y un suscriptor en Python o Node-RED puede añadir la condición de "durante más de una hora".
  • Aparato olvidado. Una plancha, un calefactor o una plancha de pelo que consume durante más tiempo del habitual es una automatización clásica con enchufe inteligente MQTT: publica off en el topic de comandos del enchufe tras un tiempo de espera.
  • Lavadora terminada. Una potencia que baja de cientos de vatios a casi cero y se mantiene así unos minutos es una señal fiable de "ciclo terminado" para enviar una notificación al teléfono.

Mantén la lógica en un solo suscriptor en lugar de repartirla entre dispositivos, para poder cambiar los umbrales sin volver a flashear nada.

Lista de comprobación para resolver problemas

Problema Causa Solución
Los totales diarios son 1000 veces mayores Los Wh de Shelly se tratan como kWh Divide aenergy.total entre 1000
No llegan datos de Tasmota durante minutos TelePeriod demasiado largo Configura TelePeriod 60 o menos (mínimo 10)
Los enchufes se desconectan entre sí Client IDs MQTT duplicados Un MqttClient único por enchufe
Valores diarios negativos No se gestiona la puesta a cero del contador Omite las diferencias negativas como arriba
Las lecturas de potencia parecen erróneas Enchufe sin calibrar Calibra con PowerSet, VoltageSet y CurrentSet en Tasmota

Pasar a un broker privado

El broker público es perfecto para este experimento, pero los datos de energía revelan cuándo estás en casa, y cualquiera que adivine tu prefijo también puede conmutar tus enchufes. Antes de dejar la instalación funcionando, pasa a un broker MQTT en la nube con credenciales y TLS. Con ConnectMQ, crea un broker en el portal y asigna a cada enchufe su propio nombre de usuario, contraseña y client ID. En Tasmota eso implica una compilación con TLS y MqttPort 8883; en Shelly, activa SSL con el paquete de CA integrado. En el registrador, añade:

client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="YOUR_CLIENT_ID")
client.username_pw_set("YOUR_USERNAME", "YOUR_PASSWORD")
client.tls_set()
client.connect("broker.connectmq.com", 8883, keepalive=60)

Las 25 conexiones del plan Serverless gratuito bastan para una docena de enchufes, el registrador y un dashboard. Un broker MQTT gestionado también significa que el broker es accesible desde tu teléfono sin abrir puertos en el router. La guía de automatización IoT muestra cómo los datos de los enchufes también pueden disparar automatizaciones.

Empieza a monitorizar tus enchufes con ConnectMQ

ConnectMQ ofrece a tus enchufes inteligentes, registradores y dashboards un broker privado protegido con TLS, con explorador de topics en vivo y reglas de alerta por umbral, por ejemplo para avisarte cuando el enchufe de un congelador informa de cero vatios durante demasiado tiempo. Crea un broker Serverless gratuito en app.connectmq.com, sin tarjeta de crédito.

Preguntas frecuentes

¿Puede cualquier enchufe inteligente enviar datos por MQTT?

No. Solo los enchufes con MQTT en su firmware, como los dispositivos Tasmota, Shelly Gen2/Gen3 o ESPHome, pueden publicar en un broker de tu elección. Los enchufes que solo funcionan con la nube necesitan una integración del fabricante.

¿Qué precisión tienen las lecturas de energía de un enchufe inteligente?

Suelen ser suficientes para comparar aparatos y detectar derroches, pero no son contadores de facturación. Calibrarlos con una carga resistiva conocida mejora notablemente la precisión en los enchufes Tasmota.

¿Por qué usar el total de energía en lugar del valor de potencia?

El enchufe integra la energía de forma continua, mientras que la potencia solo se muestrea cuando se envía un mensaje. Las diferencias entre totales acumulados capturan cargas breves que las muestras de potencia pasan por alto.

¿Con qué frecuencia debe publicar un enchufe inteligente?

Cada 30 a 60 segundos es un buen equilibrio para el histórico y los dashboards. Intervalos más cortos añaden tráfico sin mejorar los totales diarios, porque estos proceden del contador de energía.

Artículos relacionados

Guía para configurar Zigbee2MQTT: del coordinador al panel

Instala Zigbee2MQTT con Docker, configura el coordinador y la conexión MQTT, empareja y renombra dispositivos, contrólalos por MQTT y consulta sus estados en un panel, probando primero en un servidor MQTT público gratuito.

8 min de lectura

Todos los artículos →

Tu broker MQTT privado, a unos pocos clics

Crea una cuenta, obtén las credenciales de tu broker y conecta tu primer dispositivo, sin servidores que instalar, parchear ni escalar.