Add energy/cost toggle to energy device cards#51687
Draft
V0lantis wants to merge 2 commits into
Draft
Conversation
Add a toggle on the individual devices summary and detail graph cards
that switches the displayed unit between kWh and the configured currency.
Per-device cost is computed in the frontend only: for each statistics
bucket, device_kWh(h) * (grid_cost(h) / grid_kWh(h)). Helpers and unit
tests live in src/data/energy_device_cost.ts. No backend change.
Toggle state is shared across all cards (and persisted) via
@storage({ subscribe: true }). When no grid cost data is present the
toggle stays, with a tooltip explaining why, and cost selection reverts
to energy.
Untracked-consumption bars are hidden in cost mode (they'd otherwise
double-count since grid cost is already correct at aggregate level).
Solar self-consumption is not allocated; devices running on self-
produced solar still show a grid-priced cost. Both documented.
|
Please take a look at the requested changes, and use the Ready for review button when you are done, thanks 👍 |
Show the untracked residual in cost mode priced per-hour (falls back to
the period-average rate for buckets where the per-hour grid import was
zero — typically solar-covered hours). This replaces the earlier "hide
untracked in cost mode" simplification, which left the chart looking
empty for users whose consumption is mostly untracked.
Other review fixes:
- Guard the toggle on hass.config.currency to avoid a RangeError when
Intl.NumberFormat({ style: "currency" }) gets an empty code
- Hide the toggle entirely when cost is unavailable (previously a
phantom "Cost" button would flip and flip back, flickering)
- Drop the dead deviceCostSeries helper, superseded by the post-process
ratio scaling in the detail card
- Pre-index per-device stats into Map<start, change> so the untracked
cost computation is O(buckets * devices) rather than O(buckets *
devices^2) on long windows
- Unify the two cards' header layout: shared .header-actions wrapper,
conditional title rendering instead of a fragile :empty selector
- Apply the maximumFractionDigits: 3 precision bump only in energy
mode; in cost mode defer to Intl's per-currency minimum fraction
digits. Note this also fixes a pre-existing latent bug where
params.value < 0.1 compared an array to a number and was always false
Member
|
While I'm a bit skeptical of this approach (I still think this should probably get resolved via architecture), I will point out that if you want someone to review your PR you need to mark "Ready for review". |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Proposed change
Add an Energy ↔ Cost toggle to the two "Individual devices" cards on the energy dashboard, so you can see at a glance how much each device is costing rather than just its kWh.
The toggle is shared across both cards (and persisted across reloads) via the existing
@storage({ subscribe: true })decorator — no changes to the energy collection wiring.Per-device cost is computed in the frontend only, no backend change. For each statistics bucket:
device_cost(h) = device_kWh(h) × (Σgrid_cost(h) / Σgrid_kWh(h)). Multiple grid sources sum first, so a user with two grid imports gets a single ratio per hour. Untracked consumption is included in cost mode: per-hour where the bucket has a grid ratio, period-average where it doesn't (typically hours fully covered by solar). Helpers and unit tests live insrc/data/energy_device_cost.ts.The toggle only appears when a grid cost source is configured and
hass.config.currencyis set, soIntl.NumberFormat({ style: "currency" })never gets an empty code.Screenshots
Added below.
Type of change
Additional information
Design notes / known limitations
ratio = grid_cost / grid_kWhformula only prices grid imports; a device running entirely off solar that hour gets a strict 0. Deliberate.grid_kWh = 0. A strict per-hour ratio would drop those buckets to 0 and the untracked series would mostly disappear in cost mode. Falling back to the period-average rate keeps the series visible, at the cost of slight inaccuracy for ToU/dynamic tariffs.architecture#790on the "parent grid" concept. This PR never allocates devices to grids — every grid source's cost and kWh are aggregated first, then one ratio is applied, soballoob's point that HA doesn't model multiple grid networks no longer applies.Checklist
If user exposed functionality or configuration variables are added/changed:
To help with the load of incoming pull requests: