IoT and AI

Energy Load Forecasting with IoT Meter Data and MQTT

A practical use case for energy load forecasting: collecting meter data over MQTT, turning energy counters into demand, adding weather and calendar features, and publishing day-ahead forecasts for buildings and plants.

Energy load forecasting dashboard comparing measured building demand with a day-ahead forecast and a peak demand limit
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

Energy load forecasting predicts how much electricity a building, plant or site will draw over the coming hours or days. With IoT meters streaming readings over MQTT, you can build a forecast from your own data rather than relying on monthly bills. This use case walks through the data path from meter to model, the features that matter for demand, a working day-ahead forecasting script, and how to publish the result so it can drive peak shaving and scheduling decisions.

Why Forecast Energy Load

A load forecast answers practical questions that facility and production managers face every day:

  • Peak demand management. Many tariffs include demand charges based on the highest interval of the month. Knowing in advance that tomorrow afternoon will approach the limit lets you shift flexible loads.
  • Scheduling flexible loads. Batch processes, EV charging, pre-cooling and water heating can be moved to hours with lower demand or lower prices.
  • Procurement and self-consumption. Sites with solar, batteries or time-of-use contracts need a demand forecast to decide when to charge, discharge or buy.
  • Anomaly spotting. A large, persistent gap between forecast and actual load often indicates equipment left running, a failing compressor or a metering fault.

The forecasting horizon depends on the decision: intraday forecasts (next few hours) support real-time control, day-ahead forecasts support scheduling and purchasing, and longer horizons support budgeting.

The Data Path: From Meter to Model

A typical setup has electricity meters or sub-meters connected through a gateway that reads them over Modbus, M-Bus or a vendor API, and publishes readings to an MQTT broker. Weather data and production or occupancy schedules are published or stored alongside.

Meters (Modbus RTU/TCP) -> gateway -> MQTT broker -> historian subscriber -> forecasting service
                                           ^                                         |
                       weather / schedule publisher                 forecast topic <-+

A clear topic layout keeps the model independent of meter vendors:

connectmq/site1/main/meter1/energy       {"ts":..., "kwh_total": 183422.6}
connectmq/site1/main/meter1/power        {"ts":..., "kw": 142.8}
connectmq/site1/weather/outdoor          {"ts":..., "temp_c": 27.4}
connectmq/site1/main/meter1/forecast     {"generated":..., "points":[...]}

Publish energy as a cumulative counter rather than per-interval values when you can. If a message is lost, the next counter value still contains the consumption, and interval demand can be reconstructed exactly by differencing. Instantaneous power is useful for live dashboards but noisy for forecasting. If your meters are Modbus devices, the Modbus TCP to MQTT guide shows the gateway side.

Features That Drive Energy Load Forecasting

Feature group Examples Why it matters
Calendar Hour of day, day of week, holiday flag, month Occupancy and production follow schedules
Lagged load Same hour yesterday, same hour last week Strong persistence in demand
Weather Outdoor temperature, its forecast, humidity, solar irradiance Heating and cooling loads depend on it
Derived weather Cooling and heating degree hours, temperature lag Buildings respond with thermal delay
Operations Production plan, shift pattern, occupancy counts Explains non-weather variation

For day-ahead forecasts, every feature must be available before the forecast is made. That means using the weather forecast, not the measured temperature, for future hours, and using lags of at least 24 hours. Mixing up measured and forecast weather in training is a common reason for models that look excellent in testing and disappoint in operation.

A Day-Ahead Forecast in Python

The script below simulates a commercial building's meter counter and outdoor temperature over four weeks, publishes them to the free public MQTT broker, collects them back, converts the counter into 15-minute demand, trains a gradient boosting model and publishes a 24-hour forecast. In a real deployment, the collection step would read from your historian instead of a simulator.

import json
import math
import random
import time
import uuid

import numpy as np
import pandas as pd
import paho.mqtt.client as mqtt
from sklearn.ensemble import HistGradientBoostingRegressor

BROKER = "broker.connectmq.com"
BASE = f"connectmq/demo/{uuid.uuid4().hex[:8]}/site1"
START = 1767225600  # 2026-01-01 00:00 UTC
STEPS = 28 * 96     # 4 weeks of 15-minute intervals
rows = []


def on_message(client, userdata, msg):
    p = json.loads(msg.payload)
    p["kind"] = msg.topic.rsplit("/", 1)[1]
    rows.append(p)


client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="elf-" + uuid.uuid4().hex[:8])
client.on_message = on_message
client.connect(BROKER, 1883, keepalive=60)
client.subscribe([(f"{BASE}/meter1/energy", 1), (f"{BASE}/weather/temp", 1)])
client.loop_start()
time.sleep(1)

counter = 100000.0
for i in range(STEPS):
    t = START + i * 900
    hour = (t % 86400) / 3600
    workday = time.gmtime(t).tm_wday < 5
    temp = 24 + 7 * math.sin((hour - 9) / 24 * 2 * math.pi) + random.gauss(0, 1)
    occupied = workday and 7 <= hour < 19
    kw = 40 + (90 if occupied else 0) + 6 * max(temp - 22, 0) + random.gauss(0, 5)
    counter += kw * 0.25
    client.publish(f"{BASE}/meter1/energy", json.dumps({"ts": t * 1000, "kwh_total": round(counter, 2)}))
    client.publish(f"{BASE}/weather/temp", json.dumps({"ts": t * 1000, "temp_c": round(temp, 2)}))
    time.sleep(0.21)  # two messages per step, stay under 10 msg/s

time.sleep(3)

