Automação IoT

Monitoramento de Energia com Tomada Inteligente MQTT: Colete Dados de Potência e Gere Gráficos de Consumo Diário

Colete leituras de potência e energia de tomadas inteligentes com MQTT, armazene-as em SQLite com um pequeno subscriber Python e transforme-as em gráficos de kWh diário por aparelho que resistem a reinicializações e zeramentos de contador.

Tomadas inteligentes em eletrodomésticos da cozinha alimentando um gráfico de barras de consumo diário em um projeto de tomada inteligente mqtt
Rode isso no seu próprio broker MQTTTenha um broker MQTT privado e gerenciado no plano Free e comece com exemplos de código prontos.
Teste grátis Exemplos de código Sem cartão de crédito

Monitorar tomadas inteligentes via MQTT é a forma mais barata de descobrir quanto cada aparelho da sua casa realmente custa para funcionar. Neste tutorial você vai conectar tomadas Tasmota e Shelly a um broker, normalizar seus payloads diferentes, armazenar as leituras em SQLite com um subscriber Python e gerar um gráfico de kWh diário por aparelho. A abordagem lida com reinicializações e zeramentos de contador, que é exatamente onde a maioria dos registradores de energia caseiros falha sem ninguém perceber.

Quais Tomadas Inteligentes Falam MQTT

Você precisa de uma tomada capaz de publicar em um broker escolhido por você, e não apenas na nuvem do fabricante. Três famílias cobrem a maior parte do mercado para esse fim:

Família de tomada Como o MQTT é ativado Campos de energia Observações
Tomadas com Tasmota (muitos modelos baseados em ESP) Embutido no firmware Tasmota ENERGY.Power (W), ENERGY.Total (kWh), Today, Yesterday Alguns modelos já vêm com Tasmota; outros precisam ser regravados
Shelly Plug S Gen3 / Plus Plug Interface web local, Settings > MQTT apower (W), aenergy.total (Wh) API JSON-RPC Gen2/Gen3
Tomadas baseadas em ESPHome Bloco mqtt: no YAML do ESPHome Um topic por sensor Flexível, mas com topics por entidade

Confira se a tomada tem medição de energia antes de comprar; muitas tomadas baratas apenas ligam e desligam. Verifique também a corrente nominal em relação ao aparelho, já que chaleiras, aquecedores e secadoras ficam perto do limite da maioria das tomadas.

Conectando uma Tomada Tasmota

Abra a interface web do Tasmota e vá em Configuration > Configure MQTT, ou use o console para uma configuração mais rápida. O comando Backlog aplica várias configurações de uma vez e reinicia a tomada:

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

Com isso, a tomada publica sua telemetria a cada 60 segundos em connectmq/demo/p4w8/tele/kettle/SENSOR, com um 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 é a energia acumulada em kWh e Power é a potência ativa instantânea em watts. Use um segmento de caminho aleatório como p4w8, porque o servidor MQTT público é compartilhado e pode ser lido por todos; use-o só para testes, nunca para dados de produção. Os detalhes específicos do Tasmota, incluindo builds com TLS, estão no guia de Tasmota MQTT.

Conectando uma Tomada Shelly

Em uma Shelly Plus Plug ou Plug S Gen3, abra a interface web local, vá em Settings > MQTT, ative-o, defina o servidor como broker.connectmq.com:1883, o prefixo como connectmq/demo/p4w8/shelly/fridge e ative Generic status update over MQTT. A tomada passa então a publicar retratos completos em connectmq/demo/p4w8/shelly/fridge/status/switch:0, onde apower está em watts e aenergy.total é a energia acumulada em watt-hora, não em kWh. Confundir essas unidades é o bug mais comum ao combinar marcas. O guia de configuração do Shelly MQTT explica toda a estrutura de topics e RPC.

Projetando o Pipeline de Dados da Tomada Inteligente MQTT

Todas as tomadas já publicam no broker; o que falta é algo que escute e guarde o histórico. Brokers entregam mensagens ao vivo e valores retidos, mas não são bancos de dados, então o registrador é um cliente MQTT separado. O plano:

  1. Assinar os dois formatos de tomada com wildcards.
  2. Normalizar cada mensagem em (time, plug, power_w, total_kwh).
  3. Armazenar cada amostra no SQLite.
  4. Calcular a energia diária a partir da diferença entre totais acumulados consecutivos, ignorando saltos negativos causados por zeramento de contador.
  5. Plotar uma série de barras por tomada por dia.

Por que calcular a partir dos totais acumulados em vez de integrar a potência? Porque a potência é amostrada uma vez por minuto, e uma chaleira que funciona por 90 segundos entre duas amostras pode aparecer como zero. O contador de energia da própria tomada mede continuamente, então as diferenças do total são precisas mesmo com amostragem esparsa. Se uma mensagem se perder, a diferença seguinte simplesmente cobre um período maior.

O Registrador em 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 zerado ou tomada substituída: ignora 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()

Deixe python plug_logger.py rodando e, depois de um ou dois dias, execute python plug_logger.py plot para gerar daily_kwh.png e imprimir os números. Os dias são agrupados pelo horário local do registrador, que normalmente é o que você quer em relatórios domésticos.

Interpretando os Números

