Add gas and battery to energy widget - #5576
Merged
Merged
Conversation
Resolve battery and gas sources from the energy dashboard preferences and show them alongside grid and solar. Battery joins the chart as its own stacked series, matching the frontend's energy usage graph: discharge above the axis, charging below it. Gas stays out of the chart, as it does on the dashboard, because it is metered in volume as often as in energy — it gets a figure with its own unit instead, resolved from the recorder's statistics metadata. The consumption split is now a port of computeConsumptionSingle from the frontend, so energy that charged the battery is not counted as demand and discharge displaces the grid. Cost covers every priced source, electricity and gas together, the way the dashboard's totals row does. Layouts step their type down and rearrange as sources are added, so a home with all four still fits the small card and the lock screen accessories.
Contributor
There was a problem hiding this comment.
Pull request overview
Extends the Energy widget’s data model, timeline provider, and rendering to support battery (charge/discharge stacked above/below axis) and gas (figure + cost contribution, no chart series), aligning behavior and visual stacking with the Home Assistant frontend energy dashboard.
Changes:
- Add battery + gas fields to the widget entry, metrics, and sample/test data; update metric ordering and labels.
- Extend statistics fetching to include battery/gas IDs and fetch recorder metadata/config needed for gas units and combined cost.
- Update HADesignSystem energy widget layouts/chart rendering to handle up to four figures and battery in/out chart layers, with density-based typography.
Reviewed changes
Copilot reviewed 25 out of 99 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| Tests/Widgets/WidgetsSnapshot.test.swift | Adds snapshot coverage for battery/gas scenarios and four-source layouts. |
| Tests/Widgets/WidgetEnergyMetricTests.swift | Updates expectations for new metric ordering (grid-first) and direction/unit assertions. |
| Tests/Widgets/WidgetEnergyGasTests.swift | New unit tests covering gas unit handling, ordering, and combined cost behavior. |
| Tests/Widgets/WidgetEnergyBatteryTests.swift | New unit tests covering battery allocation math, aggregation, and metric behavior. |
| Sources/Shared/Resources/Swiftgen/Strings.swift | Updates SwiftGen accessors for new/renamed energy widget localization keys. |
| Sources/Shared/API/WebSocket/Energy/EnergyStatistics.swift | Adds recorder metadata model + request and supports volume-unit conversion for statistics. |
| Sources/HADesignSystem/Sources/Widgets/Energy/WidgetEnergyStatView.swift | Introduces density-driven sizing for energy figures and updates preview coverage. |
| Sources/HADesignSystem/Sources/Widgets/Energy/WidgetEnergyStatDensity.swift | New density model to scale figure typography/layout as sources increase. |
| Sources/HADesignSystem/Sources/Widgets/Energy/WidgetEnergySmallContentView.swift | Reworks small layout to support crowded 2×2 figure arrangements. |
| Sources/HADesignSystem/Sources/Widgets/Energy/WidgetEnergySampleData.swift | Updates sample stats and adds four-source sample set including battery + gas. |
| Sources/HADesignSystem/Sources/Widgets/Energy/WidgetEnergyPalette.swift | Adds battery/gas colors and a generic quantity formatter (non-kWh values). |
| Sources/HADesignSystem/Sources/Widgets/Energy/WidgetEnergyMediumContentView.swift | Adapts medium/large layout for up to four figures and revised cost placement. |
| Sources/HADesignSystem/Sources/Widgets/Energy/WidgetEnergyChartView.swift | Adds battery-in/out stacked layers and updates stacking logic for positive/negative flows. |
| Sources/HADesignSystem/Sources/Widgets/Energy/WidgetEnergyChartPoint.swift | Extends chart point model and ports frontend allocation logic including battery flows. |
| Sources/HADesignSystem/Sources/Widgets/Energy/WidgetEnergyAccessoryRectangularContentView.swift | Adjusts rectangular accessory layout to handle 3–4 figures via columns. |
| Sources/HADesignSystem/Sources/Widgets/Energy/WidgetEnergyAccessoryCircularContentView.swift | Updates empty-state behavior/icon for circular accessory. |
| Sources/Extensions/Widgets/Energy/WidgetEnergyStyle.swift | Exposes new palette colors and quantity formatting for gas. |
| Sources/Extensions/Widgets/Energy/WidgetEnergyMetric.swift | Adds battery/gas metric kinds, ordering, labeling, and design-system model mapping updates. |
| Sources/Extensions/Widgets/Energy/WidgetEnergyMediumView.swift | Wires showsBattery/cost display rules and adds an every-source preview timeline entry. |
| Sources/Extensions/Widgets/Energy/WidgetEnergyAccessoryCircularView.swift | Updates documentation to match new “headline series” behavior. |
| Sources/Extensions/AppIntents/Widget/Energy/WidgetEnergySource.swift | Adds source options for battery/gas and updates inclusion rules. |
| Sources/Extensions/AppIntents/Widget/Energy/WidgetEnergyEntry.swift | Extends entry with battery/gas totals, live battery power, and updated hasStatistics/net helpers. |
| Sources/Extensions/AppIntents/Widget/Energy/WidgetEnergyChartSample.swift | Adds battery sample day and extends totals to include battery charge/discharge. |
| Sources/Extensions/AppIntents/Widget/Energy/WidgetEnergyAppIntentTimelineProvider.swift | Fetches additional stats + metadata/config, aggregates battery/gas totals, and computes combined cost. |
| Sources/App/Resources/en.lproj/Localizable.strings | Adds/renames English strings for battery/gas and revised electricity/grid labeling. |
Suppressed comments (1)
Sources/Extensions/AppIntents/Widget/Energy/WidgetEnergyAppIntentTimelineProvider.swift:313
costStatIdsnow iterates overgridSources + gasSourceswhen building thecompensationlist. If a gas source ever hasstatCompensationset (orstatEnergyTothat maps to a cost sensor), it would be incorrectly treated as export compensation and netted off the bill, even though gas has no export/compensation concept.
Keep gas contributing to cost, but restrict compensation collection to grid sources only.
for source in gridSources + gasSources {
if let id = source.statCost ?? source.statEnergyFrom.flatMap({ info?.costSensors[$0] }) {
cost.append(id)
}
if let id = source.statCompensation ?? source.statEnergyTo.flatMap({ info?.costSensors[$0] }) {
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+46
to
50
| // The headline series' own icon, so an accessory with nothing to report still says what | ||
| // it would have been reporting. | ||
| Text(verbatim: MaterialDesignIcons.transmissionTowerIcon.unicode) | ||
| .font(.custom(MaterialDesignIcons.familyName, size: 20)) | ||
| .foregroundStyle(.secondary) |
The lock screen circular accessory shows a stand-in icon until statistics arrive. It was hard-coded to the grid, so a widget narrowed to solar, the battery or gas waited behind a pylon it would never show.
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.
AI Policy
Select exactly one option that describes AI usage in this contribution:
Summary
Adds gas and battery to the energy widget, alongside the existing grid and solar figures.
Battery is drawn as its own stacked series on the chart — discharge above the axis, charging below — matching the frontend's energy usage graph. Gas is shown as a figure only, not a chart series, because it is metered in volume as often as in energy; its unit comes from the recorder's statistics metadata. The consumption split is a port of
computeConsumptionSinglefrom the frontend, so energy that charged the battery is not counted as demand. Cost now covers electricity and gas together, like the dashboard's totals row.Layouts adapt as sources are added, so a home with all four still fits the small card and the lock screen accessories.
Screenshots
Recorded snapshots for every family and configuration, in light and dark, are in
Tests/Widgets/__Snapshots__/WidgetsSnapshot.test/— for exampleenergyWidgetEverySourceSystemMediumSnapshot.{light,dark}.png,energyWidgetEverySourceSystemSmallSnapshot.{light,dark}.pngandenergyWidgetEverySourceAccessoryRectangularSnapshot.{light,dark}.png.Link to pull request in Documentation repository
Documentation: home-assistant/companion.home-assistant#
Any other notes
Gas is deliberately kept off the chart to match the dashboard, which gives it a separate card for the same reason.