Skip to content

feat(dashboard): add cross-pack Battery Health view with bundled heatmap card#79

Merged
dewet22 merged 1 commit into
mainfrom
feat/dashboard-battery-health
May 30, 2026
Merged

feat(dashboard): add cross-pack Battery Health view with bundled heatmap card#79
dewet22 merged 1 commit into
mainfrom
feat/dashboard-battery-health

Conversation

@dewet22

@dewet22 dewet22 commented May 30, 2026

Copy link
Copy Markdown
Owner

Battery Health dashboard view

Replaces the per-battery list of 16 cell voltages (hard to scan for outliers, worse with multiple packs) with a dedicated, cross-pack Battery Health view.

What's in it

  • Cell-balance heatmap (custom:ge-cell-heatmap) — each cell coloured by its mV deviation from its own pack's mean (imbalance shows at any charge level), plus per-pack mean and spread. Bundled with the integration and served automatically (static path + add_extra_js_url); users install nothing.
  • Cell voltages + temperatures — every cell (left axis) with the four cell-group temperatures (right), sharing one amber LFP warn band; the right axis is scaled so 3.00 V↔10 °C and 3.50 V↔45 °C coincide. Those thresholds were sanity-checked against two winters of GivTCP history.
  • Battery power + SoC — 2-min-averaged power with each pack's SoC, showing the rate driving state of charge.
  • All three generalise to N packs via cycling colour palettes — no hardcoding.

