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:
- Net power over the last 24 hours, with zero highlighted so export is obvious.
- Daily import and export from the difference of the kWh counters per day.
- Base load, the lowest net power between 2 and 5 a.m., which reveals always-on consumers.
- 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_wstays 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.



