Repository navigation
Highlights
BoilerJuice 2.0.0 is a breaking rewrite of the 1.3.x integration. One config entry is now one BoilerJuice account, and every tank on that account is its own device. A page the parser cannot read is no longer treated as an empty tank or an empty account.
Requires Home Assistant 2025.2.5 or newer. Read Upgrading from 1.3.x before you update.
What is new
- Every tank is a device. The 1.3.x integration kept the first tank and ignored the rest. After upgrade, every tank on the account appears as its own device and set of sensors. Use Reconfigure to narrow that down.
- Existing entity IDs are kept. Devices and entities are still keyed by tank ID, so dashboards and automations keep working. Unique IDs move from Python class names to stable keys; Home Assistant migrates those on first start.
- Heating season is its own sensor (winter, spring, summer, autumn), read from the calendar. It is always set, whether or not that season has recorded consumption yet.
- Last successful update reports when the account was last polled. Last level change (the old last-updated sensor) still reports when the tank level last moved.
- Seasonal history survives a reset.
reset_consumptionzeroes counters and takes the current level as the new baseline. Dated history is kept unless you passclear_history: true. - Total oil energy honours the configured kWh per litre from the moment you change it. That is the Energy dashboard sensor.
- Reconfigure and reauthentication are first-class. A password change raises a repair rather than silently stopping.
- YAML configuration is deprecated. It still imports once and logs a warning asking you to remove the block.
Sensors (one set per tank)
Tank: oil level (%), volume (L), capacity (L), height (cm).
Consumption: daily oil consumption (L/day, rolling 7-day average), total oil consumption (L), total oil energy (kWh), seasonal oil consumption (L/day, with per-season and per-month attributes), days until empty (d).
Price and energy: oil price (GBP/L), oil energy content (kWh/L), oil cost per kWh (GBP/kWh).
Diagnostic: last level change, last successful update, heating season.
Days until empty uses the tank’s real capacity for the 2%-per-day fallback, not a hard-coded 510 L.
Actions
boilerjuice.reset_consumption— zeroes counters and the daily override, keeps dated history. Passclear_history: trueto delete history as well (it takes a year to rebuild).boilerjuice.set_consumption— seeds totals, optionally with a persistent daily override.
A target resolves to one account and the tanks named. Entity, device, area, floor and label targets all work. A target that reaches two accounts, or no BoilerJuice tank, is refused with nothing changed.
Reliability
A failed scrape is no longer accepted as a reading. In 1.3.x a page the parser did not understand became “0 litres, 0%”, and the drop to that zero was recorded as real consumption.
- Values outside sanity bounds are omitted, not clamped or zeroed.
- Sensors report unknown rather than 0 when there is nothing to report (a daily rate before a complete day, a season with no data).
- An empty account is recognised only from an explicit empty-state message. A status line such as “No tanks need a delivery today”, an add-tank link, or a JavaScript app shell cannot retire devices.
- A JSON listing is authoritative only when every object has a readable tank ID. A mixed or unreadable list raises rather than omitting tanks.
- A singleton tank document with an explicit ID must match the requested tank. A missing ID is accepted as the page that was asked for; an invalid or null ID is not.
- The HTML tanks and edit pages are still the primary source. The client reads the full decoded body in bounded chunks (a sized stream read on the live site returned only the HTML
<head>). JSON is a fallback if a real JavaScript shell arrives. - Unexpected pages are described by counts and a fixed allowlist of field names (size, forms, links, known interstitials). Page HTML, tank IDs, emails and arbitrary JSON keys are never copied into logs, repairs or diagnostics.
- Redirects are followed by hand and validated on every hop. Network errors are redacted so URLs and tank IDs do not reach a log.
- Sessions that lapse (HTML sign-in page or JSON 401, including a UTF-8 BOM) are renewed once.
Consumption history moves to a per-account, versioned storage document on first start. A tank belongs to exactly one account. A tank that disappears is retired after three consecutive authoritative listings, not erased; its history is kept and resumes if it comes back. Unreadable stored data raises a repair rather than silently resetting.
If 1.3.x history already contains an implausible consumption spike from a failed scrape, run reset_consumption with clear_history: true and re-seed with set_consumption.
Upgrading from 1.3.x
This is a breaking release.
| Entity | Change |
|---|---|
sensor.<tank>_oil_consumption_kwh |
Removed. It accumulated as a side effect of being read. Use Total oil energy on the Energy dashboard. Its historical statistics do not carry across. |
sensor.<tank>_last_updated |
Renamed to Last level change. Entity ID is unchanged. A new Last successful update reports when the account was last polled. |
sensor.<tank>_seasonal_oil_consumption |
The current_season attribute is gone. Read states('sensor.<tank>_heating_season') instead. Seasonal and monthly averages stay on this sensor. |
Two repairs appear on the first start after upgrading. Height no longer has a state class (it is a fixed number from the tank configuration). Days until empty now reports its unit as d rather than days. Take the offered action on both. Neither comes back.
Other changes you will notice:
- Oil level is no longer a battery device class, so it leaves battery dashboards and low-battery alerts.
- Changing kWh per litre now affects every kWh figure from that point on, not retrospectively.
- If you have an automation that runs
reset_consumptionafter each refill, it was silently deleting seasonal history. That no longer happens unless you passclear_history: true.
The full migration guide is in the README, Upgrading → To 2.0.0.
Installation
HACS
Add https://github.com/willbeeching/boilerjuice as a custom repository with category Integration, download BoilerJuice, then restart Home Assistant.
Manual
Download boilerjuice.zip below, extract it into config/custom_components/, and restart Home Assistant.
Verifying the download
sha256sum boilerjuice.zip
5532abda52e34eac183194e0c023855fa381600a0bca9860235f6978b3608aea
Built from a93ce61, which passed the full CI suite (lint, strict typing, both supported Home Assistant versions, hassfest and HACS validation) before publication.
Full changelog: v1.3.1...v2.0.0