Supporting changes

  • Per-battery sections lose the 16-row Cell Voltages card; Pack Details / Cell Temperatures / BMS Diagnostics stay.
  • Generate-dashboard service gains a pre-flight check: warns (doesn't block) if apexcharts-card / power-flow-card-plus aren't registered, so you get a clear note rather than a broken card. Advisory only (storage-mode resources are all it can enumerate).
  • DASHBOARD_VERSION → 4 raises the existing "dashboard outdated" Repairs prompt.

Notes

  • The chart bad-read filters (implausible single samples → gaps) are a readability stopgap; the real fix is library-side garbage filtering, tracked in givenergy-modbus#78.
  • Generated YAML round-trips cleanly through HA's own loader (transforms + unicode intact). 137 tests pass; mypy-neutral.

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Added Battery Health dashboard view with cell heatmap visualization across all battery packs
    • Bundled heatmap card now automatically included with the integration
    • Dashboard generation displays warning notifications for any missing required cards
  • Tests

    • Added dashboard validation test suite

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 30, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@dewet22, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 44 minutes and 27 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e5b30e3b-fc98-4484-b7ad-9da347c639cc

📥 Commits

Reviewing files that changed from the base of the PR and between 6b95241 and 4bfe9c4.

📒 Files selected for processing (6)
  • custom_components/givenergy_local/__init__.py
  • custom_components/givenergy_local/dashboard.py
  • custom_components/givenergy_local/manifest.json
  • custom_components/givenergy_local/www/ge-cell-heatmap.js
  • tests/test_dashboard.py
  • tests/test_init.py
📝 Walkthrough

Walkthrough

The PR adds a bundled cell-heatmap frontend card, registers it automatically on setup, detects missing required Lovelace resources, and generates a new cross-battery Battery Health dashboard view with a custom heatmap table and aggregated voltage/temperature/power charts.

Changes

Battery Health Dashboard with Bundled Heatmap Card

Layer / File(s) Summary
Frontend card registration and dashboard card detection
custom_components/givenergy_local/__init__.py, tests/test_init.py
Registers the bundled ge-cell-heatmap JavaScript card via Home Assistant's static path mechanism with idempotency guards; adds best-effort detection of missing required HACS Lovelace resources; updates the dashboard service to append warnings for missing cards to generated dashboards.
Battery Health view generation with cross-pack charts
custom_components/givenergy_local/dashboard.py
Adds YAML infrastructure (custom dumper to suppress aliases, palette/filters, warn-band annotations); bumps dashboard version to 4; inserts the new Battery Health view with heatmap inputs and two cross-pack apexcharts for voltage/temperature and power/SoC; removes per-battery Cell Voltages card and updates documentation.
Heatmap custom element implementation
custom_components/givenergy_local/www/ge-cell-heatmap.js
Implements GeCellHeatmap web component that validates battery serials, reads per-cell voltage sensors from Home Assistant state, computes per-pack mean and spread, calculates cell deviations, and renders an interactive HTML heatmap table with configurable color scaling.
Dashboard structure and content validation tests
tests/test_dashboard.py
Validates generated dashboard YAML structure: confirms version 4, verifies Battery Health view with sections layout and full-width grid, checks heatmap lists correct batteries, confirms chart series scale with battery count, validates entity IDs match expected sensors, checks pack color distinctness, and verifies Cell Voltages removal from Batteries view.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • dewet22/givenergy-hass#41: Introduces the dashboard generation pipeline and service that this PR extends with the new Battery Health view and card registration infrastructure.

Suggested labels

v1.0

Poem

🐰 A heatmap blooms across the battery pack,
Cell voltages dance in a colorful stack,
Charts cross the plants with a dashboard so bright,
The bundled card registers, locked in just right!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main changes: adding a cross-pack Battery Health view with a bundled heatmap card, which is the central feature across all modified files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/dashboard-battery-health

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new 'Battery Health' view to the GivEnergy Local integration dashboard, featuring a bundled cell-balance heatmap card (ge-cell-heatmap.js) and comprehensive time-series charts for cell voltages, temperatures, power, and state of charge. It also implements pre-flight checks for required HACS cards and removes the cluttered cell voltage list from the main batteries view. Feedback on these changes highlights three key improvements: caching battery states in the custom card to prevent DOM thrashing on frequent updates, using a unique index-based tag for battery series to avoid naming collisions in the charts when multiple identical battery models are used, and replacing Number(x) with parseFloat(x) in the JavaScript filters to ensure null or empty readings are correctly rendered as gaps rather than plotted as zero.

Comment thread custom_components/givenergy_local/www/ge-cell-heatmap.js Outdated
Comment thread custom_components/givenergy_local/dashboard.py Outdated
Comment thread custom_components/givenergy_local/dashboard.py Outdated
@dewet22 dewet22 force-pushed the feat/dashboard-battery-health branch from 6b95241 to 891e9c4 Compare May 30, 2026 21:36

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
custom_components/givenergy_local/dashboard.py (1)

87-95: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Skip the Battery Health view when no packs are present.

handle_generate_dashboard(...) builds bats from the coordinator's battery list, so this can be []. In that case this still emits _battery_health_view(...), which in turn generates custom:ge-cell-heatmap with batteries: []; GeCellHeatmap.setConfig() rejects that config and the generated dashboard breaks for inverter-only installs.

Suggested fix
     views = "\n".join(
         [
             _overview_view(inv, max_power_kw),
             _energy_view(inv),
             _battery_view(bats),
-            _battery_health_view(inv, bats),
+            *([_battery_health_view(inv, bats)] if bats else []),
             _controls_view(inv),
             _diagnostics_view(inv, max_power_kw),
         ]
     )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@custom_components/givenergy_local/dashboard.py` around lines 87 - 95,
handle_generate_dashboard currently always includes _battery_health_view(inv,
bats) even when bats is empty, which causes GeCellHeatmap to reject the config;
update handle_generate_dashboard (where views is built) to only append/call
_battery_health_view when bats is non-empty (e.g., if bats and len(bats) > 0) so
the battery health card is skipped for inverter-only installs and the rest of
the dashboard remains valid.
🧹 Nitpick comments (1)
tests/test_dashboard.py (1)

56-67: ⚡ Quick win

Add the zero-battery case here.

This loop only exercises 1+ pack inputs, so it misses the bats=[] path that currently produces an invalid heatmap config. Adding that case will lock in the fix for inverter-only systems.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_dashboard.py` around lines 56 - 67, The test
test_series_scale_with_battery_count currently iterates only over non-empty
battery lists and misses the bats=[] path that exposes an invalid heatmap
config; update the iteration in test_series_scale_with_battery_count to include
an empty list (bats=[]) when calling _health_cards so cell_chart and power_chart
are exercised for zero-battery systems, then assert expected counts for n =
len(bats) (volt and temp series lengths should be 16*n and 4*n respectively) and
verify power_chart["series"] equals 1 when n == 0 (otherwise 1 + n) to lock in
the inverter-only behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@custom_components/givenergy_local/www/ge-cell-heatmap.js`:
- Line 87: The file currently calls customElements.define("ge-cell-heatmap",
GeCellHeatmap) unconditionally which throws if the element is already
registered; change it to first check customElements.get("ge-cell-heatmap") and
only call customElements.define("ge-cell-heatmap", GeCellHeatmap) when that
returns undefined (i.e., if not already registered) so duplicate loads won't
throw; locate the define call for GeCellHeatmap and wrap it with the get-check.

---

Outside diff comments:
In `@custom_components/givenergy_local/dashboard.py`:
- Around line 87-95: handle_generate_dashboard currently always includes
_battery_health_view(inv, bats) even when bats is empty, which causes
GeCellHeatmap to reject the config; update handle_generate_dashboard (where
views is built) to only append/call _battery_health_view when bats is non-empty
(e.g., if bats and len(bats) > 0) so the battery health card is skipped for
inverter-only installs and the rest of the dashboard remains valid.

---

Nitpick comments:
In `@tests/test_dashboard.py`:
- Around line 56-67: The test test_series_scale_with_battery_count currently
iterates only over non-empty battery lists and misses the bats=[] path that
exposes an invalid heatmap config; update the iteration in
test_series_scale_with_battery_count to include an empty list (bats=[]) when
calling _health_cards so cell_chart and power_chart are exercised for
zero-battery systems, then assert expected counts for n = len(bats) (volt and
temp series lengths should be 16*n and 4*n respectively) and verify
power_chart["series"] equals 1 when n == 0 (otherwise 1 + n) to lock in the
inverter-only behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: cacb6d92-197d-46eb-8b74-416d8606b443

📥 Commits

Reviewing files that changed from the base of the PR and between a7419f9 and 6b95241.

📒 Files selected for processing (5)
  • custom_components/givenergy_local/__init__.py
  • custom_components/givenergy_local/dashboard.py
  • custom_components/givenergy_local/www/ge-cell-heatmap.js
  • tests/test_dashboard.py
  • tests/test_init.py

Comment thread custom_components/givenergy_local/www/ge-cell-heatmap.js Outdated
@dewet22-codex

Copy link
Copy Markdown
Collaborator

I reviewed the current PR head and do not have any actionable concerns. I ran uv run pytest -q (136 passed), uv lock --check, and targeted ruff on the changed files; the GitHub checks are also green on the refreshed commit.

@dewet22 dewet22 force-pushed the feat/dashboard-battery-health branch 2 times, most recently from cb1d6c1 to f1fb53d Compare May 30, 2026 21:46
…map card

Replaces the hard-to-scan per-battery list of 16 cell voltages with a
plant-level "Battery Health" view in the generated dashboard:

- custom:ge-cell-heatmap cell-balance card, bundled with the integration
  and auto-served (async_register_static_paths + add_extra_js_url) — no
  HACS or manual resource install needed
- a cell-voltage + cell-group-temperature chart whose right axis is scaled
  so the LFP warn bands align across both metrics, plus a battery-power +
  per-pack-SoC chart; both generalised to N packs with cycling palettes
- removes the 16-row Cell Voltages list from each per-battery section
- pre-flight check warns (never blocks) when apexcharts-card or
  power-flow-card-plus aren't registered before generating
- bumps DASHBOARD_VERSION to 4 to raise the regenerate Repairs prompt

The chart bad-read filters are a readability stopgap until the dongle
garbage is filtered library-side (givenergy-modbus#78).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@dewet22 dewet22 force-pushed the feat/dashboard-battery-health branch from f1fb53d to 4bfe9c4 Compare May 30, 2026 21:47

@dewet22-codex dewet22-codex left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved. I reviewed the current head and do not have any actionable concerns.

@dewet22 dewet22 merged commit 08f71a0 into main May 30, 2026
8 checks passed
@dewet22 dewet22 deleted the feat/dashboard-battery-health branch May 30, 2026 22:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants