Unlocking Green Button Data for Home Assistant

Unlocking Green Button Data for Home Assistant — Enbridge Gas + Milton Hydro into InfluxDB + Grafana

Tags: influxdb grafana energy green-button ontario enbridge utility-monitoring python tou-rates


TL;DR

Green Button is a standard for downloading your own utility consumption data. In Ontario, both Enbridge Gas and Milton Hydro support it. In theory: click Download My Data, get a file, analyze it. In practice: the XML format is complex, the Excel from Milton Hydro has a quirky structure, and nobody in the HA community seems to have published a working parser that gets meaningful data into InfluxDB and Grafana.

This guide fixes that. You'll end up with:

  • 22+ months of Enbridge gas consumption and billing data in InfluxDB
  • 900+ days of hourly Milton Hydro electricity data in InfluxDB
  • Actual TOU cost calculations per hour (not estimates)
  • A Grafana dashboard showing gas consumption, billing breakdown, carbon tax elimination, and hydro cost per day/month

What You Can Download

Utility Format Data Granularity
Enbridge Gas Green Button XML Monthly consumption + full billing breakdown Monthly
Milton Hydro Excel (hourly) kWh per hour Hourly — 24 readings/day

ENBRIDGE GAS — Green Button XML

How to Download

  1. Log into myaccount.enbridgegas.com
  2. Navigate to My UsageDownload My DataGreen Button Download My Data
  3. Download the XML file — no developer registration needed

:warning: The Enbridge developer API (Green Button Connect My Data) requires formal business onboarding, technical evaluation, and legal approval from Enbridge. That's the enterprise path. The personal Download My Data path requires zero registration and is what this guide uses.

:warning: The XML file may appear empty if opened in Excel due to cell protection. Do not use Excel to inspect it — parse it directly with Python as shown below.

What the XML Contains

The Green Button XML has two types of data blocks:

  • IntervalBlock — monthly consumption readings in m³ (raw value divided by 1000)
  • UsageSummary — full billing breakdown per period including: Amount Due, HST, Gas Supply Charge, Gas Delivery Variable Charge, Federal Carbon Charge, Customer Charge

Key Insight — Carbon Tax Elimination Visible in Data

The Federal Carbon Charge field drops to $0.00 starting April 2025 when the carbon tax was eliminated. This is immediately visible in Grafana without any manual annotation — a real-world example of why having utility data in a time-series database matters.

Step 1 — Upload File to HA

Upload the XML to /homeassistant/ via the File Editor addon in Home Assistant.

Step 2 — Import Gas Consumption to InfluxDB

Run this in the HA Terminal addon:

python3 - << PYEOF
import xml.etree.ElementTree as ET, urllib.request
from datetime import datetime

HOST = "a0d7b954-influxdb"
PORT = 8086
DB = "home_assistant"
USER = "your_influxdb_user"
PASS = "your_influxdb_password"

ns1 = "http://www.w3.org/2005/Atom"
ns2 = "http://naesb.org/espi"
ns = {"atom": ns1, "espi": ns2}

tree = ET.parse("/homeassistant/your_enbridge_file.xml")
root = tree.getroot()

lines = []
for entry in root.findall("atom:entry", ns):
    content = entry.find("atom:content", ns)
    if content is None: continue
    for ib in content.findall(".//espi:IntervalBlock", ns):
        for ir in ib.findall("espi:IntervalReading", ns):
            start = ir.find("espi:timePeriod/espi:start", ns)
            value = ir.find("espi:value", ns)
            if start is None or value is None: continue
            ts_ns = int(start.text) * 1000000000
            m3 = int(value.text) / 1000
            lines.append("gas_usage,source=enbridge,unit=m3 consumption=" + str(m3) + " " + str(ts_ns))

payload = "\n".join(lines).encode("utf-8")
url = "http://" + HOST + ":" + str(PORT) + "/write?db=" + DB + "&u=" + USER + "&p=" + PASS + "&precision=ns"
req = urllib.request.Request(url, data=payload, method="POST")
req.add_header("Content-Type", "application/octet-stream")
with urllib.request.urlopen(req) as resp:
    print("Written " + str(len(lines)) + " records (HTTP " + str(resp.status) + ")")
PYEOF