df = pd.DataFrame(rows)
df["ts"] = pd.to_datetime(df["ts"], unit="ms", utc=True)
energy = df[df.kind == "energy"].set_index("ts")["kwh_total"].sort_index().resample("15min").last()
temp = df[df.kind == "temp"].set_index("ts")["temp_c"].sort_index().resample("15min").mean()

data = pd.DataFrame({"kw": energy.interpolate().diff() * 4, "temp": temp.interpolate()})
data["hour"] = data.index.hour + data.index.minute / 60
data["dow"] = data.index.dayofweek
data["lag_1d"] = data["kw"].shift(96)
data["lag_7d"] = data["kw"].shift(7 * 96)
data["cdh"] = (data["temp"] - 22).clip(lower=0)
FEATS = ["hour", "dow", "lag_1d", "lag_7d", "temp", "cdh"]
data = data.dropna()

train, test = data.iloc[:-96], data.iloc[-96:]
model = HistGradientBoostingRegressor(max_iter=300, learning_rate=0.05).fit(train[FEATS], train["kw"])
pred = model.predict(test[FEATS])
mae = np.mean(np.abs(pred - test["kw"]))
print(f"Day-ahead MAE: {mae:.1f} kW, peak forecast {pred.max():.0f} kW, actual peak {test['kw'].max():.0f} kW")

forecast = {
    "generated": int(time.time() * 1000),
    "model": "gbr-load-v1",
    "unit": "kW",
    "points": [{"ts": int(ts.timestamp() * 1000), "kw": round(float(v), 1)} for ts, v in zip(test.index, pred)],
}
client.publish(f"{BASE}/meter1/forecast", json.dumps(forecast), qos=1, retain=True).wait_for_publish()
client.loop_stop()
client.disconnect()

Install with pip install paho-mqtt pandas numpy scikit-learn. The run takes about ten minutes because the simulator respects the public broker's rate limit. The test day here uses simulated measured temperature as a stand-in for a weather forecast; in production, feed the model the forecast temperature for future hours. For background on backtesting with several forecast origins and comparing against a naive baseline, see IoT time series forecasting.

Turning the Forecast into Action

A forecast only pays off when it changes decisions. Common patterns:

  1. Peak alerts. Compare the forecast peak with your demand limit and notify the facility team the evening before.
  2. Load shifting. A scheduling script subscribes to the forecast topic and moves flexible loads, such as EV charging or batch heating, into low-demand intervals.
  3. Pre-cooling and pre-heating. HVAC can use cheap or low-demand hours to store thermal energy in the building mass, a pattern covered in AI HVAC optimization.
  4. Forecast versus actual monitoring. Publish the live deviation as its own topic and alert on persistent gaps.

With ConnectMQ, you can watch the forecast and measured power topics in the live topic explorer and set threshold alert rules on the measured demand, so the alerts log records every interval that crossed your limit. More advanced actions run in your own clients, such as Node-RED flows or Python services subscribed to the same broker.

Updating Forecasts During the Day

A day-ahead forecast is made once, but the day rarely goes exactly as planned. An unplanned overtime shift or a hotter afternoon than predicted shifts the load. A simple improvement is to re-run the forecast every hour using the latest measured demand as an extra input, and to publish each new version to the same retained topic with a generation timestamp. Consumers always see the latest view, and you can store every version to measure how much intraday updates improve accuracy compared with the original day-ahead run.

Practical Pitfalls

  • Counter resets and rollovers. Meters wrap around or reset after replacement; treat negative differences as resets, not negative demand.
  • Time zones and daylight saving. Store in UTC, compute calendar features in local time, or your 08:00 start-up will move by an hour twice a year.
  • Holidays and shutdowns. Without a holiday flag, the model will forecast a normal weekday load on a public holiday.
  • Changing baselines. New equipment, retrofits or changed opening hours make older history misleading; weight recent data more or retrain on a sliding window.
  • Sub-meter sums that do not match the main meter. Unmetered loads and losses exist; forecast the main meter directly rather than summing sub-meter forecasts, and use sub-meters for diagnosis.

Scaling Across Sites

One building is a script; fifty sites is a platform. Keep the topic layout identical at every site, run one forecasting service that subscribes with wildcards, and store results per site. A managed MQTT broker removes the operational work of running the messaging layer, and ConnectMQ offers dedicated clusters and BYOC deployments when sites require isolation. For more on combining models with connected devices, see the AI and IoT guide, and for a model-based view of energy systems, digital twins for energy.

Get Started with ConnectMQ

Create a free Serverless broker at app.connectmq.com, no credit card required. Connect your meter gateway and forecasting service with the generated YOUR_USERNAME, YOUR_PASSWORD and YOUR_CLIENT_ID, and start building the history your energy load forecasting model needs. As you add sites, move to a larger cloud MQTT broker plan without changing your topics.

Frequently Asked Questions

What is energy load forecasting?

Energy load forecasting predicts the electricity demand of a building, plant or grid area for future time intervals, typically from historical meter data, weather and calendar information.

How much data do I need to forecast energy load?

A few weeks of 15-minute data can produce a usable day-ahead forecast for a building with stable schedules. A year or more is needed to capture seasonal heating and cooling patterns and holidays.

Should I publish energy or power from my meters?

Publish the cumulative energy counter for forecasting and billing accuracy, because lost messages do not lose consumption. Publish instantaneous power additionally if you need live dashboards.

Which model works best for load forecasting?

Gradient boosting on calendar, lag and weather features is a strong, explainable default. Compare it against a same-day-last-week baseline and switch only if another model wins in a rolling backtest.

Related articles

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.