IoT Automation

Home Energy Monitor MQTT Guide: Smart Meter and CT Clamp Data to Dashboards

Measure whole-house consumption with a smart meter P1 reader or CT clamps, publish it as MQTT JSON with a short Python script, and store and chart it with Telegraf, InfluxDB or any dashboard that speaks MQTT.

Electrical panel with CT clamps and a smart meter connected to a live consumption graph in a home energy monitor mqtt setup
Run this on your own MQTT brokerGet a private, managed MQTT broker on the Free plan and start from ready-made code samples.
Try it free Code samples No card required

A home energy monitor MQTT setup shows what your whole house consumes, second by second, and makes that number available to every dashboard and automation you run. In this guide you will choose between a smart meter reader and CT clamps, publish consumption with a Python script, and store and chart it with Telegraf and InfluxDB. You will also see which numbers matter for solar self-consumption and how to keep the data private.

Two Ways to Measure the Whole House

You can measure at the utility meter or at your distribution board. Both work well; the right choice depends on your meter and your comfort with electrical work.

Approach What you need Measures Effort and safety
Smart meter port (P1 / DSMR, other consumer ports) Meter with an enabled customer port, USB cable or ESP-based reader Import, export, tariffs, voltage, often gas Plug-in, no electrical work
Ready-made CT meter (e.g. Shelly Pro 3EM, Shelly EM) Device mounted in the panel with clamps Per-phase power, energy, voltage Installed in the panel by a qualified person
DIY CT clamps (SCT-013 + ESP32) Clamps, burden resistor, bias circuit Current per circuit, estimated power Clamps are non-invasive, but panel access is still required
Pulse LED on the meter Light sensor taped over the LED Energy from pulse rate No electrical work, lower resolution

In the Netherlands, Belgium and Luxembourg, most smart meters have a P1 port that streams a text "telegram" every second (DSMR 5) or every ten seconds (DSMR 4). It is the easiest and most accurate source, because the numbers are the ones your utility bills. Elsewhere, look for an equivalent customer interface, or use CT clamps.

Any work inside a consumer unit should be done by a qualified electrician. Clamp-on sensors do not cut wires, but opening the panel exposes live parts.

Topic Design for a Home Energy Monitor MQTT Feed

Keep one telemetry topic per meter with a compact JSON payload, plus retained status:

connectmq/demo/<random-id>/energy/grid/telemetry      (JSON, every 1-10 s)
connectmq/demo/<random-id>/energy/grid/status         (online/offline, retained)
{
  "import_w": 1193,
  "export_w": 0,
  "net_w": 1193,
  "import_kwh_t1": 4182.517,
  "import_kwh_t2": 3970.204,
  "export_kwh_t1": 1520.110,
  "export_kwh_t2": 3184.623,
  "voltage_l1": 230.1,
  "ts": 1760605123
}

Publish net_w (import minus export) as a signed value. Solar and battery automations care about that single number: negative means you are exporting.

Reading a P1 Smart Meter with Python

Connect a P1-to-USB cable to a Raspberry Pi or any Linux machine. DSMR 4 and 5 meters use 115200 baud, 8 data bits, no parity, 1 stop bit. Each telegram starts with /, ends with ! plus a CRC, and contains lines like 1-0:1.7.0(01.193*kW). The OBIS codes you need:

OBIS code Meaning Unit
1-0:1.8.1 / 1-0:1.8.2 Imported energy, tariff 1 / 2 kWh
1-0:2.8.1 / 1-0:2.8.2 Exported energy, tariff 1 / 2 kWh
1-0:1.7.0 Current import power kW
1-0:2.7.0 Current export power kW
1-0:32.7.0 Voltage L1 V
0-1:24.2.1 Gas meter reading (with timestamp) m3

Install the dependencies:

pip install "paho-mqtt>=2.0" pyserial
import json
import re
import time
import uuid
import serial
import paho.mqtt.client as mqtt

PORT = "/dev/ttyUSB0"
PREFIX = f"connectmq/demo/{uuid.uuid4().hex[:8]}/energy/grid"
PUBLISH_EVERY = 5   # seconds; DSMR 5 sends a telegram every second

