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
- Log into myaccount.enbridgegas.com
- Navigate to My Usage → Download My Data → Green Button Download My Data
- Download the XML file — no developer registration needed
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.
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
- Log into Milton Hydro MyAccount
- Navigate to My Usage → Export / Download → select hourly data (Excel format)
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 hourhydro_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'
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.