Step 3 — Import Billing Data (from CSV export)

Enbridge also offers a CSV invoice export via myaccount.enbridgegas.com — cleaner access to billing amounts. Key columns: Invoice Date, Consumption M3, Total Amount Due, Gas Supply Charge, Federal Carbon Charge, HST, Customer Charge.

Upload the CSV to /homeassistant/ and adapt the script to parse it with Python's csv module, writing to measurement gas_bill with fields: total, supply, carbon, customer, hst.


MILTON HYDRO — Hourly Excel Data

How to Download

  1. Log into Milton Hydro MyAccount
  2. Navigate to My UsageExport / Download → select hourly data (Excel format)

:warning: Known issue as of July 2026: Milton Hydro's Green Button portal has a validation bug — account number and meter number from the PDF bill are rejected even when entered correctly. Solution: call Milton Hydro directly and ask them to email 24 months of hourly usage data. Resolved in under 10 minutes, data arrives by email within 30 minutes.

Excel File Structure

  • Rows 1-7: Header summary with TOU consumption totals (Winter/Summer × On/Mid/Off-Peak kWh totals)
  • Row 8: Column headers — Date, 00:00, 01:00, ... 23:00
  • Row 9+: Daily data rows with kWh consumed per hour

TOU Rates — Summer 2026 (Ontario RPP)

Period Weekday Hours Summer Rate Winter Rate
On-Peak 11 AM – 5 PM 20.3 ¢/kWh 13.4 ¢/kWh
Mid-Peak 7–11 AM and 5–7 PM 15.7 ¢/kWh 11.9 ¢/kWh
Off-Peak Evenings, nights, weekends 9.8 ¢/kWh 8.7 ¢/kWh

Weekends and statutory holidays are Off-Peak all day.

Step 1 — Install openpyxl

In the HA Terminal:

pip3 install openpyxl --break-system-packages

Step 2 — Upload File to HA

Upload the Excel file to /homeassistant/ via File Editor.

Step 3 — Import Hourly Data + TOU Cost to InfluxDB

python3 - << PYEOF
import urllib.request, openpyxl
from datetime import datetime

HOST = "a0d7b954-influxdb"
PORT = 8086
DB = "home_assistant"
USER = "your_influxdb_user"
PASS = "your_influxdb_password"

def get_tou_rate(dt):
    summer = 5 <= dt.month <= 10
    if dt.weekday() >= 5: return 0.098 if summer else 0.087
    h = dt.hour
    if summer:
        if 7 <= h < 11 or 17 <= h < 19: return 0.157
        elif 11 <= h < 17: return 0.203
        else: return 0.098
    else:
        if 7 <= h < 11 or 17 <= h < 19: return 0.119
        elif 11 <= h < 17: return 0.134
        else: return 0.087

wb = openpyxl.load_workbook("/homeassistant/your_hydro_file.xlsx", data_only=True)
ws = wb.active
lines = []
header_found = False
for row in ws.iter_rows(values_only=True):
    if row[0] == "Date": header_found = True; continue
    if not header_found or not row[0]: continue
    date_str = str(row[0])
    for h in range(24):
        val = row[h+1]
        if val is None: continue
        kwh = float(val)
        dt = datetime.strptime(date_str + " " + str(h).zfill(2) + ":00:00", "%Y-%m-%d %H:%M:%S")
        rate = get_tou_rate(dt)
        ts_ns = int(dt.timestamp()) * 1000000000
        lines.append("hydro_usage,source=milton_hydro consumption=" + str(kwh) + " " + str(ts_ns))
        lines.append("hydro_cost,source=milton_hydro cost=" + str(round(kwh*rate,6)) + ",rate=" + str(rate) + " " + str(ts_ns))

for i in range(0, len(lines), 1000):
    batch = lines[i:i+1000]
    payload = "\n".join(batch).encode("utf-8")
    url = "http://" + HOST + ":" + str(PORT) + "/write?db=" + DB + "&u=" + USER + "&p=" + PASS + "&precision=ns"
    req = urllib.request.Request(url, data=payload, method="POST")
    req.add_header("Content-Type", "application/octet-stream")
    urllib.request.urlopen(req)
print("Done: " + str(len(lines)) + " records imported")
PYEOF