LINE = re.compile(r"^(\d+-\d+:\d+\.\d+\.\d+)\((.*)\)$")
VALUE = re.compile(r"([\d.]+)\*")

FIELDS = {
    "1-0:1.8.1": ("import_kwh_t1", 1),
    "1-0:1.8.2": ("import_kwh_t2", 1),
    "1-0:2.8.1": ("export_kwh_t1", 1),
    "1-0:2.8.2": ("export_kwh_t2", 1),
    "1-0:1.7.0": ("import_w", 1000),   # kW -> W
    "1-0:2.7.0": ("export_w", 1000),
    "1-0:32.7.0": ("voltage_l1", 1),
}


def parse(telegram):
    out = {}
    for line in telegram.splitlines():
        m = LINE.match(line.strip())
        if not m or m.group(1) not in FIELDS:
            continue
        name, factor = FIELDS[m.group(1)]
        v = VALUE.search(m.group(2))
        if v:
            out[name] = round(float(v.group(1)) * factor, 3)
    if "import_w" in out and "export_w" in out:
        out["net_w"] = round(out["import_w"] - out["export_w"], 1)
    return out


mq = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=f"p1-{uuid.uuid4().hex[:6]}")
mq.will_set(f"{PREFIX}/status", "offline", qos=1, retain=True)
mq.connect("broker.connectmq.com", 1883, keepalive=60)
mq.loop_start()
mq.publish(f"{PREFIX}/status", "online", qos=1, retain=True)
print("Publishing to", PREFIX)

ser = serial.Serial(PORT, 115200, bytesize=8, parity="N", stopbits=1, timeout=12)
buf, last_pub = [], 0.0
while True:
    raw = ser.readline().decode("ascii", errors="ignore")
    if not raw:
        continue
    if raw.startswith("/"):
        buf = [raw]
    elif buf:
        buf.append(raw)
        if raw.startswith("!"):
            data = parse("".join(buf))
            buf = []
            if data and time.time() - last_pub >= PUBLISH_EVERY:
                data["ts"] = int(time.time())
                mq.publish(f"{PREFIX}/telemetry", json.dumps(data), qos=0, retain=True)
                last_pub = time.time()
                print(data)

The script throttles to one message every five seconds. That is plenty for dashboards and stays far below the public test broker's limit of 10 messages per second per client. For a production build, add CRC16 validation of each telegram; corrupted telegrams are rare but do happen with long cables.

Prefer an ESP-based P1 reader instead of a Raspberry Pi? Several open firmware projects publish DSMR data directly to MQTT; point them at the same broker and topic layout.

The CT Clamp Route

If you have no usable meter port, a three-phase CT meter such as a Shelly Pro 3EM is the low-effort option. It publishes per-phase power and totals over MQTT once configured, and the Shelly MQTT guide explains its topics and TLS settings. DIY builds with an ESP32 and SCT-013 clamps are popular too, but note that a current clamp alone cannot tell import from export; you need a voltage reference to compute real power and its direction. For individual appliances, plugs are simpler; see smart plug MQTT energy monitoring.

Storing and Charting with Telegraf and InfluxDB

The broker delivers live values but does not keep history. Telegraf's mqtt_consumer input subscribes like any other client and writes into InfluxDB, which Grafana or InfluxDB's own UI can chart.

[[inputs.mqtt_consumer]]
  servers = ["tcp://broker.connectmq.com:1883"]
  topics = ["connectmq/demo/+/energy/+/telemetry"]
  client_id = "telegraf-energy-5527"
  qos = 0
  data_format = "json"
  name_override = "energy"
  json_time_key = "ts"
  json_time_format = "unix"
  [[inputs.mqtt_consumer.topic_parsing]]
    topic = "connectmq/demo/+/energy/+/telemetry"
    tags = "_/_/_/_/meter/_"

[[outputs.influxdb_v2]]
  urls = ["http://localhost:8086"]
  token = "YOUR_INFLUX_TOKEN"
  organization = "home"
  bucket = "energy"