Depois de uma semana de dados, alguns padrões costumam se destacar:

  • Consumo em standby. Televisores, consoles e equipamentos de rede que nunca caem abaixo de alguns watts somam bastante ao longo de um ano. Observe o power_w mínimo por tomada, e não apenas o total diário.
  • Geladeiras e freezers mostram um ciclo de trabalho regular. Um total diário crescente com a mesma temperatura ambiente pode indicar uma borracha de vedação com defeito ou um condensador sujo.
  • Cargas altas e curtas, como chaleiras e cafeteiras, quase não aparecem nas amostras de potência, mas o contador de energia as registra, o que valida o método das diferenças.
  • Custo anual é o kWh diário multiplicado por 365 e pela sua tarifa. Calcule-o por tomada para saber qual mudança vale a pena.

Para uma visão da casa inteira para comparar, veja o tutorial de monitor de energia residencial com MQTT.

Transformando Dados da Tomada Inteligente MQTT em Alertas

O histórico mostra o que aconteceu; os alertas avisam enquanto ainda está acontecendo. Como todas as leituras já passam pelo broker, você pode adicionar alertas sem mexer nas tomadas:

  • Freezer parado. Uma tomada de freezer informando menos de alguns watts por mais de uma hora geralmente indica um termostato desarmado ou uma porta aberta. As regras de alerta por limite do portal ConnectMQ podem monitorar um campo numérico em um topic, e um subscriber em Python ou Node-RED pode acrescentar a condição "por mais de uma hora".
  • Aparelho esquecido. Um ferro, aquecedor ou chapinha consumindo energia por mais tempo que o normal é uma automação clássica de tomada inteligente MQTT: publique off no topic de comando da tomada após um tempo limite.
  • Máquina de lavar terminou. A potência caindo de centenas de watts para perto de zero e ficando assim por alguns minutos é um sinal confiável de "ciclo concluído" para uma notificação no celular.

Mantenha a lógica em um único subscriber, em vez de espalhá-la pelos dispositivos, para poder mudar os limites sem regravar nada.

Checklist de Solução de Problemas

Problema Causa Solução
Totais diários 1000 vezes maiores Wh do Shelly tratado como kWh Divida aenergy.total por 1000
Sem dados do Tasmota por minutos TelePeriod longo demais Defina TelePeriod 60 ou menos (mínimo 10)
Tomadas derrubam umas às outras Client IDs MQTT duplicados MqttClient único por tomada
Valores diários negativos Zeramento de contador não tratado Ignore diferenças negativas, como acima
Leituras de potência estranhas Tomada não calibrada Calibre com PowerSet, VoltageSet, CurrentSet no Tasmota

Migrando para um Broker Privado

O servidor MQTT público é perfeito para este experimento, mas dados de energia revelam quando você está em casa, e qualquer pessoa que adivinhe seu prefixo também pode acionar suas tomadas. Antes de deixar a instalação rodando, migre para um broker MQTT na nuvem com credenciais e TLS. Com o ConnectMQ, crie um broker no portal e dê a cada tomada seu próprio usuário, senha e client ID. No Tasmota isso significa um build com TLS e MqttPort 8883; no Shelly, ative o SSL com o pacote de CAs embutido. No registrador, acrescente:

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)

As 25 conexões do plano Serverless gratuito bastam para uma dúzia de tomadas, o registrador e um dashboard. Um broker MQTT gerenciado também significa que o broker fica acessível pelo celular sem abrir portas no roteador. O guia de automação com IoT mostra como os dados das tomadas também podem disparar automações.

Comece a Monitorar suas Tomadas com o ConnectMQ

O ConnectMQ oferece às suas tomadas inteligentes, registradores e dashboards um broker privado protegido por TLS, com explorador de topics ao vivo e regras de alerta por limite, por exemplo para avisar quando a tomada do freezer informar zero watt por tempo demais. Crie um broker Serverless gratuito em app.connectmq.com, sem cartão de crédito.

Perguntas frequentes

Qualquer tomada inteligente pode enviar dados via MQTT?

Não. Somente tomadas com MQTT no firmware, como dispositivos Tasmota, Shelly Gen2/Gen3 ou ESPHome, podem publicar em um broker escolhido por você. Tomadas que funcionam só pela nuvem precisam de uma integração do fabricante.

Qual é a precisão das leituras de energia de uma tomada inteligente?

Normalmente é boa o suficiente para comparar aparelhos e identificar desperdícios, mas elas não são medidores com precisão de faturamento. Calibrar com uma carga resistiva conhecida melhora bastante a precisão em tomadas Tasmota.

Por que usar o total de energia em vez do valor de potência?

A tomada integra a energia continuamente, enquanto a potência só é amostrada quando uma mensagem é enviada. As diferenças entre os totais acumulados capturam cargas curtas que as amostras de potência deixam passar.

Com que frequência uma tomada inteligente deve publicar?

A cada 30 a 60 segundos é um bom equilíbrio para histórico e dashboards. Intervalos menores aumentam o tráfego sem melhorar os totais diários, porque estes vêm do contador de energia.

Artigos relacionados

Guia de Configuração do Zigbee2MQTT: do Coordenador ao Painel

Instale o Zigbee2MQTT com Docker, configure o coordenador e a conexão MQTT, pareie e renomeie dispositivos, controle-os via MQTT e veja seus estados em um painel, testando primeiro no servidor MQTT público (gratuito).

8 min de leitura

Todos os artigos →

Seu broker MQTT privado está a poucos cliques de distância

Crie uma conta, receba as credenciais do seu broker e conecte seu primeiro dispositivo — sem servidores para instalar, atualizar ou escalar.