This imports two measurements:

  • hydro_usage — kWh per hour
  • hydro_cost — dollar cost per hour using actual TOU rate

GRAFANA DASHBOARD QUERIES

Panel 1 — Daily Hydro Consumption (Bar Chart)

SELECT sum("consumption") AS "Daily kWh"
FROM "home_assistant"."autogen"."hydro_usage"
WHERE time >= '2024-01-01T00:00:00Z'
AND "source"='milton_hydro'
GROUP BY time(1d) FILL(null)

Panel 2 — Monthly Gas Consumption (Bar Chart)

SELECT mean("consumption") AS "consumption_m3"
FROM "home_assistant"."autogen"."gas_usage"
WHERE time >= '2024-06-01T00:00:00Z'
AND "source"='enbridge' AND "unit"='m3'
GROUP BY time(30d) FILL(null)

Panel 3 — Monthly Gas Bill (Bar Chart)

SELECT mean("total") AS "Bill CAD"
FROM "home_assistant"."autogen"."gas_bill"
WHERE time >= '2024-06-01T00:00:00Z'
AND "source"='enbridge'
GROUP BY time(30d) FILL(null)

Panel 4 — Gas Bill Breakdown (Stacked Bar)

SELECT mean("supply") AS "Gas Supply",
  mean("delivery") AS "Delivery",
  mean("carbon") AS "Carbon Tax",
  mean("customer") AS "Customer Charge",
  mean("hst") AS "HST"
FROM "home_assistant"."autogen"."gas_bill"
WHERE time >= '2024-06-01T00:00:00Z'
AND "source"='enbridge'
GROUP BY time(30d) FILL(null)

Set Stacking: Normal in the Bar Chart panel options to show stacked components.

Panel 5 — This Month Hydro Cost (Stat Panel)

SELECT sum("cost") AS "Month CAD"
FROM "home_assistant"."autogen"."hydro_cost"
WHERE time >= '2026-06-01T00:00:00Z'
AND "source"='milton_hydro'

:warning: These are energy charges only. Actual bills are typically 1.7–2× higher after delivery charges, regulatory fees, and HST. Add a panel description noting this.


WHAT YOU WILL SEE IN THE DASHBOARD

  • Daily electricity consumption with hourly granularity across 2+ years
  • R720 server shutdown — visible as ~121 kWh/month consumption drop in June 2024
  • Federal Carbon Tax elimination April 2025 — visible as $0.00 carbon field in gas bill breakdown
  • Summer AC load vs winter heating patterns for both utilities
  • Real TOU cost per hour, day, and month (energy charge only)
  • Year-over-year heating season comparison (Jan 2025: 671 m³ vs Jan 2026: 676 m³ — nearly identical)

IMPORTANT NOTES

  • Hydro cost = energy charge only. Actual Milton Hydro bills are ~1.7–2× higher after Global Adjustment, Distribution, Transmission, Regulatory charges, and HST.
  • Enbridge personal download ≠ developer API. You do not need to register as a third-party developer. The Download My Data path is personal use only.
  • Milton Hydro Green Button portal bug (July 2026): Call them directly. Data by email in 30 minutes.
  • Water usage is not available from Milton Hydro — billed quarterly by Halton Region. An ESP32-CAM running AI on the Edge firmware (github.com/jomjol/AI-on-the-edge-device) can read spinning dial meters locally via MQTT.
  • This entire pipeline runs locally on a Lenovo M710q running HAOS 18.0 with InfluxDB 1.x and Grafana addons. No cloud, no subscriptions, no ongoing costs.

STACK

HAOS 18.0 | InfluxDB 1.x addon | Grafana addon | Python 3.14 | openpyxl


Questions welcome. If you're on a different Ontario utility (Toronto Hydro, Hydro One, etc.) the Milton Hydro Excel structure may differ slightly — post your column headers and I can help adapt the script.

Have you seen this integration yet? Your paths may align.

Hi Rick,

Thank you for your comment.

Yes I have and I believe we both posted around the same time :slightly_smiling_face:
My power company is having issues with the Green Button setup and I am unable to download the data directly or via API. They had to download it for me and email me the files.

Will be checking with them on regular basis and definitely try the hands free automated process for sure.