The topic_parsing block turns the meter name in the topic into a tag, so grid, solar and heatpump meters end up as one measurement with a meter tag. Useful charts to build first:

  1. Net power over the last 24 hours, with zero highlighted so export is obvious.
  2. Daily import and export from the difference of the kWh counters per day.
  3. Base load, the lowest net power between 2 and 5 a.m., which reveals always-on consumers.
  4. Import by tariff, to check that flexible loads really run in the cheap period.

Node-RED dashboards and Home Assistant work equally well; each simply subscribes to the telemetry topic.

Acting on the Numbers

A live net_w value on MQTT is more than a chart; it is an input for automation. A few patterns are worth setting up early:

  • Surplus switching. When net_w stays below a negative threshold (you are exporting) for a few minutes, switch on a water heater, dishwasher or EV charger, and switch it off again with hysteresis when import returns.
  • Peak limiting. If import approaches what your main fuse or capacity tariff allows, delay flexible loads instead of tripping a breaker or paying a peak charge.
  • Base load alerts. A night-time base load that suddenly doubles often points to a faulty appliance, a stuck pump or a heater left on.

These rules run well in Node-RED, Home Assistant or a short Python subscriber, all connecting to the broker as normal clients and reading the same telemetry topic.

Pitfalls to Avoid

  • Counting energy from power samples. Integrating sampled power drifts over time. Use the meter's kWh counters for daily totals.
  • Mixing kW and W. DSMR reports power in kW; convert once, at the source.
  • Retaining high-rate data unnecessarily. Retaining is useful for the latest value but there is no need to retain per-second data on separate topics.
  • Clock skew. Use the publisher's timestamp field (ts) as the measurement time so that delays in delivery do not distort charts.
  • Publishing in the open. Second-by-second consumption reveals when you are home or away. The public test broker is for experiments only.

Moving to a Private Broker

For a permanent home energy monitor, publish to a private broker with TLS. A hosted MQTT broker such as ConnectMQ means no broker to maintain on the Raspberry Pi and secure remote access from your phone without opening router ports. Create a broker in the ConnectMQ portal, then change the client and Telegraf settings:

mq = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="YOUR_CLIENT_ID")
mq.username_pw_set("YOUR_USERNAME", "YOUR_PASSWORD")
mq.tls_set()
mq.connect("broker.connectmq.com", 8883, keepalive=60)
  servers = ["ssl://broker.connectmq.com:8883"]
  username = "YOUR_USERNAME"
  password = "YOUR_PASSWORD"

Each client (the P1 reader and Telegraf) needs its own credentials and client ID. To compare against production, add solar inverter monitoring, and for the broader picture of energy-aware automation, read the IoT automation guide. If you are deciding where to host the broker, the cloud MQTT broker guide compares the options.

Watch Your Home's Energy Live on ConnectMQ

ConnectMQ gives your meter readers, Telegraf and dashboards one secure broker with TLS, WebSocket access for browser dashboards and threshold alert rules, for example when net import exceeds your main fuse budget. Create a free Serverless broker at app.connectmq.com, no credit card required.

Frequently Asked Questions

Does my smart meter have a P1 port?

Meters in the Netherlands, Belgium and Luxembourg usually do, and in some countries the port must be activated by the grid operator. Other regions use different customer interfaces or none, in which case CT clamps or a pulse LED reader are the alternatives.

How often should a home energy monitor publish over MQTT?

Every 1 to 10 seconds is common. Fast updates help with solar surplus control, while history and daily totals work fine at lower rates because they come from the kWh counters.

Can CT clamps detect solar export?

Only if the device also measures voltage to calculate real power and its sign. Current-only clamps show how much current flows but not in which direction.

Is InfluxDB required?

No. Any subscriber can store the data, including Home Assistant's recorder, a Node-RED flow writing to a database, or a simple Python script writing CSV files.

Related articles

Zigbee2MQTT Setup Guide: From Coordinator to Dashboard

Install Zigbee2MQTT with Docker, configure the coordinator and MQTT connection, pair and rename devices, control them over MQTT and view their states on a dashboard, testing first on a free public broker.

7 min read

All articles →

Your private MQTT broker is a few clicks away

Create an account, get your broker credentials and connect your first device — no servers to install, patch or scale.